From 950b4cb604eeac0e43739715bbc8f641a680191e Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 25 Apr 2019 16:54:17 -0600 Subject: [PATCH] wm4Nx is a port of twm, Tab Window Manager (or Tom's Window Manager) version 1.0.10 to NuttX NX windows server. No, a port is not the right word. It is a re-design of TWM from the inside out to work with the NuttX NX server. The name Twm4Nx reflects this legacy. But Twm4Nx is more a homage to TWM than a port of TWM. The original TWM was based on X11 which provides a rich set of features. TWM provided titlebars, shaped windows, several forms of icon management, user-defined macro functions, click-to-type and pointer-driven keyboard focus, graphic contexts, and user-specified key and pointer button bindings, etc. Twm4Nx, on the other hand is based on the NuttX NX server which provides comparatively minimal support. Additional drawing support comes from the NuttX NxWidgets library (which necessitated the change to C++). Twm4Nx is greatly stripped down and targeted on small embedded systems with minimal resources. For example, no assumption is made about the availability of a file system; no .twmrc file is used. Bitmaps are not used (other than for fonts). The TWM license is, I believe compatible with the BSD license used by NuttX. The origin TWM license required notice of copyrights within each file and a full copy of the original license which you can find in the COPYING file. within this directory. STATUS: This port was brutal. Much TWM logic was removed because it depending on X11 features (or just because I could not understand how to use it). The logic is partial. A lot more needs to be done to have a complete system (hence, it is marked EXPERIMENTAL). The kinds of things that need to done are: 1. Update some logic that is only fragmentary for how like resizing, and menus. 2. Integrate NxWidgets into the windows: The resize menu needs a CLabel, the menus are CListBox'es, but not completely integrated, the Icon Manager needs to be a button array. 3. Resit Icons. They are windows now, but need to be compound widgets lying on the background. 4. Widget events are only partially integrated. A lot more needs to be done. A partial change to thoe event system that hints at the redesign is in place but it is far from complete. --- graphics/nxglyphs/Makefile | 4 +- graphics/nxglyphs/images/menu21x21.png | Bin 0 -> 308 bytes graphics/nxglyphs/images/menu42x42.png | Bin 0 -> 456 bytes graphics/nxglyphs/images/nxicon-21x21.png | Bin 0 -> 734 bytes graphics/nxglyphs/images/nxicon-42x42.png | Bin 0 -> 1541 bytes graphics/nxglyphs/images/resize21x21.png | Bin 0 -> 281 bytes graphics/nxglyphs/images/resize42x42.png | Bin 0 -> 423 bytes graphics/nxglyphs/include/mkcursor.c | 2 +- graphics/nxglyphs/src/.gitignore | 2 + graphics/nxglyphs/src/glyph_menu21x21.cxx | 169 +++ graphics/nxglyphs/src/glyph_menu42x42.cxx | 209 +++ graphics/nxglyphs/src/glyph_nxicon21x21.cxx | 207 +++ graphics/nxglyphs/src/glyph_nxicon42x42.cxx | 306 ++++ graphics/nxglyphs/src/glyph_resize21x21.cxx | 169 +++ graphics/nxglyphs/src/glyph_resize42x42.cxx | 214 +++ graphics/nxglyphs/src/mksrle.c | 577 ++++++++ graphics/nxglyphs/src/mksrle.sh | 110 ++ .../UnitTests/CListBox/clistbox_main.cxx | 7 +- graphics/twm4nx/.gitignore | 12 + graphics/twm4nx/COPYING | 82 ++ graphics/twm4nx/Kconfig | 44 + graphics/twm4nx/Make.defs | 40 + graphics/twm4nx/Makefile | 69 + graphics/twm4nx/README.txt | 28 + graphics/twm4nx/Twm4NX-Threading.pdf | Bin 0 -> 33844 bytes graphics/twm4nx/src/cbackground.cxx | 310 +++++ graphics/twm4nx/src/cfonts.cxx | 177 +++ graphics/twm4nx/src/cicon.cxx | 469 +++++++ graphics/twm4nx/src/ciconmgr.cxx | 757 ++++++++++ graphics/twm4nx/src/ciconwin.cxx | 385 ++++++ graphics/twm4nx/src/cinput.cxx | 692 ++++++++++ graphics/twm4nx/src/cmenus.cxx | 882 ++++++++++++ graphics/twm4nx/src/cresize.cxx | 1080 +++++++++++++++ graphics/twm4nx/src/ctwm4nx.cxx | 596 ++++++++ graphics/twm4nx/src/cwindow.cxx | 1229 +++++++++++++++++ graphics/twm4nx/src/cwindowevent.cxx | 249 ++++ graphics/twm4nx/src/cwindowfactory.cxx | 330 +++++ graphics/twm4nx/src/twm4nx_cursor.cxx | 65 + include/graphics/nxglyphs.hxx | 5 +- include/graphics/nxwidgets/cnxfont.hxx | 2 + include/graphics/nxwidgets/cwidgetcontrol.hxx | 4 +- include/graphics/twm4nx/cbackground.hxx | 141 ++ include/graphics/twm4nx/cfonts.hxx | 182 +++ include/graphics/twm4nx/cicon.hxx | 189 +++ include/graphics/twm4nx/ciconmgr.hxx | 269 ++++ include/graphics/twm4nx/ciconwin.hxx | 214 +++ include/graphics/twm4nx/cinput.hxx | 209 +++ include/graphics/twm4nx/cmenus.hxx | 289 ++++ include/graphics/twm4nx/cresize.hxx | 248 ++++ include/graphics/twm4nx/ctwm4nx.hxx | 315 +++++ include/graphics/twm4nx/cwindow.hxx | 592 ++++++++ include/graphics/twm4nx/cwindowevent.hxx | 145 ++ include/graphics/twm4nx/cwindowfactory.hxx | 194 +++ include/graphics/twm4nx/twm4nx_config.hxx | 455 ++++++ include/graphics/twm4nx/twm4nx_cursor.hxx | 70 + .../graphics/twm4nx/twm4nx_widgetevents.hxx | 215 +++ 56 files changed, 13204 insertions(+), 6 deletions(-) create mode 100644 graphics/nxglyphs/images/menu21x21.png create mode 100644 graphics/nxglyphs/images/menu42x42.png create mode 100644 graphics/nxglyphs/images/nxicon-21x21.png create mode 100644 graphics/nxglyphs/images/nxicon-42x42.png create mode 100644 graphics/nxglyphs/images/resize21x21.png create mode 100644 graphics/nxglyphs/images/resize42x42.png create mode 100644 graphics/nxglyphs/src/.gitignore create mode 100644 graphics/nxglyphs/src/glyph_menu21x21.cxx create mode 100644 graphics/nxglyphs/src/glyph_menu42x42.cxx create mode 100644 graphics/nxglyphs/src/glyph_nxicon21x21.cxx create mode 100644 graphics/nxglyphs/src/glyph_nxicon42x42.cxx create mode 100644 graphics/nxglyphs/src/glyph_resize21x21.cxx create mode 100644 graphics/nxglyphs/src/glyph_resize42x42.cxx create mode 100644 graphics/nxglyphs/src/mksrle.c create mode 100644 graphics/nxglyphs/src/mksrle.sh create mode 100644 graphics/twm4nx/.gitignore create mode 100644 graphics/twm4nx/COPYING create mode 100644 graphics/twm4nx/Kconfig create mode 100644 graphics/twm4nx/Make.defs create mode 100644 graphics/twm4nx/Makefile create mode 100644 graphics/twm4nx/README.txt create mode 100644 graphics/twm4nx/Twm4NX-Threading.pdf create mode 100644 graphics/twm4nx/src/cbackground.cxx create mode 100644 graphics/twm4nx/src/cfonts.cxx create mode 100644 graphics/twm4nx/src/cicon.cxx create mode 100644 graphics/twm4nx/src/ciconmgr.cxx create mode 100644 graphics/twm4nx/src/ciconwin.cxx create mode 100644 graphics/twm4nx/src/cinput.cxx create mode 100644 graphics/twm4nx/src/cmenus.cxx create mode 100644 graphics/twm4nx/src/cresize.cxx create mode 100644 graphics/twm4nx/src/ctwm4nx.cxx create mode 100644 graphics/twm4nx/src/cwindow.cxx create mode 100644 graphics/twm4nx/src/cwindowevent.cxx create mode 100644 graphics/twm4nx/src/cwindowfactory.cxx create mode 100644 graphics/twm4nx/src/twm4nx_cursor.cxx create mode 100644 include/graphics/twm4nx/cbackground.hxx create mode 100644 include/graphics/twm4nx/cfonts.hxx create mode 100644 include/graphics/twm4nx/cicon.hxx create mode 100644 include/graphics/twm4nx/ciconmgr.hxx create mode 100644 include/graphics/twm4nx/ciconwin.hxx create mode 100644 include/graphics/twm4nx/cinput.hxx create mode 100644 include/graphics/twm4nx/cmenus.hxx create mode 100644 include/graphics/twm4nx/cresize.hxx create mode 100644 include/graphics/twm4nx/ctwm4nx.hxx create mode 100644 include/graphics/twm4nx/cwindow.hxx create mode 100644 include/graphics/twm4nx/cwindowevent.hxx create mode 100644 include/graphics/twm4nx/cwindowfactory.hxx create mode 100644 include/graphics/twm4nx/twm4nx_config.hxx create mode 100644 include/graphics/twm4nx/twm4nx_cursor.hxx create mode 100644 include/graphics/twm4nx/twm4nx_widgetevents.hxx diff --git a/graphics/nxglyphs/Makefile b/graphics/nxglyphs/Makefile index ef4e44294..3634e3030 100644 --- a/graphics/nxglyphs/Makefile +++ b/graphics/nxglyphs/Makefile @@ -48,19 +48,21 @@ CXXSRCS += glyph_capslock.cxx glyph_radiobuttonon.cxx glyph_windowdepthdown.cxx CXXSRCS += glyph_checkboxmu.cxx glyph_return.cxx glyph_windowdepthup.cxx CXXSRCS += glyph_checkboxoff.cxx glyph_screendepthdown.cxx -# Glyphs used by NxWM +# Glyphs used by NxWM and Twm4Nx ifeq ($(CONFIG_NXGLPYHS_LARGE_ICONS),y) # Large icons CXXSRCS += glyph_calculator47x49.cxx glyph_calibration48x42.cxx glyph_cmd49x43.cxx CXXSRCS += glyph_minimize42x42.cxx glyph_play48x48.cxx glyph_stop42x42.cxx +CXXSRCS += glyph_menu42x42.cxx glyph_resize42x42.cxx glyph_nxicon42x42.cxx else # Small icons CXXSRCS += glyph_calculator24x25.cxx glyph_calibration24x21.cxx glyph_cmd25x22.cxx CXXSRCS += glyph_minimize21x21.cxx glyph_play24x24.cxx glyph_stop21x21.cxx +CXXSRCS += glyph_menu21x21.cxx glyph_resize21x21.cxx glyph_nxicon21x21.cxx endif ifeq ($(CONFIG_NXGLPYHS_LARGE_ICONS),y) diff --git a/graphics/nxglyphs/images/menu21x21.png b/graphics/nxglyphs/images/menu21x21.png new file mode 100644 index 0000000000000000000000000000000000000000..d1da97196597c652103f7e93a305291bef1d6507 GIT binary patch literal 308 zcmeAS@N?(olHy`uVBq!ia0vp^q9Dw{1|(OCFP#RY*pj^6T^Rm@;DWu&Cj&(|3p^r= z85sDEfH31!Z9ZwBAbW|YuPggw7BMj`gWmUkoD}rCZyb-s9`A8@y)KQ@m))E#7SB24L*rSOhj1Uq^M}x zOf3@NtNh9Jsy1nluMf+^9t|(vBX4WB6dV<6yK&%jILo0aBG(n$HShd>!8YMlY)bf| z9U^HHCRr~#o3cDOCbLgMJj(2^y6v~lk4BEugv}GZGCYsePLU<=BIr^J2%$n yb17fcQ#uvk#p`T1C92KPz`!78_t^ss40B%CO`G#{##*3f7(8A5T-G@yGywp_TXD4j literal 0 HcmV?d00001 diff --git a/graphics/nxglyphs/images/menu42x42.png b/graphics/nxglyphs/images/menu42x42.png new file mode 100644 index 0000000000000000000000000000000000000000..cfe61c5e9df78506d2a27f1bc7c73e213d233126 GIT binary patch literal 456 zcmV;(0XP1MP)kunOPQ%mM=KQA|lgM34g%Mu=8xqLmnpi70LuYpU(hSyHZl*f?bh)Zm{i0V_YOC zR1>llstxIcvXQLm_fLJ+f5n;%yrETsLtSaw?J{^-&AbpX3lY11-JwS$(dLUr>%b*1 z@E&FMCi7Pb+M`;KHz+GjHnQnYYNDZ%#MVt4U>WxH(+EsFWgQ4IUBNHE@ ylvJn&pckqM=!9wnR`nfJBha0w$)(zrs-YKet#ktuFuk<^0000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf00v@9M??Vs0RI60 zpuMM)00007bV*G`2jc`74+<+`CQQo!00K@)L_t(IPmPsLXcIvc$KP(ML22t2L87Sj zB7#UkO%Ch%1gr z-+n3aM-X9gW|?k2YNC&yhU<#o|5(sjm3061W{y3h?TA>4 zxSpHf2x^uO@uf3q^8Jl^#3By`5Z@Rq@|e3iP$LZwkK;^flw&n_o@KaNaH?Ca5$3vj57X)Hq^a`5ttown!bsD5zv;|UU2W&?s~pcl zdOpc{Zft^r#y;ve@Q$wmOOLnzqzaXJ07yk+PY3At-@G0r3N|;IIjQn-D8>FJ5-sNN zd?j4s3*o}aA&$8D&ytmbz7w-LQ}>}tLAt_!F}cMYj*C>J_Es$wWS<8*BP#rw*O_Hk zW}RC8%c&jVcT}9|Dmf3cbE)Q}8AspF&SyCXtpg2ow>M=EDtkYrGmCV>;)2?q-0RD< zHI!mpR)S6dA_PXduWh}~EU4DyUwN4$_EP513Fuo90wb-5R0IyS27E2ZT>r>9J)&4q z+Lk$D_RZZ}MEAr8#}_$v?AgZe3t>emS_6kCGVGxnF)w@Qu0)7PAxSnQ^p)z0a=F0O z;>W16rRieiP#}CWUF2NwLXqv45Lt%%f^c7huCOkU#sU9PJ=yR2YBegA|LX3W!q^s0 QmH+?%07*qoM6N<$g7~0Hod5s; literal 0 HcmV?d00001 diff --git a/graphics/nxglyphs/images/nxicon-42x42.png b/graphics/nxglyphs/images/nxicon-42x42.png new file mode 100644 index 0000000000000000000000000000000000000000..858c6c1a963cefc4e19f52a6daa3f21e1dad50df GIT binary patch literal 1541 zcmV+g2KxDlP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf00v@9M??Vs0RI60 zpuMM)00007bV*G`2jc`74+l6AO=33X}*g zC@u(;Xf+h9hQve^7d8>9nAW(%1c-5^8zJ$rGAuL_7cPpJ7&ICqI};LPd{#qOMgvx{ zC0Ik-nLc3JGE?vOzxTUy=FGV>x9$BU)BlSON&=3#p>wq6Z3L2 zKS$4A^3D{YlO#J;PzU={YIbf}4SkbVqkp}pX6C03PlP34?HBU(oKTv4t2dH&z8qEIHZfB#LdR1RJJ>hh}+nNDmR*#5fjDi#4S`p1Msg7crB`$@{{ zT8_!{vE16kmI&?b{?GZFcfV*r5ON-1UIm%CA&EB9?M+_EZ6GqocVlms?8* zol35n;5ZwD>r+X$I^I_)AL}B4FBG`%G?m8;&|T$fH9zMjcaoVbbraXu)F%A=i3VgQ z-PaD?Rfsl4f)b%%=##s>QZRHCaO^RXOIJ?&+c?tSdq!qFU<0rR(AjpPrc5L#6S{L( z@SacyEvGxok0#v4Aycq>)9sD^8jt(92bj#hZ*`KC2@T81KBp@^cWjt$GH(v_-thMT z1g^&84S^!Ts)Yi$q_0*wx|>`oxkJJjH(lL*vPV5{dHW=55(-ysm~L`aYj1r?BE~pe z)n|K8=jMv}CX~?5qq`;Q4<`C*MSAXSlZfLOlQ!_I;eXsoi44%QW3!ZP@AM#)(E9a_ zYS)Rq)T5cFn9#>KGr(M~eA7-scRfS~tzddyCHPJ^>uS6F^aYWL zxcfU41nPP9)H6L&Uhyv_Hf&-|S4}tTQ(Y2ukpSXMSA$rwP+$|QyK1@#OpycvF;M(;6B11*7VkKKu5x1OZr-ZDU=<1AYBKJmt8A{M;pY2&#otHGR+%^B$JxPW zC!_+7!LjRSR8xyP>zf;%bdDzjMe0~NESi3o$T17-eWOhsm`%_Zh`F2@tuflvbhGR?jhdD2Fp106$ zbxV6+05`A8Z%u=;wvOFI>Ib?moYtwo74&jjpuoaYKbP|gvoXB=bC{9M XUuoU3WuF!RUCiL=>gTe~DWM4fW2tHV literal 0 HcmV?d00001 diff --git a/graphics/nxglyphs/images/resize42x42.png b/graphics/nxglyphs/images/resize42x42.png new file mode 100644 index 0000000000000000000000000000000000000000..b2c0ffced06a8166c4e236d7d47227a6f263b8d3 GIT binary patch literal 423 zcmV;Y0a*TtP)?XW0zm{WwOfZ= zdP$p4zvGmL* diff --git a/graphics/nxglyphs/src/.gitignore b/graphics/nxglyphs/src/.gitignore new file mode 100644 index 000000000..e953c8174 --- /dev/null +++ b/graphics/nxglyphs/src/.gitignore @@ -0,0 +1,2 @@ +/_mksrle.exe + diff --git a/graphics/nxglyphs/src/glyph_menu21x21.cxx b/graphics/nxglyphs/src/glyph_menu21x21.cxx new file mode 100644 index 000000000..4df453177 --- /dev/null +++ b/graphics/nxglyphs/src/glyph_menu21x21.cxx @@ -0,0 +1,169 @@ +/******************************************************************************************** + * apps/graphics/nxwm/src/glyph_menu21x21.cxx + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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, NxWidgets, nor the names of its contributors + * me 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 +#include +#include + +#include "graphics/nxwidgets/crlepalettebitmap.hxx" +#include "graphics/nxglyphs.hxx" + +/******************************************************************************************** + * Pre-Processor Definitions + ********************************************************************************************/ + +#define BITMAP_NROWS 21 +#define BITMAP_NCOLUMNS 21 +#define BITMAP_NLUTCODES 6 + +/******************************************************************************************** + * Private Bitmap Data + ********************************************************************************************/ + +using namespace NXWidgets; + +#if CONFIG_NXWIDGETS_BPP == 24 || CONFIG_NXWIDGETS_BPP == 32 +// RGB24 (8-8-8) Colors + +static const uint32_t g_menuNormalLut[BITMAP_NLUTCODES] = +{ + 0xc49c4c, 0xdc9000, 0xfcb800, 0xfcfcfc, 0xc47c00, 0x9c5800, /* Codes 0-5 */ +}; + +static const uint32_t g_menuBrightLut[BITMAP_NLUTCODES] = +{ + 0xd2b478, 0xe4ab3f, 0xfcc93f, 0xfcfcfc, 0xd29c3f, 0xb4813f, /* Codes 0-5 */ +}; + +#elif CONFIG_NXWIDGETS_BPP == 16 +// RGB16 (565) Colors (four of the colors in this map are duplicates) + +static const uint16_t g_menuNormalLut[BITMAP_NLUTCODES] = +{ + 0xc4e9, 0xdc80, 0xfdc0, 0xffff, 0xc3e0, 0x9ac0, /* Codes 0-5 */ +}; + +static const uint16_t g_menuBrightLut[BITMAP_NLUTCODES] = +{ + 0xd5af, 0xe547, 0xfe47, 0xffff, 0xd4e7, 0xb407, /* Codes 0-5 */ +}; + +#elif CONFIG_NXWIDGETS_BPP == 8 +// 8-bit color lookups. NOTE: This is really dumb! The lookup index is 8-bits and it used +// to lookup an 8-bit value. There is no savings in that! It would be better to just put +// the 8-bit color/greyscale value in the run-length encoded image and save the cost of these +// pointless lookups. But these p;ointless lookups do make the logic compatible with the +// 16- and 24-bit types. +/// + +# ifdef CONFIG_NXWIDGETS_GREYSCALE +// 8-bit Greyscale + +static const uint8_t g_menuNormalLut[BITMAP_NLUTCODES] = +{ + 0x9e, 0x96, 0xb7, 0xfc, 0x83, 0x62, /* Codes 0-5 */ +} + +static const uint8_t g_menuBrightLut[BITMAP_NLUTCODES] = +{ + 0xb6, 0xaf, 0xc8, 0xfc, 0xa1, 0x88, /* Codes 0-5 */ +}; + +# else /* CONFIG_NXWIDGETS_GREYSCALE */ +// RGB8 (332) Colors + +static const nxgl_mxpixel_t g_menuNormalLut[BITMAP_NLUTCODES] = +{ + 0xd1, 0xd0, 0xf4, 0xff, 0xcc, 0x88, /* Codes 0-5 */ +}; + +static const uint8_t g_menuBrightLut[BITMAP_NLUTCODES] = +{ + 0xd5, 0xf5, 0xf9, 0xff, 0xd1, 0xb1, /* Codes 0-5 */ +}; + +# endif +#else +# error Unsupported pixel format +#endif + +static const struct SRlePaletteBitmapEntry g_menuRleEntries[] = +{ + { 21, 0}, // Row 0 + { 1, 0}, { 4, 1}, { 7, 2}, { 9, 1}, // Row 1 + { 1, 0}, { 3, 1}, { 9, 2}, { 8, 1}, // Row 2 + { 1, 0}, { 2, 1}, { 10, 2}, { 8, 1}, // Row 3 + { 1, 0}, { 1, 1}, { 2, 2}, { 14, 3}, { 3, 1}, // Row 4 + { 1, 0}, { 1, 1}, { 2, 2}, { 1, 3}, { 6, 2}, { 6, 1}, { 1, 3}, { 2, 1}, // Row 5 + { 1, 4}, + { 1, 0}, { 3, 2}, { 1, 3}, { 5, 2}, { 7, 1}, { 1, 3}, { 2, 1}, { 1, 4}, // Row 6 + { 1, 0}, { 3, 2}, { 1, 3}, { 4, 2}, { 8, 1}, { 1, 3}, { 2, 1}, { 1, 4}, // Row 7 + { 1, 0}, { 3, 2}, { 14, 3}, { 1, 1}, { 2, 4}, // Row 8 + { 1, 0}, { 3, 2}, { 1, 3}, { 1, 2}, { 11, 1}, { 1, 3}, { 1, 1}, { 2, 4}, // Row 9 + { 1, 0}, { 1, 1}, { 2, 2}, { 1, 3}, { 12, 1}, { 1, 3}, { 3, 4}, // Row 10 + { 1, 0}, { 3, 1}, { 14, 3}, { 3, 4}, // Row 11 + { 1, 0}, { 3, 1}, { 1, 3}, { 11, 1}, { 1, 4}, { 1, 3}, { 3, 4}, // Row 12 + { 1, 0}, { 3, 1}, { 1, 3}, { 10, 1}, { 2, 4}, { 1, 3}, { 3, 4}, // Row 13 + { 1, 0}, { 3, 1}, { 14, 3}, { 3, 4}, // Row 14 + { 1, 0}, { 3, 1}, { 1, 3}, { 8, 1}, { 4, 4}, { 1, 3}, { 3, 4}, // Row 15 + { 1, 0}, { 3, 1}, { 1, 3}, { 6, 1}, { 6, 4}, { 1, 3}, { 3, 4}, // Row 16 + { 1, 0}, { 3, 1}, { 14, 3}, { 3, 4}, // Row 17 + { 1, 0}, { 4, 1}, { 16, 4}, // Row 18 + { 1, 0}, { 2, 1}, { 18, 4}, // Row 19 + { 1, 0}, { 19, 4}, { 1, 5}, // Row 20 + }; + +/******************************************************************************************** + * Public Bitmap Structure Definitions + ********************************************************************************************/ + +const struct SRlePaletteBitmap NXWidgets::g_menuBitmap = +{ + CONFIG_NXWIDGETS_BPP, // bpp - Bits per pixel + CONFIG_NXWIDGETS_FMT, // fmt - Color format + BITMAP_NLUTCODES, // nlut - Number of colors in the lLook-Up Table (LUT) + BITMAP_NCOLUMNS, // width - Width in pixels + BITMAP_NROWS, // height - Height in rows + { // lut - Pointer to the beginning of the Look-Up Table (LUT) + g_menuNormalLut, // Index 0: Unselected LUT + g_menuBrightLut, // Index 1: Selected LUT + }, + g_menuRleEntries // data - Pointer to the beginning of the RLE data +}; + diff --git a/graphics/nxglyphs/src/glyph_menu42x42.cxx b/graphics/nxglyphs/src/glyph_menu42x42.cxx new file mode 100644 index 000000000..fda701f43 --- /dev/null +++ b/graphics/nxglyphs/src/glyph_menu42x42.cxx @@ -0,0 +1,209 @@ +/******************************************************************************************** + * apps/graphics/nxwm/src/glyph_men42x42.cxx + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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, NxWidgets, nor the names of its contributors + * me 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 +#include +#include + +#include "graphics/nxwidgets/crlepalettebitmap.hxx" +#include "graphics/nxglyphs.hxx" + +/******************************************************************************************** + * Pre-Processor Definitions + ********************************************************************************************/ + +#define BITMAP_NROWS 42 +#define BITMAP_NCOLUMNS 42 +#define BITMAP_NLUTCODES 7 + +/******************************************************************************************** + * Private Bitmap Data + ********************************************************************************************/ + +using namespace NXWidgets; + +#if CONFIG_NXWIDGETS_BPP == 24 || CONFIG_NXWIDGETS_BPP == 32 +// RGB24 (8-8-8) Colors + +static const uint32_t g_menuNormalLut[BITMAP_NLUTCODES] = +{ + 0xc49c4c, 0xdc9000, 0xfcb800, 0x9c5800, 0xfcfcfc, 0xdcb468, 0xc47c00, /* Codes 0-6 */ +}; + +static const uint32_t g_menuBrightLut[BITMAP_NLUTCODES] = +{ + 0xd2b478, 0xe4ab3f, 0xfcc93f, 0xb4813f, 0xfcfcfc, 0xe4c68d, 0xd29c3f, /* Codes 0-6 */ +}; + +#elif CONFIG_NXWIDGETS_BPP == 16 +// RGB16 (565) Colors (four of the colors in this map are duplicates) + +static const uint16_t g_menuNormalLut[BITMAP_NLUTCODES] = +{ + 0xc4e9, 0xdc80, 0xfdc0, 0x9ac0, 0xffff, 0xddad, 0xc3e0, /* Codes 0-6 */ +}; + +static const uint16_t g_menuBrightLut[BITMAP_NLUTCODES] = +{ + 0xd5af, 0xe547, 0xfe47, 0xb407, 0xffff, 0xe631, 0xd4e7, /* Codes 0-6 */ +}; + +#elif CONFIG_NXWIDGETS_BPP == 8 +// 8-bit color lookups. NOTE: This is really dumb! The lookup index is 8-bits and it used +// to lookup an 8-bit value. There is no savings in that! It would be better to just put +// the 8-bit color/greyscale value in the run-length encoded image and save the cost of these +// pointless lookups. But these p;ointless lookups do make the logic compatible with the +// 16- and 24-bit types. +/// + +# ifdef CONFIG_NXWIDGETS_GREYSCALE +// 8-bit Greyscale + +static const uint8_t g_menuNormalLut[BITMAP_NLUTCODES] = +{ + 0x9e, 0x96, 0xb7, 0x62, 0xfc, 0xb7, 0x83, /* Codes 0-6 */ +} + +static const uint8_t g_menuBrightLut[BITMAP_NLUTCODES] = +{ + 0xb6, 0xaf, 0xc8, 0x88, 0xfc, 0xc8, 0xa1, /* Codes 0-6 */ +}; + +# else /* CONFIG_NXWIDGETS_GREYSCALE */ +// RGB8 (332) Colors + +static const nxgl_mxpixel_t g_menuNormalLut[BITMAP_NLUTCODES] = +{ + 0xd1, 0xd0, 0xf4, 0x88, 0xff, 0xd5, 0xcc, /* Codes 0-6 */ +}; + +static const uint8_t g_menuBrightLut[BITMAP_NLUTCODES] = +{ + 0xd5, 0xf5, 0xf9, 0xb1, 0xff, 0xfa, 0xd1, /* Codes 0-6 */ +}; + +# endif +#else +# error Unsupported pixel format +#endif + +static const struct SRlePaletteBitmapEntry g_menuRleEntries[] = +{ + { 42, 0}, // Row 0 + { 1, 0}, { 11, 1}, { 10, 2}, { 19, 1}, { 1, 0}, // Row 1 + { 1, 0}, { 9, 1}, { 14, 2}, { 17, 1}, { 1, 3}, // Row 2 + { 1, 0}, { 7, 1}, { 17, 2}, { 16, 1}, { 1, 3}, // Row 3 + { 1, 0}, { 6, 1}, { 18, 2}, { 16, 1}, { 1, 3}, // Row 4 + { 1, 0}, { 5, 1}, { 19, 2}, { 16, 1}, { 1, 3}, // Row 5 + { 1, 0}, { 4, 1}, { 20, 2}, { 16, 1}, { 1, 3}, // Row 6 + { 1, 0}, { 3, 1}, { 20, 2}, { 17, 1}, { 1, 3}, // Row 7 + { 1, 0}, { 3, 1}, { 3, 2}, { 27, 4}, { 7, 1}, { 1, 3}, // Row 8 + { 1, 0}, { 2, 1}, { 4, 2}, { 1, 4}, { 25, 5}, { 1, 4}, { 1, 5}, { 5, 1}, // Row 9 + { 1, 6}, { 1, 3}, + { 1, 0}, { 2, 1}, { 4, 2}, { 1, 4}, { 1, 5}, { 13, 2}, { 11, 1}, { 1, 4}, // Row 10 + { 1, 5}, { 5, 1}, { 1, 6}, { 1, 3}, + { 1, 0}, { 1, 1}, { 5, 2}, { 1, 4}, { 1, 5}, { 12, 2}, { 12, 1}, { 1, 4}, // Row 11 + { 1, 5}, { 5, 1}, { 1, 6}, { 1, 3}, + { 1, 0}, { 1, 1}, { 5, 2}, { 1, 4}, { 1, 5}, { 11, 2}, { 13, 1}, { 1, 4}, // Row 12 + { 1, 5}, { 5, 1}, { 1, 6}, { 1, 3}, + { 1, 0}, { 6, 2}, { 1, 4}, { 1, 5}, { 10, 2}, { 14, 1}, { 1, 4}, { 1, 5}, // Row 13 + { 4, 1}, { 2, 6}, { 1, 3}, + { 1, 0}, { 6, 2}, { 1, 4}, { 1, 5}, { 9, 2}, { 15, 1}, { 1, 4}, { 1, 5}, // Row 14 + { 4, 1}, { 2, 6}, { 1, 3}, + { 1, 0}, { 6, 2}, { 27, 4}, { 1, 5}, { 3, 1}, { 3, 6}, { 1, 3}, // Row 15 + { 1, 0}, { 6, 2}, { 1, 4}, { 25, 5}, { 1, 4}, { 1, 5}, { 3, 1}, { 3, 6}, // Row 16 + { 1, 3}, + { 1, 0}, { 6, 2}, { 1, 4}, { 1, 5}, { 4, 2}, { 20, 1}, { 1, 4}, { 1, 5}, // Row 17 + { 2, 1}, { 4, 6}, { 1, 3}, + { 1, 0}, { 6, 2}, { 1, 4}, { 1, 5}, { 2, 2}, { 22, 1}, { 1, 4}, { 1, 5}, // Row 18 + { 2, 1}, { 4, 6}, { 1, 3}, + { 1, 0}, { 1, 1}, { 5, 2}, { 1, 4}, { 1, 5}, { 1, 2}, { 23, 1}, { 1, 4}, // Row 19 + { 1, 5}, { 1, 1}, { 5, 6}, { 1, 3}, + { 1, 0}, { 2, 1}, { 4, 2}, { 1, 4}, { 1, 5}, { 24, 1}, { 1, 4}, { 1, 5}, // Row 20 + { 1, 1}, { 5, 6}, { 1, 3}, + { 1, 0}, { 4, 1}, { 2, 2}, { 1, 4}, { 1, 5}, { 24, 1}, { 1, 4}, { 1, 5}, // Row 21 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 27, 4}, { 1, 5}, { 6, 6}, { 1, 3}, // Row 22 + { 1, 0}, { 6, 1}, { 1, 4}, { 25, 5}, { 1, 4}, { 1, 5}, { 6, 6}, { 1, 3}, // Row 23 + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 23, 1}, { 1, 6}, { 1, 4}, { 1, 5}, // Row 24 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 22, 1}, { 2, 6}, { 1, 4}, { 1, 5}, // Row 25 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 21, 1}, { 3, 6}, { 1, 4}, { 1, 5}, // Row 26 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 20, 1}, { 4, 6}, { 1, 4}, { 1, 5}, // Row 27 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 27, 4}, { 1, 5}, { 6, 6}, { 1, 3}, // Row 28 + { 1, 0}, { 6, 1}, { 1, 4}, { 25, 5}, { 1, 4}, { 1, 5}, { 6, 6}, { 1, 3}, // Row 29 + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 16, 1}, { 8, 6}, { 1, 4}, { 1, 5}, // Row 30 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 14, 1}, { 10, 6}, { 1, 4}, { 1, 5}, // Row 31 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 13, 1}, { 11, 6}, { 1, 4}, { 1, 5}, // Row 32 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 12, 1}, { 12, 6}, { 1, 4}, { 1, 5}, // Row 33 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 27, 4}, { 1, 5}, { 6, 6}, { 1, 3}, // Row 34 + { 1, 0}, { 7, 1}, { 27, 5}, { 6, 6}, { 1, 3}, // Row 35 + { 1, 0}, { 8, 1}, { 32, 6}, { 1, 3}, // Row 36 + { 1, 0}, { 6, 1}, { 34, 6}, { 1, 3}, // Row 37 + { 1, 0}, { 4, 1}, { 36, 6}, { 1, 3}, // Row 38 + { 1, 0}, { 2, 1}, { 37, 6}, { 2, 3}, // Row 39 + { 1, 0}, { 39, 6}, { 2, 3}, // Row 40 + { 2, 0}, { 40, 3}, // Row 41 + }; + +/******************************************************************************************** + * Public Bitmap Structure Definitions + ********************************************************************************************/ + +const struct SRlePaletteBitmap NXWidgets::g_menuBitmap = +{ + CONFIG_NXWIDGETS_BPP, // bpp - Bits per pixel + CONFIG_NXWIDGETS_FMT, // fmt - Color format + BITMAP_NLUTCODES, // nlut - Number of colors in the lLook-Up Table (LUT) + BITMAP_NCOLUMNS, // width - Width in pixels + BITMAP_NROWS, // height - Height in rows + { // lut - Pointer to the beginning of the Look-Up Table (LUT) + g_menuNormalLut, // Index 0: Unselected LUT + g_menuBrightLut, // Index 1: Selected LUT + }, + g_menuRleEntries // data - Pointer to the beginning of the RLE data +}; + diff --git a/graphics/nxglyphs/src/glyph_nxicon21x21.cxx b/graphics/nxglyphs/src/glyph_nxicon21x21.cxx new file mode 100644 index 000000000..af39667bc --- /dev/null +++ b/graphics/nxglyphs/src/glyph_nxicon21x21.cxx @@ -0,0 +1,207 @@ +/******************************************************************************************** + * apps/graphics/nxwm/src/glyph_nxicon21x21.cxx + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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, NxWidgets, nor the names of its contributors + * me 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 +#include +#include + +#include "graphics/nxwidgets/crlepalettebitmap.hxx" +#include "graphics/nxglyphs.hxx" + +/******************************************************************************************** + * Pre-Processor Definitions + ********************************************************************************************/ + +#define BITMAP_NROWS 21 +#define BITMAP_NCOLUMNS 21 +#define BITMAP_NLUTCODES 31 + +/******************************************************************************************** + * Private Bitmap Data + ********************************************************************************************/ + +using namespace NXWidgets; + +#if CONFIG_NXWIDGETS_BPP == 24 || CONFIG_NXWIDGETS_BPP == 32 +// RGB24 (8-8-8) Colors + +static const uint32_t g_nxiconNormalLut[BITMAP_NLUTCODES] = +{ + 0xfcfcfc, 0x3830e0, 0x3c34e0, 0xcce0f0, 0x2c20e0, 0xc8e0f0, 0x181074, 0xd4e8f4, /* Codes 0-7 */ + 0x5894bc, 0xd4ecf0, 0x282480, 0x3c34ec, 0x848cf0, 0x4c8cb4, 0x7c84b8, 0x8488e8, /* Codes 8-15 */ + 0x3028e4, 0x100870, 0x3830d0, 0x3c34e8, 0x3028e0, 0x302cb0, 0x20187c, 0xd8ecf8, /* Codes 16-23 */ + 0x58a0e4, 0xd8ecf4, 0xe4f0f8, 0xd0d0f8, 0xc8e0ec, 0x94bcd4, 0xd4e4f4, /* Codes 24-30 */ +}; + +static const uint32_t g_nxiconBrightLut[BITMAP_NLUTCODES] = +{ + 0xfcfcfc, 0x6963e7, 0x6c66e7, 0xd8e7f3, 0x6057e7, 0xd5e7f3, 0x514b96, 0xdeedf6, /* Codes 0-7 */ + 0x81aecc, 0xdef0f3, 0x5d5a9f, 0x6c66f0, 0xa2a8f3, 0x78a8c6, 0x9ca2c9, 0xa2a5ed, /* Codes 8-15 */ + 0x635dea, 0x4b4593, 0x6963db, 0x6c66ed, 0x635de7, 0x6360c3, 0x57519c, 0xe1f0f9, /* Codes 16-23 */ + 0x81b7ea, 0xe1f0f6, 0xeaf3f9, 0xdbdbf9, 0xd5e7f0, 0xaeccde, 0xdeeaf6, /* Codes 24-30 */ +}; + +#elif CONFIG_NXWIDGETS_BPP == 16 +// RGB16 (565) Colors (four of the colors in this map are duplicates) + +static const uint16_t g_nxiconNormalLut[BITMAP_NLUTCODES] = +{ + 0xffff, 0x399c, 0x39bc, 0xcf1e, 0x291c, 0xcf1e, 0x188e, 0xd75e, 0x5cb7, 0xd77e, /* Codes 0-9 */ + 0x2930, 0x39bd, 0x847e, 0x4c76, 0x7c37, 0x845d, 0x315c, 0x104e, 0x399a, 0x39bd, /* Codes 10-19 */ + 0x315c, 0x3176, 0x20cf, 0xdf7f, 0x5d1c, 0xdf7e, 0xe79f, 0xd69f, 0xcf1d, 0x95fa, /* Codes 20-29 */ + 0xd73e, /* Codes 30-30 */ +}; + +static const uint16_t g_nxiconBrightLut[BITMAP_NLUTCODES] = +{ + 0xffff, 0x6b1c, 0x6b3c, 0xdf3e, 0x62bc, 0xd73e, 0x5252, 0xdf7e, 0x8579, 0xdf9e, /* Codes 0-9 */ + 0x5ad3, 0x6b3e, 0xa55e, 0x7d58, 0x9d19, 0xa53d, 0x62fd, 0x4a32, 0x6b1b, 0x6b3d, /* Codes 10-19 */ + 0x62fc, 0x6318, 0x5293, 0xe79f, 0x85bd, 0xe79e, 0xef9f, 0xdedf, 0xd73e, 0xae7b, /* Codes 20-29 */ + 0xdf5e, /* Codes 30-30 */ +}; + +#elif CONFIG_NXWIDGETS_BPP == 8 +// 8-bit color lookups. NOTE: This is really dumb! The lookup index is 8-bits and it used +// to lookup an 8-bit value. There is no savings in that! It would be better to just put +// the 8-bit color/greyscale value in the run-length encoded image and save the cost of these +// pointless lookups. But these p;ointless lookups do make the logic compatible with the +// 16- and 24-bit types. +/// + +# ifdef CONFIG_NXWIDGETS_GREYSCALE +// 8-bit Greyscale + +static const uint8_t g_nxiconNormalLut[BITMAP_NLUTCODES] = +{ + 0xfc, 0x46, 0x4a, 0xdb, 0x39, 0xda, 0x1d, 0xe3, 0x86, 0xe5, 0x2f, 0x4b, 0x95, 0x7d, 0x87, 0x91, /* Codes 0-15 */ + 0x3f, 0x16, 0x44, 0x4a, 0x3f, 0x3c, 0x25, 0xe7, 0x92, 0xe6, 0xed, 0xd4, 0xda, 0xb2, 0xe1, /* Codes 16-30 */ +} + +static const uint8_t g_nxiconBrightLut[BITMAP_NLUTCODES] = +{ + 0xfc, 0x73, 0x76, 0xe3, 0x6a, 0xe2, 0x55, 0xe9, 0xa3, 0xea, 0x62, 0x77, 0xae, 0x9d, 0xa4, 0xac, /* Codes 0-15 */ + 0x6e, 0x4f, 0x72, 0x77, 0x6e, 0x6c, 0x5b, 0xec, 0xac, 0xec, 0xf0, 0xde, 0xe2, 0xc5, 0xe7, /* Codes 16-30 */ +}; + +# else /* CONFIG_NXWIDGETS_GREYSCALE */ +// RGB8 (332) Colors + +static const nxgl_mxpixel_t g_nxiconNormalLut[BITMAP_NLUTCODES] = +{ + 0xff, 0x27, 0x27, 0xdf, 0x27, 0xdf, 0x01, 0xdf, 0x53, 0xdf, 0x26, 0x27, 0x93, 0x52, 0x72, 0x93, /* Codes 0-15 */ + 0x27, 0x01, 0x27, 0x27, 0x27, 0x26, 0x22, 0xdf, 0x57, 0xdf, 0xff, 0xdb, 0xdf, 0x97, 0xdf, /* Codes 16-30 */ +}; + +static const uint8_t g_nxiconBrightLut[BITMAP_NLUTCODES] = +{ + 0xff, 0x6f, 0x6f, 0xdf, 0x6b, 0xdf, 0x4a, 0xff, 0x97, 0xff, 0x4a, 0x6f, 0xb7, 0x77, 0x97, 0xb7, /* Codes 0-15 */ + 0x6b, 0x4a, 0x6f, 0x6f, 0x6b, 0x6f, 0x4a, 0xff, 0x97, 0xff, 0xff, 0xdb, 0xdf, 0xbb, 0xff, /* Codes 16-30 */ +}; + +# endif +#else +# error Unsupported pixel format +#endif + +static const struct SRlePaletteBitmapEntry g_nxiconRleEntries[] = +{ + { 10, 0}, { 1, 1}, { 10, 0}, // Row 0 + { 9, 0}, { 1, 1}, { 1, 2}, { 1, 1}, { 9, 0}, // Row 1 + { 8, 0}, { 1, 1}, { 3, 2}, { 1, 1}, { 8, 0}, // Row 2 + { 3, 0}, { 2, 3}, { 2, 0}, { 1, 1}, { 1, 2}, { 1, 4}, { 1, 5}, { 1, 6}, // Row 3 + { 1, 2}, { 1, 1}, { 4, 0}, { 1, 7}, { 2, 0}, + { 4, 0}, { 1, 3}, { 1, 8}, { 1, 1}, { 2, 2}, { 1, 9}, { 1, 0}, { 1, 3}, // Row 4 + { 1, 10}, { 1, 2}, { 1, 1}, { 1, 0}, { 1, 3}, { 1, 0}, { 1, 8}, { 2, 0}, + { 5, 0}, { 1, 3}, { 1, 11}, { 2, 2}, { 1, 9}, { 2, 0}, { 1, 10}, { 2, 2}, // Row 5 + { 1, 12}, { 1, 0}, { 1, 3}, { 1, 8}, { 2, 0}, + { 5, 0}, { 1, 3}, { 1, 10}, { 2, 2}, { 1, 9}, { 2, 0}, { 1, 3}, { 1, 10}, // Row 6 + { 1, 2}, { 1, 3}, { 1, 0}, { 1, 13}, { 3, 0}, + { 4, 0}, { 1, 3}, { 1, 0}, { 1, 3}, { 1, 11}, { 1, 2}, { 1, 9}, { 1, 0}, // Row 7 + { 1, 3}, { 1, 0}, { 1, 14}, { 1, 15}, { 1, 0}, { 1, 3}, { 1, 10}, { 3, 0}, + { 2, 0}, { 1, 16}, { 1, 0}, { 1, 3}, { 1, 0}, { 1, 3}, { 1, 10}, { 1, 2}, // Row 8 + { 1, 9}, { 1, 0}, { 1, 17}, { 1, 0}, { 2, 3}, { 1, 0}, { 1, 14}, { 1, 1}, + { 1, 18}, { 2, 0}, + { 1, 0}, { 1, 19}, { 1, 20}, { 1, 0}, { 2, 3}, { 1, 0}, { 1, 3}, { 1, 21}, // Row 9 + { 1, 9}, { 1, 0}, { 1, 22}, { 1, 3}, { 2, 0}, { 1, 3}, { 1, 10}, { 2, 2}, + { 1, 1}, { 1, 0}, + { 1, 19}, { 1, 2}, { 1, 20}, { 1, 0}, { 1, 3}, { 1, 10}, { 1, 0}, { 1, 3}, // Row 10 + { 1, 10}, { 1, 9}, { 1, 0}, { 1, 22}, { 1, 4}, { 2, 0}, { 1, 10}, { 1, 1}, + { 3, 2}, { 1, 1}, + { 1, 0}, { 1, 1}, { 1, 20}, { 1, 0}, { 1, 3}, { 1, 10}, { 1, 3}, { 1, 0}, // Row 11 + { 1, 3}, { 1, 23}, { 1, 0}, { 1, 22}, { 1, 3}, { 2, 0}, { 1, 6}, { 1, 1}, + { 3, 2}, { 1, 24}, + { 2, 0}, { 1, 20}, { 1, 0}, { 1, 3}, { 1, 10}, { 1, 2}, { 1, 0}, { 1, 3}, // Row 12 + { 1, 25}, { 1, 0}, { 1, 22}, { 1, 26}, { 2, 0}, { 1, 3}, { 1, 10}, { 2, 2}, + { 1, 24}, { 1, 0}, + { 2, 0}, { 1, 27}, { 1, 0}, { 1, 3}, { 1, 10}, { 1, 2}, { 1, 3}, { 1, 0}, // Row 13 + { 1, 3}, { 1, 0}, { 1, 3}, { 1, 0}, { 2, 3}, { 1, 0}, { 1, 14}, { 1, 2}, + { 1, 24}, { 2, 0}, + { 4, 0}, { 1, 3}, { 1, 10}, { 2, 2}, { 1, 0}, { 1, 3}, { 1, 0}, { 1, 28}, // Row 14 + { 1, 0}, { 1, 10}, { 1, 2}, { 1, 0}, { 1, 3}, { 1, 10}, { 3, 0}, + { 4, 0}, { 1, 3}, { 1, 10}, { 2, 2}, { 1, 3}, { 3, 0}, { 1, 3}, { 1, 10}, // Row 15 + { 1, 2}, { 1, 3}, { 1, 0}, { 1, 29}, { 3, 0}, + { 4, 0}, { 1, 3}, { 1, 8}, { 1, 1}, { 2, 2}, { 3, 0}, { 1, 10}, { 1, 1}, // Row 16 + { 1, 2}, { 1, 24}, { 1, 0}, { 1, 3}, { 1, 8}, { 2, 0}, + { 4, 0}, { 1, 3}, { 1, 8}, { 1, 0}, { 1, 1}, { 1, 2}, { 1, 3}, { 1, 0}, // Row 17 + { 1, 3}, { 1, 10}, { 1, 2}, { 1, 24}, { 1, 0}, { 1, 3}, { 1, 0}, { 1, 8}, + { 2, 0}, + { 4, 0}, { 1, 30}, { 1, 8}, { 2, 0}, { 1, 18}, { 1, 2}, { 1, 3}, { 1, 10}, // Row 18 + { 1, 2}, { 1, 24}, { 3, 0}, { 1, 3}, { 1, 8}, { 2, 0}, + { 4, 0}, { 2, 8}, { 3, 0}, { 1, 1}, { 2, 2}, { 1, 24}, { 8, 0}, // Row 19 + { 10, 0}, { 1, 1}, { 1, 24}, { 9, 0}, // Row 20 + }; + +/******************************************************************************************** + * Public Bitmap Structure Definitions + ********************************************************************************************/ + +const struct SRlePaletteBitmap NXWidgets::g_nxiconBitmap = +{ + CONFIG_NXWIDGETS_BPP, // bpp - Bits per pixel + CONFIG_NXWIDGETS_FMT, // fmt - Color format + BITMAP_NLUTCODES, // nlut - Number of colors in the lLook-Up Table (LUT) + BITMAP_NCOLUMNS, // width - Width in pixels + BITMAP_NROWS, // height - Height in rows + { // lut - Pointer to the beginning of the Look-Up Table (LUT) + g_nxiconNormalLut, // Index 0: Unselected LUT + g_nxiconBrightLut, // Index 1: Selected LUT + }, + g_nxiconRleEntries // data - Pointer to the beginning of the RLE data +}; + diff --git a/graphics/nxglyphs/src/glyph_nxicon42x42.cxx b/graphics/nxglyphs/src/glyph_nxicon42x42.cxx new file mode 100644 index 000000000..50a818984 --- /dev/null +++ b/graphics/nxglyphs/src/glyph_nxicon42x42.cxx @@ -0,0 +1,306 @@ +/******************************************************************************************** + * apps/graphics/nxwm/src/glyph_nxicon42x42.cxx + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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, NxWidgets, nor the names of its contributors + * me 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 +#include +#include + +#include "graphics/nxwidgets/crlepalettebitmap.hxx" +#include "graphics/nxglyphs.hxx" + +/******************************************************************************************** + * Pre-Processor Definitions + ********************************************************************************************/ + +#define BITMAP_NROWS 42 +#define BITMAP_NCOLUMNS 42 +#define BITMAP_NLUTCODES 52 + +/******************************************************************************************** + * Private Bitmap Data + ********************************************************************************************/ + +using namespace NXWidgets; + +#if CONFIG_NXWIDGETS_BPP == 24 || CONFIG_NXWIDGETS_BPP == 32 +// RGB24 (8-8-8) Colors + +static const uint32_t g_nxiconNormalLut[BITMAP_NLUTCODES] = +{ + 0xfcfcfc, 0x3830e0, 0x3c34e0, 0x3828e0, 0xe0f0f8, 0xdcd8f8, 0x8488e8, 0xd4ecf0, /* Codes 0-7 */ + 0x2c20e0, 0x3830d0, 0xcce0f0, 0xd4e8f4, 0x5894bc, 0xc8e0f0, 0x181074, 0x2c2894, /* Codes 8-15 */ + 0xf4f8f8, 0xe4f0f4, 0xe4f0f8, 0x282480, 0x3c34ec, 0xc8e0ec, 0x90bcd4, 0x848cf0, /* Codes 16-23 */ + 0x4c8cb4, 0xe0ecf4, 0x302cb0, 0x7c84b8, 0xd8ecf8, 0x282478, 0x3028e4, 0x100870, /* Codes 24-31 */ + 0x08006c, 0x3c34e8, 0x3028e0, 0x20187c, 0xdcf4f0, 0xf0f4f8, 0x5ca4e8, 0x58a0e4, /* Codes 32-39 */ + 0xd8ecf4, 0xc4dcec, 0xdcf4fc, 0xd0e8f4, 0xd0d0f8, 0x94bcd4, 0x5080b0, 0xd4e4f4, /* Codes 40-47 */ + 0x303c8c, 0x1c1870, 0x3830cc, 0x382ce0, /* Codes 48-51 */ +}; + +static const uint32_t g_nxiconBrightLut[BITMAP_NLUTCODES] = +{ + 0xfcfcfc, 0x6963e7, 0x6c66e7, 0x695de7, 0xe7f3f9, 0xe4e1f9, 0xa2a5ed, 0xdef0f3, /* Codes 0-7 */ + 0x6057e7, 0x6963db, 0xd8e7f3, 0xdeedf6, 0x81aecc, 0xd5e7f3, 0x514b96, 0x605dae, /* Codes 8-15 */ + 0xf6f9f9, 0xeaf3f6, 0xeaf3f9, 0x5d5a9f, 0x6c66f0, 0xd5e7f0, 0xabccde, 0xa2a8f3, /* Codes 16-23 */ + 0x78a8c6, 0xe7f0f6, 0x6360c3, 0x9ca2c9, 0xe1f0f9, 0x5d5a99, 0x635dea, 0x4b4593, /* Codes 24-31 */ + 0x453f90, 0x6c66ed, 0x635de7, 0x57519c, 0xe4f6f3, 0xf3f6f9, 0x84baed, 0x81b7ea, /* Codes 32-39 */ + 0xe1f0f6, 0xd2e4f0, 0xe4f6fc, 0xdbedf6, 0xdbdbf9, 0xaeccde, 0x7b9fc3, 0xdeeaf6, /* Codes 40-47 */ + 0x636ca8, 0x545193, 0x6963d8, 0x6960e7, /* Codes 48-51 */ +}; + +#elif CONFIG_NXWIDGETS_BPP == 16 +// RGB16 (565) Colors (four of the colors in this map are duplicates) + +static const uint16_t g_nxiconNormalLut[BITMAP_NLUTCODES] = +{ + 0xffff, 0x399c, 0x39bc, 0x395c, 0xe79f, 0xdedf, 0x845d, 0xd77e, 0x291c, 0x399a, /* Codes 0-9 */ + 0xcf1e, 0xd75e, 0x5cb7, 0xcf1e, 0x188e, 0x2952, 0xf7df, 0xe79e, 0xe79f, 0x2930, /* Codes 10-19 */ + 0x39bd, 0xcf1d, 0x95fa, 0x847e, 0x4c76, 0xe77e, 0x3176, 0x7c37, 0xdf7f, 0x292f, /* Codes 20-29 */ + 0x315c, 0x104e, 0x080d, 0x39bd, 0x315c, 0x20cf, 0xdfbe, 0xf7bf, 0x5d3d, 0x5d1c, /* Codes 30-39 */ + 0xdf7e, 0xc6fd, 0xdfbf, 0xd75e, 0xd69f, 0x95fa, 0x5416, 0xd73e, 0x31f1, 0x18ce, /* Codes 40-49 */ + 0x3999, 0x397c, /* Codes 50-51 */ +}; + +static const uint16_t g_nxiconBrightLut[BITMAP_NLUTCODES] = +{ + 0xffff, 0x6b1c, 0x6b3c, 0x6afc, 0xe79f, 0xe71f, 0xa53d, 0xdf9e, 0x62bc, 0x6b1b, /* Codes 0-9 */ + 0xdf3e, 0xdf7e, 0x8579, 0xd73e, 0x5252, 0x62f5, 0xf7df, 0xef9e, 0xef9f, 0x5ad3, /* Codes 10-19 */ + 0x6b3e, 0xd73e, 0xae7b, 0xa55e, 0x7d58, 0xe79e, 0x6318, 0x9d19, 0xe79f, 0x5ad3, /* Codes 20-29 */ + 0x62fd, 0x4a32, 0x41f2, 0x6b3d, 0x62fc, 0x5293, 0xe7be, 0xf7bf, 0x85dd, 0x85bd, /* Codes 30-39 */ + 0xe79e, 0xd73e, 0xe7bf, 0xdf7e, 0xdedf, 0xae7b, 0x7cf8, 0xdf5e, 0x6375, 0x5292, /* Codes 40-49 */ + 0x6b1b, 0x6b1c, /* Codes 50-51 */ +}; + +#elif CONFIG_NXWIDGETS_BPP == 8 +// 8-bit color lookups. NOTE: This is really dumb! The lookup index is 8-bits and it used +// to lookup an 8-bit value. There is no savings in that! It would be better to just put +// the 8-bit color/greyscale value in the run-length encoded image and save the cost of these +// pointless lookups. But these p;ointless lookups do make the logic compatible with the +// 16- and 24-bit types. +/// + +# ifdef CONFIG_NXWIDGETS_GREYSCALE +// 8-bit Greyscale + +static const uint8_t g_nxiconNormalLut[BITMAP_NLUTCODES] = +{ + 0xfc, 0x46, 0x4a, 0x41, 0xec, 0xdc, 0x91, 0xe5, 0x39, 0x44, 0xdb, 0xe3, 0x86, 0xda, 0x1d, 0x35, /* Codes 0-15 */ + 0xf6, 0xec, 0xed, 0x2f, 0x4b, 0xda, 0xb1, 0x95, 0x7d, 0xe9, 0x3c, 0x87, 0xe7, 0x2e, 0x3f, 0x16, /* Codes 16-31 */ + 0x0e, 0x4a, 0x3f, 0x25, 0xec, 0xf3, 0x96, 0x92, 0xe6, 0xd6, 0xed, 0xe2, 0xd4, 0xb2, 0x77, 0xe1, /* Codes 32-47 */ + 0x41, 0x23, 0x44, 0x44, /* Codes 48-51 */ +} + +static const uint8_t g_nxiconBrightLut[BITMAP_NLUTCODES] = +{ + 0xfc, 0x73, 0x76, 0x70, 0xf0, 0xe4, 0xac, 0xea, 0x6a, 0x72, 0xe3, 0xe9, 0xa3, 0xe2, 0x55, 0x67, /* Codes 0-15 */ + 0xf8, 0xf0, 0xf0, 0x62, 0x77, 0xe2, 0xc4, 0xae, 0x9d, 0xed, 0x6c, 0xa4, 0xec, 0x62, 0x6e, 0x4f, /* Codes 16-31 */ + 0x4a, 0x77, 0x6e, 0x5b, 0xf0, 0xf5, 0xaf, 0xac, 0xec, 0xdf, 0xf1, 0xe8, 0xde, 0xc5, 0x98, 0xe7, /* Codes 32-47 */ + 0x70, 0x59, 0x72, 0x72, /* Codes 48-51 */ +}; + +# else /* CONFIG_NXWIDGETS_GREYSCALE */ +// RGB8 (332) Colors + +static const nxgl_mxpixel_t g_nxiconNormalLut[BITMAP_NLUTCODES] = +{ + 0xff, 0x27, 0x27, 0x27, 0xff, 0xdb, 0x93, 0xdf, 0x27, 0x27, 0xdf, 0xdf, 0x53, 0xdf, 0x01, 0x26, /* Codes 0-15 */ + 0xff, 0xff, 0xff, 0x26, 0x27, 0xdf, 0x97, 0x93, 0x52, 0xff, 0x26, 0x72, 0xdf, 0x25, 0x27, 0x01, /* Codes 16-31 */ + 0x01, 0x27, 0x27, 0x22, 0xdf, 0xff, 0x57, 0x57, 0xdf, 0xdb, 0xdf, 0xdf, 0xdb, 0x97, 0x52, 0xdf, /* Codes 32-47 */ + 0x26, 0x01, 0x27, 0x27, /* Codes 48-51 */ +}; + +static const uint8_t g_nxiconBrightLut[BITMAP_NLUTCODES] = +{ + 0xff, 0x6f, 0x6f, 0x6b, 0xff, 0xff, 0xb7, 0xff, 0x6b, 0x6f, 0xdf, 0xff, 0x97, 0xdf, 0x4a, 0x6a, /* Codes 0-15 */ + 0xff, 0xff, 0xff, 0x4a, 0x6f, 0xdf, 0xbb, 0xb7, 0x77, 0xff, 0x6f, 0x97, 0xff, 0x4a, 0x6b, 0x4a, /* Codes 16-31 */ + 0x4a, 0x6f, 0x6b, 0x4a, 0xff, 0xff, 0x97, 0x97, 0xff, 0xdf, 0xff, 0xdf, 0xdb, 0xbb, 0x77, 0xff, /* Codes 32-47 */ + 0x6e, 0x4a, 0x6f, 0x6f, /* Codes 48-51 */ +}; + +# endif +#else +# error Unsupported pixel format +#endif + +static const struct SRlePaletteBitmapEntry g_nxiconRleEntries[] = +{ + { 20, 0}, { 1, 1}, { 1, 2}, { 20, 0}, // Row 0 + { 19, 0}, { 1, 1}, { 1, 3}, { 1, 1}, { 1, 2}, { 19, 0}, // Row 1 + { 18, 0}, { 1, 1}, { 1, 3}, { 2, 2}, { 1, 1}, { 1, 2}, { 18, 0}, // Row 2 + { 17, 0}, { 1, 1}, { 1, 3}, { 4, 2}, { 1, 1}, { 1, 2}, { 17, 0}, // Row 3 + { 15, 0}, { 1, 4}, { 1, 1}, { 1, 3}, { 6, 2}, { 1, 1}, { 1, 2}, { 1, 5}, // Row 4 + { 15, 0}, + { 15, 0}, { 1, 1}, { 3, 2}, { 1, 6}, { 1, 7}, { 1, 8}, { 3, 2}, { 1, 9}, // Row 5 + { 1, 2}, { 6, 0}, { 3, 10}, { 6, 0}, + { 5, 0}, { 1, 11}, { 3, 10}, { 1, 12}, { 4, 0}, { 1, 1}, { 1, 3}, { 2, 2}, // Row 6 + { 1, 8}, { 1, 10}, { 1, 13}, { 1, 10}, { 1, 14}, { 1, 15}, { 2, 2}, { 1, 1}, + { 1, 2}, { 5, 0}, { 1, 10}, { 1, 0}, { 1, 10}, { 1, 11}, { 5, 0}, + { 5, 0}, { 1, 10}, { 1, 0}, { 1, 16}, { 1, 10}, { 2, 12}, { 2, 0}, { 1, 1}, // Row 7 + { 1, 3}, { 3, 2}, { 1, 7}, { 1, 17}, { 1, 0}, { 1, 18}, { 1, 10}, { 1, 19}, + { 1, 20}, { 2, 2}, { 1, 1}, { 1, 2}, { 3, 0}, { 1, 10}, { 1, 18}, { 1, 0}, + { 1, 21}, { 1, 10}, { 1, 12}, { 4, 0}, + { 5, 0}, { 1, 10}, { 2, 0}, { 2, 10}, { 1, 12}, { 1, 0}, { 1, 1}, { 1, 3}, // Row 8 + { 4, 2}, { 1, 7}, { 3, 0}, { 1, 10}, { 1, 14}, { 1, 19}, { 3, 2}, { 1, 1}, + { 1, 2}, { 2, 0}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 12}, { 4, 0}, + { 5, 0}, { 1, 10}, { 3, 0}, { 1, 10}, { 1, 22}, { 1, 19}, { 1, 3}, { 5, 2}, // Row 9 + { 1, 7}, { 3, 0}, { 1, 18}, { 1, 10}, { 1, 19}, { 1, 20}, { 3, 2}, { 1, 1}, + { 1, 2}, { 1, 10}, { 1, 18}, { 1, 0}, { 1, 21}, { 1, 10}, { 2, 12}, { 4, 0}, + { 5, 0}, { 1, 10}, { 3, 0}, { 2, 10}, { 1, 19}, { 1, 20}, { 5, 2}, { 1, 7}, // Row 10 + { 4, 0}, { 1, 10}, { 2, 19}, { 4, 2}, { 1, 23}, { 1, 10}, { 2, 0}, { 1, 10}, + { 1, 24}, { 1, 12}, { 5, 0}, + { 5, 0}, { 1, 10}, { 3, 0}, { 1, 18}, { 1, 10}, { 1, 14}, { 1, 19}, { 5, 2}, // Row 11 + { 1, 7}, { 2, 0}, { 1, 25}, { 1, 0}, { 1, 21}, { 1, 10}, { 1, 19}, { 1, 26}, + { 3, 2}, { 1, 10}, { 1, 21}, { 1, 0}, { 1, 18}, { 1, 10}, { 2, 12}, { 5, 0}, + { 5, 0}, { 1, 10}, { 4, 0}, { 2, 10}, { 1, 19}, { 1, 20}, { 4, 2}, { 1, 7}, // Row 12 + { 2, 0}, { 1, 13}, { 2, 0}, { 1, 10}, { 2, 19}, { 2, 2}, { 1, 6}, { 1, 10}, + { 2, 0}, { 1, 10}, { 1, 24}, { 1, 12}, { 6, 0}, + { 5, 0}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 0}, { 1, 10}, { 1, 14}, { 1, 19}, // Row 13 + { 4, 2}, { 1, 7}, { 2, 0}, { 1, 13}, { 1, 18}, { 1, 0}, { 1, 21}, { 1, 10}, + { 1, 19}, { 1, 26}, { 1, 2}, { 1, 10}, { 2, 0}, { 1, 18}, { 1, 10}, { 1, 19}, + { 1, 12}, { 6, 0}, + { 5, 0}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 0}, { 2, 10}, { 1, 19}, { 1, 20}, // Row 14 + { 3, 2}, { 1, 7}, { 2, 0}, { 1, 13}, { 1, 10}, { 2, 0}, { 1, 10}, { 1, 27}, + { 1, 19}, { 1, 6}, { 1, 10}, { 2, 0}, { 1, 10}, { 1, 14}, { 1, 19}, { 1, 1}, + { 6, 0}, + { 4, 0}, { 1, 28}, { 1, 10}, { 2, 0}, { 2, 10}, { 2, 0}, { 1, 10}, { 1, 14}, // Row 15 + { 1, 19}, { 3, 2}, { 1, 7}, { 2, 0}, { 1, 13}, { 1, 10}, { 1, 18}, { 1, 0}, + { 1, 21}, { 1, 10}, { 1, 19}, { 1, 10}, { 2, 0}, { 1, 18}, { 1, 10}, { 1, 19}, + { 1, 29}, { 1, 1}, { 1, 2}, { 5, 0}, + { 4, 0}, { 1, 30}, { 1, 10}, { 2, 0}, { 2, 10}, { 2, 0}, { 2, 10}, { 1, 19}, // Row 16 + { 1, 1}, { 2, 2}, { 1, 7}, { 2, 0}, { 1, 13}, { 1, 31}, { 1, 10}, { 2, 0}, + { 1, 10}, { 1, 32}, { 1, 10}, { 2, 0}, { 1, 10}, { 1, 27}, { 1, 19}, { 1, 1}, + { 1, 2}, { 1, 9}, { 1, 2}, { 4, 0}, + { 3, 0}, { 1, 33}, { 1, 34}, { 1, 10}, { 2, 0}, { 3, 10}, { 2, 0}, { 1, 10}, // Row 17 + { 2, 19}, { 2, 2}, { 1, 7}, { 2, 0}, { 1, 13}, { 1, 35}, { 1, 10}, { 2, 0}, + { 1, 18}, { 1, 10}, { 1, 18}, { 1, 0}, { 1, 21}, { 1, 10}, { 2, 19}, { 3, 2}, + { 1, 1}, { 1, 2}, { 3, 0}, + { 2, 0}, { 1, 33}, { 1, 2}, { 1, 34}, { 1, 10}, { 2, 0}, { 1, 10}, { 1, 19}, // Row 18 + { 1, 10}, { 2, 0}, { 2, 10}, { 1, 19}, { 1, 26}, { 1, 2}, { 1, 7}, { 2, 0}, + { 1, 13}, { 1, 35}, { 1, 14}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 0}, { 1, 10}, + { 1, 27}, { 1, 19}, { 1, 1}, { 4, 2}, { 1, 1}, { 1, 2}, { 2, 0}, + { 1, 0}, { 1, 33}, { 2, 2}, { 1, 34}, { 1, 10}, { 2, 0}, { 1, 10}, { 1, 19}, // Row 19 + { 1, 27}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 19}, { 1, 2}, { 1, 7}, { 2, 0}, + { 1, 13}, { 1, 35}, { 1, 19}, { 1, 10}, { 4, 0}, { 1, 21}, { 1, 10}, { 2, 19}, + { 6, 2}, { 1, 1}, { 1, 2}, { 1, 0}, + { 1, 33}, { 3, 2}, { 1, 34}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 19}, { 1, 10}, // Row 20 + { 2, 0}, { 2, 10}, { 1, 19}, { 1, 26}, { 1, 7}, { 2, 0}, { 1, 13}, { 1, 35}, + { 1, 19}, { 1, 8}, { 1, 10}, { 3, 0}, { 1, 10}, { 2, 19}, { 1, 1}, { 7, 2}, + { 1, 1}, { 1, 2}, + { 1, 2}, { 1, 1}, { 2, 2}, { 1, 34}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 19}, // Row 21 + { 1, 36}, { 1, 10}, { 1, 0}, { 1, 18}, { 1, 10}, { 1, 14}, { 1, 19}, { 1, 7}, + { 2, 0}, { 1, 13}, { 1, 35}, { 1, 19}, { 1, 8}, { 1, 10}, { 2, 0}, { 1, 37}, + { 1, 10}, { 2, 19}, { 9, 2}, { 1, 38}, + { 1, 0}, { 1, 2}, { 1, 1}, { 1, 2}, { 1, 34}, { 1, 10}, { 2, 0}, { 1, 10}, // Row 22 + { 2, 19}, { 1, 2}, { 1, 10}, { 2, 0}, { 2, 10}, { 1, 19}, { 1, 28}, { 2, 0}, + { 1, 13}, { 1, 35}, { 1, 19}, { 1, 10}, { 1, 18}, { 3, 0}, { 1, 10}, { 1, 14}, + { 1, 19}, { 1, 1}, { 7, 2}, { 1, 39}, { 1, 0}, + { 2, 0}, { 1, 2}, { 1, 1}, { 1, 34}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 19}, // Row 23 + { 1, 2}, { 1, 36}, { 1, 10}, { 1, 0}, { 1, 18}, { 1, 10}, { 1, 14}, { 1, 40}, + { 2, 0}, { 1, 13}, { 1, 35}, { 1, 14}, { 1, 10}, { 2, 0}, { 1, 41}, { 1, 0}, + { 1, 18}, { 1, 10}, { 2, 19}, { 6, 2}, { 1, 39}, { 2, 0}, + { 3, 0}, { 1, 2}, { 1, 34}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 19}, { 2, 2}, // Row 24 + { 1, 10}, { 2, 0}, { 2, 10}, { 1, 40}, { 2, 0}, { 1, 13}, { 1, 35}, { 1, 10}, + { 1, 18}, { 2, 0}, { 1, 10}, { 2, 0}, { 1, 10}, { 1, 42}, { 1, 19}, { 1, 1}, + { 4, 2}, { 1, 39}, { 3, 0}, + { 4, 0}, { 1, 34}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 19}, { 2, 2}, { 1, 36}, // Row 25 + { 1, 10}, { 2, 0}, { 2, 10}, { 2, 0}, { 1, 13}, { 1, 31}, { 1, 10}, { 2, 0}, + { 1, 10}, { 1, 43}, { 1, 21}, { 1, 0}, { 1, 18}, { 1, 10}, { 2, 19}, { 2, 2}, + { 1, 1}, { 1, 39}, { 4, 0}, + { 4, 0}, { 1, 44}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 19}, { 3, 2}, { 1, 10}, // Row 26 + { 2, 0}, { 2, 10}, { 2, 0}, { 1, 13}, { 1, 10}, { 1, 21}, { 2, 0}, { 1, 10}, + { 1, 19}, { 1, 10}, { 2, 0}, { 1, 10}, { 1, 27}, { 1, 19}, { 2, 2}, { 1, 39}, + { 5, 0}, + { 5, 0}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 19}, { 3, 2}, { 1, 10}, { 1, 21}, // Row 27 + { 2, 0}, { 1, 10}, { 2, 0}, { 1, 13}, { 1, 10}, { 2, 0}, { 2, 10}, { 1, 19}, + { 1, 42}, { 1, 18}, { 2, 0}, { 1, 10}, { 1, 19}, { 1, 29}, { 1, 39}, { 6, 0}, + { 5, 0}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 19}, { 4, 2}, { 1, 10}, { 2, 0}, // Row 28 + { 1, 10}, { 2, 0}, { 1, 13}, { 1, 21}, { 2, 0}, { 1, 10}, { 2, 19}, { 1, 2}, + { 1, 10}, { 2, 0}, { 1, 10}, { 1, 27}, { 1, 19}, { 7, 0}, + { 5, 0}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 19}, { 4, 2}, { 2, 10}, { 4, 0}, // Row 29 + { 1, 13}, { 2, 0}, { 1, 10}, { 1, 27}, { 1, 19}, { 1, 29}, { 1, 2}, { 1, 36}, + { 1, 18}, { 2, 0}, { 1, 10}, { 2, 12}, { 6, 0}, + { 5, 0}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 19}, { 5, 2}, { 1, 10}, { 4, 0}, // Row 30 + { 1, 41}, { 2, 0}, { 1, 10}, { 2, 19}, { 3, 2}, { 1, 10}, { 2, 0}, { 1, 10}, + { 1, 45}, { 1, 12}, { 6, 0}, + { 5, 0}, { 1, 10}, { 2, 0}, { 1, 10}, { 1, 46}, { 1, 19}, { 1, 1}, { 4, 2}, // Row 31 + { 1, 36}, { 1, 10}, { 5, 0}, { 1, 10}, { 1, 42}, { 2, 19}, { 3, 2}, { 1, 10}, + { 1, 21}, { 1, 0}, { 1, 18}, { 1, 10}, { 2, 12}, { 5, 0}, + { 5, 0}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 12}, { 1, 2}, { 1, 1}, { 4, 2}, // Row 32 + { 1, 10}, { 5, 0}, { 1, 10}, { 2, 19}, { 1, 1}, { 2, 2}, { 1, 9}, { 1, 2}, + { 1, 10}, { 2, 0}, { 1, 10}, { 1, 24}, { 1, 12}, { 5, 0}, + { 5, 0}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 12}, { 1, 0}, { 1, 2}, { 1, 1}, // Row 33 + { 3, 2}, { 1, 36}, { 1, 10}, { 3, 0}, { 1, 10}, { 1, 42}, { 1, 19}, { 1, 26}, + { 2, 2}, { 1, 9}, { 1, 2}, { 1, 0}, { 1, 18}, { 1, 21}, { 1, 0}, { 1, 18}, + { 1, 10}, { 2, 12}, { 4, 0}, + { 5, 0}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 12}, { 2, 0}, { 1, 2}, { 1, 1}, // Row 34 + { 3, 2}, { 1, 10}, { 3, 0}, { 1, 10}, { 2, 19}, { 2, 2}, { 1, 9}, { 1, 2}, + { 3, 0}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 12}, { 4, 0}, + { 5, 0}, { 1, 10}, { 2, 0}, { 1, 10}, { 2, 12}, { 3, 0}, { 1, 2}, { 1, 1}, // Row 35 + { 2, 2}, { 1, 36}, { 1, 10}, { 1, 0}, { 1, 10}, { 1, 42}, { 1, 19}, { 1, 26}, + { 1, 2}, { 1, 9}, { 1, 2}, { 4, 0}, { 1, 18}, { 1, 13}, { 1, 18}, { 1, 10}, + { 3, 12}, { 3, 0}, + { 5, 0}, { 1, 10}, { 2, 0}, { 1, 47}, { 2, 12}, { 4, 0}, { 1, 2}, { 1, 9}, // Row 36 + { 2, 2}, { 3, 10}, { 2, 19}, { 1, 2}, { 1, 48}, { 1, 2}, { 6, 0}, { 3, 10}, + { 2, 12}, { 4, 0}, + { 7, 0}, { 4, 12}, { 4, 0}, { 1, 5}, { 1, 2}, { 1, 1}, { 2, 2}, { 1, 49}, // Row 37 + { 2, 19}, { 1, 50}, { 1, 9}, { 1, 2}, { 8, 0}, { 4, 12}, { 4, 0}, + { 7, 0}, { 4, 12}, { 6, 0}, { 1, 2}, { 1, 1}, { 4, 2}, { 1, 9}, { 1, 2}, // Row 38 + { 17, 0}, + { 18, 0}, { 1, 2}, { 1, 1}, { 2, 2}, { 1, 9}, { 1, 2}, { 18, 0}, // Row 39 + { 19, 0}, { 1, 2}, { 1, 1}, { 1, 9}, { 1, 2}, { 19, 0}, // Row 40 + { 20, 0}, { 1, 51}, { 1, 2}, { 20, 0}, // Row 41 + }; + +/******************************************************************************************** + * Public Bitmap Structure Definitions + ********************************************************************************************/ + +const struct SRlePaletteBitmap NXWidgets::g_nxiconBitmap = +{ + CONFIG_NXWIDGETS_BPP, // bpp - Bits per pixel + CONFIG_NXWIDGETS_FMT, // fmt - Color format + BITMAP_NLUTCODES, // nlut - Number of colors in the lLook-Up Table (LUT) + BITMAP_NCOLUMNS, // width - Width in pixels + BITMAP_NROWS, // height - Height in rows + { // lut - Pointer to the beginning of the Look-Up Table (LUT) + g_nxiconNormalLut, // Index 0: Unselected LUT + g_nxiconBrightLut, // Index 1: Selected LUT + }, + g_nxiconRleEntries // data - Pointer to the beginning of the RLE data +}; + diff --git a/graphics/nxglyphs/src/glyph_resize21x21.cxx b/graphics/nxglyphs/src/glyph_resize21x21.cxx new file mode 100644 index 000000000..79c0c3457 --- /dev/null +++ b/graphics/nxglyphs/src/glyph_resize21x21.cxx @@ -0,0 +1,169 @@ +/******************************************************************************************** + * apps/graphics/nxwm/src/glyph_resize21x21.cxx + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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, NxWidgets, nor the names of its contributors + * me 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 +#include +#include + +#include "graphics/nxwidgets/crlepalettebitmap.hxx" +#include "graphics/nxglyphs.hxx" + +/******************************************************************************************** + * Pre-Processor Definitions + ********************************************************************************************/ + +#define BITMAP_NROWS 21 +#define BITMAP_NCOLUMNS 21 +#define BITMAP_NLUTCODES 6 + +/******************************************************************************************** + * Private Bitmap Data + ********************************************************************************************/ + +using namespace NXWidgets; + +#if CONFIG_NXWIDGETS_BPP == 24 || CONFIG_NXWIDGETS_BPP == 32 +// RGB24 (8-8-8) Colors + +static const uint32_t g_resizeNormalLut[BITMAP_NLUTCODES] = +{ + 0x90f0cc, 0x00b400, 0x00d800, 0xfcfcfc, 0x00a400, 0x046414, /* Codes 0-5 */ +}; + +static const uint32_t g_resizeBrightLut[BITMAP_NLUTCODES] = +{ + 0xabf3d8, 0x3fc63f, 0x3fe13f, 0xfcfcfc, 0x3fba3f, 0x428a4e, /* Codes 0-5 */ +}; + +#elif CONFIG_NXWIDGETS_BPP == 16 +// RGB16 (565) Colors (four of the colors in this map are duplicates) + +static const uint16_t g_resizeNormalLut[BITMAP_NLUTCODES] = +{ + 0x9799, 0x05a0, 0x06c0, 0xffff, 0x0520, 0x0322, /* Codes 0-5 */ +}; + +static const uint16_t g_resizeBrightLut[BITMAP_NLUTCODES] = +{ + 0xaf9b, 0x3e27, 0x3f07, 0xffff, 0x3dc7, 0x4449, /* Codes 0-5 */ +}; + +#elif CONFIG_NXWIDGETS_BPP == 8 +// 8-bit color lookups. NOTE: This is really dumb! The lookup index is 8-bits and it used +// to lookup an 8-bit value. There is no savings in that! It would be better to just put +// the 8-bit color/greyscale value in the run-length encoded image and save the cost of these +// pointless lookups. But these p;ointless lookups do make the logic compatible with the +// 16- and 24-bit types. +/// + +# ifdef CONFIG_NXWIDGETS_GREYSCALE +// 8-bit Greyscale + +static const uint8_t g_resizeNormalLut[BITMAP_NLUTCODES] = +{ + 0xcf, 0x69, 0x7e, 0xfc, 0x60, 0x3e, /* Codes 0-5 */ +} + +static const uint8_t g_resizeBrightLut[BITMAP_NLUTCODES] = +{ + 0xda, 0x8e, 0x9e, 0xfc, 0x87, 0x6d, /* Codes 0-5 */ +}; + +# else /* CONFIG_NXWIDGETS_GREYSCALE */ +// RGB8 (332) Colors + +static const nxgl_mxpixel_t g_resizeNormalLut[BITMAP_NLUTCODES] = +{ + 0x9f, 0x14, 0x18, 0xff, 0x14, 0x0c, /* Codes 0-5 */ +}; + +static const uint8_t g_resizeBrightLut[BITMAP_NLUTCODES] = +{ + 0xbf, 0x59, 0x5d, 0xff, 0x55, 0x51, /* Codes 0-5 */ +}; + +# endif +#else +# error Unsupported pixel format +#endif + +static const struct SRlePaletteBitmapEntry g_resizeRleEntries[] = +{ + { 21, 0}, // Row 0 + { 1, 0}, { 4, 1}, { 7, 2}, { 9, 1}, // Row 1 + { 1, 0}, { 3, 1}, { 9, 2}, { 8, 1}, // Row 2 + { 1, 0}, { 2, 1}, { 10, 2}, { 8, 1}, // Row 3 + { 1, 0}, { 1, 1}, { 2, 2}, { 14, 3}, { 3, 1}, // Row 4 + { 1, 0}, { 1, 1}, { 2, 2}, { 1, 3}, { 6, 2}, { 6, 1}, { 1, 3}, { 2, 1}, // Row 5 + { 1, 4}, + { 1, 0}, { 3, 2}, { 1, 3}, { 5, 2}, { 7, 1}, { 1, 3}, { 2, 1}, { 1, 4}, // Row 6 + { 1, 0}, { 3, 2}, { 1, 3}, { 4, 2}, { 8, 1}, { 1, 3}, { 2, 1}, { 1, 4}, // Row 7 + { 1, 0}, { 3, 2}, { 1, 3}, { 3, 2}, { 9, 1}, { 1, 3}, { 1, 1}, { 2, 4}, // Row 8 + { 1, 0}, { 3, 2}, { 1, 3}, { 1, 2}, { 11, 1}, { 1, 3}, { 1, 1}, { 2, 4}, // Row 9 + { 1, 0}, { 1, 1}, { 2, 2}, { 1, 3}, { 12, 1}, { 1, 3}, { 3, 4}, // Row 10 + { 1, 0}, { 3, 1}, { 1, 3}, { 12, 1}, { 1, 3}, { 3, 4}, // Row 11 + { 1, 0}, { 3, 1}, { 1, 3}, { 11, 1}, { 1, 4}, { 1, 3}, { 3, 4}, // Row 12 + { 1, 0}, { 3, 1}, { 1, 3}, { 10, 1}, { 2, 4}, { 1, 3}, { 3, 4}, // Row 13 + { 1, 0}, { 3, 1}, { 1, 3}, { 9, 1}, { 3, 4}, { 1, 3}, { 3, 4}, // Row 14 + { 1, 0}, { 3, 1}, { 1, 3}, { 8, 1}, { 4, 4}, { 1, 3}, { 3, 4}, // Row 15 + { 1, 0}, { 3, 1}, { 1, 3}, { 6, 1}, { 6, 4}, { 1, 3}, { 3, 4}, // Row 16 + { 1, 0}, { 3, 1}, { 14, 3}, { 3, 4}, // Row 17 + { 1, 0}, { 4, 1}, { 16, 4}, // Row 18 + { 1, 0}, { 2, 1}, { 18, 4}, // Row 19 + { 1, 0}, { 19, 4}, { 1, 5}, // Row 20 + }; + +/******************************************************************************************** + * Public Bitmap Structure Definitions + ********************************************************************************************/ + +const struct SRlePaletteBitmap NXWidgets::g_resizeBitmap = +{ + CONFIG_NXWIDGETS_BPP, // bpp - Bits per pixel + CONFIG_NXWIDGETS_FMT, // fmt - Color format + BITMAP_NLUTCODES, // nlut - Number of colors in the lLook-Up Table (LUT) + BITMAP_NCOLUMNS, // width - Width in pixels + BITMAP_NROWS, // height - Height in rows + { // lut - Pointer to the beginning of the Look-Up Table (LUT) + g_resizeNormalLut, // Index 0: Unselected LUT + g_resizeBrightLut, // Index 1: Selected LUT + }, + g_resizeRleEntries // data - Pointer to the beginning of the RLE data +}; + diff --git a/graphics/nxglyphs/src/glyph_resize42x42.cxx b/graphics/nxglyphs/src/glyph_resize42x42.cxx new file mode 100644 index 000000000..6c46a69f8 --- /dev/null +++ b/graphics/nxglyphs/src/glyph_resize42x42.cxx @@ -0,0 +1,214 @@ +/******************************************************************************************** + * apps/graphics/nxwm/src/glyph_resize42x42.cxx + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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, NxWidgets, nor the names of its contributors + * me 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 +#include +#include + +#include "graphics/nxwidgets/crlepalettebitmap.hxx" +#include "graphics/nxglyphs.hxx" + +/******************************************************************************************** + * Pre-Processor Definitions + ********************************************************************************************/ + +#define BITMAP_NROWS 42 +#define BITMAP_NCOLUMNS 42 +#define BITMAP_NLUTCODES 7 + +/******************************************************************************************** + * Private Bitmap Data + ********************************************************************************************/ + +using namespace NXWidgets; + +#if CONFIG_NXWIDGETS_BPP == 24 || CONFIG_NXWIDGETS_BPP == 32 +// RGB24 (8-8-8) Colors + +static const uint32_t g_resizeNormalLut[BITMAP_NLUTCODES] = +{ + 0x90f0cc, 0x00b400, 0x00d800, 0x046414, 0xfcfcfc, 0xd8fcfc, 0x00a400, /* Codes 0-6 */ +}; + +static const uint32_t g_resizeBrightLut[BITMAP_NLUTCODES] = +{ + 0xabf3d8, 0x3fc63f, 0x3fe13f, 0x428a4e, 0xfcfcfc, 0xe1fcfc, 0x3fba3f, /* Codes 0-6 */ +}; + +#elif CONFIG_NXWIDGETS_BPP == 16 +// RGB16 (565) Colors (four of the colors in this map are duplicates) + +static const uint16_t g_resizeNormalLut[BITMAP_NLUTCODES] = +{ + 0x9799, 0x05a0, 0x06c0, 0x0322, 0xffff, 0xdfff, 0x0520, /* Codes 0-6 */ +}; + +static const uint16_t g_resizeBrightLut[BITMAP_NLUTCODES] = +{ + 0xaf9b, 0x3e27, 0x3f07, 0x4449, 0xffff, 0xe7ff, 0x3dc7, /* Codes 0-6 */ +}; + +#elif CONFIG_NXWIDGETS_BPP == 8 +// 8-bit color lookups. NOTE: This is really dumb! The lookup index is 8-bits and it used +// to lookup an 8-bit value. There is no savings in that! It would be better to just put +// the 8-bit color/greyscale value in the run-length encoded image and save the cost of these +// pointless lookups. But these p;ointless lookups do make the logic compatible with the +// 16- and 24-bit types. +/// + +# ifdef CONFIG_NXWIDGETS_GREYSCALE +// 8-bit Greyscale + +static const uint8_t g_resizeNormalLut[BITMAP_NLUTCODES] = +{ + 0xcf, 0x69, 0x7e, 0x3e, 0xfc, 0xf1, 0x60, /* Codes 0-6 */ +} + +static const uint8_t g_resizeBrightLut[BITMAP_NLUTCODES] = +{ + 0xda, 0x8e, 0x9e, 0x6d, 0xfc, 0xf3, 0x87, /* Codes 0-6 */ +}; + +# else /* CONFIG_NXWIDGETS_GREYSCALE */ +// RGB8 (332) Colors + +static const nxgl_mxpixel_t g_resizeNormalLut[BITMAP_NLUTCODES] = +{ + 0x9f, 0x14, 0x18, 0x0c, 0xff, 0xdf, 0x14, /* Codes 0-6 */ +}; + +static const uint8_t g_resizeBrightLut[BITMAP_NLUTCODES] = +{ + 0xbf, 0x59, 0x5d, 0x51, 0xff, 0xff, 0x55, /* Codes 0-6 */ +}; + +# endif +#else +# error Unsupported pixel format +#endif + +static const struct SRlePaletteBitmapEntry g_resizeRleEntries[] = +{ + { 42, 0}, // Row 0 + { 1, 0}, { 11, 1}, { 10, 2}, { 19, 1}, { 1, 0}, // Row 1 + { 1, 0}, { 9, 1}, { 14, 2}, { 17, 1}, { 1, 3}, // Row 2 + { 1, 0}, { 7, 1}, { 17, 2}, { 16, 1}, { 1, 3}, // Row 3 + { 1, 0}, { 6, 1}, { 18, 2}, { 16, 1}, { 1, 3}, // Row 4 + { 1, 0}, { 5, 1}, { 19, 2}, { 16, 1}, { 1, 3}, // Row 5 + { 1, 0}, { 4, 1}, { 20, 2}, { 16, 1}, { 1, 3}, // Row 6 + { 1, 0}, { 3, 1}, { 20, 2}, { 17, 1}, { 1, 3}, // Row 7 + { 1, 0}, { 3, 1}, { 3, 2}, { 27, 4}, { 7, 1}, { 1, 3}, // Row 8 + { 1, 0}, { 2, 1}, { 4, 2}, { 1, 4}, { 24, 5}, { 2, 4}, { 1, 5}, { 5, 1}, // Row 9 + { 1, 6}, { 1, 3}, + { 1, 0}, { 2, 1}, { 4, 2}, { 1, 4}, { 1, 5}, { 13, 2}, { 11, 1}, { 1, 4}, // Row 10 + { 1, 5}, { 5, 1}, { 1, 6}, { 1, 3}, + { 1, 0}, { 1, 1}, { 5, 2}, { 1, 4}, { 1, 5}, { 12, 2}, { 12, 1}, { 1, 4}, // Row 11 + { 1, 5}, { 5, 1}, { 1, 6}, { 1, 3}, + { 1, 0}, { 1, 1}, { 5, 2}, { 1, 4}, { 1, 5}, { 11, 2}, { 13, 1}, { 1, 4}, // Row 12 + { 1, 5}, { 5, 1}, { 1, 6}, { 1, 3}, + { 1, 0}, { 6, 2}, { 1, 4}, { 1, 5}, { 10, 2}, { 14, 1}, { 1, 4}, { 1, 5}, // Row 13 + { 4, 1}, { 2, 6}, { 1, 3}, + { 1, 0}, { 6, 2}, { 1, 4}, { 1, 5}, { 9, 2}, { 15, 1}, { 1, 4}, { 1, 5}, // Row 14 + { 4, 1}, { 2, 6}, { 1, 3}, + { 1, 0}, { 6, 2}, { 1, 4}, { 1, 5}, { 7, 2}, { 17, 1}, { 1, 4}, { 1, 5}, // Row 15 + { 3, 1}, { 3, 6}, { 1, 3}, + { 1, 0}, { 6, 2}, { 1, 4}, { 1, 5}, { 6, 2}, { 18, 1}, { 1, 4}, { 1, 5}, // Row 16 + { 3, 1}, { 3, 6}, { 1, 3}, + { 1, 0}, { 6, 2}, { 1, 4}, { 1, 5}, { 4, 2}, { 20, 1}, { 1, 4}, { 1, 5}, // Row 17 + { 2, 1}, { 4, 6}, { 1, 3}, + { 1, 0}, { 6, 2}, { 1, 4}, { 1, 5}, { 2, 2}, { 22, 1}, { 1, 4}, { 1, 5}, // Row 18 + { 2, 1}, { 4, 6}, { 1, 3}, + { 1, 0}, { 1, 1}, { 5, 2}, { 1, 4}, { 1, 5}, { 1, 2}, { 23, 1}, { 1, 4}, // Row 19 + { 1, 5}, { 1, 1}, { 5, 6}, { 1, 3}, + { 1, 0}, { 2, 1}, { 4, 2}, { 1, 4}, { 1, 5}, { 24, 1}, { 1, 4}, { 1, 5}, // Row 20 + { 1, 1}, { 5, 6}, { 1, 3}, + { 1, 0}, { 4, 1}, { 2, 2}, { 1, 4}, { 1, 5}, { 24, 1}, { 1, 4}, { 1, 5}, // Row 21 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 24, 1}, { 1, 4}, { 1, 5}, { 6, 6}, // Row 22 + { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 24, 1}, { 1, 4}, { 1, 5}, { 6, 6}, // Row 23 + { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 23, 1}, { 1, 6}, { 1, 4}, { 1, 5}, // Row 24 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 22, 1}, { 2, 6}, { 1, 4}, { 1, 5}, // Row 25 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 21, 1}, { 3, 6}, { 1, 4}, { 1, 5}, // Row 26 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 20, 1}, { 4, 6}, { 1, 4}, { 1, 5}, // Row 27 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 19, 1}, { 5, 6}, { 1, 4}, { 1, 5}, // Row 28 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 18, 1}, { 6, 6}, { 1, 4}, { 1, 5}, // Row 29 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 16, 1}, { 8, 6}, { 1, 4}, { 1, 5}, // Row 30 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 14, 1}, { 10, 6}, { 1, 4}, { 1, 5}, // Row 31 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 1, 4}, { 1, 5}, { 13, 1}, { 11, 6}, { 1, 4}, { 1, 5}, // Row 32 + { 6, 6}, { 1, 3}, + { 1, 0}, { 6, 1}, { 2, 4}, { 12, 1}, { 12, 6}, { 1, 4}, { 1, 5}, { 6, 6}, // Row 33 + { 1, 3}, + { 1, 0}, { 6, 1}, { 27, 4}, { 1, 5}, { 6, 6}, { 1, 3}, // Row 34 + { 1, 0}, { 7, 1}, { 27, 5}, { 6, 6}, { 1, 3}, // Row 35 + { 1, 0}, { 8, 1}, { 32, 6}, { 1, 3}, // Row 36 + { 1, 0}, { 6, 1}, { 34, 6}, { 1, 3}, // Row 37 + { 1, 0}, { 4, 1}, { 36, 6}, { 1, 3}, // Row 38 + { 1, 0}, { 2, 1}, { 37, 6}, { 2, 3}, // Row 39 + { 1, 0}, { 39, 6}, { 2, 3}, // Row 40 + { 2, 0}, { 40, 3}, // Row 41 + }; + +/******************************************************************************************** + * Public Bitmap Structure Definitions + ********************************************************************************************/ + +const struct SRlePaletteBitmap NXWidgets::g_resizeBitmap = +{ + CONFIG_NXWIDGETS_BPP, // bpp - Bits per pixel + CONFIG_NXWIDGETS_FMT, // fmt - Color format + BITMAP_NLUTCODES, // nlut - Number of colors in the lLook-Up Table (LUT) + BITMAP_NCOLUMNS, // width - Width in pixels + BITMAP_NROWS, // height - Height in rows + { // lut - Pointer to the beginning of the Look-Up Table (LUT) + g_resizeNormalLut, // Index 0: Unselected LUT + g_resizeBrightLut, // Index 1: Selected LUT + }, + g_resizeRleEntries // data - Pointer to the beginning of the RLE data +}; + diff --git a/graphics/nxglyphs/src/mksrle.c b/graphics/nxglyphs/src/mksrle.c new file mode 100644 index 000000000..6a9e7539e --- /dev/null +++ b/graphics/nxglyphs/src/mksrle.c @@ -0,0 +1,577 @@ +/**************************************************************************** + * apps/graphics/nxglyphs/src/mksrle.c + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct rgb_s +{ + unsigned char r; + unsigned char g; + unsigned char b; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct rgb_s pixels[1024]; +static int npixels = 0; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static unsigned char getmono(unsigned char r, unsigned char g, unsigned char b) +{ + float mono; + unsigned int imono; + + //mono = 0.2125 * (float)r +(0.7154 * (float)g + 0.0721 * (float)b; + mono = 0.299 * (float)r + 0.587 * (float)g + 0.114 * (float)b; + + imono = (unsigned int)mono; + if (mono > 255) + { + mono = 255; + } + + return mono; +} + +static int findpixel(unsigned char r, unsigned char g, unsigned char b) +{ + int i; + + /* Throw away some accuracy */ + + r &= 0xfc; + g &= 0xfc; + b &= 0xfc; + + for (i = 0; i < npixels; i++) + { + if (pixels[i].r == r && pixels[i].g == g && pixels[i].b == b) + { + return i; + } + } + + fprintf(stderr, "Pixel not found\n"); + exit(1); +} + +static void addpixel(unsigned char r, unsigned char g, unsigned char b) +{ + int i; + + /* Throw away some accuracy */ + + r &= 0xfc; + g &= 0xfc; + b &= 0xfc; + + for (i = 0; i < npixels; i++) + { + if (pixels[i].r == r && pixels[i].g == g && pixels[i].b == b) + { + return; + } + } + + pixels[npixels].r = r; + pixels[npixels].g = g; + pixels[npixels].b = b; + npixels++; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, char **argv, char **envp) +{ + const unsigned char *ptr; + unsigned char r; + unsigned char g; + unsigned char b; + int ncode; + int code; + int last; + int nruns; + int first; + int len; + int i; + int j; + + printf("/********************************************************************************************\n"); + printf(" * apps/graphics/nxwm/src/glyph_xxxxxx.cxx\n"); + printf(" *\n"); + printf(" * Copyright (C) 2019 Gregory Nutt. All rights reserved.\n"); + printf(" * Author: Gregory Nutt \n"); + printf(" *\n"); + printf(" * Redistribution and use in source and binary forms, with or without\n"); + printf(" * modification, are permitted provided that the following conditions\n"); + printf(" * are met:\n"); + printf(" *\n"); + printf(" * 1. Redistributions of source code must retain the above copyright\n"); + printf(" * notice, this list of conditions and the following disclaimer.\n"); + printf(" * 2. Redistributions in binary form must reproduce the above copyright\n"); + printf(" * notice, this list of conditions and the following disclaimer in\n"); + printf(" * the documentation and/or other materials provided with the\n"); + printf(" * distribution.\n"); + printf(" * 3. Neither the name NuttX, NxWidgets, nor the names of its contributors\n"); + printf(" * me be used to endorse or promote products derived from this software\n"); + printf(" * without specific prior written permission.\n"); + printf(" *\n"); + printf(" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"); + printf(" * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"); + printf(" * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\n"); + printf(" * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n"); + printf(" * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n"); + printf(" * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n"); + printf(" * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS\n"); + printf(" * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\n"); + printf(" * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n"); + printf(" * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\n"); + printf(" * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n"); + printf(" * POSSIBILITY OF SUCH DAMAGE.\n"); + printf(" *\n"); + printf(" ********************************************************************************************/\n\n"); + + printf("/********************************************************************************************\n"); + printf(" * Included Files\n"); + printf(" ********************************************************************************************/\n\n"); + printf("#include \n"); + printf("#include \n"); + printf("#include \n\n"); + printf("#include \"graphics/nxwidgets/crlepalettebitmap.hxx\"\n"); + printf("#include \"graphics/nxglyphs.hxx\"\n\n"); + + /* Count the number of colors (npixels) */ + + ptr = gimp_image.pixel_data; + + for (i = 0; i < gimp_image.height; i++) + { + for (j = 0; j < gimp_image.width; j++) + { + r = *ptr++; + g = *ptr++; + b = *ptr++; + + addpixel(r, g, b); + } + } + + printf("/********************************************************************************************\n"); + printf(" * Pre-Processor Definitions\n"); + printf(" ********************************************************************************************/\n\n"); + printf("#define BITMAP_NROWS %u\n", gimp_image.height); + printf("#define BITMAP_NCOLUMNS %u\n", gimp_image.width); + printf("#define BITMAP_NLUTCODES %u\n\n", npixels); + + printf("/********************************************************************************************\n"); + printf(" * Private Bitmap Data\n"); + printf(" ********************************************************************************************/\n\n"); + printf("using namespace NXWidgets;\n\n"); + + printf("#if CONFIG_NXWIDGETS_BPP == 24 || CONFIG_NXWIDGETS_BPP == 32\n"); + printf("// RGB24 (8-8-8) Colors\n\n"); + printf("static const uint32_t g_xxxNormalLut[BITMAP_NLUTCODES] =\n"); + printf("{\n"); + + for (i = 0; i < npixels; i += 8) + { + printf(" "); + for (j = 0; j < 8 && i + j < npixels; j++) + { + unsigned int r = pixels[i+j].r; /* 8->8 bits */ + unsigned int g = pixels[i+j].g; /* 8->8 bits */ + unsigned int b = pixels[i+j].b; /* 8->8 bits */ + unsigned int pix24 = r << 16 | g << 8 | b; + printf(" 0x%06x,", pix24); + } + + printf(" /* Codes %d-%d */\n", i, i+j-1); + } + + printf("};\n\n"); + printf("static const uint32_t g_xxxBrightLut[BITMAP_NLUTCODES] =\n"); + printf("{\n"); + + for (i = 0; i < npixels; i += 8) + { + printf(" "); + for (j = 0; j < 8 && i + j < npixels; j++) + { + unsigned int r = pixels[i+j].r; /* 8->8 bits */ + unsigned int g = pixels[i+j].g; /* 8->8 bits */ + unsigned int b = pixels[i+j].b; /* 8->8 bits */ + + r = (3*r + 0xff) >> 2; + g = (3*g + 0xff) >> 2; + b = (3*b + 0xff) >> 2; + + unsigned int pix24 = r << 16 | g << 8 | b; + printf(" 0x%06x,", pix24); + } + + printf(" /* Codes %d-%d */\n", i, i+j-1); + } + + printf("};\n\n"); + printf("#elif CONFIG_NXWIDGETS_BPP == 16\n"); + printf("// RGB16 (565) Colors (four of the colors in this map are duplicates)\n\n"); + printf("static const uint16_t g_xxxNormalLut[BITMAP_NLUTCODES] =\n"); + printf("{\n"); + + for (i = 0; i < npixels; i += 10) + { + printf(" "); + for (j = 0; j < 10 && i+j < npixels; j++) + { + unsigned int r = pixels[i+j].r >> 3; /* 8->5 bits */ + unsigned int g = pixels[i+j].g >> 2; /* 8->6 bits */ + unsigned int b = pixels[i+j].b >> 3; /* 8->5 bits */ + + if (r > 0x1f) + { + r = 0x1f; + } + + if (g > 0x3f) + { + g = 0x3f; + } + + if (b > 0x1f) + { + b = 0x1f; + } + + unsigned int pix16 = r << 11 | g << 5 | b; + printf(" 0x%04x,", pix16); + } + + printf(" /* Codes %d-%d */\n", i, i+j-1); + } + + printf("};\n\n"); + printf("static const uint16_t g_xxxBrightLut[BITMAP_NLUTCODES] =\n"); + printf("{\n"); + + for (i = 0; i < npixels; i += 10) + { + printf(" "); + for (j = 0; j < 10 && i+j < npixels; j++) + { + unsigned int r = pixels[i+j].r; + unsigned int g = pixels[i+j].g; + unsigned int b = pixels[i+j].b; + + r = (3*r + 0xff) >> 2; + g = (3*g + 0xff) >> 2; + b = (3*b + 0xff) >> 2; + + r >>= 3; /* 8->5 bits */ + g >>= 2; /* 8->6 bits */ + b >>= 3; /* 8->5 bits */ + + if (r > 0x1f) + { + r = 0x1f; + } + + if (g > 0x3f) + { + g = 0x3f; + } + + if (b > 0x1f) + { + b = 0x1f; + } + + unsigned int pix16 = r << 11 | g << 5 | b; + printf(" 0x%04x,", pix16); + } + + printf(" /* Codes %d-%d */\n", i, i+j-1); + } + + printf("};\n\n"); + + printf("#elif CONFIG_NXWIDGETS_BPP == 8\n"); + printf("// 8-bit color lookups. NOTE: This is really dumb! The lookup index is 8-bits and it used\n"); + printf("// to lookup an 8-bit value. There is no savings in that! It would be better to just put\n"); + printf("// the 8-bit color/greyscale value in the run-length encoded image and save the cost of these\n"); + printf("// pointless lookups. But these p;ointless lookups do make the logic compatible with the\n"); + printf("// 16- and 24-bit types.\n"); + printf("///\n\n"); + + printf("# ifdef CONFIG_NXWIDGETS_GREYSCALE\n"); + printf("// 8-bit Greyscale\n\n"); + printf("static const uint8_t g_xxxNormalLut[BITMAP_NLUTCODES] =\n"); + printf("{\n"); + + for (i = 0; i < npixels; i += 16) + { + printf(" "); + for (j = 0; j < 16 && i+j < npixels; j++) + { + unsigned int r = pixels[i+j].r; /* 8->8 bits */ + unsigned int g = pixels[i+j].g; /* 8->8 bits */ + unsigned int b = pixels[i+j].b; /* 8->8 bits */ + + printf(" 0x%02x,", getmono(r, g, b)); + } + + printf(" /* Codes %d-%d */\n", i, i+j-1); + } + + printf("}\n\n"); + printf("static const uint8_t g_xxxBrightLut[BITMAP_NLUTCODES] =\n"); + printf("{\n"); + + for (i = 0; i < npixels; i += 16) + { + printf(" "); + for (j = 0; j < 16 && i+j < npixels; j++) + { + unsigned int r = pixels[i+j].r; /* 8->8 bits */ + unsigned int g = pixels[i+j].g; /* 8->8 bits */ + unsigned int b = pixels[i+j].b; /* 8->8 bits */ + + r = (3*r + 0xff) >> 2; + g = (3*g + 0xff) >> 2; + b = (3*b + 0xff) >> 2; + + printf(" 0x%02x,", getmono(r, g, b)); + } + + printf(" /* Codes %d-%d */\n", i, i+j-1); + } + + printf("};\n\n"); + printf("# else /* CONFIG_NXWIDGETS_GREYSCALE */\n"); + printf("// RGB8 (332) Colors\n\n"); + printf("static const nxgl_mxpixel_t g_xxxNormalLut[BITMAP_NLUTCODES] =\n"); + printf("{\n"); + + for (i = 0; i < npixels; i += 16) + { + printf(" "); + for (j = 0; j < 16 && i+j < npixels; j++) + { + unsigned int r = (pixels[i+j].r + 2) >> 5; /* 8->3 bits */ + unsigned int g = (pixels[i+j].g + 2) >> 5; /* 8->3 bits */ + unsigned int b = (pixels[i+j].b + 4) >> 6; /* 8->2 bits */ + + if (r > 0x07) + { + r = 0x07; + } + if (g > 0x07) + { + g = 0x07; + } + if (b > 0x03) + { + b = 0x03; + } + + unsigned int pix8 = r << 5 | g << 2 | b; + printf(" 0x%02x,", pix8); + } + + printf(" /* Codes %d-%d */\n", i, i+j-1); + } + + printf("};\n\n"); + printf("static const uint8_t g_xxxBrightLut[BITMAP_NLUTCODES] =\n"); + printf("{\n"); + + for (i = 0; i < npixels; i += 16) + { + printf(" "); + for (j = 0; j < 16 && i+j < npixels; j++) + { + unsigned int r = pixels[i+j].r; + unsigned int g = pixels[i+j].g; + unsigned int b = pixels[i+j].b; + + r = (3*r + 0xff) >> 2; + g = (3*g + 0xff) >> 2; + b = (3*b + 0xff) >> 2; + + r = (r + 2) >> 5; /* 8->3 bits */ + g = (g + 2) >> 5; /* 8->3 bits */ + b = (b + 4) >> 6; /* 8->2 bits */ + + if (r > 0x07) + { + r = 0x07; + } + if (g > 0x07) + { + g = 0x07; + } + if (b > 0x03) + { + b = 0x03; + } + + unsigned int pix8 = r << 5 | g << 2 | b; + printf(" 0x%02x,", pix8); + } + + printf(" /* Codes %d-%d */\n", i, i+j-1); + } + + printf("};\n\n"); + printf("# endif\n"); + printf("#else\n"); + printf("# error Unsupported pixel format\n"); + printf("#endif\n\n"); + + printf("static const struct SRlePaletteBitmapEntry g_xxxRleEntries[] =\n"); + printf("{\n "); + + ptr = gimp_image.pixel_data; + + for (i = 0; i < gimp_image.height; i++) + { + ncode = 0; + last = -1; + nruns = 0; + first = 1; + len = 0; + + for (j = 0; j < gimp_image.width; j++) + { + r = *ptr++; + g = *ptr++; + b = *ptr++; + + code = findpixel(r, g, b); + if (code == last && ncode < 256) + { + ncode++; + } + else + { + if (ncode > 0) + { + len += printf(" {%3d, %3d},", ncode, last); + if (++nruns > 7) + { + if (first) + { + while (len < 100) + { + putchar(' '); + len++; + } + + printf("// Row %d\n ", i); + first = 0; + len = 0; + } + else + { + printf("\n "); + len = 0; + } + + nruns = 0; + } + } + + ncode = 1; + last = code; + } + } + + if (ncode > 0) + { + len += printf(" {%3d, %3d},", ncode, last); + } + + if (first) + { + while (len < 100) + { + putchar(' '); + len++; + } + + printf("// Row %d\n ", i); + } + else + { + printf("\n "); + } + } + + printf("};\n\n"); + printf("/********************************************************************************************\n"); + printf(" * Public Bitmap Structure Definitions\n"); + printf(" ********************************************************************************************/\n\n"); + printf("const struct SRlePaletteBitmap NXWidgets::g_xxxBitmap =\n"); + printf("{\n"); + printf(" CONFIG_NXWIDGETS_BPP, // bpp - Bits per pixel\n"); + printf(" CONFIG_NXWIDGETS_FMT, // fmt - Color format\n"); + printf(" BITMAP_NLUTCODES, // nlut - Number of colors in the lLook-Up Table (LUT)\n"); + printf(" BITMAP_NCOLUMNS, // width - Width in pixels\n"); + printf(" BITMAP_NROWS, // height - Height in rows\n"); + printf(" { // lut - Pointer to the beginning of the Look-Up Table (LUT)\n"); + printf(" g_xxxNormalLut, // Index 0: Unselected LUT\n"); + printf(" g_xxxBrightLut, // Index 1: Selected LUT\n"); + printf(" },\n"); + printf(" g_xxxRleEntries // data - Pointer to the beginning of the RLE data\n"); + printf("};\n\n"); + + return 0; +} diff --git a/graphics/nxglyphs/src/mksrle.sh b/graphics/nxglyphs/src/mksrle.sh new file mode 100644 index 000000000..fc4e4a1d7 --- /dev/null +++ b/graphics/nxglyphs/src/mksrle.sh @@ -0,0 +1,110 @@ +#!/bin/bash +# apps/graphics/nxglyphs/src/mksrle.sh +# +# Copyright (C) 2019 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# 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. +# + +# Get the input parameter list +# +# - A 4-color image exported as a GIMP C-source file. +# - A 2-bpp cursor image in NuttX cursor format +# - Treated as the transparent background color (default, 0x000000) +# - Usually the primary color of the image (default, 0xff0000) +# - Usually the outline color of the image (default, 0x00007f) +# - Usually blend of color1 and color2 for low-cost anti-aliasing (default, 0x7f003f) +# Output is to stdout, but may be re-directed to a file. + +PROGNAME=$0 +USAGE="USAGE: $PROGNAME [-d] -f -o " + +CFILE=mksrle.c +TMPFILE1=_tmpfile1.c +TMPFILE2=_mksrle.c +TMPPROG=_mksrle.exe + +unset INFILE +unset OUTFILE + +while [ ! -z "$1" ]; do + case $1 in + -d ) + set -x + ;; + -f ) + shift + INFILE=$1 + ;; + -o ) + shift + OUTFILE=$1 + ;; + * ) + echo "Unrecognized argument: $1" + echo $USAGE + exit 1 + ;; + esac + shift +done + +# Check arguments + +if [ -z "${INFILE}" ]; then + echo "MK: Missing input Gimp C-source file name" + echo $USAGE + exit 1 +fi + +if [ ! -r ${INFILE} ]; then + echo "MK: No readable file at ${INFILE}" + exit 1 +fi + +if [ ! -r ${CFILE} ]; then + echo "MK: Can't find ${CFILE}" + exit 1 +fi + +if [ -z ${OUTFILE} ]; then + echo "MK: Missing output file name" + exit 1 +fi + +echo "#include " > ${TMPFILE1} +echo "typedef uint8_t guint8;" >> ${TMPFILE1} +echo "typedef uint16_t guint;" >> ${TMPFILE1} + +cat ${TMPFILE1} ${INFILE} ${CFILE} > ${TMPFILE2} + +gcc -g -o ${TMPPROG} ${TMPFILE2} +./${TMPPROG} > ${OUTFILE} + +rm ${TMPFILE1} ${TMPFILE2} diff --git a/graphics/nxwidgets/UnitTests/CListBox/clistbox_main.cxx b/graphics/nxwidgets/UnitTests/CListBox/clistbox_main.cxx index d652c18a2..db42c4505 100644 --- a/graphics/nxwidgets/UnitTests/CListBox/clistbox_main.cxx +++ b/graphics/nxwidgets/UnitTests/CListBox/clistbox_main.cxx @@ -171,7 +171,7 @@ static void initMemoryUsage(void) ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// -// Name: nxheaders_main +// Name: clistbox_main ///////////////////////////////////////////////////////////////////////////// int clistbox_main(int argc, char *argv[]) @@ -195,6 +195,7 @@ int clistbox_main(int argc, char *argv[]) delete test; return 1; } + updateMemoryUsage(g_mmPrevious, "clistbox_main: After connecting to the server"); // Create a window to draw into @@ -206,6 +207,7 @@ int clistbox_main(int argc, char *argv[]) delete test; return 1; } + updateMemoryUsage(g_mmPrevious, "clistbox_main: After creating a window"); // Create a listbox @@ -218,6 +220,7 @@ int clistbox_main(int argc, char *argv[]) delete test; return 1; } + updateMemoryUsage(g_mmPrevious, "clistbox_main: After creating a listbox"); // Show the initial state of the listbox @@ -236,6 +239,7 @@ int clistbox_main(int argc, char *argv[]) printf("clistbox_main: %d. New option %s\n", i, g_options[i]); usleep(500000); // The simulation needs this to let the X11 event loop run } + updateMemoryUsage(g_mmPrevious, "clistbox_main: After adding the listbox items"); sleep(1); @@ -310,6 +314,7 @@ int clistbox_main(int argc, char *argv[]) } sleep(1); } + updateMemoryUsage(g_mmPrevious, "clistbox_main: After the listbox is empty again"); sleep(1); diff --git a/graphics/twm4nx/.gitignore b/graphics/twm4nx/.gitignore new file mode 100644 index 000000000..6d84d42c4 --- /dev/null +++ b/graphics/twm4nx/.gitignore @@ -0,0 +1,12 @@ +/twm4nx +/Make.dep +/.depend +/.built +/*.asm +/*.obj +/*.rel +/*.lst +/*.sym +/*.adb +/*.lib +/*.src diff --git a/graphics/twm4nx/COPYING b/graphics/twm4nx/COPYING new file mode 100644 index 000000000..8cc6cb9a5 --- /dev/null +++ b/graphics/twm4nx/COPYING @@ -0,0 +1,82 @@ +The following is the full text of the COPYING file for TWM 1.0.10. Twm4Nx +is largely an original development, but owes acknowledge to TWM for its +design base and thanks fot TWM for many years in the open source community. + +This copyright notice is probably not necessary since Twm4Nx is not TWM, +but this assures that things are right. See the top-level README.txt file +for additional information. + +============================================================================ + +Copyright 1989, 1994, 1998 The Open Group +Copyright 2005 Hitachi, Ltd. + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + + Copyright 1988 by Evans & Sutherland Computer Corporation, + Salt Lake City, Utah + Cambridge, Massachusetts + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that copyright notice and this permis- +sion notice appear in supporting documentation, and that the +name of Evans & Sutherland not be used in advertising +in publicity pertaining to distribution of the software without +specific, written prior permission. + +EVANS & SUTHERLAND DISCLAIMs ALL WARRANTIES WITH REGARD +TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- +ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND +BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- +AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA +OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE +OR PERFORMANCE OF THIS SOFTWARE. + +Copyright (C) 1998 The XFree86 Project, Inc. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the XFree86 Project shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +XFree86 Project. + diff --git a/graphics/twm4nx/Kconfig b/graphics/twm4nx/Kconfig new file mode 100644 index 000000000..34a915f60 --- /dev/null +++ b/graphics/twm4nx/Kconfig @@ -0,0 +1,44 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config GRAPHICS_TWM4NX + tristate "Minimal Tom's Window Manager (TWM) for NuttX (Twm4Nx)" + default n + select NX_RAMBACKED + select NXWIDGETS + depends on NX && EXPERIMENTAL + ---help--- + Enable Tom's Window Manager (TWM) for NuttX (Twm4Nx). + + Use of this window manager requires keyboard and mouse input. + Output is through the NX server. + +if GRAPHICS_TWM4NX + +config TWM4NX_PROGNAME + string "Twm4Nx program name" + default "twm4nx" + depends on BUILD_LOADABLE + ---help--- + This is the name of the program that will be use when the NSH ELF + program is installed. + +config TWM4NX_PRIORITY + int "Twm4Nx task priority" + default 100 + +config TWM4NX_STACKSIZE + int "Twm4Nx stack size" + default 2048 + +config TWM4NX_REVMAJOR + string "Twm4Nx major version number" + default "0" + +config TWM4NX_REVMINOR + string "Twm4Nx minor version number" + default "0" + +endif # GRAPHICS_TWM4NX diff --git a/graphics/twm4nx/Make.defs b/graphics/twm4nx/Make.defs new file mode 100644 index 000000000..308106ccc --- /dev/null +++ b/graphics/twm4nx/Make.defs @@ -0,0 +1,40 @@ +############################################################################ +# apps/graphics/twm4nx/Make.defs +# Adds selected applications to apps/ build +# +# Copyright (C) 2019 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# 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. +# +############################################################################ + +ifeq ($(CONFIG_GRAPHICS_TWM4NX),y) +CONFIGURED_APPS += graphics/twm4nx +endif + diff --git a/graphics/twm4nx/Makefile b/graphics/twm4nx/Makefile new file mode 100644 index 000000000..ede5562f8 --- /dev/null +++ b/graphics/twm4nx/Makefile @@ -0,0 +1,69 @@ +############################################################################ +# apps/graphics/twm4nx/Makefile +# +# Copyright (C) 2019 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# 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 +-include $(APPDIR)/Make.defs + +# Add patch to cursor images to CXXFLAGS + +CXXFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" "$(APPDIR)/graphics/nxglyphs/include"} + +# Twm4Nx built-in application info + +CONFIG_TWM4NX_PRIORITY ?= SCHED_PRIORITY_DEFAULT +CONFIG_TWM4NX_STACKSIZE ?= 2048 + +APPNAME = twm4nx + +PRIORITY = $(CONFIG_TWM4NX_PRIORITY) +STACKSIZE = $(CONFIG_TWM4NX_STACKSIZE) + +# Twm4Nx + +ASRCS = +CSRCS = +CXXSRCS = cwindow.cxx cwindowfactory.cxx ciconwin.cxx cwindowevent.cxx +CXXSRCS += cicon.cxx ciconmgr.cxx cbackground.cxx cfonts.cxx cresize.cxx +CXXSRCS += cmenus.cxx cinput.cxx twm4nx_cursor.cxx +MAINSRC = ctwm4nx.cxx + +VPATH = src + +CONFIG_TWM4NX_PROGNAME ?= hello$(EXEEXT) +PROGNAME = $(CONFIG_TWM4NX_PROGNAME) + +MODULE = CONFIG_GRAPHICS_TWM4NX + +include $(APPDIR)/Application.mk diff --git a/graphics/twm4nx/README.txt b/graphics/twm4nx/README.txt new file mode 100644 index 000000000..0e51ee247 --- /dev/null +++ b/graphics/twm4nx/README.txt @@ -0,0 +1,28 @@ +README +====== + +Twm4Nx is a port of twm, Tab Window Manager (or Tom's Window Manager) +version 1.0.10 to NuttX NX windows server. No, a port is not the right +word. It is a re-design of TWM from the inside out to work with the NuttX +NX server. The name Twm4Nx reflects this legacy. But Twm4Nx is more a +homage to TWM than a port of TWM. + +The original TWM was based on X11 which provides a rich set of features. +TWM provided titlebars, shaped windows, several forms of icon management, +user-defined macro functions, click-to-type and pointer-driven keyboard +focus, graphic contexts, and user-specified key and pointer button bindings, +etc. + +Twm4Nx, on the other hand is based on the NuttX NX server which provides +comparatively minimal support. Additional drawing support comes from +the NuttX NxWidgets library (which necessitated the change to C++). + +Twm4Nx is greatly stripped down and targeted on small embedded systems +with minimal resources. For example, no assumption is made about the +availability of a file system; no .twmrc file is used. Bitmaps are not +used (other than for fonts). + +The TWM license is, I believe compatible with the BSD license used by NuttX. +The origin TWM license required notice of copyrights within each file and +a full copy of the original license which you can find in the COPYING file. +within this directory. diff --git a/graphics/twm4nx/Twm4NX-Threading.pdf b/graphics/twm4nx/Twm4NX-Threading.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9e857384cb5d1c6042b570669803cde3ec33ee91 GIT binary patch literal 33844 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 +// +// 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 + +#include + +#include + +#include "graphics/nxwidgets/cscaledbitmap.hxx" +#include "graphics/nxwidgets/cbgwindow.hxx" +#include "graphics/nxwidgets/cwidgetcontrol.hxx" +#include "graphics/nxwidgets/crlepalettebitmap.hxx" +#include "graphics/nxwidgets/cimage.hxx" + +#include "graphics/twm4nx/twm4nx_config.hxx" +#include "graphics/twm4nx/cwindowevent.hxx" +#include "graphics/twm4nx/cbackground.hxx" + +///////////////////////////////////////////////////////////////////////////// +// CBackground Method Implementations +///////////////////////////////////////////////////////////////////////////// + +using namespace Twm4Nx; + +/** + * CBackground Constructor + * + * @param hWnd - NX server handle + */ + +CBackground::CBackground(FAR CTwm4Nx *twm4nx) +{ + m_twm4nx = twm4nx; + m_backWindow = (NXWidgets::CBgWindow *)0; + m_backImage = (NXWidgets::CImage *)0; +} + +/** + * CBackground Destructor + */ + +CBackground::~CBackground(void) +{ + // Delete the background + + if (m_backWindow != (NXWidgets::CBgWindow *)0) + { + // Delete the contained widget control. We are responsible for it + // because we created it + + NXWidgets::CWidgetControl *control = m_backWindow->getWidgetControl(); + if (control != (NXWidgets::CWidgetControl *)0) + { + delete control; + } + + // Then delete the background + + delete m_backWindow; + m_backWindow = (NXWidgets::CBgWindow *)0; + } + + // Delete the background image + + if (m_backImage != (NXWidgets::CImage *)0) + { + delete m_backImage; + m_backImage = (NXWidgets::CImage *)0; + } +} + +/** + * Set the background image + * + * @param sbitmap. Identifies the bitmap to paint on background + * @return true on success + */ + +bool CBackground:: + setBackgroundImage(FAR const struct NXWidgets::SRlePaletteBitmap *sbitmap) +{ + // Create the background window (if we have not already done so) + + if (m_backWindow == (NXWidgets::CBgWindow *)0 && + !createBackgroundWindow()) + { + return false; + } + + // Free any existing background image + + if (m_backImage != (NXWidgets::CImage *)0) + { + delete m_backImage; + m_backImage = (NXWidgets::CImage *)0; + } + + // Create the new background image + + if (!createBackgroundImage(sbitmap)) + { + return false; + } + + return true; +} + +/** + * Get the size of the physical display device which is equivalent to + * size of the background window. + * + * @return The size of the display + */ + +void CBackground::getDisplaySize(FAR struct nxgl_size_s &size) +{ + // Get the widget control from the task bar window. The physical window geometry + // should be the same for all windows. + + NXWidgets::CWidgetControl *control = m_backWindow->getWidgetControl(); + + // Get the window bounding box from the widget control + + NXWidgets::CRect rect = control->getWindowBoundingBox(); + + // And return the size of the window + + rect.getSize(size); +} + +/** + * Create the background window. + * + * @return true on success + */ + +bool CBackground::createBackgroundWindow(void) +{ + // Create an instance of the background window + // 1. Get the server instance. m_twm4nx inherits from NXWidgets::CNXServer + // so we all ready have the server instance. + // 2. Create the style, using the selected colors (REVISIT) + + // 3. Create a Widget control instance for the window using the default + // style for now. CWindowEvent derives from CWidgetControl. + + FAR CWindowEvent *control = new CWindowEvent(m_twm4nx); + + m_backWindow = m_twm4nx->getBgWindow(control); + if (m_backWindow == (FAR NXWidgets::CBgWindow *)0) + { + return false; + } + + return true; +} + +/** + * Create the background image. + * + * @return true on success + */ + +bool CBackground:: + createBackgroundImage(FAR const struct NXWidgets::SRlePaletteBitmap *sbitmap) +{ + // Get the size of the display + + struct nxgl_size_s windowSize; + if (!m_backWindow->getSize(&windowSize)) + { + return false; + } + + // Get the widget control from the background window + + NXWidgets::CWidgetControl *control = m_backWindow->getWidgetControl(); + + // Create the sbitmap object + + NXWidgets::CRlePaletteBitmap *cbitmap = + new NXWidgets::CRlePaletteBitmap(sbitmap); + + if (cbitmap == (NXWidgets::CRlePaletteBitmap *)0) + { + return false; + } + + // Get the size of the bitmap image + + struct nxgl_size_s imageSize; + imageSize.w = cbitmap->getWidth(); + imageSize.h = (nxgl_coord_t)cbitmap->getHeight(); + + // Pick an X/Y position such that the image will be centered in the display + + struct nxgl_point_s imagePos; + if (imageSize.w >= windowSize.w) + { + imagePos.x = 0; + } + else + { + imagePos.x = (windowSize.w - imageSize.w) >> 1; + } + + if (imageSize.h >= windowSize.h) + { + imagePos.y = 0; + } + else + { + imagePos.y = (windowSize.h - imageSize.h) >> 1; + } + + // Now we have enough information to create the image + + m_backImage = new NXWidgets::CImage(control, imagePos.x, imagePos.y, + imageSize.w, imageSize.h, cbitmap); + if (!m_backImage) + { + delete cbitmap; + return false; + } + + // Configure the background image + + m_backImage->setBorderless(true); + m_backImage->setRaisesEvents(false); + + return true; +} + +/** + * (Re-)draw the background window. + * + * @return true on success + */ + +bool CBackground::redrawBackgroundWindow(void) +{ + // Get the widget control from the background window + + NXWidgets::CWidgetControl *control = m_backWindow->getWidgetControl(); + + // Get the graphics port for drawing on the background window + + NXWidgets::CGraphicsPort *port = control->getGraphicsPort(); + + // Get the size of the window + + struct nxgl_size_s windowSize; + if (!m_backWindow->getSize(&windowSize)) + { + return false; + } + + // Fill the entire window with the background color + + port->drawFilledRect(0, 0, windowSize.w, windowSize.h, + CONFIG_TWM4NX_DEFAULT_BACKGROUNDCOLOR); + + // Then re-draw the background image on the window + + if (m_backImage) + { + m_backImage->enableDrawing(); + m_backImage->redraw(); + } + + return true; +} diff --git a/graphics/twm4nx/src/cfonts.cxx b/graphics/twm4nx/src/cfonts.cxx new file mode 100644 index 000000000..ada145b6f --- /dev/null +++ b/graphics/twm4nx/src/cfonts.cxx @@ -0,0 +1,177 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/src/cfonts.cxx +// Font support for twm4nx +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// Copyright 1988 by Evans & Sutherland Computer Corporation, +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 + +#include "graphics/nxwidgets/cnxfont.hxx" + +#include "graphics/twm4nx/twm4nx_config.hxx" +#include "graphics/twm4nx/ctwm4nx.hxx" +#include "graphics/twm4nx/cfonts.hxx" + +///////////////////////////////////////////////////////////////////////////// +// CFonts Method Implementations +///////////////////////////////////////////////////////////////////////////// + +using namespace Twm4Nx; + +/** + * CFonts Constructor + * + * @param twm4nx. An instance of the NX server. + */ + +CFonts::CFonts(CTwm4Nx *twm4nx) +{ + m_twm4nx = twm4nx; // Save the NX server + m_titleFont = (FAR NXWidgets::CNxFont *)0; // Title bar font + m_menuFont = (FAR NXWidgets::CNxFont *)0; // Menu font + m_iconFont = (FAR NXWidgets::CNxFont *)0; // Icon font + m_sizeFont = (FAR NXWidgets::CNxFont *)0; // Resize font + m_iconManagerFont = (FAR NXWidgets::CNxFont *)0; // Window list font + m_defaultFont = (FAR NXWidgets::CNxFont *)0; // The default found +} + +/** + * CFonts Destructor + */ + +CFonts::~CFonts(void) +{ + if (m_titleFont != (FAR NXWidgets::CNxFont *)0) + { + delete m_titleFont; + } + + if (m_menuFont != (FAR NXWidgets::CNxFont *)0) + { + delete m_menuFont; + } + + if (m_iconFont != (FAR NXWidgets::CNxFont *)0) + { + delete m_iconFont; + } + + if (m_sizeFont != (FAR NXWidgets::CNxFont *)0) + { + delete m_sizeFont; + } + + if (m_iconManagerFont != (FAR NXWidgets::CNxFont *)0) + { + delete m_iconManagerFont; + } + + if (m_defaultFont != (FAR NXWidgets::CNxFont *)0) + { + delete m_defaultFont; + } +} + +/** + * Initialize fonts + */ + +bool CFonts::initialize(void) +{ + m_titleFont = + new NXWidgets::CNxFont((enum nx_fontid_e)CONFIG_TWM4NX_TITLE_FONTID, + CONFIG_TWM4NX_TITLE_FONTCOLOR, + CONFIG_TWM4NX_TRANSPARENT_COLOR); + if (m_titleFont == (FAR NXWidgets::CNxFont *)0) + { + return false; + } + + m_menuFont = + new NXWidgets::CNxFont((enum nx_fontid_e)CONFIG_TWM4NX_MENU_FONTID, + CONFIG_TWM4NX_MENU_FONTCOLOR, + CONFIG_TWM4NX_TRANSPARENT_COLOR); + if (m_menuFont == (FAR NXWidgets::CNxFont *)0) + { + return false; + } + + m_iconFont = + new NXWidgets::CNxFont((enum nx_fontid_e)CONFIG_TWM4NX_ICON_FONTID, + CONFIG_TWM4NX_ICON_FONTCOLOR, + CONFIG_TWM4NX_TRANSPARENT_COLOR); + if (m_iconFont == (FAR NXWidgets::CNxFont *)0) + { + return false; + } + + m_sizeFont = + new NXWidgets::CNxFont((enum nx_fontid_e)CONFIG_TWM4NX_SIZE_FONTID, + CONFIG_TWM4NX_SIZE_FONTCOLOR, + CONFIG_TWM4NX_TRANSPARENT_COLOR); + if (m_sizeFont == (FAR NXWidgets::CNxFont *)0) + { + return false; + } + + m_iconManagerFont = + new NXWidgets::CNxFont((enum nx_fontid_e)CONFIG_TWM4NX_ICONMGR_SIZEFONTID, + CONFIG_TWM4NX_ICONMGR_FONTCOLOR, + CONFIG_TWM4NX_TRANSPARENT_COLOR); + if (m_iconManagerFont == (FAR NXWidgets::CNxFont *)0) + { + return false; + } + + m_defaultFont = + new NXWidgets::CNxFont((enum nx_fontid_e)NXFONT_DEFAULT, + CONFIG_TWM4NX_DEFAULT_FONTCOLOR, + CONFIG_TWM4NX_TRANSPARENT_COLOR); + if (m_defaultFont == (FAR NXWidgets::CNxFont *)0) + { + return false; + } + + return true; +} diff --git a/graphics/twm4nx/src/cicon.cxx b/graphics/twm4nx/src/cicon.cxx new file mode 100644 index 000000000..c96d4b780 --- /dev/null +++ b/graphics/twm4nx/src/cicon.cxx @@ -0,0 +1,469 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/src/cicon.cxx +// Icon releated routines +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 + +#include "nuttx/nx/nxglib.h" + +#include "graphics/twm4nx/ctwm4nx.hxx" +#include "graphics/twm4nx/cwindow.hxx" +#include "graphics/twm4nx/cwindowevent.hxx" +#include "graphics/twm4nx/cicon.hxx" + +///////////////////////////////////////////////////////////////////////////// +// CTwm4Nx Implementation +///////////////////////////////////////////////////////////////////////////// + +using namespace Twm4Nx; + +/** + * CIcon Constructor + */ + +CIcon::CIcon(CTwm4Nx *twm4nx) +{ + m_twm4nx = twm4nx; // Cached the Twm4Nx session + m_icons = (FAR struct SNameList *)0; // List of icon images + m_regionHead = (FAR struct SIconRegion *)0; // Pointer to icon regions + m_regionTail = (FAR struct SIconRegion *)0; // Pointer to the last icon region +} + +/** + * CIcon Destructor + */ + +CIcon::~CIcon(void) +{ + freeIconRegions(); +} + +/** + * Create a new icon region and add it to the list of icon regions. + * + * @param pos The position of the region on the background + * @param size The size of the region + * @param step + */ + +void CIcon::addIconRegion(FAR nxgl_point_s *pos, FAR nxgl_size_s *size, + FAR struct nxgl_point_s *step) +{ + FAR struct SIconRegion *ir; + + // Allocate the new region + + ir = (FAR struct SIconRegion *)std::malloc(sizeof(struct SIconRegion)); + + // Add the new region to the list of regions + + ir->flink = (FAR struct SIconRegion *)0; + + if (m_regionTail != (FAR struct SIconRegion *)0) + { + m_regionTail->flink = ir; + } + + m_regionTail = ir; + + if (m_regionHead != (FAR struct SIconRegion *)0) + { + m_regionHead = ir; + } + + // Initiliaze the region + + ir->entries = NULL; + + if (step->x <= 0) + { + step->x = 1; + } + + if (step->y <= 0) + { + step->y = 1; + } + + ir->step.x = step->x; + ir->step.y = step->y; + ir->pos.x = pos->x; + ir->pos.y = pos->y; + ir->size.w = size->w; + ir->size.h = size->h; + + struct nxgl_size_s displaySize; + m_twm4nx->getDisplaySize(&displaySize); + + if (ir->pos.x < 0) + { + ir->pos.x += displaySize.w - ir->size.w; + } + + if (ir->pos.y < 0) + { + ir->pos.y += displaySize.h - ir->size.h; + } + + // Allocate one region entry + + ir->entries = (FAR struct SIconEntry *)malloc(sizeof(struct SIconRegion)); + if (ir->entries != (FAR struct SIconEntry *)0) + { + ir->entries->flink = (FAR struct SIconEntry *)0; + ir->entries->pos.x = ir->pos.x; + ir->entries->pos.y = ir->pos.y; + ir->entries->size.w = ir->size.w; + ir->entries->size.h = ir->size.h; + ir->entries->cwin = (FAR CWindow *)0; + ir->entries->used = false; + } +} + +/** + * Position an icon on the background + * + * @param cwin The Window whose icon will be placed + * @param pos An backup position to use is there are no available regions + * @param final A location in which to return the selection icon position + */ + +void CIcon::place(FAR CWindow *cwin, FAR const struct nxgl_point_s *pos, + FAR struct nxgl_point_s *final) +{ + // Try each region + + FAR struct SIconEntry *ie = (FAR struct SIconEntry *)0; + for (FAR struct SIconRegion *ir = m_regionHead; ir; ir = ir->flink) + { + struct nxgl_size_s iconWindowSize; + cwin->getIconWindowSize(&iconWindowSize); + + struct nxgl_size_s tmpsize; + tmpsize.w = roundUp(iconWindowSize.w, ir->step.x); + tmpsize.h = roundUp(iconWindowSize.h, ir->step.y); + + // Try each entry in the regions + + for (ie = ir->entries; ie; ie = ie->flink) + { + // Look for an unused entry + + if (ie->used) + { + continue; + } + + // Does the entry describe a region that is of sufficient size? + + if (ie->size.w >= tmpsize.w && ie->size.h >= tmpsize.h) + { + // Yes.. We have it. Break out with ie non-NULL + + break; + } + } + + // Break out of the outer loop if the the region entry was found by + // the inner loop + + if (ie != (FAR struct SIconEntry *)0) + { + break; + } + } + + // Did we find an entry? + + if (ie != (FAR struct SIconEntry *)0) + { + // Yes.. place the icon in this region + + ie->used = true; + ie->cwin = cwin; + + struct nxgl_size_s iconWindowSize; + cwin->getIconWindowSize(&iconWindowSize); + + final->x = ie->pos.x + (ie->size.w - iconWindowSize.w) / 2; + final->y = ie->pos.y + (ie->size.h - iconWindowSize.h) / 2; + } + else + { + // No.. place it.. wherever + + final->x = pos->x; + final->y = pos->y; + } +} + +/** + * Bring the window up. + * + * @param cwin The window to be brought up. + */ + +void CIcon::up(FAR CWindow *cwin) +{ + struct nxgl_point_s newpos; + struct nxgl_point_s oldpos; + + // Did the user move the icon? + + if (cwin->hasIconMoved()) + { + struct nxgl_size_s oldsize; + if (!cwin->getIconWindowSize(&oldsize)) + { + return; + } + + if (!cwin->getIconWindowPosition(&oldpos)) + { + return; + } + + newpos.x = oldpos.x + ((int)oldsize.w) / 2; + newpos.y = oldpos.y + ((int)oldsize.h) / 2; + + FAR struct SIconRegion *ir; + for (ir = m_regionHead; ir; ir = ir->flink) + { + if (newpos.x >= ir->pos.x && + newpos.x < (ir->pos.x + ir->size.w) && + newpos.y >= ir->pos.y && + newpos.y < (ir->pos.y + ir->size.h)) + { + break; + } + } + + if (ir == NULL) + { + return; // outside icon regions, leave alone + } + } + + oldpos.x = -100; + oldpos.y = -100; + + place(cwin, &oldpos, &newpos); + + if (newpos.x != oldpos.x || newpos.y != oldpos.y) + { + (void)cwin->getIconWindowPosition(&newpos); + cwin->setIconMoved(false); // since we've restored it + } +} + +/** + * Take the window down. + * + * @param vwin The window to be taken down. + */ + +void CIcon::down(FAR CWindow *cwin) +{ + FAR struct SIconRegion *ir; + FAR struct SIconEntry *ie; + + ie = findEntry(cwin, &ir); + if (ie != (FAR struct SIconEntry *)0) + { + ie->cwin = 0; + ie->used = false; + + FAR struct SIconEntry *ip = prevEntry(ie, ir); + FAR struct SIconEntry *in = ie->flink; + + for (; ; ) + { + if (ip && ip->used == false && + ((ip->pos.x == ie->pos.x && ip->size.w == ie->size.w) || + (ip->pos.y == ie->pos.y && ip->size.h == ie->size.h))) + { + ip->flink = ie->flink; + mergeEntries(ie, ip); + free(ie); + ie = ip; + ip = prevEntry(ip, ir); + } + else if (in && in->used == false && + ((in->pos.x == ie->pos.x && in->size.w == ie->size.w) || + (in->pos.y == ie->pos.y && in->size.h == ie->size.h))) + { + ie->flink = in->flink; + mergeEntries(in, ie); + free(in); + in = ie->flink; + } + else + { + break; + } + } + } +} + +/** + * Find the icon region holding the window 'cwin' + * + * @param cwin The window whose icon region is sought + * @param irp A location in which to provide the region + */ + +FAR struct SIconEntry *CIcon::findEntry(FAR CWindow *cwin, + FAR struct SIconRegion **irp) +{ + FAR struct SIconRegion *ir; + FAR struct SIconEntry *ie; + + for (ir = m_regionHead; ir; ir = ir->flink) + { + for (ie = ir->entries; ie; ie = ie->flink) + if (ie->cwin == cwin) + { + if (irp) + { + *irp = ir; + } + + return ie; + } + } + + return (FAR struct SIconEntry *)0; +} + +/** + * Given entry 'ie' in the list 'ir', return the entry just prior to 'ie' + * + * @param ie The entry whose predecessor is sought + * @param ir The region containing the entry + * @return The entry just before 'ie' in the list + */ + +FAR struct SIconEntry *CIcon::prevEntry(FAR struct SIconEntry *ie, + FAR struct SIconRegion *ir) +{ + FAR struct SIconEntry *ip; + + if (ie == ir->entries) + { + return (FAR struct SIconEntry *)0; + } + + for (ip = ir->entries; ip->flink != ie; ip = ip->flink) + { + } + + return ip; +} + +/** + * 'old' is being freed; and is adjacent to ie. Merge + * regions together + */ + +void CIcon::mergeEntries(FAR struct SIconEntry *old, + FAR struct SIconEntry *ie) +{ + if (old->pos.y == ie->pos.y) + { + ie->size.w = old->size.w + ie->size.w; + if (old->pos.x < ie->pos.x) + { + ie->pos.x = old->pos.x; + } + } + else + { + ie->size.h = old->size.h + ie->size.h; + if (old->pos.y < ie->pos.y) + { + ie->pos.y = old->pos.y; + } + } +} + +/** + * Free all of the icon entries linked to a region + * + * @param ir The region whose entries will be freed + */ + +void CIcon::freeIconEntries(FAR struct SIconRegion *ir) +{ + FAR struct SIconEntry *ie; + FAR struct SIconEntry *tmp; + + for (ie = ir->entries; ie; ie = tmp) + { + tmp = ie->flink; + std::free(ie); + } +} + +/** + * Free all icon regions and all of the region entries linked into the + * region + */ + +void CIcon::freeIconRegions(void) +{ + struct SIconRegion *ir; + struct SIconRegion *tmp; + + for (ir = m_regionHead; ir != NULL;) + { + tmp = ir; + freeIconEntries(ir); + ir = ir->flink; + free(tmp); + } + + m_regionHead = NULL; + m_regionTail = NULL; +} diff --git a/graphics/twm4nx/src/ciconmgr.cxx b/graphics/twm4nx/src/ciconmgr.cxx new file mode 100644 index 000000000..507d1329b --- /dev/null +++ b/graphics/twm4nx/src/ciconmgr.cxx @@ -0,0 +1,757 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/src/ciconmgr.cxx +// Icon Manager routines +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 + +#include +#include +#include + +#include "graphics/nxwidgets/cnxwindow.hxx" +#include "graphics/nxwidgets/cnxfont.hxx" + +#include +#include + +#include "graphics/nxglyphs.hxx" + +#include "graphics/twm4nx/twm4nx_config.hxx" +#include "graphics/twm4nx/ctwm4nx.hxx" +#include "graphics/twm4nx/cfonts.hxx" +#include "graphics/twm4nx/cresize.hxx" +#include "graphics/twm4nx/cmenus.hxx" +#include "graphics/twm4nx/cwindow.hxx" +#include "graphics/twm4nx/cwindowevent.hxx" +#include "graphics/twm4nx/cwindowfactory.hxx" +#include "graphics/twm4nx/ciconmgr.hxx" + +///////////////////////////////////////////////////////////////////////////// +// Class Implementations +///////////////////////////////////////////////////////////////////////////// + +using namespace Twm4Nx; + +/** + * CIconMgr Constructor + * + * @param twm4nx The Twm4Nx session + * @param ncolumns The number of columns this icon manager has + */ + +CIconMgr::CIconMgr(CTwm4Nx *twm4nx, int ncolumns) +{ + m_twm4nx = twm4nx; // Cached the Twm4Nx session + m_head = (FAR struct SWindowEntry *)0; // Head of the winow list + m_tail = (FAR struct SWindowEntry *)0; // Tail of the winow list + m_active = (FAR struct SWindowEntry *)0; // No active window + m_window = (FAR CWindow *)0; // No icon manager Window + m_columns = ncolumns; + m_currows = 0; + m_curcolumns = 0; + m_count = 0; +} + +/** + * CIconMgr Destructor + */ + +CIconMgr::~CIconMgr(void) +{ + // Free memory allocations + + // Free the icon manager window + + if (m_window != (FAR CWindow *)0) + { + delete m_window; + } +} + +/** + * Create and initialize the icon manager window + * + * @param name The prefix for this icon manager name + */ + +bool CIconMgr::initialize(FAR const char *prefix) +{ + // Create the icon manager window + + if (!createWindow(prefix)) + { + gerr("ERROR: Failed to create window\n"); + return false; + } + + // Create the button array widget + + if (!createButtonArray()) + { + gerr("ERROR: Failed to button array\n"); + + CWindowFactory *factory = m_twm4nx->getWindowFactory(); + factory->destroyWindow(m_window); + m_window = (FAR CWindow *)0; + return false; + } + + return true; +} + +/** + * Add a window to an icon manager + * + * @param win the TWM window structure + */ + +bool CIconMgr::add(FAR CWindow *cwin) +{ + // Don't add the icon manager to itself + + if (cwin->isIconMgr()) + { + return false; + } + + // Allocate a new icon manager entry + + FAR struct SWindowEntry *wentry = + (FAR struct SWindowEntry *)malloc(sizeof(struct SWindowEntry)); + + if (wentry == (FAR struct SWindowEntry *)0) + { + return false; + } + + wentry->flink = NULL; + wentry->iconmgr = this; + wentry->active = false; + wentry->down = false; + wentry->cwin = cwin; + + FAR CFonts *fonts = m_twm4nx->getFonts(); + FAR NXWidgets::CNxFont *iconManagerFont = fonts->getIconManagerFont(); + + wentry->me = m_count; + wentry->pos.x = -1; + wentry->pos.y = -1; + + // Insert the new entry into the list + + insertEntry(wentry, cwin); + + // The height of one row is determined (mostly) by the fond height + + int rowHeight = iconManagerFont->getHeight() + 10; + if (rowHeight < (CONFIG_TWM4NX_ICONMGR_IMAGE.width + 4)) + { + rowHeight = CONFIG_TWM4NX_ICONMGR_IMAGE.width + 4; + } + + // Increase the icon window size + + struct nxgl_size_s windowSize; + if (!m_window->getWindowSize(&windowSize)) + { + gerr("ERROR: Failed to get window size\n"); + } + else + { + windowSize.h = rowHeight * m_count; + m_window->setWindowSize(&windowSize); + } + + // Increment the window count + + m_count++; + + // Pack the windows + + pack(); + + // If no other window is active, then mark this as the active window + + if (m_active == NULL) + { + m_active = wentry; + } + + return true; +} + +/** + * Remove a window from the icon manager + * + * @param win the TWM window structure + */ + +void CIconMgr::remove(FAR struct SWindow *win) +{ + FAR struct SWindowEntry *wentry = win->wentry; + + if (wentry != NULL) + { + // Remove the list from the window structure + + removeEntry(wentry); + + // Destroy the button array widget +#warning Missing logic + + // Destroy the window + + CWindowFactory *factory = m_twm4nx->getWindowFactory(); + factory->destroyWindow(wentry->cwin); + + m_count -= 1; + std::free(wentry); + pack(); + } +} + +/** + * Move the pointer around in an icon manager + * + * @param dir one of the following: + * - EVENT_ICONMGR_FORWARD: Forward in the window list + * - EVENT_ICONMGR_BACK: Backward in the window list + * - EVENT_ICONMGR_UP: Up one row + * - EVENT_ICONMGR_DOWN: Down one row + * - EVENT_ICONMGR_LEFT: Left one column + * - EVENT_ICONMGR_RIGHT: Right one column + */ + +void CIconMgr::move(int dir) +{ + if (!m_active) + { + return; + } + + int curRow = m_active->row; + int curCol = m_active->col; + + int rowIncr = 0; + int colIncr = 0; + bool gotIt = false; + + FAR struct SWindowEntry *wentry = (FAR struct SWindowEntry *)0; + + switch (dir) + { + case EVENT_ICONMGR_FORWARD: + if ((wentry = m_active->flink) == (FAR struct SWindowEntry *)0) + { + wentry = m_head; + } + + gotIt = true; + break; + + case EVENT_ICONMGR_BACK: + if ((wentry = m_active->blink) == (FAR struct SWindowEntry *)0) + { + wentry = m_tail; + } + + gotIt = true; + break; + + case EVENT_ICONMGR_UP: + rowIncr = -1; + break; + + case EVENT_ICONMGR_DOWN: + rowIncr = 1; + break; + + case EVENT_ICONMGR_LEFT: + colIncr = -1; + break; + + case EVENT_ICONMGR_RIGHT: + colIncr = 1; + break; + } + + // If gotIt is false ast this point then we got a left, right, up, or down, + // command. + + int newRow = curRow; + int newCol = curCol; + + while (!gotIt) + { + newRow += rowIncr; + newCol += colIncr; + + if (newRow < 0) + { + newRow = m_currows - 1; + } + + if (newCol < 0) + { + newCol = m_curcolumns - 1; + } + + if (newRow >= (int)m_currows) + { + newRow = 0; + } + + if (newCol >= (int)m_curcolumns) + { + newCol = 0; + } + + // Now let's go through the list to see if there is an entry with this + // new position. + + for (wentry = m_head; wentry != NULL; wentry = wentry->flink) + { + if (wentry->row == newRow && wentry->col == newCol) + { + gotIt = true; + break; + } + } + } + + if (!gotIt) + { + gwarn("WARNING: unable to find window (%d, %d) in icon manager\n", + newRow, newCol); + return; + } + + // raise the frame so the icon manager is visible +} + +/** + * Pack the icon manager windows following an addition or deletion + */ + +void CIconMgr::pack(void) +{ + FAR CFonts *fonts = m_twm4nx->getFonts(); + FAR NXWidgets::CNxFont *iconManagerFont = fonts->getIconManagerFont(); + + struct nxgl_size_s colsize; + + colsize.h = iconManagerFont->getHeight() + 10; + if (colsize.h < (CONFIG_TWM4NX_ICONMGR_IMAGE.height + 4)) + { + colsize.h = CONFIG_TWM4NX_ICONMGR_IMAGE.height + 4; + } + + struct nxgl_size_s windowSize; + if (!m_window->getWindowSize(&windowSize)) + { + gerr("ERROR: Failed to get window size\n"); + return; + } + + colsize.w = windowSize.w / m_columns; + + int rowIncr = colsize.h; + int colIncr = colsize.w; + + int row = 0; + int col = m_columns; + int maxcol = 0; + + FAR struct SWindowEntry *wentry; + int i; + + for (i = 0, wentry = m_head; + wentry != (FAR struct SWindowEntry *)0; + i++, wentry = wentry->flink) + { + wentry->me = i; + if (++col >= (int)m_columns) + { + col = 0; + row += 1; + } + + if (col > maxcol) + { + maxcol = col; + } + + struct nxgl_point_s newpos; + newpos.x = col * colIncr; + newpos.y = (row - 1) * rowIncr; + + wentry->row = row - 1; + wentry->col = col; + + // If the position or size has not changed, don't touch it + + if (wentry->pos.x != newpos.x || wentry->size.w != colsize.w) + { + if (!wentry->cwin->setWindowSize(&colsize)) + { + return; + } + + wentry->pos.x = newpos.x; + wentry->pos.y = newpos.y; + wentry->size.w = colsize.w; + wentry->size.h = colsize.h; + } + } + + maxcol += 1; + m_currows = row; + m_curcolumns = maxcol; + + // The height of one row is determined (mostly) by the fond height + + int rowHeight = iconManagerFont->getHeight() + 10; + if (rowHeight < (CONFIG_TWM4NX_ICONMGR_IMAGE.width + 4)) + { + rowHeight = CONFIG_TWM4NX_ICONMGR_IMAGE.width + 4; + } + + windowSize.h = rowHeight * m_count; + m_window->setWindowSize(&windowSize); + + if (windowSize.h == 0) + { + windowSize.h = rowIncr; + } + + struct nxgl_size_s newsize; + newsize.w = maxcol * colIncr; + + if (newsize.w == 0) + { + newsize.w = colIncr; + } + + newsize.h = windowSize.h; + + if (!m_window->setWindowSize(&newsize)) + { + return; + } + + // Get the net size of the containing frame + + struct nxgl_size_s frameSize; + m_window->windowToFrameSize(&windowSize, &frameSize); + + struct nxgl_point_s framePos; + m_window->getFramePosition(&framePos); + + // Resize the frame + + FAR CResize *resize = m_twm4nx->getResize(); + resize->setupWindow(m_window, &framePos, &frameSize); +} + +/** + * Sort the windows + */ + +void CIconMgr::sort(void) +{ + FAR struct SWindowEntry *tmpwin1; + FAR struct SWindowEntry *tmpwin2; + bool done; + + done = false; + do + { + for (tmpwin1 = m_head; tmpwin1 != NULL; tmpwin1 = tmpwin1->flink) + { + if ((tmpwin2 = tmpwin1->flink) == NULL) + { + done = true; + break; + } + + if (std::strcmp(tmpwin1->cwin->getWindowName(), + tmpwin2->cwin->getWindowName()) > 0) + { + // Take it out and put it back in + + removeEntry(tmpwin2); + insertEntry(tmpwin2, tmpwin2->cwin); + break; + } + } + } + while (!done); + + pack(); +} + +/** + * Handle ICONMGR events. + * + * @param msg. The received NxWidget ICONMGR event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + +bool CIconMgr::event(FAR struct SEventMsg *msg) +{ + bool ret = true; + + switch (msg->eventID) + { + case EVENT_ICONMGR_UP: + case EVENT_ICONMGR_DOWN: + case EVENT_ICONMGR_LEFT: + case EVENT_ICONMGR_RIGHT: + case EVENT_ICONMGR_FORWARD: + case EVENT_ICONMGR_BACK: + { + move(msg->eventID); + } + break; + + case EVENT_ICONMGR_SHOWPARENT: // Raise Icon manager parent window + { + m_window->deIconify(); + } + break; + + case EVENT_ICONMGR_HIDE: // Hide the Icon Manager + { + hide(); + } + break; + + case EVENT_ICONMGR_SORT: // Sort the Icon Manager + { + sort(); + } + break; + + default: + ret = false; + break; + } + + return ret; +} + +/** + * Create and initialize the icon manager window + * + * @param name The prefix for this icon manager name + */ + +bool CIconMgr::createWindow(FAR const char *prefix) +{ + static FAR const char *rootName = "Icon Manager"; + + // Create the icon manager name using any prefix provided by the creator + + FAR char *allocName = (FAR char *)0; + + if (prefix != (FAR const char *)0) + { + std::asprintf(&allocName, "%s %s", prefix, rootName); + } + + FAR const char *name = (allocName == (FAR char *)0) ? rootName : allocName; + + // Create the icon manager window + + CWindowFactory *factory = m_twm4nx->getWindowFactory(); + bool success = true; + + m_window = factory->createWindow(name, &CONFIG_TWM4NX_ICONMGR_IMAGE, + true, this, false); + + if (m_window == (FAR CWindow *)0) + { + gerr("ERROR: Failed to create icon manager window"); + success = false; + } + + // Free any temporary name strings + + if (allocName != (FAR char *)0) + { + std::free(allocName); + } + + return success; +} + +/** + * Create the button array widget + */ + +bool CIconMgr::createButtonArray(void) +{ +#warning Missing logic + return false; +} + +/** + * Put an allocated entry into an icon manager + * + * @param wentry the entry to insert + */ + +void CIconMgr::insertEntry(FAR struct SWindowEntry *wentry, + FAR CWindow *cwin) +{ + FAR struct SWindowEntry *tmpwin; + bool added; + + added = false; + if (m_head == NULL) + { + m_head = wentry; + wentry->blink = NULL; + m_tail = wentry; + added = true; + } + + for (tmpwin = m_head; tmpwin != NULL; tmpwin = tmpwin->flink) + { + // Insert the new window in name order + + if (strcmp(cwin->getWindowName(), tmpwin->cwin->getWindowName()) < 0) + { + wentry->flink = tmpwin; + wentry->blink = tmpwin->blink; + tmpwin->blink = wentry; + + if (wentry->blink == NULL) + { + m_head = wentry; + } + else + { + wentry->blink->flink = wentry; + } + + added = true; + break; + } + } + + if (!added) + { + m_tail->flink = wentry; + wentry->blink = m_tail; + m_tail = wentry; + } +} + +/** + * Remove an entry from an icon manager + * + * @param wentry the entry to remove + */ + +void CIconMgr::removeEntry(FAR struct SWindowEntry *wentry) +{ + if (wentry->blink == NULL) + { + m_head = wentry->flink; + } + else + { + wentry->blink->flink = wentry->flink; + } + + if (wentry->flink == NULL) + { + m_tail = wentry->blink; + } + else + { + wentry->flink->blink = wentry->blink; + } +} + +/** + * Set active window + * + * @active Window to become active. + */ + +void CIconMgr::active(FAR struct SWindowEntry *wentry) +{ + wentry->active = true; + m_active = wentry; +} + +/** + * Set window inactive + * + * @active windows to become inactive. + */ + +void CIconMgr::inactive(FAR struct SWindowEntry *wentry) +{ + wentry->active = false; +} + +/** + * Free window list entry. + */ + +void CIconMgr::freeWEntry(FAR struct SWindowEntry *wentry) +{ + if (wentry->cwin != (FAR CWindow *)0) + { + delete wentry->cwin; + wentry->cwin = (FAR CWindow *)0; + } + + free(wentry); +} diff --git a/graphics/twm4nx/src/ciconwin.cxx b/graphics/twm4nx/src/ciconwin.cxx new file mode 100644 index 000000000..4bdaef963 --- /dev/null +++ b/graphics/twm4nx/src/ciconwin.cxx @@ -0,0 +1,385 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/src/ciconwin.cxx +// Icon Windows +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 + +#include "graphics/nxwidgets/cnxwindow.hxx" +#include "graphics/nxwidgets/crlepalettebitmap.hxx" + +#include "graphics/twm4nx/twm4nx_config.hxx" +#include "graphics/twm4nx/ctwm4nx.hxx" +#include "graphics/twm4nx/cfonts.hxx" +#include "graphics/twm4nx/cmenus.hxx" +#include "graphics/twm4nx/cwindow.hxx" +#include "graphics/twm4nx/cwindowevent.hxx" +#include "graphics/twm4nx/cicon.hxx" +#include "graphics/twm4nx/ciconwin.hxx" +#include "graphics/twm4nx/twm4nx_widgetevents.hxx" +#include "graphics/twm4nx/twm4nx_cursor.hxx" + +///////////////////////////////////////////////////////////////////////////// +// CTwm4Nx Implementation +///////////////////////////////////////////////////////////////////////////// + +using namespace Twm4Nx; + +/** + * CIconWin Constructor + */ + +CIconWin::CIconWin(CTwm4Nx *twm4nx) +{ + m_twm4nx = twm4nx; // Cached the Twm4Nx session + m_nxwin = (FAR NXWidgets::CNxWindow *)0; // The cursor "raw" window + + // Dragging + + m_drag = false; // No drag in progress + m_dragOffset.x = 0; // Offset from mouse to window origin + m_dragOffset.y = 0; + m_dragCSize.w = 0; // The grab cursor size + m_dragCSize.h = 0; +} + +/** + * CIconWin Destructor + */ + +CIconWin::~CIconWin(void) +{ + cleanup(); +} + +/** + * Create the icon window + * + * @param parent The parent window + * @param sbitmap The Icon image + * @param pos The default position + */ + +bool CIconWin::initialize(FAR CWindow *parent, + FAR const NXWidgets::SRlePaletteBitmap *sbitmap, + FAR const struct nxgl_point_s *pos) +{ + struct nxgl_point_s final; + + // Git the size of the Icon Image + + struct nxgl_size_s iconImageSize; + iconImageSize.h = sbitmap->height; + iconImageSize.w = sbitmap->height; + + // Git the size of the Icon name + + FAR CFonts *fonts = m_twm4nx->getFonts(); + FAR NXWidgets::CNxFont *iconFont = fonts->getIconFont(); + FAR const char *iconName = parent->getWindowName(); + + struct nxgl_size_s iconWindowSize; + iconWindowSize.w = iconFont->getStringWidth(iconName); + iconWindowSize.w += 6; + + // Handle the case where the name string is wider than the icon + + struct nxgl_point_s iconWindowPos; + if (iconWindowSize.w < iconImageSize.w) + { + // Center + + iconWindowPos.x = (iconImageSize.w - iconWindowSize.w) / 2; + iconWindowPos.x += 3; + iconWindowSize.w = iconImageSize.w; + } + else + { + iconWindowPos.x = 3; + } + + iconWindowPos.y = iconImageSize.h + iconFont->getHeight(); + iconWindowSize.h = iconImageSize.h + iconFont->getHeight() + 4; + + // Create the icon window + // 1. Get the server instance. m_twm4nx inherits from NXWidgets::CNXServer + // so we all ready have the server instance. + // 2. Create the style, using the selected colors (REVISIT) + + // 3. Create a Widget control instance for the window using the default + // style for now. CWindowEvent derives from CWidgetControl. + + FAR CWindowEvent *control = new CWindowEvent(m_twm4nx); + + // 4. Create the icon window + + m_nxwin = m_twm4nx->createRawWindow(control); + if (m_nxwin == (FAR NXWidgets::CNxWindow *)0) + { + delete control; + return false; + } + + // 5. Open and initialize the icon window + + bool success = m_nxwin->open(); + if (!success) + { + delete m_nxwin; + m_nxwin = (FAR NXWidgets::CNxWindow *)0; + return false; + } + + // 6. Set the initial window size + + if (!m_nxwin->setSize(&iconWindowSize)) + { + delete m_nxwin; + m_nxwin = (FAR NXWidgets::CNxWindow *)0; + return false; + } + + // 7. Set the initial window position + + if (!m_nxwin->setPosition(&iconWindowPos)) + { + delete m_nxwin; + m_nxwin = (FAR NXWidgets::CNxWindow *)0; + return false; + } + + // We need to figure out where to put the icon window now, because getting + // here means that we am going to make the icon visible. + + FAR CIcon *cicon = m_twm4nx->getIcon(); + cicon->place(parent, pos, &final); + + struct nxgl_size_s displaySize; + m_twm4nx->getDisplaySize(&displaySize); + + if (final.x > displaySize.w) + { + final.x = displaySize.w - iconWindowSize.w; + } + + if (final.y > displaySize.h) + { + final.y = displaySize.h - iconImageSize.h - iconFont->getHeight() - 4; + } + + (void)m_nxwin->setPosition(&final); + return true; +} + +/** + * Handle ICON events. + * + * @param eventmsg. The received NxWidget ICON event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + +bool CIconWin::event(FAR struct SEventMsg *eventmsg) +{ + bool success = true; + + switch (eventmsg->eventID) + { + case EVENT_ICONWIN_GRAB: /* Left click on icon. Start drag */ + success = iconGrab(eventmsg); + break; + + case EVENT_ICONWIN_DRAG: /* Mouse movement while clicked */ + success = iconDrag(eventmsg); + break; + + case EVENT_ICONWIN_UNGRAB: /* Left click release while dragging. */ + success = iconUngrab(eventmsg); + break; + + default: + success = false; + break; + } + + return success; +} + +/** + * Handle the ICON_GRAB event. That corresponds to a left + * mouse click on the icon + * + * @param eventmsg. The received NxWidget event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + +bool CIconWin::iconGrab(FAR struct SEventMsg *eventmsg) +{ + // Promote the icon to a modal window + + m_nxwin->modal(true); + + // Indicate that dragging has started. + + m_drag = false; + + // Get the icon position. + + struct nxgl_point_s framePos; + m_nxwin->getPosition(&framePos); + + // Determine the relative position of the icon and the mouse + + m_dragOffset.x = framePos.x - eventmsg->pos.x; + m_dragOffset.y = framePos.y - eventmsg->pos.y; + + // Select the grab cursor image + + m_twm4nx->setCursorImage(&CONFIG_TWM4NX_GBCURSOR_IMAGE); + + // 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; +} + +/** + * Handle the ICON_DRAG event. That corresponds to a mouse + * movement when the icon is in a grabbed state. + * + * @param eventmsg. The received NxWidget event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + +bool CIconWin::iconDrag(FAR struct SEventMsg *eventmsg) +{ + if (m_drag) + { + // Calculate the new icon position + + struct nxgl_point_s newpos; + newpos.x = eventmsg->pos.x + m_dragOffset.x; + newpos.y = eventmsg->pos.y + m_dragOffset.y; + + // Keep the icon on the display (at least enough of it so that we + // can still grab it) + + struct nxgl_size_s displaySize; + m_twm4nx->getDisplaySize(&displaySize); + + if (newpos.x < 0) + { + newpos.x = 0; + } + else if (newpos.x + m_dragCSize.w > displaySize.w) + { + newpos.x = displaySize.w - m_dragCSize.w; + } + + if (newpos.y < 0) + { + newpos.y = 0; + } + else if (newpos.y + m_dragCSize.h > displaySize.h) + { + newpos.y = displaySize.h - m_dragCSize.h; + } + + // Set the new window position + + return m_nxwin->setPosition(&newpos); + } + + return false; +} + +/** + * Handle the ICON_UNGRAB event. The corresponds to a mouse + * left button release while in the grabbed + * + * @param eventmsg. The received NxWidget event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + +bool CIconWin::iconUngrab(FAR struct SEventMsg *eventmsg) +{ + // One last position update + + if (!iconDrag(eventmsg)) + { + return false; + } + + // Indicate no longer dragging + + m_drag = false; + + // No long modal + + m_nxwin->modal(false); + + // Restore the normal cursor image + + m_twm4nx->setCursorImage(&CONFIG_TWM4NX_CURSOR_IMAGE); + return false; +} + +/** + * Cleanup on failure or as part of the destructor + */ + +void CIconWin::cleanup(void) +{ + // Close windows + + if (m_nxwin != (FAR NXWidgets::CNxWindow *)0) + { + delete m_nxwin; + m_nxwin = (FAR NXWidgets::CNxWindow *)0; + } +} diff --git a/graphics/twm4nx/src/cinput.cxx b/graphics/twm4nx/src/cinput.cxx new file mode 100644 index 000000000..7e741bab6 --- /dev/null +++ b/graphics/twm4nx/src/cinput.cxx @@ -0,0 +1,692 @@ +/******************************************************************************************** + * apps/graphics/NxWidgets/nxwm/src/cinput.cxx + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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, NxWidgets, nor the names of its contributors + * me 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 + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "graphics/twm4nx/twm4nx_config.hxx" +#include "graphics/twm4nx/ctwm4nx.hxx" +#include "graphics/twm4nx/twm4nx_cursor.hxx" +#include "graphics/twm4nx/cinput.hxx" + +/******************************************************************************************** + * Pre-Processor Definitions + ********************************************************************************************/ + +/******************************************************************************************** + * CInput Method Implementations + ********************************************************************************************/ + +using namespace Twm4Nx; + +/** + * CInput Constructor + * + * @param twm4nx. An instance of the NX server. This will be needed for + * injecting keyboard data. + */ + +CInput::CInput(CTwm4Nx *twm4nx) +{ + m_twm4nx = twm4nx; // Save the NX server + m_kbdFd = -1; // Device driver is not opened + m_state = LISTENER_NOTRUNNING; // The listener thread is not running yet + + // Initialize the semaphore used to synchronize with the listener thread + + sem_init(&m_waitSem, 0, 0); +} + +/** + * CInput Destructor + */ + +CInput::~CInput(void) +{ + // Stop the listener thread + + m_state = LISTENER_STOPREQUESTED; + + // Wake up the listener thread so that it will use our buffer + // to receive data + // REVISIT: Need wait here for the listener thread to terminate + + (void)pthread_kill(m_thread, CONFIG_TWM4NX_INPUT_SIGNO); + + // Close the keyboard device (or should these be done when the thread exits?) + + if (m_kbdFd >= 0) + { + std::close(m_kbdFd); + } +} + +/** + * Start the keyboard listener thread. + * + * @return True if the keyboard listener thread was correctly started. + */ + +bool CInput::start(void) +{ + pthread_attr_t attr; + + ginfo("Starting listener\n"); + + // Start a separate thread to listen for keyboard events + + (void)pthread_attr_init(&attr); + + struct sched_param param; + param.sched_priority = CONFIG_TWM4NX_INPUT_LISTENERPRIO; + (void)pthread_attr_setschedparam(&attr, ¶m); + + (void)pthread_attr_setstacksize(&attr, CONFIG_TWM4NX_INPUT_LISTENERSTACK); + + m_state = LISTENER_STARTED; // The listener thread has been started, but is not yet running + + int ret = pthread_create(&m_thread, &attr, listener, (FAR void *)this); + if (ret != 0) + { + gerr("ERROR: CInput::start: pthread_create failed: %d\n", ret); + return false; + } + + // Detach from the thread + + (void)pthread_detach(m_thread); + + // Don't return until we are sure that the listener thread is running + // (or until it reports an error). + + while (m_state == LISTENER_STARTED) + { + // Wait for the listener thread to wake us up when we really + // are connected. + + (void)sem_wait(&m_waitSem); + } + + // Then return true only if the listener thread reported successful + // initialization. + + ginfo("Listener m_state=%d\n", (int)m_state); + return m_state == LISTENER_RUNNING; +} + +/** + * Open the keyboard device. Not very interesting for the case of + * standard device but much more interesting for a USB keyboard device + * that may disappear when the keyboard is disconnect but later reappear + * when the keyboard is reconnected. In this case, this function will + * not return until the keyboard device was successfully opened (or + * until an irrecoverable error occurs. + * + * Opens the keyboard device specified by CONFIG_TWM4NX_KEYBOARD_DEVPATH. + * + * @return On success, then method returns a valid file descriptor. A + * negated errno value is returned if an irrecoverable error occurs. + */ + +int CInput::keyboardOpen(void) +{ + int fd; + + // Loop until we have successfully opened the USB keyboard (or until some + // irrecoverable error occurs). + + do + { + // Try to open the keyboard device + + fd = std::open(CONFIG_TWM4NX_KEYBOARD_DEVPATH, O_RDONLY); + if (fd < 0) + { + int errcode = errno; + DEBUGASSERT(errcode > 0); + + // EINTR should be ignored because it is not really an error at + // all. We should retry immediately + + if (errcode != EINTR) + { +#ifdef CONFIG_TWM4NX_KEYBOARD_USBHOST + // ENOENT means that the USB keyboard is not yet connected and, + // hence, has no entry under /dev. If the USB driver still + // exists under /dev (because other threads still have the driver + // open), then we might also get ENODEV. + + if (errcode == ENOENT || errcode == ENODEV) + { + // REVIST: Can we inject a constant string here to let the + // user know that we are waiting for a USB keyboard to be + // connected? + + // Sleep a bit and try again + + ginfo("WAITING for a USB keyboard\n"); + std::sleep(2); + } + + // Anything else would be really bad. + + else +#endif + { + // Let the top-level logic decide what it wants to do + // about all really bad things + + gerr("ERROR: Failed to open %s for reading: %d\n", + CONFIG_TWM4NX_KEYBOARD_DEVPATH, errcode); + return -errcode; + } + } + } + } + while (fd < 0); + + return fd; +} + +/** + * Open the mouse input devices. Not very interesting for the + * case of standard character device but much more interesting for + * USB mouse devices that may disappear when disconnected but later + * reappear when reconnected. In this case, this function will + * not return until the input device was successfully opened (or + * until an irrecoverable error occurs). + * + * Opens the mouse input device specified by CONFIG_TWM4NX_MOUSE_DEVPATH. + * + * @return On success, then method returns a valid file descriptor. A + * negated errno value is returned if an irrecoverable error occurs. + */ + +inline int CInput::mouseOpen(void) +{ + int fd; + + // Loop until we have successfully opened the USB mouse (or until some + // irrecoverable error occurs). + + do + { + // Try to open the mouse device + + fd = std::open(CONFIG_TWM4NX_MOUSE_DEVPATH, O_RDONLY); + if (fd < 0) + { + int errcode = errno; + DEBUGASSERT(errcode > 0); + + // EINTR should be ignored because it is not really an error at + // all. We should retry immediately + + if (errcode != EINTR) + { +#ifdef CONFIG_TWM4NX_MOUSE_USBHOST + // ENOENT means that the USB mouse is not yet connected and, + // hence, has no entry under /dev. If the USB driver still + // exists under /dev (because other threads still have the driver + // open), then we might also get ENODEV. + + if (errcode == ENOENT || errcode == ENODEV) + { + // REVIST: Can we inject a constant string here to let the + // user know that we are waiting for a USB mouse to be + // connected? + + // Sleep a bit and try again + + ginfo("WAITING for a USB mouse\n"); + std::sleep(2); + } + + // Anything else would be really bad. + + else +#endif + { + // Let the top-level logic decide what it wants to do + // about all really bad things + + gerr("ERROR: Failed to open %s for reading: %d\n", + CONFIG_TWM4NX_MOUSE_DEVPATH, errcode); + return -errcode; + } + } + } + } + while (fd < 0); + + return fd; +} + +/** + * Read data from the keyboard device and inject the keyboard data + * into NX for proper distribution. + * + * @return On success, then method returns a valid file descriptor. A + * negated errno value is returned if an irrecoverable error occurs. + */ + +int CInput::keyboardInput(void) +{ + // Read one keyboard sample + + ginfo("Reading keyboard input\n"); + + uint8_t rxbuffer[CONFIG_TWM4NX_KEYBOARD_BUFSIZE]; + ssize_t nbytes = read(m_kbdFd, rxbuffer, + CONFIG_TWM4NX_KEYBOARD_BUFSIZE); + + // Check for errors + + if (nbytes < 0) + { + int errcode = errno; + DEBUGASSERT(errcode > 0); + + // EINTR is not really an error, it simply means that something is + // trying to get our attention. We need to check m_state to see + // if we were asked to terminate + + if (errcode != EINTR) + { + // Let the top-level listener logic decide what to do about + // the read failure. + + gerr("ERROR: read %s failed: %d\n", + CONFIG_TWM4NX_KEYBOARD_DEVPATH, errcode); + return -errcode; + } + + fwarn("WARNING: Awakened with EINTR\n"); + } + + // Give the keyboard input to NX + + else if (nbytes > 0) + { + // Looks like good keyboard input... process it. + // NOTE: m_twm4nx inherits from NXWidgets::CNXServer so we all ready + // have the server instance. + + // Inject the keyboard input into NX + + int ret = nx_kbdin(m_twm4nx, (uint8_t)nbytes, rxbuffer); + if (ret < 0) + { + gerr("ERROR: nx_kbdin failed: %d\n", ret); + + // Ignore the error + } + } + + return OK; +} + +/** + * Read data from the mouse device, update the cursor position, and + * inject the mouse data into NX for proper distribution. + * + * @return On success, then method returns a valid file descriptor. A + * negated errno value is returned if an irrecoverable error occurs. + */ + +int CInput::mouseInput(void) +{ + // Read one mouse sample + + ginfo("Reading mouse input\n"); + + uint8_t rxbuffer[CONFIG_TWM4NX_MOUSE_BUFSIZE]; + ssize_t nbytes = read(m_mouseFd, rxbuffer, + CONFIG_TWM4NX_MOUSE_BUFSIZE); + + // Check for errors + + if (nbytes < 0) + { + int errcode = errno; + DEBUGASSERT(errcode > 0); + + // EINTR is not really an error, it simply means that something is + // trying to get our attention. We need to check m_state to see + // if we were asked to terminate + + if (errcode != EINTR) + { + // Let the top-level listener logic decide what to do about + // the read failure. + + gerr("ERROR: read %s failed: %d\n", + CONFIG_TWM4NX_KEYBOARD_DEVPATH, errcode); + return -errcode; + } + + fwarn("WARNING: Awakened with EINTR\n"); + } + + // On a truly successful read, the size of the returned data will + // be greater than or equal to size of one touchscreen sample. It + // be greater only in the case of a multi-touch touchscreen device + // when multi-touches are reported. + + else if (nbytes < (ssize_t)sizeof(struct mouse_report_s)) + { + gerr("ERROR Unexpected read size=%d, expected=%d\n", + nbytes, sizeof(struct mouse_report_s)); + return -EIO; + } + else + { + // Looks like good mouse input... process it. + // NOTE: m_twm4nx inherits from NXWidgets::CNXServer so we all ready + // have the server instance. + + // Update the cursor position + + FAR struct mouse_report_s *rpt = + (FAR struct mouse_report_s *)rxbuffer; + + struct nxgl_point_s pos = + { + .x = rpt->x, + .y = rpt->y + }; + + int ret = nxcursor_setposition(m_twm4nx, &pos); + if (ret < 0) + { + gerr("ERROR: nxcursor_setposition failed: %d\n", ret); + + // Ignore the error + } + + // Then inject the mouse input into NX + + ret = nx_mousein(m_twm4nx, rpt->x, rpt->y, rpt->buttons); + if (ret < 0) + { + gerr("ERROR: nx_mousein failed: %d\n", ret); + + // Ignore the error + } + } + + return OK; +} + +/** + * This is the heart of the keyboard/mouse listener thread. It + * contains the actual logic that listeners for and dispatches input + * events to the NX server. + * + * @return If the session terminates gracefully (i.e., because >m_state + * is no longer equal to LISTENER_RUNNING, then method returns OK. A + * negated errno value is returned if an error occurs while reading from + * the input device. A read error, depending upon the type of the + * error, may simply indicate that a USB device was removed and we + * should wait for the device to be connected. + */ + +int CInput::session(void) +{ + ginfo("Session started\n"); + + // Center the cursor + + struct nxgl_size_s size; + m_twm4nx->getDisplaySize(&size); + + struct nxgl_point_s pos; + pos.x = size.w / 2, + pos.y = size.h / 2, + + m_twm4nx->setCursorPosition(&pos); + + // Set the default cursor image + + m_twm4nx->setCursorImage(&CONFIG_TWM4NX_CURSOR_IMAGE); + + // Enable the cursor + + m_twm4nx->enableCursor(true); + + // Loop, reading and dispatching keyboard data + + int ret = OK; + while (m_state == LISTENER_RUNNING) + { + // Wait for data availability + + struct pollfd pfd[2] = + { + { + .fd = m_kbdFd, + .events = POLLIN | POLLERR | POLLHUP, + .revents = 0 + }, + { + .fd = m_mouseFd, + .events = POLLIN | POLLERR | POLLHUP, + .revents = 0 + }, + }; + + ret = poll(pfd, 2, -1); + if (ret < 0) + { + int errcode = errno; + + /* Ignore signal interruptions */ + + if (errcode == EINTR) + { + continue; + } + else + { + gerr("ERROR: poll() failed"); + break; + } + } + + // Check for keyboard input + + if ((pfd[0].revents & (POLLERR | POLLHUP)) != 0) + { + gerr("ERROR: keyboard poll() failed. revents=%04x\n", + pfd[0].revents); + ret = -EIO; + break; + } + + if ((pfd[0].revents & POLLIN) != 0) + { + ret = keyboardInput(); + if (ret < 0) + { + gerr("ERROR: keyboardInput() failed: %d\n", ret); + break; + } + } + + // Check for mouse input + + if ((pfd[1].revents & (POLLERR | POLLHUP)) != 0) + { + gerr("ERROR: Mouse poll() failed. revents=%04x\n", + pfd[1].revents); + ret = -EIO; + break; + } + + if ((pfd[1].revents & POLLIN) != 0) + { + ret = mouseInput(); + if (ret < 0) + { + gerr("ERROR: mouseInput() failed: %d\n", ret); + break; + } + } + } + + // Disable the cursor + + m_twm4nx->enableCursor(false); + return ret; +} + +/** + * The keyboard/mouse listener thread. This is the entry point of a + * thread that listeners for and dispatches keyboard and mouse events + * to the NX server. It simply opens the input devices (using + * CInput::keyboardOpen() and CInput::mouseOpen()) and executes the + * session (via CInput::session()). + * + * If an errors while reading from the input device AND that device is + * configured to use a USB connection, then this function will wait for + * the USB device to be re-connected. + * + * @param arg. The CInput 'this' pointer cast to a void*. + * @return This function normally does not return but may return NULL + * on error conditions. + */ + +FAR void *CInput::listener(FAR void *arg) +{ + CInput *This = (CInput *)arg; + + ginfo("Listener started\n"); + +#if defined(CONFIG_TWM4NX_KEYBOARD_USBHOST) || defined(CONFIG_TWM4NX_MOUSE_USBHOST) + // Indicate that we have successfully started. We might be stuck waiting + // for a USB keyboard to be connected, but we are technically running + + This->m_state = LISTENER_RUNNING; + sem_post(&This->m_waitSem); + + // Loop until we are told to quit + + while (This->m_state == LISTENER_RUNNING) +#endif + { + // Open/Re-open the keyboard device + + This->m_kbdFd = This->keyboardOpen(); + if (This->m_kbdFd < 0) + { + gerr("ERROR: open failed: %d\n", This->m_kbdFd); + This->m_state = LISTENER_FAILED; + sem_post(&This->m_waitSem); + return (FAR void *)0; + } + + // Open/Re-open the mouse device + + This->m_mouseFd = This->mouseOpen(); + if (This->m_mouseFd < 0) + { + gerr("ERROR: open failed: %d\n", This->m_mouseFd); + This->m_state = LISTENER_FAILED; + sem_post(&This->m_waitSem); + return (FAR void *)0; + } + +#if !defined(CONFIG_TWM4NX_KEYBOARD_USBHOST) && !defined(CONFIG_TWM4NX_MOUSE_USBHOST) + // Indicate that we have successfully initialized + + This->m_state = LISTENER_RUNNING; + sem_post(&This->m_waitSem); +#endif + + // Now execute the session. The session will run until either (1) we + // were asked to terminate gracefully (with m_state !=LISTENER_RUNNING), + // of if an error occurred while reading from the keyboard device. If + // we are configured to use a USB keyboard, then this error, depending + // upon what the error is, may indicate that the USB keyboard has been + // removed. In that case, we need to continue looping and, hopefully, + // the USB keyboard will be reconnected. + + int ret = This->session(); +#if defined(CONFIG_TWM4NX_KEYBOARD_USBHOST) || defined(CONFIG_TWM4NX_MOUSE_USBHOST) + if (ret < 0) + { + ferr("ERROR: CInput::session() returned %d\n", ret); + } +#else + // No errors from session() are expected + + DEBUGASSERT(ret == OK); + UNUSED(ret); +#endif + + // Close the keyboard device + + (void)std::close(This->m_kbdFd); + This->m_kbdFd = -1; + + // Close the mouse device + + (void)std::close(This->m_mouseFd); + This->m_mouseFd = -1; + } + + // We should get here only if we were asked to terminate via + // m_state = LISTENER_STOPREQUESTED (or perhaps if some irrecoverable + // error has occurred). + + ginfo("Listener exiting\n"); + This->m_state = LISTENER_TERMINATED; + return (FAR void *)0; +} diff --git a/graphics/twm4nx/src/cmenus.cxx b/graphics/twm4nx/src/cmenus.cxx new file mode 100644 index 000000000..660149090 --- /dev/null +++ b/graphics/twm4nx/src/cmenus.cxx @@ -0,0 +1,882 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/src/cmenus.cxx +// twm menu code +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// Copyright 1988 by Evans & Sutherland Computer Corporation, +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 + +#include +#include +#include +#include +#include +#include + +#include + +#include "graphics/nxwidgets/cnxfont.hxx" +#include "graphics/nxwidgets/clistbox.hxx" + +#include "graphics/twm4nx/ctwm4nx.hxx" +#include "graphics/twm4nx/cmenus.hxx" +#include "graphics/twm4nx/cresize.hxx" +#include "graphics/twm4nx/cfonts.hxx" +#include "graphics/twm4nx/cicon.hxx" +#include "graphics/twm4nx/ciconmgr.hxx" +#include "graphics/twm4nx/cwindow.hxx" +#include "graphics/twm4nx/cwindowfactory.hxx" +#include "graphics/twm4nx/cwindowevent.hxx" +#include "graphics/twm4nx/twm4nx_widgetevents.hxx" +#include "graphics/twm4nx/cmenus.hxx" + +//////////////////////////////////////////////////////////////////////////// +// Class Implementations +///////////////////////////////////////////////////////////////////////////// + +using namespace Twm4Nx; + +/** + * CMenus Constructor + */ + +CMenus::CMenus(CTwm4Nx *twm4nx) +{ + // Save the Twm4Nx session + + m_twm4nx = twm4nx; // Save the Twm4Nx session + + // Menus + + m_popUpMenu = (FAR CMenus *)0; // No pop-up menu + m_activeItem = (FAR struct SMenuItem *)0; // No active menu item + m_nMenuItems = 0; // No menu items yet + m_menuDepth = 0; // No menus up + m_entryHeight = 0; // Menu entry height + m_menuPull = false; // No pull right entry + + // Windows + + m_menuWindow = (FAR NXWidgets::CNxTkWindow *)0; // The menu window + + // Widgets + + m_menuListBox = (FAR NXWidgets::CListBox *)0; //The menu list box + + // Functions + + m_funcKeyHead = (FAR struct SFuncKey *)0; +} + +/** + * CMenus Destructor + */ + +CMenus::~CMenus(void) +{ + cleanup(); +} + +/** + * CMenus Initializer. Performs the parts of the CMenus construction + * that may fail. + * + * @result True is returned on success + */ + +bool CMenus::initialize(FAR const char *name) +{ + // Open a message queue to NX events. + + FAR const char *mqname = m_twm4nx->getEventQueueName(); + m_eventq = mq_open(mqname, O_WRONLY | O_NONBLOCK); + if (m_eventq == (mqd_t)-1) + { + gerr("ERROR: Failed open message queue '%s': %d\n", + mqname, errno); + } + + // Save the menu name + + m_menuName = strdup(name); + if (m_menuName == (FAR char *)0) + { + return false; + } + + // Create the menu window + + if (!createMenuWindow()) + { + gerr("ERROR: Failed to create menu window\n"); + cleanup(); + return false; + } + + // Create the menu list box + + if (!createMenuListBox()) + { + gerr("ERROR: Failed to create menu list box\n"); + cleanup(); + return false; + } + + return true; +} + +/** + * Add an item to a menu + * + * \param text The text to appear in the menu + * \param action The string to possibly execute + * \param subMenu The menu if it is a pull-right entry + * \param func The numeric function + */ + +// REVISIT: Only used internally. Was used in .twmrc parsing. + +bool CMenus::addMenuItem(FAR const char *text, + FAR const char *action, FAR CMenus *subMenu, + int func) +{ + ginfo("Adding menu text=\"%s\", action=%s, subMenu=%d, f=%d\n", + text, action, subMenu, func); + + // Allocate a new menu item entry + + FAR struct SMenuItem *item = new SMenuItem; + + if (item == (FAR struct SMenuItem *)0) + { + gerr("ERROR: Failed to allocate menu item\n"); + return false; + } + + // Clone the item name so that we have control over its lifespan + + item->text = std::strdup(text); + if (item->text == (FAR char *)0) + { + gerr("ERROR: strdup of item text failed\n"); + std::free(item); + return false; + } + + // Save information about the menu item + + item->action = action; + item->flink = NULL; + item->subMenu = NULL; + item->func = func; + + CFonts *fonts = m_twm4nx->getFonts(); + FAR NXWidgets::CNxFont *menuFont = fonts->getMenuFont(); + int width = menuFont->getStringWidth(text); + + if (width <= 0) + { + width = 1; + } + + struct nxgl_size_s menuSize; + m_menuWindow->getSize(&menuSize); + + if (width > menuSize.w) + { + menuSize.w = width; + m_menuWindow->setSize(&menuSize); + } + + if (subMenu != NULL) + { + item->subMenu = subMenu; + m_menuPull = true; + } + + // Save the index to this item and increment the total number of menu + // items + + item->index = m_nMenuItems++; + + // Add the menu item to the tail of the item list + + if (m_menuHead == NULL) + { + m_menuHead = item; + item->blink = (FAR struct SMenuItem *)0; + } + else + { + m_menuTail->flink = item; + item->blink = m_menuTail; + } + + m_menuTail = item; + item->flink = (FAR struct SMenuItem *)0; + + // Add the item text to the list box + + m_menuListBox->addOption(item->text, item->index); + + // Update the menu window size + + setMenuWindowSize(); + + // Redraw the list box + + m_menuListBox->enableDrawing(); + m_menuListBox->setRaisesEvents(true); + m_menuListBox->redraw(); + return true; +} + +/** + * Handle MENU events. + * + * @param eventmsg. The received NxWidget MENU event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + +bool CMenus::event(FAR struct SEventMsg *eventmsg) +{ + bool success = true; + + switch (eventmsg->eventID) + { + case EVENT_MENU_IDENTIFY: // Describe the window + { + identify((FAR CWindow *)eventmsg->obj); + } + break; + + case EVENT_MENU_VERSION: // Show the Twm4Nx version + identify((FAR CWindow *) NULL); + break; + + case EVENT_MENU_DEICONIFY: // Window icon pressed + case EVENT_MENU_ICONIFY: // Tool bar minimize button pressed + { + FAR CWindow *cwin = (FAR CWindow *)eventmsg->obj; + if (cwin->isIconified()) + { + cwin->deIconify(); + } + else if (eventmsg->eventID == EVENT_MENU_ICONIFY) + { + cwin->iconify(); + } + } + break; + + case EVENT_MENU_FUNCTION: // Perform function on unknown menu + { + FAR struct SMenuItem *item; + + for (item = m_menuHead; item != NULL; item = item->flink) + { + // Send another event message to the session manager + + struct SEventMsg newmsg; + newmsg.eventID = item->func; + newmsg.pos.x = eventmsg->pos.x; + newmsg.pos.y = eventmsg->pos.y; + newmsg.context = eventmsg->context; + newmsg.pulldown = eventmsg->pulldown; + newmsg.action = item->action; + newmsg.nxwin = eventmsg->nxwin; + newmsg.obj = eventmsg->obj; + + // 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 runawy stack usage. + + int ret = mq_send(m_eventq, (FAR const char *)&newmsg, + sizeof(struct SEventMsg), 100); + if (ret < 0) + { + gerr("ERROR: mq_send failed: %d\n", ret); + success = false; + } + } + } + break; + + case EVENT_MENU_TITLE: // Really an action not an event + case EVENT_MENU_ROOT: // Popup root menu, really an action not an event + default: + success = false; + break; + } + + return success; +} + +void CMenus::identify(FAR CWindow *cwin) +{ + int n = 0; +#if CONFIG_VERSION_MAJOR != 0 || CONFIG_VERSION_MINOR != 0 + std::snprintf(m_info[n], INFO_SIZE, "Twm4Nx: NuttX-" CONFIG_VERSION_STRING); +#else + std::snprintf(m_info[n], INFO_SIZE, "Twm4Nx:"); +#endif + m_info[n++][0] = '\0'; + + if (cwin != (FAR CWindow *)0) + { + // Get the size of the window + + struct nxgl_size_s windowSize; + if (!cwin->getFrameSize(&windowSize)) + { + return; + } + + struct nxgl_point_s windowPos; + if (!cwin->getFramePosition(&windowPos)) + { + return; + } + + std::snprintf(m_info[n++], INFO_SIZE, "Name = \"%s\"", + cwin->getWindowName()); + m_info[n++][0] = '\0'; + std::snprintf(m_info[n++], INFO_SIZE, "Geometry/root = %dx%d+%d+%d", + windowSize.w, windowSize.h, windowPos.x, windowPos.y); + } + + m_info[n++][0] = '\0'; + std::snprintf(m_info[n++], INFO_SIZE, "Click to dismiss...."); + + // Figure out the width and height of the info window + + FAR CFonts *fonts = m_twm4nx->getFonts(); + FAR NXWidgets::CNxFont *defaultFont = fonts->getDefaultFont(); + + struct nxgl_size_s menuSize; + menuSize.h = n * (defaultFont->getHeight() + 2); + menuSize.w = 1; + + for (int i = 0; i < n; i++) + { + int twidth = defaultFont->getStringWidth(m_info[i]); + if (twidth > menuSize.w) + { + menuSize.w = twidth; + } + } + + menuSize.w += 10; // some padding + + // Make sure that the window is on the display + + struct nxgl_point_s menuPos; + if (m_menuWindow->getPosition(&menuPos)) + { + menuPos.x -= (menuSize.w / 2); + menuPos.y -= (menuSize.h / 3); + + struct nxgl_size_s displaySize; + m_twm4nx->getDisplaySize(&displaySize); + + struct nxgl_size_s frameSize; + menuToFrameSize(&menuSize, &frameSize); + + if (menuPos.x + frameSize.w >= displaySize.w) + { + menuPos.x = displaySize.w - frameSize.w; + } + + if (menuPos.y + frameSize.h >= displaySize.h) + { + menuPos.y = displaySize.h - frameSize.h; + } + + if (menuPos.x < 0) + { + menuPos.x = 0; + } + + if (menuPos.y < 0) + { + menuPos.y = 0; + } + + frameToMenuSize(&frameSize, &menuSize); + } + else + { + menuPos.x = 0; + menuPos.y = 0; + } + + // Set the new window size and position + + if (!m_menuWindow->setPosition(&menuPos) || + !m_menuWindow->setSize(&menuSize)) + { + return; + } + + // Raise it to the top of the hiearchy + + m_menuWindow->raise(); +} + +/** + * Create the menu window + * + * @result True is returned on success + */ + +bool CMenus::createMenuWindow(void) +{ + // Create the menu window + // 1. Get the server instance. m_twm4nx inherits from NXWidgets::CNXServer + // so we all ready have the server instance. + // 2. Create the style, using the selected colors (REVISIT) + + // 3. Create a Widget control instance for the window using the default + // style for now. CWindowEvent derives from CWidgetControl. + + FAR CWindowEvent *control = new CWindowEvent(m_twm4nx); + + // 4. Create the menu window + + m_menuWindow = m_twm4nx->createFramedWindow(control); + if (m_menuWindow == (FAR NXWidgets::CNxTkWindow *)0) + { + delete control; + return false; + } + + // 5. Open and initialize the menu window + + bool success = m_menuWindow->open(); + if (!success) + { + delete m_menuWindow; + m_menuWindow = (FAR NXWidgets::CNxTkWindow *)0; + return false; + } + + // 6. Set the initial window size + + if (!setMenuWindowSize()) + { + delete m_menuWindow; + m_menuWindow = (FAR NXWidgets::CNxTkWindow *)0; + return false; + } + + // 7. Set the initial window position + + struct nxgl_point_s pos = + { + .x = 0, + .y = 0 + }; + + if (!m_menuWindow->setPosition(&pos)) + { + delete m_menuWindow; + m_menuWindow = (FAR NXWidgets::CNxTkWindow *)0; + return false; + } + + return true; +} + +/** + * Update the menu window size + * + * @result True is returned on success + */ + +bool CMenus::setMenuWindowSize(void) +{ + CFonts *fonts = m_twm4nx->getFonts(); + FAR NXWidgets::CNxFont *menuFont = fonts->getMenuFont(); + + m_entryHeight = menuFont->getHeight() + 4; + + // Get the length of the longest item string in in the menu + + nxgl_coord_t maxstring = 0; + for (FAR struct SMenuItem *curr = m_menuHead; + curr != NULL; + curr = curr->flink) + { + if (curr->text != (FAR char *)0) + { + nxgl_coord_t stringlen = menuFont->getStringWidth(curr->text); + if (stringlen > maxstring) + { + maxstring = stringlen; + } + } + } + + // Lets first size the window accordingly + + struct nxgl_size_s menuSize; + menuSize.w = maxstring + 10; + + unsigned int nMenuItems = m_nMenuItems > 0 ? m_nMenuItems : 1; + menuSize.h = nMenuItems * m_entryHeight; + + if (m_menuPull == true) + { + menuSize.w += 16; + } + + // Clip to the size of the display + + struct nxgl_size_s displaySize; + m_twm4nx->getDisplaySize(&displaySize); + + struct nxgl_size_s frameSize; + menuToFrameSize(&menuSize, &frameSize); + + if (frameSize.w > displaySize.w) + { + frameSize.w = displaySize.w; + } + + if (frameSize.h > displaySize.h) + { + frameSize.h = displaySize.h; + } + + // Set the new menu window size + + frameToMenuSize(&frameSize, &menuSize); + + if (!m_menuWindow->setSize(&menuSize)) + { + gerr("ERROR: Failed to set window size\n"); + return false; + } + + return true; +} + +/** + * Set the position of the menu window. Supports positioning of a + * pop-up window. + * + * @param framePos The position of the menu window frame + * @result True is returned on success + */ + +bool CMenus::setMenuWindowPosition(FAR struct nxgl_point_s *framePos) +{ + struct nxgl_point_s menuPos; + frameToMenuPos(framePos, &menuPos); + return m_menuWindow->setPosition(&menuPos); +} + +/** + * Create the menu list box + * + * @result True is returned on success + */ + +bool CMenus::createMenuListBox(void) +{ + // Create the menu list box + // 1. Get the server instance. m_twm4nx inherits from NXWidgets::CNXServer + // so we all ready have the server instance. + // 2. Create the style, using the selected colors (REVISIT) + + // 3. Create a Widget control instance for the window using the default + // style for now. CWindowEvent derives from CWidgetControl. + + FAR CWindowEvent *control = new CWindowEvent(m_twm4nx); + + // 4. Create the menu list box + + struct nxgl_point_s pos; + pos.x = 0; + pos.y = 0; + + struct nxgl_size_s size; + pos.x = 0; + pos.y = 0; + + m_menuListBox = new NXWidgets::CListBox(control, pos.x, pos.y, + size.w, size.h); + if (m_menuListBox == (FAR NXWidgets::CListBox *)0) + { + gerr("ERROR: Failed to instantiate list box\n"); + delete control; + return false; + } + + // Configure the list box + + m_menuListBox->disable(); + m_menuListBox->disableDrawing(); + m_menuListBox->disableDrawing(); + + // Register to get events from the mouse clicks on the image + + m_menuListBox->addWidgetEventHandler(this); + return true; +} + +/** + * Pop up a pull down menu. + * + * @param pos Location of upper left of menu frame + */ + +bool CMenus::popUpMenu(FAR struct nxgl_point_s *pos) +{ + // If there is already a popup menu, then delete it. We only permit + // one popup at this level. + + if (m_popUpMenu != (FAR CMenus *)0) + { + delete m_popUpMenu; + } + + // Create and initialize a new menu + + m_popUpMenu = new CMenus(m_twm4nx); + if (m_popUpMenu == (FAR CMenus *)0) + { + gerr("ERROR: Failed to create popup menu.\n"); + return false; + } + + if (!m_popUpMenu->initialize(m_activeItem->text)) + { + gerr("ERROR: Failed to intialize popup menu.\n"); + delete m_popUpMenu; + m_popUpMenu = (FAR CMenus *)0; + return false; + } + + m_popUpMenu->addMenuItem("TWM Windows", (FAR const char *)0, + (FAR CMenus *)0, 0); + + FAR CWindowFactory *factory = m_twm4nx->getWindowFactory(); + int nWindowNames; + + FAR struct SWindow *swin; + for (swin = factory->windowHead(), nWindowNames = 0; + swin != NULL; swin = swin->flink) + { + nWindowNames++; + } + + if (nWindowNames != 0) + { + FAR CWindow **windowNames = + (FAR CWindow **)std::malloc(sizeof(FAR CWindow *) * nWindowNames); + + if (windowNames == (FAR CWindow **)0) + { + gerr("ERROR: Failed to allocat window name\n"); + return false; + } + + swin = factory->windowHead(); + windowNames[0] = swin->cwin; + + for (nWindowNames = 1; + swin != NULL; + swin = swin->flink, nWindowNames++) + { + FAR CWindow *tmpcwin1 = swin->cwin; + for (int i = 0; i < nWindowNames; i++) + { + FAR const char *windowName1 = tmpcwin1->getWindowName(); + FAR const char *windowName2 = windowNames[i]->getWindowName(); + + if (std::strcmp(windowName1, windowName2) < 0) + { + FAR CWindow *tmpcwin2; + tmpcwin2 = tmpcwin1; + tmpcwin1 = windowNames[i]; + windowNames[i] = tmpcwin2; + } + } + + windowNames[nWindowNames] = tmpcwin1; + } + + for (int i = 0; i < nWindowNames; i++) + { + m_popUpMenu->addMenuItem(windowNames[i]->getWindowName(), + (FAR const char *)0, (FAR CMenus *)0, + EVENT_WINDOW_POPUP); + } + + std::free(windowNames); + } + + if (m_nMenuItems == 0) + { + delete m_popUpMenu; + m_popUpMenu = (FAR CMenus *)0; + return false; + } + + // Clip to screen + + struct nxgl_size_s displaySize; + m_twm4nx->getDisplaySize(&displaySize); + + struct nxgl_size_s menuSize; + m_menuWindow->getSize(&menuSize); + + struct nxgl_size_s frameSize; + menuToFrameSize(&menuSize, &frameSize); + + if (pos->x + frameSize.w > displaySize.w) + { + pos->x = displaySize.w - frameSize.w; + } + + if (pos->x < 0) + { + pos->x = 0; + } + + if (pos->y + frameSize.h > displaySize.h) + { + pos->y = displaySize.h - frameSize.h; + } + + if (pos->y < 0) + { + pos->y = 0; + } + + DEBUGASSERT(m_menuDepth < UINT8_MAX); + m_menuDepth++; + + if (!m_popUpMenu->setMenuWindowPosition(pos)) + { + delete m_popUpMenu; + m_popUpMenu = (FAR CMenus *)0; + return false; + } + + m_popUpMenu->raiseMenuWindow(); + m_menuWindow->synchronize(); + return m_popUpMenu; +} + +/** + * Cleanup or initialization error or on deconstruction. + */ + +void CMenus::cleanup(void) +{ + // Close the NxWidget event message queue + + if (m_eventq != (mqd_t)-1) + { + (void)mq_close(m_eventq); + m_eventq = (mqd_t)-1; + } + + // Free any popup menus + + if (m_popUpMenu != (FAR CMenus *)0) + { + delete m_popUpMenu; + } + + // Free the menu window + + if (m_menuWindow != (FAR NXWidgets::CNxTkWindow *)0) + { + delete m_menuWindow; + m_menuWindow = (FAR NXWidgets::CNxTkWindow *)0; + } + + // Free each menu item + + FAR struct SMenuItem *curr; + FAR struct SMenuItem *next; + + for (curr = m_menuHead; curr != (FAR struct SMenuItem *)0; curr = next) + { + next = curr->flink; + + // Free the menu item text + + if (curr->text != (FAR char *)0) + { + std::free(curr->text); + } + + // Free any subMenu + + if (curr->subMenu != (FAR CMenus *)0) + { + delete curr->subMenu; + } + + // Free the menu item + + delete curr; + } + + // Free allocated memory + + if (m_menuName != (FAR char *)0) + { + std::free(m_menuName); + m_menuName = (FAR char *)0; + } +} diff --git a/graphics/twm4nx/src/cresize.cxx b/graphics/twm4nx/src/cresize.cxx new file mode 100644 index 000000000..74132b333 --- /dev/null +++ b/graphics/twm4nx/src/cresize.cxx @@ -0,0 +1,1080 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/src/cresize.cxx +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// Copyright 1988 by Evans & Sutherland Computer Corporation, +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 + +#include "graphics/nxwidgets/cnxfont.hxx" + +#include "graphics/twm4nx/twm4nx_config.hxx" +#include "graphics/twm4nx/ctwm4nx.hxx" +#include "graphics/twm4nx/cmenus.hxx" +#include "graphics/twm4nx/cresize.hxx" +#include "graphics/twm4nx/ciconmgr.hxx" +#include "graphics/twm4nx/cwindowevent.hxx" +#include "graphics/twm4nx/cfonts.hxx" +#include "graphics/twm4nx/cwindow.hxx" + +///////////////////////////////////////////////////////////////////////////// +// Pre-processor Definitions +///////////////////////////////////////////////////////////////////////////// + +#define MINHEIGHT 0 // had been 32 +#define MINWIDTH 0 // had been 60 + +#define makemult(a,b) ((b==1) ? (a) : (((int)((a) / (b))) * (b))) + +#ifndef MIN +# define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +///////////////////////////////////////////////////////////////////////////// +// Class Implementations +///////////////////////////////////////////////////////////////////////////// + +using namespace Twm4Nx; + +/** + * CResize Constructor + */ + +CResize::CResize(CTwm4Nx *twm4nx) +{ + // Save the Twm4Nx session + + m_twm4nx = twm4nx; + + // Windows + + m_sizeWindow = (FAR NXWidgets::CNxTkWindow *)0; + + // Strings + + m_stringWidth = 0; +} + +/** + * CResize Destructor + */ + +CResize::~CResize(void) +{ + // Free the resize dimensions window + + if (m_sizeWindow != (FAR NXWidgets::CNxTkWindow *)0) + { + delete m_sizeWindow; + m_sizeWindow = (FAR NXWidgets::CNxTkWindow *)0; + } +} + +/** + * CResize Initializer. Performs the parts of the CResize construction + * that may fail. + * + * @result True is returned on success + */ + +bool CResize::initialize(void) +{ + // Create the main window + // 1. Get the server instance. m_twm4nx inherits from NXWidgets::CNXServer + // so we all ready have the server instance. + // 2. Create the style, using the selected colors (REVISIT) + + // 3. Create a Widget control instance for the window using the default + // style for now. CWindowEvent derives from CWidgetControl. + + FAR CWindowEvent *control = new CWindowEvent(m_twm4nx); + + // 4. Create the main window + + m_sizeWindow = m_twm4nx->createFramedWindow(control); + if (m_sizeWindow == (FAR NXWidgets::CNxTkWindow *)0) + { + delete control; + return false; + } + + // 5. Open and initialize the main window + + bool success = m_sizeWindow->open(); + if (!success) + { + delete m_sizeWindow; + m_sizeWindow = (FAR NXWidgets::CNxTkWindow *)0; + return false; + } + + // 6. Set the initial window size + + // Create the resize dimension window + + FAR CFonts *fonts = m_twm4nx->getFonts(); + FAR NXWidgets::CNxFont *sizeFont = fonts->getSizeFont(); + + m_stringWidth = sizeFont->getStringWidth(" 8888 x 8888 "); + + struct nxgl_size_s size; + size.w = m_stringWidth, + size.h = (sizeFont->getHeight() + CONFIG_TWM4NX_ICONMGR_VSPACING * 2); + + if (!m_sizeWindow->setSize(&size)) + { + delete m_sizeWindow; + m_sizeWindow = (FAR NXWidgets::CNxTkWindow *)0; + return false; + } + + // 7. Set the initial window position + + struct nxgl_point_s pos = + { + .x = 0, + .y = 0 + }; + + if (!m_sizeWindow->setPosition(&pos)) + { + delete m_sizeWindow; + m_sizeWindow = (FAR NXWidgets::CNxTkWindow *)0; + return false; + } + + return true; +} + +void CResize::resizeFromCenter(FAR CWindow *cwin) +{ + // Get the current frame size and position + + struct nxgl_point_s winpos; + if (!cwin->getFramePosition(&winpos)) + { + return; + } + + struct nxgl_size_s winsize; + if (!cwin->getFrameSize(&winsize)) + { + return; + } + + FAR CResize *resize = m_twm4nx->getResize(); + resize->addingSize(&winsize); + + resize->menuStartResize(cwin, &winpos, &winsize); +} + +/** + * Begin a window resize operation + * + * @param ev the event structure (button press) + * @param cwin the TWM window pointer + */ + +void CResize::startResize(FAR struct SEventMsg *eventmsg, FAR CWindow *cwin) +{ + m_resizeWindow = cwin; + + // Get the current position and size + + if (!cwin->getFramePosition(&m_dragpos)) + { + return; + } + + if (!cwin->getFrameSize(&m_dragsize)) + { + return; + } + + m_dragpos.x += 0; + m_dragpos.y += 0; + m_origpos.x = m_dragpos.x; + m_origpos.y = m_dragpos.y; + m_origsize.w = m_dragsize.w; + m_origsize.h = m_dragsize.h; + m_clamp.pt1.y = 0; + m_clamp.pt2.y = 0; + m_clamp.pt1.x = 0; + m_clamp.pt2.x = 0; + m_delta.x = 0; + m_delta.y = 0; + +#ifdef CONFIG_TWM4NX_AUTO_RERESIZE // Resize relative to position in quad + autoClamp(cwin, eventmsg); +#endif + + FAR CFonts *fonts = m_twm4nx->getFonts(); + FAR NXWidgets::CNxFont *sizeFont = fonts->getSizeFont(); + + struct nxgl_size_s size; + size.w = m_stringWidth + CONFIG_TWM4NX_ICONMGR_HSPACING * 2; + size.h = sizeFont->getHeight() + CONFIG_TWM4NX_ICONMGR_VSPACING * 2; + + // Set the window size + + if (!m_sizeWindow->setSize(&size)) + { + return; + } + + // Move the window to the top of the hierarchy + + m_sizeWindow->raise(); + + m_last.w = 0; + m_last.h = 0; + + displaySize(cwin, &m_origsize); + + // Set the new frame position and size + + if (!cwin->resizeFrame(&m_dragsize, &m_dragpos)) + { + gerr("ERROR: Failed to resize frame\n"); + } +} + +void CResize::menuStartResize(FAR CWindow *cwin, + FAR struct nxgl_point_s *pos, + FAR struct nxgl_size_s *size) +{ + m_dragpos.x = pos->x; + m_dragpos.y = pos->y; + m_origpos.x = m_dragpos.x; + m_origpos.y = m_dragpos.y; + m_origsize.w = size->w; + m_origsize.h = size->h; + m_dragsize.w = size->w; + m_dragsize.h = size->h; + m_clamp.pt1.x = 0; + m_clamp.pt1.y = 0; + m_clamp.pt2.x = 0; + m_clamp.pt2.y = 0; + m_delta.x = 0; + m_delta.y = 0; + m_last.w = 0; + m_last.h = 0; + + FAR CFonts *fonts = m_twm4nx->getFonts(); + FAR NXWidgets::CNxFont *sizeFont = fonts->getSizeFont(); + + // Set the window size + + struct nxgl_size_s winsize; + winsize.w = m_stringWidth + CONFIG_TWM4NX_ICONMGR_HSPACING * 2; + winsize.h = sizeFont->getHeight() + CONFIG_TWM4NX_ICONMGR_VSPACING * 2; + + if (!m_sizeWindow->setSize(&winsize)) + { + return; + } + + // Move the size window it to the top of the hieararchy + + m_sizeWindow->raise(); + displaySize(cwin, &m_origsize); + + // Set the new frame position and size + + if (!cwin->resizeFrame(&m_dragsize, &m_dragpos)) + { + gerr("ERROR: Failed to resize frame\n"); + } +} + +/** + * Begin a window resize operation + * + * @param cwin the Twm4Nx window pointer + */ + +void CResize::addStartResize(FAR CWindow *cwin, + FAR struct nxgl_point_s *pos, + FAR struct nxgl_size_s *size) +{ + m_dragpos.x = pos->x; + m_dragpos.y = pos->y; + m_origpos.x = m_dragpos.x; + m_origpos.y = m_dragpos.y; + m_origsize.w = size->w; + m_origsize.h = size->h; + m_dragsize.w = m_origsize.w; + m_dragsize.h = m_origsize.h; + + m_clamp.pt1.x = 0; + m_clamp.pt1.y = 0; + m_clamp.pt2.x = 0; + m_clamp.pt2.y = 0; + m_delta.x = 0; + m_delta.y = 0; + m_last.w = 0; + m_last.h = 0; + + m_last.w = 0; + m_last.h = 0; + displaySize(cwin, &m_origsize); +} + +/** + * @param cwin The current Twm4Nx window + * @param root The X position in the root window + */ + +void CResize::menuDoResize(FAR CWindow *cwin, + FAR struct nxgl_point_s *root) +{ + int action; + + action = 0; + + root->x -= m_delta.x; + root->y -= m_delta.y; + + if (m_clamp.pt1.y) + { + int delta = root->y - m_dragpos.y; + if (m_dragsize.h - delta < MINHEIGHT) + { + delta = m_dragsize.h - MINHEIGHT; + m_clamp.pt1.y = 0; + } + + m_dragpos.y += delta; + m_dragsize.h -= delta; + action = 1; + } + else if (root->y <= m_dragpos.y) + { + m_dragpos.y = root->y; + m_dragsize.h = m_origpos.y + m_origsize.h - root->y; + m_clamp.pt2.y = 0; + m_clamp.pt1.y = 1; + m_delta.y = 0; + action = 1; + } + + if (m_clamp.pt1.x) + { + int delta = root->x - m_dragpos.x; + if (m_dragsize.w - delta < MINWIDTH) + { + delta = m_dragsize.w - MINWIDTH; + m_clamp.pt1.x = 0; + } + + m_dragpos.x += delta; + m_dragsize.w -= delta; + action = 1; + } + else if (root->x <= m_dragpos.x) + { + m_dragpos.x = root->x; + m_dragsize.w = m_origpos.x + m_origsize.w - root->x; + m_clamp.pt2.x = 0; + m_clamp.pt1.x = 1; + m_delta.x = 0; + action = 1; + } + + if (m_clamp.pt2.y) + { + int delta = root->y - m_dragpos.y - m_dragsize.h; + if (m_dragsize.h + delta < MINHEIGHT) + { + delta = MINHEIGHT - m_dragsize.h; + m_clamp.pt2.y = 0; + } + + m_dragsize.h += delta; + action = 1; + } + else if (root->y >= m_dragpos.y + m_dragsize.h) + { + m_dragpos.y = m_origpos.y; + m_dragsize.h = 1 + root->y - m_dragpos.y; + m_clamp.pt1.y = 0; + m_clamp.pt2.y = 1; + m_delta.y = 0; + action = 1; + } + + if (m_clamp.pt2.x) + { + int delta = root->x - m_dragpos.x - m_dragsize.w; + if (m_dragsize.w + delta < MINWIDTH) + { + delta = MINWIDTH - m_dragsize.w; + m_clamp.pt2.x = 0; + } + + m_dragsize.w += delta; + action = 1; + } + else if (root->x >= m_dragpos.x + m_dragsize.w) + { + m_dragpos.x = m_origpos.x; + m_dragsize.w = 1 + root->x - m_origpos.x; + m_clamp.pt1.x = 0; + m_clamp.pt2.x = 1; + m_delta.x = 0; + action = 1; + } + + if (action) + { + constrainSize(cwin, &m_dragsize); + if (m_clamp.pt1.x) + { + m_dragpos.x = m_origpos.x + m_origsize.w - m_dragsize.w; + } + + if (m_clamp.pt1.y) + { + m_dragpos.y = m_origpos.y + m_origsize.h - m_dragsize.h; + } + + // Set the new frame position and size + + if (!cwin->resizeFrame(&m_dragsize, &m_dragpos)) + { + gerr("ERROR: Failed to resize frame\n"); + } + } + + displaySize(cwin, &m_dragsize); +} + +/** + * Move the rubberband around. This is called for each motion event when + * we are resizing + * + * @param cwin The current Twm4Nx window + * @param root The X position in the root window + */ + +void CResize::doResize(FAR CWindow *cwin, + FAR struct nxgl_point_s *root) +{ + int action; + + action = 0; + + root->x -= m_delta.x; + root->y -= m_delta.y; + + if (m_clamp.pt1.y) + { + int delta = root->y - m_dragpos.y; + if (m_dragsize.h - delta < MINHEIGHT) + { + delta = m_dragsize.h - MINHEIGHT; + m_clamp.pt1.y = 0; + } + + m_dragpos.y += delta; + m_dragsize.h -= delta; + action = 1; + } + else if (root->y <= m_dragpos.y) + { + m_dragpos.y = root->y; + m_dragsize.h = m_origpos.y + m_origsize.h - root->y; + m_clamp.pt2.y = 0; + m_clamp.pt1.y = 1; + m_delta.y = 0; + action = 1; + } + + if (m_clamp.pt1.x) + { + int delta = root->x - m_dragpos.x; + if (m_dragsize.w - delta < MINWIDTH) + { + delta = m_dragsize.w - MINWIDTH; + m_clamp.pt1.x = 0; + } + + m_dragpos.x += delta; + m_dragsize.w -= delta; + action = 1; + } + else if (root->x <= m_dragpos.x) + { + m_dragpos.x = root->x; + m_dragsize.w = m_origpos.x + m_origsize.w - root->x; + m_clamp.pt2.x = 0; + m_clamp.pt1.x = 1; + m_delta.x = 0; + action = 1; + } + + if (m_clamp.pt2.y) + { + int delta = root->y - m_dragpos.y - m_dragsize.h; + if (m_dragsize.h + delta < MINHEIGHT) + { + delta = MINHEIGHT - m_dragsize.h; + m_clamp.pt2.y = 0; + } + + m_dragsize.h += delta; + action = 1; + } + else if (root->y >= m_dragpos.y + m_dragsize.h - 1) + { + m_dragpos.y = m_origpos.y; + m_dragsize.h = 1 + root->y - m_dragpos.y; + m_clamp.pt1.y = 0; + m_clamp.pt2.y = 1; + m_delta.y = 0; + action = 1; + } + + if (m_clamp.pt2.x) + { + int delta = root->x - m_dragpos.x - m_dragsize.w; + if (m_dragsize.w + delta < MINWIDTH) + { + delta = MINWIDTH - m_dragsize.w; + m_clamp.pt2.x = 0; + } + + m_dragsize.w += delta; + action = 1; + } + else if (root->x >= m_dragpos.x + m_dragsize.w - 1) + { + m_dragpos.x = m_origpos.x; + m_dragsize.w = 1 + root->x - m_origpos.x; + m_clamp.pt1.x = 0; + m_clamp.pt2.x = 1; + m_delta.x = 0; + action = 1; + } + + if (action) + { + constrainSize(cwin, &m_dragsize); + if (m_clamp.pt1.x) + { + m_dragpos.x = m_origpos.x + m_origsize.w - m_dragsize.w; + } + + if (m_clamp.pt1.y) + { + m_dragpos.y = m_origpos.y + m_origsize.h - m_dragsize.h; + } + + // Set the new frame position and size + + if (!cwin->resizeFrame(&m_dragsize, &m_dragpos)) + { + gerr("ERROR: Failed to resize frame\n"); + } + } + + displaySize(cwin, &m_dragsize); +} + +/** + * Finish the resize operation + */ + +void CResize::endResize(FAR CWindow *cwin) +{ + struct nxgl_point_s pos = + { + .x = 0, + .y = 0 + }; + + struct nxgl_size_s size = + { + .w = 0, + .h = 0 + }; + + if (!cwin->resizeFrame(&size, &pos)) + { + gerr("ERROR: Failed to resize frame\n"); + } + + constrainSize(cwin, &m_dragsize); + + struct nxgl_size_s framesize; + cwin->getFrameSize(&framesize); + + if (m_dragsize.w != framesize.w || m_dragsize.h != framesize.h) + { + cwin->setZoom(ZOOM_NONE); + } + + setupWindow(cwin, &m_dragpos, &m_dragsize); + + if (cwin->isIconMgr()) + { + CIconMgr *iconMgr = cwin->getIconMgr(); + DEBUGASSERT(iconMgr != (CIconMgr *)0); + + unsigned int currcol = iconMgr->getCurrColumn(); + if (currcol == 0) + { + currcol = 1; + } + + struct nxgl_size_s iconMgrSize; + iconMgr->getSize(&iconMgrSize); + + iconMgrSize.w = (unsigned int) + ((m_dragsize.w * (unsigned long)iconMgr->getColumns()) / currcol); + + cwin->resizeFrame(&iconMgrSize, &pos); + iconMgr->pack(); + } + + cwin->raiseWindow(); + m_resizeWindow = (FAR CWindow *)0; +} + +void CResize::menuEndResize(FAR CWindow *cwin) +{ + struct nxgl_point_s pos = + { + .x = 0, + .y = 0 + }; + + struct nxgl_size_s size = + { + .w = 0, + .h = 0 + }; + + // Set the window frame size (and position) + + if (!cwin->resizeFrame(&size, &pos)) + { + gerr("ERROR: CWindow::resizeFrame() failed\n"); + } + + constrainSize(cwin, &m_dragsize); + setupWindow(cwin, &m_dragpos, &m_dragsize); +} + +/** + * Finish the resize operation for AddWindowindowToFrameSize(&nullSize, &minSize); + + // Clip to minimim size + + if (size->w < minSize.w) + { + size->w = minSize.w; + } + + if (size->h < minSize.h) + { + size->h = minSize.h; + } + + // Get the maximum window size from CTwm4Nx + + struct nxgl_size_s maxSize; + m_twm4nx->maxWindowSize(&maxSize); + + // Clip to maximim size + + if (size->w > maxSize.w) + { + size->w = maxSize.w; + } + + if (size->h > maxSize.h) + { + size->h = maxSize.h; + } +} + +/** + * Set window sizes. + * + * Special Considerations: + * This routine will check to make sure the window is not completely off the + * display, if it is, it'll bring some of it back on. + * + * The cwin->frame_XXX variables should NOT be updated with the values of + * x,y,w,h prior to calling this routine, since the new values are compared + * against the old to see whether a synthetic ConfigureNotify event should be + * sent. (It should be sent if the window was moved but not resized.) + * + * @param cwin The CWindow instance + * @param pos The position of the upper-left outer corner of the frame + * @param size The size of the frame window + */ + +void CResize::setupWindow(FAR CWindow *cwin, FAR nxgl_point_s *pos, + FAR nxgl_size_s *size) +{ + ginfo("pos={%d, %d} size={%d, %d}\n", + pos->x, pos->y, size->w, size->h); + + // Clip the position the so that it is within the display (with a little + // extra space for the cursor) + + struct nxgl_size_s displaySize; + m_twm4nx->getDisplaySize(&displaySize); + + if (pos->x >= displaySize.w - 16) + { + pos->x = displaySize.w - 16; // one "average" cursor width + } + + if (pos->y >= displaySize.h - 16) + { + pos->y = displaySize.h - 16; // one "average" cursor width + } + + if (cwin->isIconMgr()) + { + struct nxgl_size_s imsize; + cwin->getFrameSize(&imsize); + size->h = imsize.h; + } + + // Set the window frame size (and position) + + if (!cwin->resizeFrame(size, pos)) + { + gerr("ERROR: CWindow::resizeFrame() failed\n"); + } +} + +/** + * Zooms window to full height of screen or to full height and width of screen. + * (Toggles so that it can undo the zoom - even when switching between fullZoom + * and vertical zoom.) + * + * @param cwin the TWM window pointer + */ + +void CResize::fullZoom(FAR CWindow *cwin, int flag) +{ + // Get the current position and size + + if (!cwin->getFramePosition(&m_dragpos)) + { + return; + } + + if (!cwin->getFrameSize(&m_dragsize)) + { + return; + } + + struct nxgl_point_s base; + base.x = 0; + base.y = 0; + + uint16_t zoom = cwin->getZoom(); + if (zoom == flag) + { + cwin->getFramePosition(&m_dragpos); + cwin->getFrameSize(&m_dragsize); + cwin->setZoom(ZOOM_NONE); + } + else + { + if (zoom == ZOOM_NONE) + { + cwin->resizeFrame(&m_dragsize, &m_dragpos); + } + + cwin->setZoom(flag); + + struct nxgl_size_s displaySize; + m_twm4nx->getDisplaySize(&displaySize); + + switch (flag) + { + case ZOOM_NONE: + break; + + case EVENT_RESIZE_VERTZOOM: + m_dragsize.h = displaySize.h; + m_dragpos.y = base.y; + break; + + case EVENT_RESIZE_HORIZOOM: + m_dragpos.x = base.x; + m_dragsize.w = displaySize.w; + break; + + case EVENT_RESIZE_FULLZOOM: + m_dragpos.x = base.x; + m_dragpos.y = base.y; + m_dragsize.h = displaySize.h; + m_dragsize.w = displaySize.w; + break; + + case EVENT_RESIZE_LEFTZOOM: + m_dragpos.x = base.x; + m_dragpos.y = base.y; + m_dragsize.h = displaySize.h; + m_dragsize.w = displaySize.w / 2; + break; + + case EVENT_RESIZE_RIGHTZOOM: + m_dragpos.x = base.x + displaySize.w / 2; + m_dragpos.y = base.y; + m_dragsize.h = displaySize.h; + m_dragsize.w = displaySize.w / 2; + break; + + case EVENT_RESIZE_TOPZOOM: + m_dragpos.x = base.x; + m_dragpos.y = base.y; + m_dragsize.h = displaySize.h / 2; + m_dragsize.w = displaySize.w; + break; + + case EVENT_RESIZE_BOTTOMZOOM: + m_dragpos.x = base.x; + m_dragpos.y = base.y + displaySize.h / 2; + m_dragsize.h = displaySize.h / 2; + m_dragsize.w = displaySize.w; + break; + } + } + + cwin->raiseWindow(); + constrainSize(cwin, &m_dragsize); + setupWindow(cwin, &m_dragpos, &m_dragsize); +} + +/** + * Handle RESIZE events. + * + * @param eventmsg. The received NxWidget RESIZE event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + +bool CResize::event(FAR struct SEventMsg *eventmsg) +{ + bool success = true; + + switch (eventmsg->eventID) + { + case EVENT_RESIZE_START: // Start window resize + { + // Can't resize icons + + FAR CWindow *cwin = (FAR CWindow *)eventmsg->obj; + DEBUGASSERT(cwin != (FAR CWindow *)0); + + if (cwin->isIconMgr()) + { + // Check for resize from a menu + + if (eventmsg->context == EVENT_CONTEXT_FRAME || + eventmsg->context == EVENT_CONTEXT_WINDOW || + eventmsg->context == EVENT_CONTEXT_TITLE) + { + resizeFromCenter(cwin); + } + else + { + startResize(eventmsg, cwin); + } + } + } + break; + + case EVENT_RESIZE_VERTZOOM: // Zoom vertically only + case EVENT_RESIZE_HORIZOOM: // Zoom horizontally only + case EVENT_RESIZE_FULLZOOM: // Zoom both vertically and horizontally + case EVENT_RESIZE_LEFTZOOM: // Zoom left only + case EVENT_RESIZE_RIGHTZOOM: // Zoom right only + case EVENT_RESIZE_TOPZOOM: // Zoom top only + case EVENT_RESIZE_BOTTOMZOOM: // Zoom bottom only + fullZoom((FAR CWindow *)eventmsg->obj, eventmsg->eventID); + break; + + default: + success = false; + break; + } + + return success; +} + +#ifdef CONFIG_TWM4NX_AUTO_RERESIZE // Resize relative to position in quad +void CResize::autoClamp(FAR CWindow *cwin, + FAR struct SEventMsg *eventmsg *eventmsg) +{ + FAR NXWidgets::CNxTkWindow *root; + struct nxgl_point_s pos; + int h; + int v; + unsigned int mask; + + switch (eventmsg->type) + { + case ButtonPress: + pos.x = eventmsg->pos.x; + pos.y = eventmsg->pos.y; + break; + + case KeyPress: + pos.x = eventmsg->pos.x; + pos.y = eventmsg->pos.y; + break; + + default: + // Root window position + + root.x = 0; // REVISIT + root.y = 0; + + // Relative window position + + if (!xxx->getPosition(&pos)) + { + return; + } + } + + h = ((pos.x - m_dragpos.x) / (m_dragsize.w < 3 ? 1 : (m_dragsize.w / 3))); + v = ((pos.y - m_dragpos.y) / (m_dragsize.h < 3 ? 1 : (m_dragsize.h / 3))); + + if (h <= 0) + { + m_clamp.pt1.x = 1; + m_delta.x = (pos.x - m_dragpos.x); + } + else if (h >= 2) + { + m_clamp.pt2.x = 1; + m_delta.x = (pos.x - m_dragpos.x - m_dragsize.w); + } + + if (v <= 0) + { + m_clamp.pt1.y = 1; + m_delta.y = (pos.y - m_dragpos.y); + } + else if (v >= 2) + { + m_clamp.pt2.y = 1; + m_delta.y = (pos.y - m_dragpos.y - m_dragsize.h); + } +} +#endif + +/** + * Display the size in the dimensions window. + * + * @param cwin The current window being resize + * @param size She size of the rubber band + */ + +void CResize::displaySize(FAR CWindow *cwin, FAR struct nxgl_size_s *size) +{ + if (m_last.w == size->w && m_last.h == size->h) + { + return; + } + + m_last.w = size->w; + m_last.h = size->h; + + char str[100]; + (void)snprintf(str, sizeof(str), " %4d x %-4d ", size->w, size->h); + + m_sizeWindow->raise(); + +#warning Missing logic +#if 0 + FAR CFonts *fonts = m_twm4nx->getFonts(); + FAR NXWidgets::CNxFont *sizeFont = fonts->getSizeFont(); + + // Show the string in the CLable in the size window + + // REVISIT: This no longer exists + fonts->renderString(m_twm4nx, m_sizeWindow, sizeFont, + CONFIG_TWM4NX_ICONMGR_HSPACING, + sizeFont->getHeight() + CONFIG_TWM4NX_ICONMGR_VSPACING, str); +#endif +} diff --git a/graphics/twm4nx/src/ctwm4nx.cxx b/graphics/twm4nx/src/ctwm4nx.cxx new file mode 100644 index 000000000..18e008254 --- /dev/null +++ b/graphics/twm4nx/src/ctwm4nx.cxx @@ -0,0 +1,596 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/src/ctwm4nx.cxx +// Twm4Nx - "Tom's Window Manager" for the NuttX NX Server +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// Copyright 1988 by Evans & Sutherland Computer Corporation, +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "platform/cxxinitialize.h" + +#include "graphics/twm4nx/twm4nx_config.hxx" +#include "graphics/twm4nx/ctwm4nx.hxx" +#include "graphics/twm4nx/cbackground.hxx" +#include "graphics/twm4nx/cwindow.hxx" +#include "graphics/twm4nx/cwindowfactory.hxx" +#include "graphics/twm4nx/cwindowevent.hxx" +#include "graphics/twm4nx/cinput.hxx" +#include "graphics/twm4nx/cicon.hxx" +#include "graphics/twm4nx/ciconwin.hxx" +#include "graphics/twm4nx/ciconmgr.hxx" +#include "graphics/twm4nx/cmenus.hxx" +#include "graphics/twm4nx/cresize.hxx" +#include "graphics/twm4nx/cfonts.hxx" +#include "graphics/twm4nx/twm4nx_widgetevents.hxx" + +///////////////////////////////////////////////////////////////////////////// +// Pre-processor Definitions +///////////////////////////////////////////////////////////////////////////// + +#define DEFAULT_NICE_FONT "variable" +#define DEFAULT_FAST_FONT "fixed" + +///////////////////////////////////////////////////////////////////////////// +// Public Function Prototypes +///////////////////////////////////////////////////////////////////////////// + +// Suppress name-mangling + +#ifdef BUILD_MODULE +extern "C" int main(int argc, FAR char *argv[]); +#else +extern "C" int twm4nx_main(int argc, char *argv[]); +#endif + +///////////////////////////////////////////////////////////////////////////// +// Public Data +///////////////////////////////////////////////////////////////////////////// + +using namespace Twm4Nx; + +const char Twm4Nx::GNoName[] = "Untitled"; // Name if no name is specified + +///////////////////////////////////////////////////////////////////////////// +// CTwm4Nx Implementation +///////////////////////////////////////////////////////////////////////////// + +/** + * CTwm4Nx Constructor + * + * @param display. Indicates which display will be used. Usually zero + * except in the case wehre there of multiple displays. + */ + +CTwm4Nx::CTwm4Nx(int display) +{ + m_display = display; + m_eventq = (mqd_t)-1; + m_background = (FAR CBackground *)0; + m_input = (FAR CInput *)0; + m_icon = (FAR CIcon *)0; + m_iconmgr = (FAR CIconMgr *)0; + m_factory = (FAR CWindowFactory *)0; + m_fonts = (FAR CFonts *)0; + m_resize = (FAR CResize *)0; +} + +/** + * CTwm4Nx Destructor + */ + +CTwm4Nx::~CTwm4Nx(void) +{ + cleanup(); +} + +/** + * This is the main, controlling thread of the window manager. It is + * called only from the extern "C" main() entry point. + * + * NOTE: In the event of truly abnormal conditions, this function will + * not return. It will exit via the abort() method. + * + * @return True if the window manager was terminated properly. false is + * return on any failure. + */ + +bool CTwm4Nx::run(void) +{ + // Open a message queue to receive NxWidget-related events. We need to + // do this early so that the messasge queue name will be available to + // constructors + + genMqName(); // Generate a random message queue name + m_eventq = mq_open(m_queueName, O_RDONLY | O_CREAT, 0666); + if (m_eventq == (mqd_t)-1) + { + gerr("ERROR: Failed open message queue '%s': %d\n", + m_queueName, errno); + cleanup(); + return false; + } + +#if defined(CONFIG_HAVE_CXX) && defined(CONFIG_HAVE_CXXINITIALIZE) + // Call all C++ static constructors + + up_cxxinitialize(); +#endif + +#if defined(CONFIG_LIB_BOARDCTL) && !defined(CONFIG_BOARD_LATE_INITIALIZE) + // Should we perform board-specific initialization? There are two ways + // that board initialization can occur: 1) automatically via + // board_late_initialize() during bootup if CONFIG_BOARD_LATE_INITIALIZE, or + // 2) here via a call to boardctl() if the interface is enabled + // (CONFIG_LIB_BOARDCTL=y). + + (void)boardctl(BOARDIOC_INIT, 0); +#endif + + // Connect to the NX server + + if (!connect()) + { + gerr("ERROR: Failed to connect to the NX server\n"); + cleanup(); + return false; + } + + // Get the background up as soon as possible + + m_background = new CBackground(this); + if (m_background == (FAR CBackground *)0) + { + gerr("ERROR: Failed to create CBackground\n"); + cleanup(); + return false; + } + + // Paint the background image + + if (!m_background->setBackgroundImage(&CONFIG_TWM4NX_BACKGROUND_IMAGE)) + { + gerr("ERROR: Failed to set backgournd image\n"); + cleanup(); + return false; + } + + // Get the size of the display (which is equivalent to size of the + // background window). + + m_background->getDisplaySize(m_displaySize); + + DEBUGASSERT((unsigned int)m_displaySize.w <= INT16_MAX && + (unsigned int)m_displaySize.h <= INT16_MAX); + + m_maxWindow.w = INT16_MAX - m_displaySize.w; + m_maxWindow.h = INT16_MAX - m_displaySize.w; + + // Create the keyboard/mouse input device thread + + m_input = new CInput(this); + if (m_input == (CInput *)0) + { + gerr("ERROR: Failed to create CInput\n"); + cleanup(); + return false; + } + + if (!m_input->start()) + { + gerr("ERROR: Failed start the keyboard/mouse listener\n"); + cleanup(); + return false; + } + + // Create the Icon Manager + + m_iconmgr = new CIconMgr(this, 4); + if (m_iconmgr == (CIconMgr *)0) + { + cleanup(); + return false; + } + + if (!m_iconmgr->initialize("Twm4Nx")) + { + cleanup(); + return false; + } + + // Cache a CIcon instance for use across the session + + m_icon = new CIcon(this); + if (m_iconmgr == (CIconMgr *)0) + { + cleanup(); + return false; + } + + // Cache a CFonts instance for use across the session + + m_fonts = new CFonts(this); + if (m_fonts == (CFonts *)0) + { + cleanup(); + return false; + } + + // Create all fonts + + if (!m_fonts->initialize()) + { + cleanup(); + return false; + } + + // Cache a CWindowFactory instance for use across the session + + m_factory = new CWindowFactory(this); + if (m_factory == (CWindowFactory *)0) + { + cleanup(); + return false; + } + + // Cache a CResize instance for use across the session + + m_resize = new CResize(this); + if (m_resize == (CResize *)0) + { + cleanup(); + return false; + } + + if (!m_resize->initialize()) + { + cleanup(); + return false; + } + + // Enter the event loop + + for (; ; ) + { + // Wait for the next NxWidget event + + struct SEventMsg eventmsg; + int ret = mq_receive(m_eventq, (FAR char *)&eventmsg, + sizeof(struct SEventMsg), (FAR unsigned int *)0); + if (ret < 0) + { + gerr("ERROR: mq_receive failed: %d\n", errno); + cleanup(); + return false; + } + + // Dispatch the new event + + if (!dispatchEvent(&eventmsg)) + { + gerr("ERROR: dispatchEvent failed\n"); + cleanup(); + return false; + } + } + + return true; // Not reachable +} + +/** + * Connect to the NX server + * + * @return True if the message was properly handled. false is + * return on any failure. + */ + +bool CTwm4Nx::connect(void) +{ + // Connect to the server + + bool nxConnected = CNxServer::connect(); + if (nxConnected) + { + // Set the background color + + if (!setBackgroundColor(CONFIG_TWM4NX_DEFAULT_BACKGROUNDCOLOR)) + { + // Failed + } + } + + return nxConnected; +} + +/** + * Generate a random message queue name. Different message queue + * names are required for each instance of Twm4Nx that is started. + */ + +void CTwm4Nx::genMqName(void) +{ + unsigned long randvalue = + (unsigned long)std::random() & 0x00fffffful; + + (void)std::asprintf(&m_queueName, "Twm4Nx%06ul", randvalue); +} + +/** + * Handle SYSTEM events. + * + * @param eventmsg. The received NxWidget event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + +bool CTwm4Nx::systemEvent(FAR struct SEventMsg *eventmsg) +{ + switch (eventmsg->eventID) + { + case EVENT_SYSTEM_ERROR: // Report system error + // REVISIT: An audible tone should be generated + break; + + case EVENT_SYSTEM_EXIT: // Terminate the Twm4Nx session + abort(); + break; // Does not return + + default: + return false; + } + + return true; +}; + +/** + * Dispatch NxWidget-related events. + * + * @param eventmsg. The received NxWidget event message. + * @return True if the message was properly dispatched. false is + * return on any failure. + */ + +bool CTwm4Nx::dispatchEvent(FAR struct SEventMsg *eventmsg) +{ + enum EEventRecipient recipient = + (enum EEventRecipient)(eventmsg->eventID & EVENT_RECIPIENT_MASK); + + bool ret = false; + switch (recipient) + { + case EVENT_RECIPIENT_MSG: // NX message event + ret = CWindowEvent::event(eventmsg); + break; + + case EVENT_RECIPIENT_SYSTEM: // Twm4Nx system event + ret = systemEvent(eventmsg); + break; + + case EVENT_RECIPIENT_ICONWIN: // Icon window event + { + FAR CIconWin *iconWin = (FAR CIconWin *)eventmsg->obj; + DEBUGASSERT(iconWin != (FAR CIconWin *)0); + ret = iconWin->event(eventmsg); + } + break; + + case EVENT_RECIPIENT_ICONMGR: // Icon Manager event + ret = m_iconmgr->event(eventmsg); + break; + + case EVENT_RECIPIENT_MENU: // Menu related event + { + FAR CMenus *menus = (FAR CMenus *)eventmsg->obj; + DEBUGASSERT(menus != (FAR CMenus *)0); + ret = menus->event(eventmsg); + } + break; + + case EVENT_RECIPIENT_WINDOW: // Window related event + case EVENT_RECIPIENT_TOOLBAR: // Toolbar related event + case EVENT_RECIPIENT_BORDER: // Window border related event + ret = m_factory->event(eventmsg); + break; + + case EVENT_RECIPIENT_RESIZE: // Windw resize event + ret = m_resize->event(eventmsg); + break; + + case EVENT_RECIPIENT_MASK: // Used to isolate recipient + default: + break; + } + + return ret; +} + +/** + * Cleanup and exit Twm4Nx abnormally. + */ + +void CTwm4Nx::abort() +{ + cleanup(); + std::exit(EXIT_FAILURE); +} + +/** + * Cleanup in preparation for termination. + */ + +void CTwm4Nx::cleanup() +{ + // Close the NxWidget event message queue + + if (m_eventq != (mqd_t)-1) + { + (void)mq_close(m_eventq); + m_eventq = (mqd_t)-1; + } + + // Delete the background + + if (m_background != (FAR CBackground *)0) + { + delete m_background; + m_background = (FAR CBackground *)0; + } + + // Halt the keyboard/mouse listener and destroy the CInput class + + if (m_input != (CInput *)0) + { + delete m_input; + m_input = (CInput *)0; + } + + // Free the Icon Manager + + if (m_iconmgr != (CIconMgr *)0) + { + delete m_iconmgr; + m_iconmgr = (CIconMgr *)0; + } + + // Free the session CWindowFactory instance + + if (m_factory != (CWindowFactory *)0) + { + delete m_factory; + m_factory = (CWindowFactory *)0; + } + + // Free the session CResize instance + + if (m_resize != (CResize *)0) + { + delete m_resize; + m_resize = (CResize *)0; + } + + CNxServer::disconnect(); +} + +///////////////////////////////////////////////////////////////////////////// +// Public Functions +///////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// +// Name: main/twm4nx_main +// +// Description: +// Start of TWM +// +///////////////////////////////////////////////////////////////////////////// + +#ifdef BUILD_MODULE +int main(int argc, FAR char *argv[]) +#else +int twm4nx_main(int argc, char *argv[]) +#endif +{ + int display = 0; + + for (int i = 1; i < argc; i++) + { + if (argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'd': // -display + if (std::strcmp(&argv[i][1], "display")) + { + goto usage; + } + + if (++i >= argc) + { + goto usage; + } + + display = atoi(argv[i]); + continue; + } + } + + usage: + gerr("Usage: %s [-display ]\n", argv[0]); + return EXIT_FAILURE; + } + + /* Create an instance of CTwm4Nx and and run it */ + + FAR CTwm4Nx *twm4nx = new CTwm4Nx(display); + if (twm4nx == (FAR CTwm4Nx *)0) + { + gerr("ERROR: Failed to instantiate CTwm4Nx\n"); + return EXIT_FAILURE; + } + + // Start the window manager + + bool success = twm4nx->run(); + if (!success) + { + gerr(" ERROR: Terminating due to failure\n"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/graphics/twm4nx/src/cwindow.cxx b/graphics/twm4nx/src/cwindow.cxx new file mode 100644 index 000000000..78dd3a270 --- /dev/null +++ b/graphics/twm4nx/src/cwindow.cxx @@ -0,0 +1,1229 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/src/cwindow.cxx +// Represents one window instance +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// Copyright 1988 by Evans & Sutherland Computer Corporation, +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 + +#include +#include +#include +#include + +#include +#include + +#include + +#include "graphics/nxglyphs.hxx" + +#include "graphics/nxwidgets/cnxtkwindow.hxx" +#include "graphics/nxwidgets/cnxtoolbar.hxx" +#include "graphics/nxwidgets/crlepalettebitmap.hxx" +#include "graphics/nxwidgets/cscaledbitmap.hxx" +#include "graphics/nxwidgets/cimage.hxx" +#include "graphics/nxwidgets/clabel.hxx" +#include "graphics/nxwidgets/cnxfont.hxx" + +#include "graphics/twm4nx/twm4nx_config.hxx" +#include "graphics/twm4nx/ctwm4nx.hxx" +#include "graphics/twm4nx/cfonts.hxx" +#include "graphics/twm4nx/cresize.hxx" +#include "graphics/twm4nx/ciconwin.hxx" +#include "graphics/twm4nx/ciconmgr.hxx" +#include "graphics/twm4nx/cwindowevent.hxx" +#include "graphics/twm4nx/cwindow.hxx" +#include "graphics/twm4nx/cwindowfactory.hxx" +#include "graphics/twm4nx/twm4nx_widgetevents.hxx" +#include "graphics/twm4nx/twm4nx_cursor.hxx" + +///////////////////////////////////////////////////////////////////////////// +// Private Data +///////////////////////////////////////////////////////////////////////////// + +using namespace Twm4Nx; + +// Association of configured bitmaps with buttons + +static FAR const NXWidgets::SRlePaletteBitmap *GTbBitmaps[NTOOLBAR_BUTTONS] = +{ + &CONFIG_TWM4NX_MENU_IMAGE, // MENU_BUTTON (first on left) + &CONFIG_TWM4NX_TERMINATE_IMAGE, // DELETE_BUTTON (first on right) + &CONFIG_TWM4NX_RESIZE_IMAGE, // RESIZE_BUTTON + &CONFIG_TWM4NX_MINIMIZE_IMAGE // MINIMIZE_BUTTON +}; + +static bool GButtonRightSide[NTOOLBAR_BUTTONS] = +{ + false, true, true, true, +}; + +///////////////////////////////////////////////////////////////////////////// +// CWindow Implementation +///////////////////////////////////////////////////////////////////////////// + +/** + * CWindow Constructor + * + * @param twm4nx. Twm4Nx session + */ + +CWindow::CWindow(CTwm4Nx *twm4nx) +{ + m_twm4nx = twm4nx; // Save the Twm4Nx session + m_eventq = (mqd_t)-1; // No widget message queue yet + + // Windows + + m_nxWin = (FAR NXWidgets::CNxTkWindow *)0; + m_toolbar = (FAR NXWidgets::CNxToolbar *)0; + m_zoom = ZOOM_NONE; + m_modal = false; + + // Toolbar + + m_tbTitle = (FAR NXWidgets::CLabel *)0; + m_tbHeight = 0; // Height of the toolbar + m_tbLeftX = 0; // Temporaries + m_tbRightX = 0; + + // Icons/Icon Manager + + m_iconWin = (FAR CIconWin *)0; + m_iconMgr = (FAR CIconMgr *)0; + m_isIconMgr = false; + m_iconOn = false; + m_iconified = false; + + // Dragging + + m_drag = false; + m_dragOffset.x = 0; + m_dragOffset.y = 0; + m_dragCSize.w = 0; + m_dragCSize.h = 0; + + // Toolbar buttons + + std::memset(m_tbButtons, 0, NTOOLBAR_BUTTONS * sizeof(NXWidgets::CImage *)); +} + +/** + * CWindow Destructor + */ + +CWindow::~CWindow(void) +{ + cleanup(); +} + +/** + * CWindow Initializer (unlike the constructor, this may fail) + * + * @param name The the name of the window (and its icon) + * @param pos The initialize position of the window + * @param size The initial size of the window + * @param sbitmap The Icon bitmap image + * @param isIconMgr Flag to tell if this is an icon manager window + * @param iconMgr Pointer to icon manager instance + * @param noToolbar True: Don't add Title Bar + * @return True if the window was successfully initialize; false on + * any failure, + */ + +bool CWindow::initialize(FAR const char *name, + FAR const struct nxgl_point_s *pos, + FAR const struct nxgl_size_s *size, + FAR const struct NXWidgets::SRlePaletteBitmap *sbitmap, + bool isIconMgr, FAR CIconMgr *iconMgr, + bool noToolbar) +{ + // Open a message queue to send fully digested NxWidget events. + + FAR const char *mqname = m_twm4nx->getEventQueueName(); + + m_eventq = mq_open(mqname, O_WRONLY); + if (m_eventq == (mqd_t)-1) + { + gerr("ERROR: Failed open message queue '%s': %d\n", + mqname, errno); + return false; + } + + m_isIconMgr = isIconMgr; + m_iconMgr = iconMgr; + + if (name == (FAR const char *)0) + { + m_name = std::strdup(GNoName); + } + else + { + m_name = std::strdup(name); + } + + // Do initial clip to the maximum window size + + struct nxgl_size_s maxWindow; + m_twm4nx->maxWindowSize(&maxWindow); + + struct nxgl_size_s winsize; + winsize.w = size->w; + if (winsize.w > maxWindow.w) + { + winsize.w = maxWindow.w; + } + + winsize.h = size->h; + if (winsize.h > maxWindow.h) + { + winsize.h = maxWindow.h; + } + + m_iconOn = false; + + // Create the window + + m_nxWin = (FAR NXWidgets::CNxTkWindow *)0; + m_toolbar = (FAR NXWidgets::CNxToolbar *)0; + + // Create the main window + + if (!createMainWindow(&winsize, pos)) + { + gerr("ERROR: createMainWindow() failed\n"); + cleanup(); + return false; + } + + m_tbHeight = 0; + m_toolbar = (FAR NXWidgets::CNxToolbar *)0; + + if (!noToolbar) + { + // Toolbar height should be based on size of images and fonts. + + if (!getToolbarHeight(name)) + { + gerr("ERROR: getToolbarHeight() failed\n"); + cleanup(); + return false; + } + + // Create the toolbar + + if (!createToolbar()) + { + gerr("ERROR: createToolbar() failed\n"); + cleanup(); + return false; + } + + // Add buttons to the toolbar + + if (!createToolbarButtons()) + { + gerr("ERROR: createToolbarButtons() failed\n"); + cleanup(); + return false; + } + + // Add the title to the toolbar + + if (!createToolbarTitle(name)) + { + gerr("ERROR: createToolbarTitle() failed\n"); + cleanup(); + return false; + } + } + + // Create and initialize the icon window + + m_iconWin = new CIconWin(m_twm4nx); + if (m_iconWin == (FAR CIconWin *)0) + { + gerr("ERROR: Failed to create the icon Window\n"); + cleanup(); + return false; + } + + if (!m_iconWin->initialize(this, sbitmap, pos)) + { + gerr("ERROR: Failed to initialize the icon Window\n"); + cleanup(); + return false; + } + + enableWidgets(); + return true; +} + +/** + * Get the raw window size (including toolbar and frame) + * + * @param framesize Location to return the window frame size + */ + +bool CWindow::getFrameSize(FAR struct nxgl_size_s *framesize) +{ + // Get the window size + + struct nxgl_size_s winsize; + bool success = getWindowSize(&winsize); + if (success) + { + // Convert the window size to the frame size + + windowToFrameSize(&winsize, framesize); + } + + return success; +} + +/** + * Update the window frame after a resize operation (includes the toolbar + * and user window) + * + * @param size The new window frame size + * @param pos The frame location which may also have changed + */ + +bool CWindow::resizeFrame(FAR const struct nxgl_size_s *size, + FAR struct nxgl_point_s *pos) +{ + // Account for toolbar and border + + struct nxgl_size_s delta; + delta.w = 2 * CONFIG_NXTK_BORDERWIDTH; + delta.h = m_tbHeight + 2 * CONFIG_NXTK_BORDERWIDTH; + + // Don't set the window size smaller than one pixel + + struct nxgl_size_s winsize; + if (size->w <= delta.w) + { + winsize.w = 1; + } + else + { + winsize.w = size->w - delta.w; + } + + if (size->h <= delta.h) + { + winsize.h = 1; + } + else + { + winsize.h = size->h - delta.h; + } + + // Set the usable window size + + bool success = m_nxWin->setSize(&winsize); + if (!success) + { + gerr("ERROR: Failed to setSize()\n"); + return false; + } + + // Set the new frame position (in case it changed too) + + success = setFramePosition(pos); + if (!success) + { + gerr("ERROR: Failed to setSize()\n"); + return false; + } + + // Synchronize with the NX server to make sure that the new geometry is + // truly in effect. + + m_nxWin->synchronize(); + + // Then update the toolbar layout + + return updateToolbarLayout(); +} + +/** + * Get the window frame position (accounting for toolbar and frame) + * + * @param size Location to return the window frame position + */ + +bool CWindow::getFramePosition(FAR struct nxgl_point_s *framepos) +{ + // Get the window position + + struct nxgl_point_s winpos; + bool success = m_nxWin->getPosition(&winpos); + if (success) + { + // Convert the window position to a frame position + + windowToFramePos(&winpos, framepos); + } + + return success; +} + +/** + * Set the window frame position (accounting for toolbar and frame) + * + * @param size The new raw window position + */ + +bool CWindow::setFramePosition(FAR const struct nxgl_point_s *framepos) +{ + // Convert the frame position to the contained, primary window positio + + struct nxgl_point_s winpos; + frameToWindowPos(framepos, &winpos); + + // And set the window position + + return m_nxWin->setPosition(&winpos); +} + +void CWindow::iconify(void) +{ + if (!isIconified()) + { + // Make sure to exit any modal state before minimizing + + m_modal = false; + m_nxWin->modal(false); + + // Raise the icon window and lower the main window + + m_iconified = true; + m_nxWin->lower(); + m_iconWin->raise(); + m_iconOn = true; + m_nxWin->synchronize(); + } +} + +void CWindow::deIconify(void) +{ + // De-iconify the window + + if (isIconified()) + { + // Raise the main window and lower the icon window + + m_iconified = false; + m_iconWin->lower(); + m_nxWin->raise(); + m_iconOn = false; + m_nxWin->synchronize(); + } +} + +/** + * Handle WINDOW events. + * + * @param eventmsg. The received NxWidget WINDOW event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + +bool CWindow::event(FAR struct SEventMsg *eventmsg) +{ + FAR NXWidgets::CNxTkWindow *nxwin = eventmsg->nxwin; + bool success = true; + + switch (eventmsg->eventID) + { + case EVENT_WINDOW_RAISE: // Raise window to the top of the heirarchy + nxwin->raise(); // Could be the main or the icon window + break; + + case EVENT_WINDOW_LOWER: // Lower window to the bottom of the heirarchy + nxwin->lower(); // Could be the main or the icon window + break; + + case EVENT_WINDOW_POPUP: // De-iconify and raise the main window + { + deIconify(); + } + break; + + case EVENT_WINDOW_FOCUS: + if (!isIconified()) + { + m_modal = !m_modal; + m_nxWin->modal(m_modal); + } + + break; + + case EVENT_TOOLBAR_TERMINATE: // Toolbar terminate button pressed + if (isIconMgr()) + { + // Don't terminate the Icon manager, just hide it + + CIconMgr *iconMgr = m_twm4nx->getIconMgr(); + DEBUGASSERT(iconMgr != (CIconMgr *)0); + + iconMgr->hide(); + } + else + { + // Close the window... but not yet. Send the blocked message. + // The actual termination will no occur until the NX server + // drains all of the message events. We will get the + // EVENT_WINDOW_DELETE event at that point + + NXWidgets::CWidgetControl *control = nxwin->getWidgetControl(); + nxtk_block(control->getWindowHandle(), (FAR void *)m_nxWin); + } + + break; + + case EVENT_WINDOW_DELETE: // Toolbar terminate button pressed + { + // Poll for pending events before closing. + + FAR CWindow *cwin = (FAR CWindow *)eventmsg->obj; + success = cwin->pollToolbarEvents(); + + FAR CWindowFactory *factory = m_twm4nx->getWindowFactory(); + factory->destroyWindow(cwin); + } + break; + + case EVENT_WINDOW_UNFOCUS: // Exit modal state + { + m_modal = false; + m_nxWin->modal(false); + } + break; + + case EVENT_TOOLBAR_GRAB: /* Left click on title widget. Start drag */ + success = toolbarGrab(eventmsg); + break; + + case EVENT_WINDOW_DRAG: /* Mouse movement while clicked */ + success = windowDrag(eventmsg); + break; + + case EVENT_TOOLBAR_UNGRAB: /* Left click release while dragging. */ + success = toolbarUngrab(eventmsg); + break; + + default: + success = false; + break; + } + + return success; +} + +/** + * Create the main window + * + * @param winsize The initial window size + * @param winpos The initial window position + */ + +bool CWindow::createMainWindow(FAR const nxgl_size_s *winsize, + FAR const nxgl_point_s *winpos) +{ + // 1. Get the server instance. m_twm4nx inherits from NXWidgets::CNXServer + // so we all ready have the server instance. + // 2. Create the style, using the selected colors (REVISIT) + + // 3. Create a Widget control instance for the window using the default + // style for now. CWindowEvent derives from CWidgetControl. + + FAR CWindowEvent *control = new CWindowEvent(m_twm4nx); + + // 4. Create the window + + m_nxWin = m_twm4nx->createFramedWindow(control); + if (m_nxWin == (FAR NXWidgets::CNxTkWindow *)0) + { + delete control; + return false; + } + + // 5. Open and initialize the window + + bool success = m_nxWin->open(); + if (!success) + { + return false; + } + + // 6. Set the initial window size + + if (!m_nxWin->setSize(winsize)) + { + return false; + } + + // 7. Set the initial window position + + if (!m_nxWin->setPosition(winpos)) + { + return false; + } + + return true; +} + +/** + * Calculate the height of the tool bar + */ + +bool CWindow::getToolbarHeight(FAR const char *name) +{ + // The tool bar height is the largest of the toolbar button heights or the + // title text font + + // Check if there is a title. If so, get the font height. + + m_tbHeight = 0; + if (name != (FAR const char *)0) + { + FAR CFonts *fonts = m_twm4nx->getFonts(); + FAR NXWidgets::CNxFont *titleFont = fonts->getTitleFont(); + m_tbHeight = titleFont->getHeight(); + } + + // Now compare this to the height of each toolbar image + + for (int btindex = 0; btindex < NTOOLBAR_BUTTONS; btindex++) + { + nxgl_coord_t btnHeight = GTbBitmaps[btindex]->height; + if (btnHeight > m_tbHeight) + { + m_tbHeight = btnHeight; + } + } + + // Plus somoe lines for good separation + + m_tbHeight += CONFIG_TWM4NX_FRAME_VSPACING; + return true; +} + +/** + * Create the tool bar + */ + +bool CWindow::createToolbar(void) +{ + // Create the toolbar + // 1. Create the style, using the selected colors (REVISIT) + + // 2. Create a Widget control instance for the window using the default + // style for now. CWindowEvent derives from CWidgetControl. + + FAR CWindowEvent *control = new CWindowEvent(m_twm4nx); + + // 3. Get the toolbar sub-window from the framed window + + m_toolbar = m_nxWin->openToolbar(m_tbHeight, control); + if (m_toolbar == (FAR NXWidgets::CNxToolbar *)0) + { + delete control; + return false; + } + + // 4. Open and initialize the tool bar + + return m_toolbar->open(); +} + +/** + * Update the toolbar layout, resizing the title text window and + * repositioning all windows on the toolbar. + */ + +bool CWindow::updateToolbarLayout(void) +{ + // Disable widget drawing and events while we do this + + disableWidgets(); + + // Reposition all right buttons. Change the width of the + // toolbar does not effect the left side spacing. + + m_tbRightX = 0; + for (int btindex = 0; btindex < NTOOLBAR_BUTTONS; btindex++) + { + if (GButtonRightSide[btindex]) + { + FAR NXWidgets::CImage *cimage = m_tbButtons[btindex]; + + // Set the position of the Icon image in the toolbar + + struct nxgl_size_s windowSize; + getWindowSize(&windowSize); + + // Center image vertically + + struct nxgl_point_s pos; + pos.y = (m_tbHeight - cimage->getHeight()) / 2; + + // Pack on the right horizontally + + m_tbRightX -= (cimage->getWidth() + CONFIG_TWM4NX_TOOLBAR_HSPACING); + pos.x = m_tbRightX; + + if (!cimage->moveTo(pos.x, pos.y)) + { + gerr("ERROR: Faile to move button image\n"); + return false; + } + } + } + + // Vertical size of the title window is selected to fill the entire + // toolbar. This really needs to be only the font height. However, + // this improves the click-ability of the widget for small fonts. + // + // The Horizontal size of the title widget is determined by the available + // space between m_tbLeftX and m_tbRightX. + + struct nxgl_size_s titleSize; + titleSize.h = m_tbHeight; + titleSize.w = m_tbRightX - m_tbLeftX - CONFIG_TWM4NX_FRAME_VSPACING + 1; + + bool success = m_tbTitle->resize(titleSize.w, titleSize.h); + enableWidgets(); + return success; +} + +/** + * Disable widget drawing and widget events. + */ + +bool CWindow::disableWidgets(void) +{ + for (int btindex = 0; btindex < NTOOLBAR_BUTTONS; btindex++) + { + FAR NXWidgets::CImage *cimage = m_tbButtons[btindex]; + cimage->disableDrawing(); + cimage->setRaisesEvents(false); + } + + m_tbTitle->disableDrawing(); + m_tbTitle->setRaisesEvents(false); + return true; +} + +/** + * Enable widget drawing and widget events. + */ + +bool CWindow::enableWidgets(void) +{ + for (int btindex = 0; btindex < NTOOLBAR_BUTTONS; btindex++) + { + FAR NXWidgets::CImage *cimage = m_tbButtons[btindex]; + cimage->enableDrawing(); + cimage->setRaisesEvents(true); + cimage->redraw(); + } + + m_tbTitle->enableDrawing(); + m_tbTitle->setRaisesEvents(true); + m_tbTitle->redraw(); + return true; +} + +/** + * Create all toolbar buttons + */ + +bool CWindow::createToolbarButtons(void) +{ + struct nxgl_size_s winsize; + if (!getWindowSize(&winsize)) + { + return false; + } + + // Create the title bar windows + // Set up the toolbar horizonal spacing + + m_tbRightX = winsize.w; + m_tbLeftX = 0; + + for (int btindex = 0; btindex < NTOOLBAR_BUTTONS; btindex++) + { + FAR const NXWidgets::SRlePaletteBitmap *sbitmap = GTbBitmaps[btindex]; + +#ifdef CONFIG_TWM4NX_TOOLBAR_ICONSCALE + // Create a CScaledBitmap to scale the bitmap icon + + struct nxgl_size_s iconSize; + iconSize.w = CONFIG_TWM4NX_TOOLBAR_ICONWIDTH; + iconSize.h = CONFIG_TWM4NX_TOOLBAR_ICONHEIGHT; + + FAR NXWidgets::CScaledBitmap *scaler = + new NXWidgets::CScaledBitmap(sbitmap, iconSize); + + if (scaler == (FAR NXWidgets::CScaledBitmap *)0) + { + gerr("ERROR: Failed to created scaled bitmap\n"); + return false; + } +#endif + // Create the image. The image will serve as button since it + // can detect clicks and release just like a button. + + m_tbButtons[btindex] = (FAR NXWidgets::CImage *)0; + nxgl_coord_t w = 1; + nxgl_coord_t h = 1; + + // Get the toolbar CWdigetControl instance + + NXWidgets::CWidgetControl *control = m_toolbar->getWidgetControl(); + +#ifdef CONFIG_TWM4NX_TOOLBAR_ICONSCALE + w = scaler->getWidth(); + h = scaler->getHeight(); + + m_tbButtons[btindex] = + new NXWidgets::CImage(control, 0, 0, w, h, scaler, 0); + if (m_tbButtons[btindex] == (FAR NXWidgets::CImage *)0) + { + gerr("ERROR: Failed to create image\n"); + delete scalar; + return false; + } +#else + FAR NXWidgets::CRlePaletteBitmap *cbitmap = + new NXWidgets::CRlePaletteBitmap(sbitmap); + if (cbitmap == (FAR NXWidgets::CRlePaletteBitmap *)0) + { + gerr("ERROR: Failed to create CrlPaletteBitmap\n"); + return false; + } + + w = cbitmap->getWidth(); + h = cbitmap->getHeight(); + + m_tbButtons[btindex] = + new NXWidgets::CImage(control, 0, 0, w, h, cbitmap, 0); + if (m_tbButtons[btindex] == (FAR NXWidgets::CImage *)0) + { + gerr("ERROR: Failed to create image\n"); + delete cbitmap; + return false; + } +#endif + + // Configure the image, disabling drawing for now + + FAR NXWidgets::CImage *cimage = m_tbButtons[btindex]; + cimage->setBorderless(true); + cimage->disableDrawing(); + cimage->setRaisesEvents(false); + + // Register to get events from the mouse clicks on the image + + cimage->addWidgetEventHandler(this); + + // Set the position of the Icon image in the toolbar + + struct nxgl_size_s windowSize; + getWindowSize(&windowSize); + + // Center image vertically + + struct nxgl_point_s pos; + pos.y = (m_tbHeight - cimage->getHeight()) / 2; + + // Pack on the left or right horizontally + + if (GButtonRightSide[btindex]) + { + m_tbRightX -= (cimage->getWidth() + CONFIG_TWM4NX_TOOLBAR_HSPACING); + pos.x = m_tbRightX; + } + else + { + m_tbLeftX += CONFIG_TWM4NX_TOOLBAR_HSPACING; + pos.x = m_tbLeftX; + m_tbLeftX += cimage->getWidth(); + } + + if (!cimage->moveTo(pos.x, pos.y)) + { + delete m_tbButtons[btindex]; + m_tbButtons[btindex] = (FAR NXWidgets::CImage *)0; + return false; + } + } + + return true; +} + +/** + * Add buttons and title widgets to the tool bar + * + * @param name The name to use for the toolbar title + */ + +bool CWindow::createToolbarTitle(FAR const char *name) +{ + // Is there a title? + + if (name != (FAR const char *)0) + { + // No.. then there is nothing to be done here + + return true; + } + + // Vertical size of the title window is selected to fill the entire + // toolbar. This really needs to be only the font height. However, + // this improves the click-ability of the widget for small fonts. + // + // The Horizontal size of the title widget is determined by the available + // space between m_tbLeftX and m_tbRightX. + + struct nxgl_size_s titleSize; + titleSize.h = m_tbHeight; + titleSize.w = m_tbRightX - m_tbLeftX - CONFIG_TWM4NX_FRAME_VSPACING + 1; + + // Position the tile. Packed to the left horizontally, positioned at the + // top of the toolbar. + + struct nxgl_point_s titlePos; + titlePos.x = m_tbLeftX + CONFIG_TWM4NX_FRAME_VSPACING; + titlePos.y = 0; + + // Create the widget control (with the window messenger) using the default style + + // REVISIT: Create the style, using the selected colors. + + // Create a Widget control instance for the window using the default style + // for now. CWindowEvent derives from CWidgetControl. + + FAR CWindowEvent *control = new CWindowEvent(m_twm4nx); + if (control == (FAR CWindowEvent *)0) + { + return false; + } + + // Create the toolbar title widget + + m_tbTitle = new NXWidgets::CLabel(control, titlePos.x, titlePos.y, + titleSize.w, titleSize.h, name); + if (m_tbTitle == (FAR NXWidgets::CLabel *)0) + { + gerr("ERROR: Failed to construct tool bar title widget\n"); + return false; + } + + // Configure the title widget + + FAR CFonts *fonts = m_twm4nx->getFonts(); + FAR NXWidgets::CNxFont *titleFont = fonts->getTitleFont(); + + m_tbTitle->setFont(titleFont); + m_tbTitle->setBorderless(true); + m_tbTitle->disableDrawing(); + m_tbTitle->setTextAlignmentHoriz(NXWidgets::CLabel::TEXT_ALIGNMENT_HORIZ_LEFT); + m_tbTitle->setTextAlignmentVert(NXWidgets::CLabel::TEXT_ALIGNMENT_VERT_CENTER); + m_tbTitle->setRaisesEvents(false); + + // Register to get events from the mouse clicks on the image + + m_tbTitle->addWidgetEventHandler(this); + return true; +} + +/** + * 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) + { +#warning Missing logic + } +} + +/** + * 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. + + if (m_drag) + { +#warning Missing logic + } +} + +/** + * Handle a key press event. + * + * @param e The event data. + */ + +void CWindow::handleKeyPressEvent(const NXWidgets::CWidgetEventArgs &e) +{ + // We are interested only the the press event on the title box + + if (!m_drag) + { +#warning Missing logic + } +} + +/** + * Override the virtual CWidgetEventHandler::handleActionEvent. This + * event will fire when the image is released but before it has been + * has been drawn. isClicked() will return true for the appropriate + * images. + */ + +void CWindow::handleActionEvent(const NXWidgets::CWidgetEventArgs &e) +{ + // We are are interested in the pre-release event for any of the + // toolbar buttons. +#warning Missing logic +} + +/** + * Handle the TOOLBAR_GRAB event. That corresponds to a left + * mouse click on the tile widget in the toolbar + * + * @param eventmsg. The received NxWidget event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + +bool CWindow::toolbarGrab(FAR struct SEventMsg *eventmsg) +{ + // Promote the window to a modal window + + m_modal = true; + m_nxWin->modal(true); + + // Indicate that dragging has started. + + m_drag = true; + + // Get the frame position. + + struct nxgl_point_s framePos; + getFramePosition(&framePos); + + // Determine the relative position of the frame and the mouse + + m_dragOffset.x = framePos.x - eventmsg->pos.x; + m_dragOffset.y = framePos.y - eventmsg->pos.y; + + // Select the grab cursor image + + m_twm4nx->setCursorImage(&CONFIG_TWM4NX_GBCURSOR_IMAGE); + + // 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; +} + +/** + * Handle the WINDOW_DRAG event. That corresponds to a mouse + * movement when the window is in a grabbed state. + * + * @param eventmsg. The received NxWidget event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + +bool CWindow::windowDrag(FAR struct SEventMsg *eventmsg) +{ + if (m_drag) + { + // Calculate the new Window position + + struct nxgl_point_s newpos; + newpos.x = eventmsg->pos.x + m_dragOffset.x; + newpos.y = eventmsg->pos.y + m_dragOffset.y; + + // Keep the window on the display (at least enough of it so that we + // can still grab it) + + struct nxgl_size_s displaySize; + m_twm4nx->getDisplaySize(&displaySize); + + if (newpos.x < 0) + { + newpos.x = 0; + } + else if (newpos.x + m_dragCSize.w > displaySize.w) + { + newpos.x = displaySize.w - m_dragCSize.w; + } + + if (newpos.y < 0) + { + newpos.y = 0; + } + else if (newpos.y + m_dragCSize.h > displaySize.h) + { + newpos.y = displaySize.h - m_dragCSize.h; + } + + // Set the new window position + + return setFramePosition(&newpos); + } + + return false; +} + +/** + * 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. + * @return True if the message was properly handled. false is + * return on any failure. + */ + +bool CWindow::toolbarUngrab(FAR struct SEventMsg *eventmsg) +{ + // One last position update + + if (!windowDrag(eventmsg)) + { + return false; + } + + // Indicate no longer dragging + + m_drag = false; + + // No longer modal + + m_modal = false; + m_nxWin->modal(false); + + // Restore the normal cursor image + + m_twm4nx->setCursorImage(&CONFIG_TWM4NX_CURSOR_IMAGE); + return false; +} + +/** + * Free windows from Twm4Nx window structure. + */ + +void CWindow::cleanup(void) +{ + // Close the NxWidget event message queue + + if (m_eventq != (mqd_t)-1) + { + (void)mq_close(m_eventq); + m_eventq = (mqd_t)-1; + } + + // Delete toolbar images + + for (int btindex = 0; btindex < NTOOLBAR_BUTTONS; btindex++) + { + FAR NXWidgets::CImage *cimage = m_tbButtons[btindex]; + if (cimage != (NXWidgets::CImage *)0) + { + delete m_tbButtons[btindex]; + m_tbButtons[btindex] = (NXWidgets::CImage *)0; + } + } + + if (m_tbTitle != (FAR NXWidgets::CLabel *)0) + { + delete m_tbTitle; + m_tbTitle = (FAR NXWidgets::CLabel *)0; + } + + // Close windows + + if (m_nxWin != (FAR NXWidgets::CNxTkWindow *)0) + { + delete m_nxWin; + m_nxWin = (FAR NXWidgets::CNxTkWindow *)0; + } + + if (m_iconWin != (FAR CIconWin *)0) + { + delete m_iconWin; + m_iconWin = (FAR CIconWin *)0; + } + + // Free memory + + if (m_name != (FAR char *)0) + { + std::free(m_name); + m_name = (FAR char *)0; + } +} diff --git a/graphics/twm4nx/src/cwindowevent.cxx b/graphics/twm4nx/src/cwindowevent.cxx new file mode 100644 index 000000000..fc1a88915 --- /dev/null +++ b/graphics/twm4nx/src/cwindowevent.cxx @@ -0,0 +1,249 @@ +// apps/graphics/twm4nx/src/cwindowevent.cxx +// Shim to manage the interface between NX messages and NxWidgets +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// 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 + +#include +#include + +#include +#include + +#include "graphics/nxwidgets/cwidgetcontrol.hxx" + +#include "graphics/twm4nx/cwindow.hxx" +#include "graphics/twm4nx/cwindowevent.hxx" + +///////////////////////////////////////////////////////////////////////////// +// CWindowEvent Method Implementations +///////////////////////////////////////////////////////////////////////////// + +using namespace Twm4Nx; + +/** + * CWindowEvent Constructor + * + * @param twm4nx. The Twm4Nx session instance. + * @param style The default style that all widgets on this display + * should use. If this is not specified, the widget will use the + * values stored in the defaultCWidgetStyle object. + */ + +CWindowEvent::CWindowEvent(FAR CTwm4Nx *twm4nx, + FAR const NXWidgets::CWidgetStyle *style) +: NXWidgets::CWidgetControl(style) +{ + m_twm4nx = twm4nx; // Cache the Twm4Nx session + + // Open a message queue to send raw NX events. This cannot fail! + + FAR const char *mqname = twm4nx->getEventQueueName(); + m_eventq = mq_open(mqname, O_WRONLY); + if (m_eventq == (mqd_t)-1) + { + gerr("ERROR: Failed open message queue '%s': %d\n", + mqname, errno); + } + + // Add ourself to the list of window event handlers + + addWindowEventHandler(this); +} + +/** + * CWindowEvent Destructor. + */ + +CWindowEvent::~CWindowEvent(void) +{ + // Close the NxWidget event message queue + + if (m_eventq != (mqd_t)-1) + { + (void)mq_close(m_eventq); + m_eventq = (mqd_t)-1; + } + + // Remove ourself from the list of the window event handlers + + removeWindowEventHandler(this); +} + +/** + * Handle MSG events. + * + * @param msg. The received system MSG event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + +bool CWindowEvent::event(FAR struct SEventMsg *eventmsg) +{ + bool success = true; + + // Handle the event + + switch (eventmsg->eventID) + { + case EVENT_MSG_POLL: // Poll for event + { + // Poll for pending events before closing. + + FAR CWindow *cwin = (FAR CWindow *)eventmsg->obj; + success = cwin->pollToolbarEvents(); + } + break; + + default: + success = false; + break; + } + + return success; +} + +/** + * Send the EVENT_MSG_POLL input event message to the Twm4Nx event loop. + */ + +void CWindowEvent::sendInputEvent(void) +{ + // The logic path here is tortuous but flexible: + // + // 1. A listener thread receives mouse or touchscreen input and injects + // that into NX via nx_mousein + // 2. In the multi-user mode, this will send a message to the NX server + // 3. The NX server will determine which window gets the mouse input + // and send a window event message to the NX listener thread. + // 4. The NX listener thread receives a windows event. The NX listener thread + // is part of CTwm4Nx and was created when NX server connection was + // established. This event may be a positional change notification, a + // redraw request, or mouse or keyboard input. In this case, mouse input. + // 5. The NX listener thread handles the message by calling nx_eventhandler(). + // nx_eventhandler() dispatches the message by calling a method in the + // NXWidgets::CCallback instance associated with the window. + // NXWidgets::CCallback is a part of the CWidgetControl. + // 6. NXWidgets::CCallback calls into NXWidgets::CWidgetControl to process + // the event. + // 7. NXWidgets::CWidgetControl records the new state data and raises a + // window event. + // 8. NXWidgets::CWindowEventHandlerList will give the event to this method + // NxWM::CWindowEvent. + // 9. This NxWM::CWindowEvent method will send a message to the Event + // loop running in the Twm4Nx main thread. + // 10. The Twm4Nx main thread will call the CWindowEvent::event() method + // which + // 11. Finally call pollEvents() to execute whatever actions the input event + // should trigger. + // 12. This might call an event handler in and overrident method of + // CWidgetEventHandler which will again notify the Event loop running + // in the Twm4Nx main thread. The event will, finally be delivered + // to the recipient in its fully digested and decorated form. + + struct SNxEventMsg msg = + { + .eventID = EVENT_MSG_POLL, + .instance = this, + .win = (FAR struct SWindow *)0 + }; + + int ret = mq_send(m_eventq, (FAR const char *)&msg, + sizeof(struct SNxEventMsg), 100); + if (ret < 0) + { + gerr("ERROR: mq_send failed: %d\n", ret); + } +} + +/** + * Handle an NX window mouse input event. + */ + +#ifdef CONFIG_NX_XYINPUT +void CWindowEvent::handleMouseEvent(void) +{ + // Stimulate an input poll + + sendInputEvent(); +} +#endif + +#ifdef CONFIG_NX_KBD +/** + * Handle a NX window keyboard input event. + */ + +void CWindowEvent::handleKeyboardEvent(void) +{ + // Stimulate an input poll + + sendInputEvent(); +} +#endif + +/** + * Handle a NX window blocked event. This handler is called when we + * receive the BLOCKED message meaning that there are no further pending + * actions on the window. It is now safe to delete the window. + * + * This is handled by sending a message to the start window thread (vs just + * calling the destructors) because in the case where an application + * destroys itself (because of pressing the stop button), then we need to + * unwind and get out of the application logic before destroying all of its + * objects. + * + * @param arg - User provided argument (see nx_block or nxtk_block) + */ + +void CWindowEvent::handleBlockedEvent(FAR void *arg) +{ + struct SNxEventMsg msg = + { + .eventID = EVENT_WINDOW_DELETE, + .instance = this, + .win = (FAR struct SWindow *)arg + }; + + int ret = mq_send(m_eventq, (FAR const char *)&msg, + sizeof(struct SNxEventMsg), 100); + if (ret < 0) + { + gerr("ERROR: mq_send failed: %d\n", ret); + } +} diff --git a/graphics/twm4nx/src/cwindowfactory.cxx b/graphics/twm4nx/src/cwindowfactory.cxx new file mode 100644 index 000000000..44b36bb1b --- /dev/null +++ b/graphics/twm4nx/src/cwindowfactory.cxx @@ -0,0 +1,330 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/src/cwindowfactory.cxx +// A collection of Window Helpers: Add a new window, put the titlebar and +// other stuff around the window +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// Copyright 1988 by Evans & Sutherland Computer Corporation, +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 + +#include +#include +#include +#include + +#include "graphics/nxwidgets/cwidgetcontrol.hxx" +#include "graphics/nxwidgets/cnxwindow.hxx" +#include "graphics/nxwidgets/cnxtkwindow.hxx" +#include "graphics/nxwidgets/cnxtoolbar.hxx" + +#include "graphics/twm4nx/ctwm4nx.hxx" +#include "graphics/twm4nx/cwindow.hxx" +#include "graphics/twm4nx/cwindowfactory.hxx" +#include "graphics/twm4nx/ciconmgr.hxx" +#include "graphics/twm4nx/twm4nx_widgetevents.hxx" + +///////////////////////////////////////////////////////////////////////////// +// CWindowFactory Implementation +///////////////////////////////////////////////////////////////////////////// + +using namespace Twm4Nx; + +/** + * CWindowFactory Constructor + * + * @param twm4nx. Twm4Nx session + */ + +CWindowFactory::CWindowFactory(FAR CTwm4Nx *twm4nx) +{ + m_twm4nx = twm4nx; // Cached copy of the Twm4Nx session object + m_windowHead = (FAR struct SWindow *)0; // List of all Windows + + // Set up the position where we will create the initial window + + m_winpos.x = 50; + m_winpos.y = 50; +} + +/** + * CWindowFactory Destructor + */ + +CWindowFactory::~CWindowFactory(void) +{ +} + +/** + * Create a new window and add it to the window list. + * + * @param name The window name + * @param sbitmap The Icon bitmap + * @param isIconMgr Flag to tell if this is an icon manager window + * @param iconMgr Pointer to icon manager instance + * @param noToolbar True: Don't add Title Bar + * @return Reference to the allocated CWindow instance + */ + +FAR CWindow * + CWindowFactory::createWindow(FAR const char *name, + FAR const struct NXWidgets::SRlePaletteBitmap *sbitmap, + bool isIconMgr, FAR CIconMgr *iconMgr, + bool noToolbar) +{ + ginfo("name=%p\n", name); + + // Allocate a container for the Twm4NX window + + FAR struct SWindow *win = + (FAR struct SWindow *)std::zalloc(sizeof(struct SWindow)); + if (win == (FAR struct SWindow *)0) + { + gerr("ERROR: Unable to allocate memory to manage window %s\n", + name); + return (FAR CWindow *)0; + } + + // Create and initialize the window itself + + win->cwin = new CWindow(m_twm4nx); + if (win->cwin == (FAR CWindow *)0) + { + gerr("ERROR: Failed to create CWindow\n"); + std::free(win); + return (FAR CWindow *)0; + } + + // Place the window at a random position + // Default size: Try a one quarter of the display. + + struct nxgl_size_s displaySize; + m_twm4nx->getDisplaySize(&displaySize); + + struct nxgl_size_s winsize; + winsize.w = displaySize.w / 2; + winsize.h = displaySize.h / 2; + + if ((m_winpos.x + winsize.w) > displaySize.w) + { + m_winpos.x = 50; + } + + if ((m_winpos.x + winsize.w) > (displaySize.w - 16)) + { + winsize.w = displaySize.w - m_winpos.x - 16; + } + + if ((m_winpos.y + winsize.h) > displaySize.h) + { + m_winpos.y = 50; + } + + if ((m_winpos.y + winsize.h) > (displaySize.h - 16)) + { + winsize.h = displaySize.h - m_winpos.y - 16; + } + + ginfo("Position window at (%d,%d), size (%d,%d)\n", + m_winpos.x, m_winpos.y, winsize.w, winsize.h); + + if (!win->cwin->initialize(name, &m_winpos, &winsize, sbitmap, + isIconMgr, iconMgr, noToolbar)) + { + gerr("ERROR: Failed to initialize CWindow\n"); + delete win->cwin; + std::free(win); + return (FAR CWindow *)0; + } + + // Update the position for the next window + + m_winpos.x += 30; + m_winpos.y += 30; + + // Add the window into the Twm4Nx window list + + addWindow(win); + + // Add the window container to the icon manager + + CIconMgr *iconmgr = m_twm4nx->getIconMgr(); + DEBUGASSERT(iconmgr != (CIconMgr *)0); + + (void)iconmgr->add(win->cwin); + + // Return the contained window + + return win->cwin; +} + +/** + * Handle the EVENT_WINDOW_DELETE event. The logic sequence is as + * follows: + * + * 1. The TERMINATE button in pressed in the Window Toolbar + * 2. CWindowFactory::event receives the widget event, + * EVENT_WINDOW_TERMINATE and request to halt the NX Server + * messages queues. + * 3. The server responds with the EVENT_WINDOW_DELETE which is + * caught by this function. + * + * @param cwin The CWindow instance. This will be deleted and its + * associated container will be freed. + */ + +void CWindowFactory::destroyWindow(FAR CWindow *cwin) +{ + // Find the container of the window + + FAR struct SWindow *win = findWindow(cwin); + if (win == (FAR struct SWindow *)0) + { + // This should not happen.. worthy of an assertion + + gerr("ERROR: Failed to find CWindow container\n"); + } + else + { + // Remove the window container from the window list + + removeWindow(win); + } + + // Delete the contained CWindow instance + + delete cwin; + + // And, finally, free the CWindow container + + free(win); +} + +/** + * Handle WINDOW events. + * + * @param eventmsg. The received NxWidget WINDOW event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + +bool CWindowFactory::event(FAR struct SEventMsg *eventmsg) +{ + FAR CWindow *cwin = (FAR CWindow *)eventmsg->obj; + DEBUGASSERT(cwin != (FAR CWindow *)0); + + // Forward the event to the appropriate window + + return cwin->event(eventmsg); +} + +/** + * Add a window container to the window list. + * + * @param win. The window container to be added to the list. + */ + +void CWindowFactory::addWindow(FAR struct SWindow *win) +{ + win->blink = (FAR struct SWindow *)0; + win->flink = m_windowHead; + + if (m_windowHead != (FAR struct SWindow *)0) + { + m_windowHead->blink = win; + } + + m_windowHead = win; +} + +/** + * Remove a window container from the window list. + * + * @param win. The window container to be removed from the list. + */ + +void CWindowFactory::removeWindow(FAR struct SWindow *win) +{ + FAR struct SWindow *prev = win->blink; + FAR struct SWindow *next = win->flink; + + if (prev == (FAR struct SWindow *)0) + { + m_windowHead = next; + } + else + { + prev->flink = next; + } + + if (next != (FAR struct SWindow *)0) + { + next->blink = prev; + } + + win->flink = NULL; + win->blink = NULL; +} + +/** + * Find the window container that contains the specified window. + * + * @param cwin. The window whose container is needed. + * @return On success, the container of the specific window is returned; + * NULL is returned on failure. + */ + +FAR struct SWindow *CWindowFactory::findWindow(FAR CWindow *cwin) +{ + for (FAR struct SWindow *win = m_windowHead; + win != (FAR struct SWindow *)0; + win = win->flink) + { + if (win->cwin == cwin) + { + return win; + } + } + + return (FAR struct SWindow *)0; +} diff --git a/graphics/twm4nx/src/twm4nx_cursor.cxx b/graphics/twm4nx/src/twm4nx_cursor.cxx new file mode 100644 index 000000000..19a7a84b2 --- /dev/null +++ b/graphics/twm4nx/src/twm4nx_cursor.cxx @@ -0,0 +1,65 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/src/twm4nx_cursor.cxx +// Cursor images +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// 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 +#include + +#include "graphics/twm4nx/twm4nx_cursor.hxx" + +#ifdef CONFIG_NX_SWCURSOR + +///////////////////////////////////////////////////////////////////////////// +// Pulbic Data +///////////////////////////////////////////////////////////////////////////// + +namespace Twm4Nx +{ +#ifdef CONFIG_TWM4NX_CURSOR_LARGE +# include "cursor-arrow1-30x30.h" +# include "cursor-grab-25x30.h" +# include "cursor-wait-23x30.h" +#else +# include "cursor-arrow1-16x16.h" +# include "cursor-grab-14x16.h" +# include "cursor-wait-13x16.h" +#endif +} + +#endif // CONFIG_NX_SWCURSOR diff --git a/include/graphics/nxglyphs.hxx b/include/graphics/nxglyphs.hxx index b71336e11..a028ab913 100644 --- a/include/graphics/nxglyphs.hxx +++ b/include/graphics/nxglyphs.hxx @@ -129,12 +129,15 @@ namespace NXWidgets extern const struct SBitmap g_capslock; extern const struct SBitmap g_control; - // Bitmaps used by NxWM + // Bitmaps used by NxWM and Twm4Nx // Global RLE Paletted Bitmaps extern const struct SRlePaletteBitmap g_calculatorBitmap; extern const struct SRlePaletteBitmap g_calibrationBitmap; extern const struct SRlePaletteBitmap g_cmdBitmap; + extern const struct SRlePaletteBitmap g_menuBitmap; + extern const struct SRlePaletteBitmap g_resizeBitmap; + extern const struct SRlePaletteBitmap g_nxiconBitmap; // Used by NxWM meda player diff --git a/include/graphics/nxwidgets/cnxfont.hxx b/include/graphics/nxwidgets/cnxfont.hxx index d7cc57a47..6b896bc5f 100644 --- a/include/graphics/nxwidgets/cnxfont.hxx +++ b/include/graphics/nxwidgets/cnxfont.hxx @@ -48,6 +48,8 @@ #include #include +#include "graphics/nxwidgets/nxconfig.hxx" + /**************************************************************************** * Pre-Processor Definitions ****************************************************************************/ diff --git a/include/graphics/nxwidgets/cwidgetcontrol.hxx b/include/graphics/nxwidgets/cwidgetcontrol.hxx index eef05dcc2..0666003f1 100644 --- a/include/graphics/nxwidgets/cwidgetcontrol.hxx +++ b/include/graphics/nxwidgets/cwidgetcontrol.hxx @@ -437,8 +437,8 @@ namespace NXWidgets * pollKeyboardEvents() * pollCursorControlEvents() * - * @param widget. Specific widget to poll. Use NULL to run the - * all widgets in the window. + * @param widget. Specific widget to poll. Use NULL to run through + * of the widgets in the window. * @return True means some interesting event occurred */ diff --git a/include/graphics/twm4nx/cbackground.hxx b/include/graphics/twm4nx/cbackground.hxx new file mode 100644 index 000000000..5f60090b7 --- /dev/null +++ b/include/graphics/twm4nx/cbackground.hxx @@ -0,0 +1,141 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/include/cbackground.hxx +// Manage background image +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// 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 __APPS_INCLUDE_GRAPHICS_TWM4NX_CBACKGROUND_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_CBACKGROUND_HXX + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "graphics/nxwidgets/nxconfig.hxx" +#include "graphics/nxwidgets/cnxwindow.hxx" +#include "graphics/nxwidgets/cnxserver.hxx" +#include "graphics/nxwidgets/cwidgeteventhandler.hxx" +#include "graphics/nxwidgets/cwidgeteventargs.hxx" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Implementation Class Definition + ****************************************************************************/ + +namespace NXWidgets +{ + class CBgWindow; // Forward reference + class CImage; // Forward reference + struct SRlePaletteBitmap; // Forward reference +} + +namespace Twm4Nx +{ + class CTwm4Nx; // Forward reference + /** + * Background management + */ + + class CBackground + { + protected: + FAR CTwm4Nx *m_twm4nx; /**< Cached CTwm4Nx instance */ + FAR NXWidgets::CBgWindow *m_backWindow; /**< The background window */ + FAR NXWidgets::CImage *m_backImage; /**< The background image */ + + /** + * Create the background window. + * + * @return true on success + */ + + bool createBackgroundWindow(void); + + /** + * Create the background image. + * + * @param sbitmap. Identifies the bitmap to paint on background + * @return true on success + */ + + bool createBackgroundImage(FAR const struct NXWidgets::SRlePaletteBitmap *sbitmap); + + /** + * (Re-)draw the background window. + * + * @return true on success + */ + + bool redrawBackgroundWindow(void); + + public: + /** + * CBackground Constructor + * + * @param twm4nx The Twm4Nx session object + */ + + CBackground(FAR CTwm4Nx *twm4nx); + + /** + * CBackground Destructor + */ + + ~CBackground(void); + + /** + * Set the background image + * + * @param sbitmap. Identifies the bitmap to paint on background + * @return true on success + */ + + bool setBackgroundImage(FAR const struct NXWidgets::SRlePaletteBitmap *sbitmap); + + /** + * Get the size of the physical display device which is equivalent to + * size of the background window. + * + * @return The size of the display + */ + + void getDisplaySize(FAR struct nxgl_size_s &size); + }; +} + +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CBACKGROUND_HXX diff --git a/include/graphics/twm4nx/cfonts.hxx b/include/graphics/twm4nx/cfonts.hxx new file mode 100644 index 000000000..916a59f1c --- /dev/null +++ b/include/graphics/twm4nx/cfonts.hxx @@ -0,0 +1,182 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/include/cfonts.hxx +// Font support for twm4nx +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// Copyright 1988 by Evans & Sutherland Computer Corporation, +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 __APPS_INCLUDE_GRAPHICS_TWM4NX_CFONTS_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_CFONTS_HXX + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include +#include + +///////////////////////////////////////////////////////////////////////////// +// Implementation Classes +///////////////////////////////////////////////////////////////////////////// + +namespace NXWidgets +{ + class CNxFont; // Forward reference +} + +namespace Twm4Nx +{ + class CTwm4Nx; // Forward reference + + /** + * The CFonts class encapsulates font support. + */ + + class CFonts + { + private: + FAR CTwm4Nx *m_twm4nx; /**< The Twm4Nx session */ + FAR NXWidgets::CNxFont *m_titleFont; /**< Title bar font */ + FAR NXWidgets::CNxFont *m_menuFont; /**< Menu font */ + FAR NXWidgets::CNxFont *m_iconFont; /**< Icon font */ + FAR NXWidgets::CNxFont *m_sizeFont; /**< Resize font */ + FAR NXWidgets::CNxFont *m_iconManagerFont; /**< Window list font */ + FAR NXWidgets::CNxFont *m_defaultFont; /**< The default found */ + + public: + + /** + * CFonts Constructor + * + * @param twm4nx. An instance of the Twm4Nx session. + */ + + CFonts(FAR CTwm4Nx *twm4nx); + + /** + * CFonts Destructor + */ + + ~CFonts(void); + + /** + * Initialize fonts + * + * @return True is returned if the fonts were correctly initialized; + * false is returned in the event of an error. + */ + + bool initialize(void); + + /** + * Return the Title font + * + * @return A reference to the initialized title font. + */ + + FAR NXWidgets::CNxFont *getTitleFont(void) + { + return m_titleFont; + } + + /** + * Return the Menu font + * + * @return A reference to the initialized menu font. + */ + + FAR NXWidgets::CNxFont *getMenuFont(void) + { + return m_menuFont; + } + + /** + * Return the Icon font + * + * @return A reference to the initialized menu font. + */ + + FAR NXWidgets::CNxFont *getIconFont(void) + { + return m_iconFont; + } + + /** + * Return the Size font + * + * @return A reference to the initialized menu font. + */ + + FAR NXWidgets::CNxFont *getSizeFont(void) + { + return m_sizeFont; + } + + /** + * Return the IconManager font + * + * @return A reference to the initialized menu font. + */ + + FAR NXWidgets::CNxFont *getIconManagerFont(void) + { + return m_iconManagerFont; + } + + /** + * Return the Default font + * + * @return A reference to the initialized menu font. + */ + + FAR NXWidgets::CNxFont *getDefaultFont(void) + { + return m_defaultFont; + } + }; +} + +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CFONTS_HXX diff --git a/include/graphics/twm4nx/cicon.hxx b/include/graphics/twm4nx/cicon.hxx new file mode 100644 index 000000000..1a4d5265d --- /dev/null +++ b/include/graphics/twm4nx/cicon.hxx @@ -0,0 +1,189 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/include/cicon.hxx +// Icon related definitions +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 __APPS_INCLUDE_GRAPHICS_TWM4NX_CICON_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_CICON_HXX + +///////////////////////////////////////////////////////////////////////////// +// Implementation Classes +///////////////////////////////////////////////////////////////////////////// + +namespace Twm4Nx +{ + class CTwm4Nx; /* Forward reference */ + struct SIconEntry; /* Forward reference */ + + struct SIconRegion + { + FAR struct SIconRegion *flink; + struct nxgl_point_s pos; + struct nxgl_size_s size; + struct nxgl_point_s step; // allocation granularity + FAR struct SIconEntry *entries; + }; + + struct SIconEntry + { + FAR struct SIconEntry *flink; + struct nxgl_point_s pos; + struct nxgl_size_s size; + FAR CWindow *cwin; + bool used; + }; + + /** + * The CIcon class supports a database of icons. + */ + + class CIcon + { + private: + + FAR CTwm4Nx *m_twm4nx; /**< The Twm4Nx session */ + FAR struct SNameList *m_icons; /**< List of icon images */ + FAR struct SIconRegion *m_regionHead; /**< Head of the icon region list */ + FAR struct SIconRegion *m_regionTail; /**< Tail of the icon region list */ + + inline int roundUp(int v, int multiple) + { + return ((v + multiple - 1) / multiple) * multiple; + } + + /** + * Find the icon region holding the window 'cwin' + * + * @param cwin The window whose icon region is sought + * @param irp A location in which to provide the region + */ + + FAR struct SIconEntry *findEntry(FAR CWindow *cwin, + FAR struct SIconRegion **irp); + + /** + * Given entry 'ie' in the list 'ir', return the entry just prior to 'ie' + * + * @param ie The entry whose predecessor is sought + * @param ir The region containing the entry + * @return The entry just before 'ie' in the list + */ + + FAR struct SIconEntry *prevEntry(FAR struct SIconEntry *ie, + FAR struct SIconRegion *ir); + + /** + * 'old' is being freed; and is adjacent to ie. Merge + * regions together + */ + + void mergeEntries(FAR struct SIconEntry *old, + FAR struct SIconEntry *ie); + + /** + * Free all of the icon entries linked to a region + * + * @param ir The region whose entries will be freed + */ + + void freeIconEntries(FAR struct SIconRegion *ir); + + /** + * Free all icon regions and all of the region entries linked into the + * region + */ + + void freeIconRegions(void); + + public: + + /** + * CIcon Constructor + */ + + CIcon(FAR CTwm4Nx *twm4nx); + + /** + * CIcon Destructor + */ + + ~CIcon(void); + + /** + * Create a new icon region and add it to the list of icon regions. + * + * @param pos The position of the region on the background + * @param size The size of the region + * @param step + */ + + void addIconRegion(FAR nxgl_point_s *pos, FAR nxgl_size_s *size, + FAR struct nxgl_point_s *step); + + /** + * Position an icon on the background + * + * @param cwin The Window whose icon will be placed + * @param pos An backup position to use is there are no available regions + * @param final A location in which to return the selection icon position + */ + + void place(FAR CWindow *cwin, FAR const struct nxgl_point_s *pos, + FAR struct nxgl_point_s *final); + + /** + * Bring the window up. + * + * @param cwin. The window to be brought up. + */ + + void up(FAR CWindow *cwin); + + /** + * Take the window down. + * + * @param cwin. The window to be taken down. + */ + + void down(FAR CWindow *cwin); + }; +} + +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CICON_HXX diff --git a/include/graphics/twm4nx/ciconmgr.hxx b/include/graphics/twm4nx/ciconmgr.hxx new file mode 100644 index 000000000..cb689b578 --- /dev/null +++ b/include/graphics/twm4nx/ciconmgr.hxx @@ -0,0 +1,269 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/include/ciconmgr.hxx +// Icon Manager includes +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 __APPS_INCLUDE_GRAPHICS_TWM4NX_CICONMGR_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_CICONMGR_HXX + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include +#include "graphics/twm4nx/cwindow.hxx" + +///////////////////////////////////////////////////////////////////////////// +// Implementation Classes +///////////////////////////////////////////////////////////////////////////// + +namespace NXWidgets +{ + class CNxTkWindow; // Forward reference + struct SRlePaletteBitmap; // Forward reference +} + +namespace Twm4Nx +{ + struct SWindowEntry + { + FAR struct SWindowEntry *flink; + FAR struct SWindowEntry *blink; + FAR CWindow *cwin; // Used only for the window name + FAR CIconMgr *iconmgr; + nxgl_point_s pos; + nxgl_size_s size; + int row; + int col; + int me; + bool active; + bool down; + }; + + class CIconMgr + { + private: + + FAR CTwm4Nx *m_twm4nx; /**< Cached Twm4Nx session */ + FAR struct SWindowEntry *m_head; /**< Head of the window list */ + FAR struct SWindowEntry *m_tail; /**< Tail of the window list */ + FAR struct SWindowEntry *m_active; /**< The active entry */ + FAR struct CWindow *m_window; /**< Parent window */ + unsigned int m_columns; /**< Number of columns icon manager */ + unsigned int m_currows; + unsigned int m_curcolumns; + unsigned int m_count; + + /** + * Create and initialize the icon manager window + * + * @param name The prefix for this icon manager name + */ + + bool createWindow(FAR const char *prefix); + + /** + * Create the button array widget + */ + + bool createButtonArray(void); + + /** + * Put an allocated entry into an icon manager + * + * @param wentry the entry to insert + */ + + void insertEntry(FAR struct SWindowEntry *wentry, + FAR CWindow *cwin); + + /** + * Remove an entry from an icon manager + * + * @param wentry the entry to remove + */ + + void removeEntry(FAR struct SWindowEntry *wentry); + + /** + * Set active window + * + * @param wentry Window to become active. + */ + + void active(FAR struct SWindowEntry *wentry); + + /** + * Set window inactive + * + * @param wentry windows to become inactive. + */ + + void inactive(FAR struct SWindowEntry *wentry); + + /** + * Free window list entry. + */ + + void freeWEntry(FAR struct SWindowEntry *wentry); + + public: + + /** + * CIconMgr Constructor + * + * @param twm4nx The Twm4Nx session + * @param ncolumns The number of columns this icon manager has + */ + + CIconMgr(CTwm4Nx *twm4nx, int ncolumns); + + /** + * CIconMgr Destructor + */ + + ~CIconMgr(void); + + /** + * Create and initialize the icon manager window + * + * @param name The prefix for this icon manager name + */ + + bool initialize(FAR const char *prefix); + + /** + * Add a window to an the icon manager + * + * @param win the TWM window structure + */ + + bool add(FAR CWindow *win); + + /** + * Hide the icon manager + */ + + inline void hide(void) + { + if (m_window != (FAR CWindow *)0) + { + m_window->iconify(); + } + } + + /** + * Remove a window from the icon manager + * + * @param win the TWM window structure + */ + + void remove(FAR struct SWindow *win); + + /** + * Get the number of columns + */ + + inline unsigned int getColumns(void) + { + return m_columns; + } + + /** + * Get the current column + */ + + inline unsigned int getCurrColumn(void) + { + return m_curcolumns; + } + + /** + * Get the current size + */ + + inline bool getSize(FAR struct nxgl_size_s *size) + { + return m_window->getFrameSize(size); + } + + /** + * Move the pointer around in an icon manager + * + * @param dir one of the following: + * - EVENT_ICONMGR_FORWARD: Forward in the window list + * - EVENT_ICONMGR_BACK: Backward in the window list + * - EVENT_ICONMGR_UP: Up one row + * - EVENT_ICONMGR_DOWN: Down one row + * - EVENT_ICONMGR_LEFT: Left one column + * - EVENT_ICONMGR_RIGHT: Right one column + */ + + void move(int dir); + + /** + * Pack the icon manager windows following an addition or deletion + */ + + void pack(void); + + /** + * sort the windows + */ + + void sort(void); + + /** + * Handle ICONMGR events. + * + * @param eventmsg. The received NxWidget ICONMGR event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + + bool event(FAR struct SEventMsg *eventmsg); + }; +} + +///////////////////////////////////////////////////////////////////////////// +// Public Function Prototypes +///////////////////////////////////////////////////////////////////////////// + +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CICONMGR_HXX diff --git a/include/graphics/twm4nx/ciconwin.hxx b/include/graphics/twm4nx/ciconwin.hxx new file mode 100644 index 000000000..4b949909e --- /dev/null +++ b/include/graphics/twm4nx/ciconwin.hxx @@ -0,0 +1,214 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/include/ciconwin.hxx +// Icon Windows +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 __APPS_INCLUDE_GRAPHICS_TWM4NX_CICONWIN_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_CICONWIN_HXX + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include + +#include "graphics/nxwidgets/cnxwindow.hxx" + +///////////////////////////////////////////////////////////////////////////// +// Implementation Classes +///////////////////////////////////////////////////////////////////////////// + +namespace NXWidgets +{ + struct SRlePaletteBitmap; // Forward reference +} + +namespace Twm4Nx +{ + class CTwm4Nx; // Forward reference + class CWindow; // Forward reference + + /** + * The CIconWin represents on icon window + */ + + class CIconWin + { + private: + + FAR CTwm4Nx *m_twm4nx; /**< The Twm4Nx session */ + FAR NXWidgets::CNxWindow *m_nxwin; /**< The cursor "raw" window */ + + // Dragging + + struct nxgl_point_s m_dragPos; /**< Last mouse 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_drag; /**< Drag in-progress */ + + /** + * Handle the ICON_GRAB event. That corresponds to a left + * mouse click on the icon + * + * @param eventmsg. The received NxWidget event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + + bool iconGrab(FAR struct SEventMsg *eventmsg); + + /** + * Handle the ICON_DRAG event. That corresponds to a mouse + * movement when the icon is in a grabbed state. + * + * @param eventmsg. The received NxWidget event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + + bool iconDrag(FAR struct SEventMsg *eventmsg); + + /** + * Handle the ICON_UNGRAB event. The corresponds to a mouse + * left button release while in the grabbed + * + * @param eventmsg. The received NxWidget event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + + bool iconUngrab(FAR struct SEventMsg *eventmsg); + + /** + * Cleanup on failure or as part of the destructor + */ + + void cleanup(void); + + public: + + /** + * CIconWin Constructor + */ + + CIconWin(CTwm4Nx *twm4nx); + + /** + * CIconWin Destructor + */ + + ~CIconWin(void); + + /** + * Initialize the icon window + * + * @param parent The parent window + * @param sbitmap The Icon bitmap image + * @param pos The default position + */ + + bool initialize(FAR CWindow *parent, + FAR const struct NXWidgets::SRlePaletteBitmap *sbitmap, + FAR const struct nxgl_point_s *pos); + + /** + * Get the size of the icon window on the background + * + * @param size The location to return the size of the icon window + */ + + inline bool getSize(FAR struct nxgl_size_s *size) + { + return m_nxwin->getSize(size); + } + + /** + * Get the icon window position on the background + * + * @param size The location to return the position of the icon window + */ + + inline bool getPosition(FAR struct nxgl_point_s *pos) + { + return m_nxwin->getPosition(pos); + } + + /** + * Set the icon window position on the background + * + * @param size The new position of the icon window + */ + + inline bool setPosition(FAR const struct nxgl_point_s *pos) + { + return m_nxwin->setPosition(pos); + } + + /** + * Raise the icon window. + */ + + inline void raise(void) + { + m_nxwin->raise(); + } + + /** + * Lower the icon window. + */ + + inline void lower(void) + { + m_nxwin->lower(); + } + + /** + * Handle ICON WINDOW events. + * + * @param eventmsg. The received NxWidget ICON event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + + bool event(FAR struct SEventMsg *eventmsg); + }; +} + +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CICONWIN_HXX diff --git a/include/graphics/twm4nx/cinput.hxx b/include/graphics/twm4nx/cinput.hxx new file mode 100644 index 000000000..e4a9ea218 --- /dev/null +++ b/include/graphics/twm4nx/cinput.hxx @@ -0,0 +1,209 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/include/cinput.hxx +// Keyboard injection +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// 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 __APPS_INCLUDE_GRAPHICS_TWM4NX_CINPUT_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_CINPUT_HXX + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include + +#include + +#include "graphics/nxwidgets/cnxserver.hxx" + +///////////////////////////////////////////////////////////////////////////// +// Implementation Classes +///////////////////////////////////////////////////////////////////////////// + +namespace Twm4Nx +{ + class CTwm4Nx; // Forward reference + + /** + * The CInput class provides receives raw keyboard and mouse inputs and + * injects that input into NX which it can be properly distributed to the + * window that has focus (i.e., the window at the top of the display + * hierarchy, often a modal window). In additional, the cursor is + * controlled to track the mouse position. + */ + + class CInput + { + private: + + /** + * The state of the listener thread. + */ + + enum EListenerState + { + LISTENER_NOTRUNNING = 0, /**< The listener thread has not yet been started */ + LISTENER_STARTED, /**< The listener thread has been started, but is not yet running */ + LISTENER_RUNNING, /**< The listener thread is running normally */ + LISTENER_STOPREQUESTED, /**< The listener thread has been requested to stop */ + LISTENER_TERMINATED, /**< The listener thread terminated normally */ + LISTENER_FAILED /**< The listener thread terminated abnormally */ + }; + + /** + * CInput state data + */ + + CTwm4Nx *m_twm4nx; /**< The Twm4Nx session */ + int m_kbdFd; /**< File descriptor of the opened keyboard device */ + int m_mouseFd; /**< File descriptor of the opened mouse device */ + 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 */ + + /** + * Open the keyboard device. Not very interesting for the case of + * standard device but much more interesting for a USB keyboard device + * that may disappear when the keyboard is disconnect but later reappear + * when the keyboard is reconnected. In this case, this function will + * not return until the keyboard device was successfully opened (or + * until an irrecoverable error occurs. + * + * Opens the keyboard device specified by CONFIG_TWM4NX_KEYBOARD_DEVPATH. + * + * @return On success, then method returns a valid file descriptor. A + * negated errno value is returned if an irrecoverable error occurs. + */ + + inline int keyboardOpen(void); + + /** + * Open the mouse input devices. Not very interesting for the + * case of standard character device but much more interesting for + * USB mouse devices that may disappear when disconnected but later + * reappear when reconnected. In this case, this function will + * not return until the input device was successfully opened (or + * until an irrecoverable error occurs). + * + * Opens the mouse input device specified by CONFIG_TWM4NX_MOUSE_DEVPATH. + * + * @return On success, then method returns a valid file descriptor. A + * negated errno value is returned if an irrecoverable error occurs. + */ + + inline int mouseOpen(void); + + /** + * Read data from the keyboard device and inject the keyboard data + * into NX for proper distribution. + * + * @return On success, then method returns a valid file descriptor. A + * negated errno value is returned if an irrecoverable error occurs. + */ + + inline int keyboardInput(void); + + /** + * Read data from the mouse device, update the cursor position, and + * inject the mouse data into NX for proper distribution. + * + * @return On success, then method returns a valid file descriptor. A + * negated errno value is returned if an irrecoverable error occurs. + */ + + inline int mouseInput(void); + + /** + * This is the heart of the keyboard/mouse listener thread. It + * contains the actual logic that listeners for and dispatches input + * events to the NX server. + * + * @return If the session terminates gracefully (i.e., because >m_state + * is no longer equal to LISTENER_RUNNING, then method returns OK. A + * negated errno value is returned if an error occurs while reading from + * the input device. A read error, depending upon the type of the + * error, may simply indicate that a USB device was removed and we + * should wait for the device to be connected. + */ + + inline int session(void); + + /** + * The keyboard/mouse listener thread. This is the entry point of a + * thread that listeners for and dispatches keyboard and mouse events + * to the NX server. It simply opens the input devices (using + * CInput::keyboardOpen() and CInput::mouseOpen()) and executes the + * session (via CInput::session()). + * + * If an errors while reading from the input device AND that device is + * configured to use a USB connection, then this function will wait for + * the USB device to be re-connected. + * + * @param arg. The CInput 'this' pointer cast to a void*. + * @return This function normally does not return but may return NULL + * on error conditions. + */ + + static FAR void *listener(FAR void *arg); + + public: + + /** + * CInput Constructor + * + * @param twm4nx. An instance of the Twm4Nx session. + */ + + CInput(CTwm4Nx *twm4nx); + + /** + * CInput Destructor + */ + + ~CInput(void); + + /** + * Start the keyboard listener thread. + * + * @return True if the keyboard listener thread was correctly started. + */ + + bool start(void); + }; +} + +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CINPUT_HXX diff --git a/include/graphics/twm4nx/cmenus.hxx b/include/graphics/twm4nx/cmenus.hxx new file mode 100644 index 000000000..f790b8590 --- /dev/null +++ b/include/graphics/twm4nx/cmenus.hxx @@ -0,0 +1,289 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/include/Cmenus.hxx +// Twm4Nx menus definitions +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// Copyright 1988 by Evans & Sutherland Computer Corporation, +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 __APPS_INCLUDE_GRAPHICS_TWM4NX_CMENUS_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_CMENUS_HXX + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include "mqueue.h" + +#include "graphics/nxwidgets/cwidgeteventhandler.hxx" +#include "graphics/nxwidgets/cwidgeteventargs.hxx" + +///////////////////////////////////////////////////////////////////////////// +// Pre-processor Definitions +///////////////////////////////////////////////////////////////////////////// + +#define TWM_WINDOWS "TwmNxWindows" // for f.menu "TwmNxWindows" + +#define SIZE_HINDENT 10 +#define SIZE_VINDENT 2 + +#define MAXMENUDEPTH 10 // max number of nested menus + +#define MOVE_NONE 0 // modes of constrained move +#define MOVE_VERT 1 +#define MOVE_HORIZ 2 + +#define SHADOWWIDTH 5 // in pixels + +// Info stings defines + +#define INFO_LINES 30 +#define INFO_SIZE 200 + +///////////////////////////////////////////////////////////////////////////// +// Implementation Classes +///////////////////////////////////////////////////////////////////////////// + +namespace NXWidgets +{ + class CNxTkWindow; // Forward reference + class CListBox; // Forward reference +} + +namespace Twm4Nx +{ + struct SEventMsg; // Forward referernce + class CWindow; // Forward reference + class CMenus; // Forward reference + + struct SMenuItem + { + FAR struct SMenuItem *flink; /**< Forward link to next menu item */ + FAR struct SMenuItem *blink; /**< Backward link previous menu item */ + FAR CMenus *subMenu; /**< Menu root of a pull right menu */ + FAR char *text; /**< The text string for the menu item */ + FAR const char *action; /**< Action to be performed */ + short index; /**< Index of this menu item */ + short func; /**< Built-in function */ + }; + + class CMenus: protected NXWidgets::CWidgetEventHandler + { + private: + + CTwm4Nx *m_twm4nx; /**< Cached Twm4Nx session */ + mqd_t m_eventq; /**< NxWidget event message queue */ + FAR struct SFuncKey *m_funcKeyHead; /**< Head of function key list */ + FAR NXWidgets::CNxTkWindow *m_menuWindow; /**< The menu window */ + FAR CMenus *m_popUpMenu; /**< Pop-up menu */ + FAR NXWidgets::CListBox *m_menuListBox; /**< The menu list box */ + FAR struct SMenuItem *m_activeItem; /**< The active menu item */ + FAR struct SMenuItem *m_menuHead; /**< First item in menu */ + FAR struct SMenuItem *m_menuTail; /**< Last item in menu */ + FAR char *m_menuName; /**< The name of the menu */ + nxgl_coord_t m_entryHeight; /**< Menu entry height */ + uint16_t m_nMenuItems; /**< Number of items in the menu */ + uint8_t m_menuDepth; /**< Number of menus up */ + bool m_menuPull; /**< Is there a pull right entry? */ + char m_info[INFO_LINES][INFO_SIZE]; + + void identify(FAR CWindow *cwin); + + /** + * Convert the position of a menu window to the position of + * the containing frame. + */ + + inline void menuToFramePos(FAR const struct nxgl_point_s *menupos, + FAR struct nxgl_point_s *framepos) + { + framepos->x = menupos->x - CONFIG_NXTK_BORDERWIDTH; + framepos->y = menupos->y - CONFIG_NXTK_BORDERWIDTH; + } + + /** + * Convert the position of the containing frame to the position of + * the menu window. + */ + + inline void frameToMenuPos(FAR const struct nxgl_point_s *framepos, + FAR struct nxgl_point_s *menupos) + { + menupos->x = framepos->x + CONFIG_NXTK_BORDERWIDTH; + menupos->y = framepos->y + CONFIG_NXTK_BORDERWIDTH; + } + + /** + * Convert the size of a menu window to the size of the containing + * frame. + */ + + inline void menuToFrameSize(FAR const struct nxgl_size_s *menusize, + FAR struct nxgl_size_s *framesize) + { + framesize->w = menusize->w + 2 * CONFIG_NXTK_BORDERWIDTH; + framesize->h = menusize->h + 2 * CONFIG_NXTK_BORDERWIDTH; + } + + /** + * Convert the size of a containing frame to the size of the menu + * window. + */ + + inline void frameToMenuSize(FAR const struct nxgl_size_s *framesize, + FAR struct nxgl_size_s *menusize) + { + menusize->w = framesize->w - 2 * CONFIG_NXTK_BORDERWIDTH; + menusize->h = framesize->h - 2 * CONFIG_NXTK_BORDERWIDTH; + } + + /** + * Create the menu window + * + * @result True is returned on success + */ + + bool createMenuWindow(void); + + /** + * Update the menu window size + * + * @result True is returned on success + */ + + bool setMenuWindowSize(void); + + /** + * Set the position of the menu window. Supports positioning of a + * pop-up window. + * + * @param framePos The position of the menu window frame + * @result True is returned on success + */ + + bool setMenuWindowPosition(FAR struct nxgl_point_s *framePos); + + /** + * Set the position of the menu window. Supports presentation of a + * pop-up window. + * + * @param framePos The position of the menu window frame + * @result True is returned on success + */ + + inline bool raiseMenuWindow() + { + return m_menuWindow->raise(); + } + + /** + * Create the menu list box + * + * @result True is returned on success + */ + + bool createMenuListBox(void); + + void paintMenu(void); + void destroyMenu(void); + + /** + * Pop up a pull down menu. + * + * @param pos Location of upper left of menu + */ + + bool popUpMenu(FAR struct nxgl_point_s *pos); + + /** + * Cleanup or initialization error or on deconstruction. + */ + + void cleanup(void); + + public: + /** + * CMenus Constructor + * + * @param twm4nx. Twm4Nx session + */ + + CMenus(CTwm4Nx *twm4nx); + + /** + * CMenus Destructor + */ + + ~CMenus(void); + + /** + * CMenus Initializer. Performs the parts of the CMenus construction + * that may fail. + * + * @param name The menu name + * @result True is returned on success + */ + + bool initialize(FAR const char *name); + + /** + * Add an item to a root menu + * + * \param text The text to appear in the menu + * \param action The string to possibly execute + * \param subMenu The menu root if it is a pull-right entry + * \param func The numeric function + */ + + bool addMenuItem(FAR const char *text, + FAR const char *action, + FAR CMenus *subMenu, int func); + + /** + * Handle MENU events. + * + * @param msg. The received NxWidget MENU event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + + bool event(FAR struct SEventMsg *msg); + }; +} + +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CMENUS_HXX diff --git a/include/graphics/twm4nx/cresize.hxx b/include/graphics/twm4nx/cresize.hxx new file mode 100644 index 000000000..139a60a9d --- /dev/null +++ b/include/graphics/twm4nx/cresize.hxx @@ -0,0 +1,248 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/include/cresize.hxx +// Resize function externs +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// Copyright 1988 by Evans & Sutherland Computer Corporation, +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 __APPS_INCLUDE_GRAPHICS_TWM4NX_CRESIZE_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_CRESIZE_HXX + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include + +#include + +///////////////////////////////////////////////////////////////////////////// +// Implementation Classes +///////////////////////////////////////////////////////////////////////////// + +namespace NXWidgets +{ + class CNxTkWindow; // Forward reference +} + +namespace Twm4Nx +{ + class CWindow; // Forward referernce + struct SEventMsg; // Forward referernce + + class CResize + { + private: + + CTwm4Nx *m_twm4nx; /**< Cached Twm4Nx session */ + FAR NXWidgets::CNxTkWindow *m_sizeWindow; /**< The resize dimensions window */ + FAR CWindow *m_resizeWindow; /**< The window being resized */ + struct nxgl_point_s m_origpos; /**< Original position */ + struct nxgl_size_s m_origsize; /**< Original size */ + struct nxgl_point_s m_dragpos; /**< Dragged position */ + struct nxgl_size_s m_dragsize; /**< Dragged size */ + struct nxgl_rect_s m_clamp; + struct nxgl_point_s m_delta; + struct nxgl_size_s m_last; + struct nxgl_point_s m_addingPos; + struct nxgl_size_s m_addingSize; + int m_stringWidth; /**< Size of current size string */ + +#ifdef CONFIG_TWM4NX_AUTO_RERESIZE // Resize relative to position in quad + void autoClamp(CWindow *cwin, FAR struct SEventMsg *eventmsg); +#endif + + void resizeFromCenter(FAR CWindow *win); + + /** + * Begin a window resize operation + * @param ev the event structure (button press) + * @param cwin the TWM window pointer + */ + + void startResize(FAR struct SEventMsg *eventmsg, FAR CWindow *cwin); + + void menuStartResize(FAR CWindow *cwin, + FAR struct nxgl_point_s *pos, + FAR struct nxgl_size_s *size); + + /** + * Display the size in the dimensions window. + * + * @param cwin The current window + * @param size The size of the rubber band + */ + + void displaySize(FAR CWindow *cwin, FAR struct nxgl_size_s *size); + + public: + + /** + * CResize Constructor + * + * @param twm4nx The Twm4Nx session + */ + + CResize(CTwm4Nx *twm4nx); + + /** + * CResize Destructor + */ + + ~CResize(void); + + /** + * CResize Initializer. Performs the parts of the CResize construction + * that may fail. + * + * @result True is returned on success + */ + + bool initialize(void); + + /** + * What is this? + */ + + void addingSize(FAR struct nxgl_size_s *size) + { + m_addingSize.w = size->w; + m_addingSize.h = size->h; + } + + /** + * Begin a window resize operation + * + * @param cwin the Twm4Nx window pointer + */ + + void addStartResize(FAR CWindow *cwin, + FAR struct nxgl_point_s *pos, + FAR struct nxgl_size_s *size); + + /** + * @param cwin The current Twm4Nx window + * @param root The X position in the root window + */ + + void menuDoResize(FAR CWindow *cwin, + FAR struct nxgl_point_s *root); + + /** + * Move the rubberband around. This is called for each motion event when + * we are resizing + * + * @param cwin The current Twm4Nx window + * @param root The X position in the root window + */ + + void doResize(FAR CWindow *cwin, + FAR struct nxgl_point_s *root); + + /** + * Finish the resize operation + */ + + void endResize(FAR CWindow *cwin); + + void menuEndResize(FAR CWindow *cwin); + + /** + * Finish the resize operation for AddWindoframe_XXX variables should NOT be updated with the values of + * x,y,w,h prior to calling this routine, since the new values are compared + * against the old to see whether a synthetic ConfigureNotify event should be + * sent. (It should be sent if the window was moved but not resized.) + * + * @param cwin The CWiondow instance + * @param pos The position of the upper-left outer corner of the frame + * @param size The size of the frame window + */ + + void setupWindow(FAR CWindow *cwin, + FAR struct nxgl_point_s *pos, + FAR struct nxgl_size_s *size); + + /** + * Zooms window to full height of screen or to full height and width of screen. + * (Toggles so that it can undo the zoom - even when switching between fullZoom + * and vertical zoom.) + * + * @param cwin the TWM window pointer + */ + + void fullZoom(FAR CWindow *cwin, int flag); + + /** + * Handle RESIZE events. + * + * @param msg. The received NxWidget RESIZE event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + + bool event(FAR struct SEventMsg *msg); + }; +} + +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CRESIZE_HXX diff --git a/include/graphics/twm4nx/ctwm4nx.hxx b/include/graphics/twm4nx/ctwm4nx.hxx new file mode 100644 index 000000000..f4234bcd6 --- /dev/null +++ b/include/graphics/twm4nx/ctwm4nx.hxx @@ -0,0 +1,315 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/include/ctwm4nx.hxx +// twm include file +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// Copyright 1988 by Evans & Sutherland Computer Corporation, +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 __APPS_INCLUDE_GRAPHICS_TWM4NX_CTWM4NX_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_CTWM4NX_HXX + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include +#include + +#include +#include +#include + +#include "graphics/nxwidgets/nxconfig.hxx" +#include "graphics/nxwidgets/cnxserver.hxx" +#include "graphics/nxwidgets/cnxwindow.hxx" +#include "graphics/nxwidgets/cimage.hxx" + +#include "graphics/twm4nx/cwindowevent.hxx" +#include "graphics/twm4nx/twm4nx_widgetevents.hxx" + +///////////////////////////////////////////////////////////////////////////// +// Pre-processor Definitions +///////////////////////////////////////////////////////////////////////////// + +// Defines for zooming/unzooming + +#define ZOOM_NONE 0 + +///////////////////////////////////////////////////////////////////////////// +// Implementation Classes +///////////////////////////////////////////////////////////////////////////// + +namespace Twm4Nx +{ + class CInput; // Forward reference + class CBackground; // Forward reference + class CWidgetEvent; // Forward reference + class CIcon; // Forward reference + class CIconMgr; // Forward reference + class CFonts; // Forward reference + class CWindow; // Forward reference + class CResize; // Forward reference + class CWindowFactory; // Forward reference + class CResize; // Forward reference + struct SWindow; // Forward reference + + /** + * Public Constant Data + */ + + extern const char GNoName[]; /**< Name to use when there is no name */ + + /** + * This class provides the overall state of the window manager. It is also + * the heart of the window manager: It inherits for CNxServer and, hence, + * represents the NX server itself. + */ + + class CTwm4Nx : public NXWidgets::CNxServer + { + private: + int m_display; /**< Display that we are using */ + FAR char *m_queueName; /**< NxWidget event queue name */ + mqd_t m_eventq; /**< NxWidget event message queue */ + FAR CBackground *m_background; /**< Background window management */ + FAR CInput *m_input; /**< Keyboard/mouse input injector */ + FAR CIcon *m_icon; /**< The cached Cicon instance */ + FAR CIconMgr *m_iconmgr; /**< The Default icon manager */ + FAR CWindowFactory *m_factory; /**< The cached CWindowFactory instance */ + FAR CFonts *m_fonts; /**< The cached Cfonts instance */ + FAR CResize *m_resize; /**< The cached CResize instance */ + + /* Display properties */ + + FAR struct nxgl_size_s m_displaySize; /**< Size of the display */ + FAR struct nxgl_size_s m_maxWindow; /**< Maximum size of a window */ + + /** + * Connect to the NX server + * + * @return True if the message was properly handled. false is + * return on any failure. + */ + + bool connect(void); + + /** + * Generate a random message queue name. Different message queue + * names are required for each instance of Twm4Nx that is started. + */ + + inline void genMqName(void); + + /** + * Handle SYSTEM events. + * + * @param eventmsg. The received NxWidget SYSTEM event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + + inline bool systemEvent(FAR struct SEventMsg *eventmsg); + + /** + * Cleanup in preparation for termination. + */ + + void cleanup(void); + + public: + + /** + * CTwm4Nx Constructor + * + * @param display. Indicates which display will be used. Usually zero + * except in the case wehre there of multiple displays. + */ + + CTwm4Nx(int display); + + /** + * CTwm4Nx Destructor + */ + + ~CTwm4Nx(void); + + /** + * This is the main, controlling thread of the window manager. It is + * called only from the extern "C" main() entry point. + * + * NOTE: In the event of truly abnormal conditions, this function will + * not return. It will exit via the abort() method. + * + * @return True if the window manager was terminated properly. false is + * return on any failure. + */ + + bool run(void); + + /** + * Return a reference to the randomly generated event messageq queue + * name. Different message queue names are required for each instance + * of Twm4Nx that is started. + */ + + inline FAR const char *getEventQueueName(void) + { + return m_queueName; + } + + /** + * Return the size of the physical display (whichi is equivalent to the + * size of the contained background window). + * + * @return The size of the display. + */ + + inline void getDisplaySize(FAR struct nxgl_size_s *size) + { + size->w = m_displaySize.w; + size->h = m_displaySize.h; + } + + /** + * Return the pixel depth. + * + * REVISIT: Currently only the pixel depth configured for NxWidgets is + * supported. That is probably compatible ith support for multiple + * displays of differing resolutions. + * + * @return The number of bits-per-pixel. + */ + + inline uint8_t getPixelDepth(void) + { + return CONFIG_NXWIDGETS_BPP; + } + + /** + * Return the maximum size of a window. + * + * @return The maximum size of a window. + */ + + inline void maxWindowSize(FAR struct nxgl_size_s *size) + { + size->w = m_maxWindow.w; + size->h = m_maxWindow.h; + } + + /** + * Return the session's Icon instance. + * + * @return The contained instance of the Icon class for this session. + */ + + inline FAR CIcon *getIcon(void) + { + return m_icon; + } + + /** + * Return the session's Icon Manager instance. + * + * @return The contained instance of the Icon Manager for this session. + */ + + inline FAR CIconMgr *getIconMgr(void) + { + return m_iconmgr; + } + + /** + * Return the session's CWindowFactory instance. + * + * @return The contained instance of the CWindow instance this session. + */ + + inline FAR CWindowFactory *getWindowFactory(void) + { + return m_factory; + } + + /** + * Return the session's CFonts instance. + * + * @return The contained instance of the CMenus instance for this session. + */ + + inline FAR CFonts *getFonts(void) + { + return m_fonts; + } + + /** + * Return the session's CResize instance. + * + * @return The contained instance of the CResize instance for this + * session. + */ + + inline FAR CResize *getResize(void) + { + return m_resize; + } + + /** + * Dispatch NxWidget-related events. Normally used only internally + * but there is one use case where messages are injected here from + * CMenus. + * + * @param eventmsg. The received NxWidget event message. + * @return True if the message was properly dispatched. false is + * return on any failure. + */ + + bool dispatchEvent(FAR struct SEventMsg *eventmsg); + + /** + * Cleanup and exit Twm4Nx abnormally. + */ + + void abort(void); + }; +} + +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CTWM4NX_HXX diff --git a/include/graphics/twm4nx/cwindow.hxx b/include/graphics/twm4nx/cwindow.hxx new file mode 100644 index 000000000..0f6f919fb --- /dev/null +++ b/include/graphics/twm4nx/cwindow.hxx @@ -0,0 +1,592 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/include/cwindow.hxx +// Represents one window instance +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// Copyright 1988 by Evans & Sutherland Computer Corporation, +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 __APPS_INCLUDE_GRAPHICS_TWM4NX_CWINDOW_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_CWINDOW_HXX + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include + +#include + +#include "graphics/nxwidgets/cnxtoolbar.hxx" +#include "graphics/nxwidgets/cwidgeteventhandler.hxx" +#include "graphics/nxwidgets/cwidgeteventargs.hxx" + +#include "graphics/twm4nx/ciconwin.hxx" + +///////////////////////////////////////////////////////////////////////////// +// Pre-processor Definitions +///////////////////////////////////////////////////////////////////////////// + +/** + * Toolbar Icons. The Title bar contains (from left to right): + * + * 1. Menu button + * 2. Window title (text) + * 3. Minimize (Iconify) button + * 4. Resize button + * 5. Delete button + * + * There is no focus indicator + */ + +#define MENU_BUTTON 0 // First on left +#define DELETE_BUTTON 1 // First on right +#define RESIZE_BUTTON 2 +#define MINIMIZE_BUTTON 3 +#define NTOOLBAR_BUTTONS 4 + +///////////////////////////////////////////////////////////////////////////// +// Implementation Classes +///////////////////////////////////////////////////////////////////////////// + +namespace NXWidgets +{ + class CImage; // Forward reference + class CLabel; // Forward reference + struct SRlePaletteBitmap; // Forward reference +} + +namespace Twm4Nx +{ + class CIconWin; // Forward reference + class CIconMgr; // Forward reference + class CWindow; // Forward reference + struct SMenuRoot; // Forward reference + struct SMenuItem; // Forward reference + struct SToolbarButton; // Forward reference + + // The CWindow class implements a standard, framed window with a toolbar + // containing the standard buttons and the window title. + + class CWindow : protected NXWidgets::CWidgetEventHandler + { + private: + CTwm4Nx *m_twm4nx; /**< Cached Twm4Nx session */ + mqd_t m_eventq; /**< NxWidget event message queue */ + + // Primary Window + + FAR char *m_name; /**< Name of the window */ + FAR NXWidgets::CNxTkWindow *m_nxWin; /**< The contained NX primary window */ + uint16_t m_zoom; /**< Window zoom: ZOOM_NONE or EVENT_RESIZE_* */ + bool m_modal; /**< Window zoom: ZOOM_NONE or EVENT_RESIZE_* */ + + // Icon + + FAR CIconWin *m_iconWin; /**< The icon window */ + FAR CIconMgr *m_iconMgr; /**< Pointer to it if this is an icon manager */ + bool m_isIconMgr; /**< This is an icon manager window */ + bool m_iconMoved; /**< User explicitly moved the icon. */ + bool m_iconOn; /**< Icon is visible. */ + bool m_iconified; /**< Is the window an icon now ? */ + + // Toolbar + + FAR NXWidgets::CNxToolbar *m_toolbar; /**< The tool bar sub-window */ + FAR NXWidgets::CLabel *m_tbTitle; /**< Toolbar title widget */ + nxgl_coord_t m_tbHeight; /**< Height of the toolbar */ + nxgl_coord_t m_tbLeftX; /**< Rightmost position of left buttons */ + nxgl_coord_t m_tbRightX; /**< Leftmost position of right buttons */ + + // List of all toolbar button images + + FAR NXWidgets::CImage *m_tbButtons[NTOOLBAR_BUTTONS]; + + // Dragging + + struct nxgl_point_s m_dragOffset; /**< Offset from mouse to window origin */ + struct nxgl_size_s m_dragCSize; /**< The grab cursor size */ + bool m_drag; /**< Drag in-progress */ + + /** + * Create the main window + * + * @param winsize The initial window size + * @param winpos The initial window position + */ + + bool createMainWindow(FAR const nxgl_size_s *winsize, + FAR const nxgl_point_s *winpos); + + /** + * Calculate the height of the tool bar + */ + + bool getToolbarHeight(FAR const char *name); + + /** + * Create all toolbar buttons + */ + + bool createToolbarButtons(void); + + /** + * Add buttons and title widgets to the tool bar + * + * @param name The name to use for the toolbar title + */ + + bool createToolbarTitle(FAR const char *name); + + /** + * Create the tool bar + */ + + bool createToolbar(void); + + /** + * Update the toolbar layout, resizing the title text window and + * repositioning all windows on the toolbar. + */ + + bool updateToolbarLayout(void); + + /** + * Disable widget drawing and widget events. + */ + + bool disableWidgets(void); + + /** + * Enable widget drawing and widget events. + */ + + bool enableWidgets(void); + + /** + * 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); + + /** + * Handle a key press event. + * + * @param e The event data. + */ + + void handleKeyPressEvent(const NXWidgets::CWidgetEventArgs &e); + + /** + * Override the virtual CWidgetEventHandler::handleActionEvent. This + * event will fire when the image is released but before it has been + * has been drawn. isClicked() will return true for the appropriate + * images. + * + * @param e The event data. + */ + + void handleActionEvent(const NXWidgets::CWidgetEventArgs &e); + + /** + * Handle the TOOLBAR_GRAB event. That corresponds to a left + * mouse click on the toolbar (other than on an icon) + * + * @param eventmsg. The received NxWidget event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + + bool toolbarGrab(FAR struct SEventMsg *eventmsg); + + /** + * Handle the WINDOW_DRAG event. That corresponds to a mouse + * movement when the window is in a grabbed state. + * + * @param eventmsg. The received NxWidget event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + + bool windowDrag(FAR struct SEventMsg *eventmsg); + + /** + * Handle the TOOLBAR_UNGRAB event. The corresponds to a mouse + * left button release while in the grabbed + * + * @param eventmsg. The received NxWidget event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + + bool toolbarUngrab(FAR struct SEventMsg *eventmsg); + + /** + * Cleanup on failure or as part of the destructor + */ + + void cleanup(void); + + public: + + /** + * CWindow Constructor + * + * @param twm4nx. Twm4Nx session + */ + + CWindow(CTwm4Nx *twm4nx); + + /** + * CWindow Destructor + */ + + ~CWindow(void); + + /** + * CWindow Initializer (unlike the constructor, this may fail) + * + * @param name The the name of the window (and its icon) + * @param pos The initial position of the window + * @param size The initial size of the window + * @param sbitmap The Icon bitmap image + * @param isIconMgr Flag to tell if this is an icon manager window + * @param iconMgr Pointer to icon manager instance + * @param noToolbar True: Don't add Title Bar + * @return True if the window was successfully initialize; false on + * any failure, + */ + + bool initialize(FAR const char *name, + FAR const struct nxgl_point_s *pos, + FAR const struct nxgl_size_s *size, + FAR const struct NXWidgets::SRlePaletteBitmap *sbitmap, + bool isIconMgr, FAR CIconMgr *iconMgr, bool noToolbar); + + /** + * Get the name of the window + */ + + inline FAR const char *getWindowName(void) + { + return m_name; + } + + /** + * Return true if this is an Icon Manager Window + */ + + inline bool isIconMgr(void) + { + return m_isIconMgr; + } + + /** + * Return the Icon Manager Window instance + */ + + inline FAR CIconMgr *getIconMgr(void) + { + return m_iconMgr; + } + + /** + * Get the size of the primary window. This is useful only + * for applications that need to know the drawing area. + * + * @param size Location to return the primary window size + */ + + inline bool getWindowSize(FAR struct nxgl_size_s *size) + { + return m_nxWin->getSize(size); + } + + /** + * Set the size of the primary window. This is useful only + * for oapplications that need to control the drawing area. + * + * @param size New primary window size + */ + + inline bool setWindowSize(FAR const struct nxgl_size_s *size) + { + return m_nxWin->setSize(size); + } + + /** + * Get the height of the tool bar + */ + + inline nxgl_coord_t getToolbarHeight(void) + { + return m_tbHeight; + } + + /** + * Raise the window to the top of the hierarchy. + */ + + inline bool raiseWindow(void) + { + return m_nxWin->raise(); + } + + /** + * Lower the window to the bottom of the hierarchy. + */ + + inline bool lowerWindow(void) + { + return m_nxWin->lower(); + } + + /** + * Convert the position of a primary window to the position of + * the containing frame. + */ + + inline void windowToFramePos(FAR const struct nxgl_point_s *winpos, + FAR struct nxgl_point_s *framepos) + { + framepos->x = winpos->x - CONFIG_NXTK_BORDERWIDTH; + framepos->y = winpos->y - m_tbHeight - CONFIG_NXTK_BORDERWIDTH; + } + + /** + * Convert the position of the containing frame to the position of the + * primary window. + */ + + inline void frameToWindowPos(FAR const struct nxgl_point_s *framepos, + FAR struct nxgl_point_s *winpos) + { + winpos->x = framepos->x + CONFIG_NXTK_BORDERWIDTH; + winpos->y = framepos->y + m_tbHeight + CONFIG_NXTK_BORDERWIDTH; + } + + /** + * Convert the size of a primary window to the size of the containing + * frame. + */ + + inline void windowToFrameSize(FAR const struct nxgl_size_s *winsize, + FAR struct nxgl_size_s *framesize) + { + framesize->w = winsize->w + 2 * CONFIG_NXTK_BORDERWIDTH; + framesize->h = winsize->h + m_tbHeight + 2 * CONFIG_NXTK_BORDERWIDTH; + } + + /** + * Convert the size of the containing frame to the size of the primary window to the size of the containing + * frame. + */ + + inline void frameToWindowSize(FAR const struct nxgl_size_s *framesize, + FAR struct nxgl_size_s *winsize) + { + winsize->w = framesize->w - 2 * CONFIG_NXTK_BORDERWIDTH; + winsize->h = framesize->h - m_tbHeight - 2 * CONFIG_NXTK_BORDERWIDTH; + } + + /** + * Get the raw window size (including toolbar and frame) + * + * @param framesize Location to return the window frame size + */ + + bool getFrameSize(FAR struct nxgl_size_s *framesize); + + /** + * Update the window frame after a resize operation (includes the toolbar + * and user window) + * + * @param size The new window frame size + * @param pos The frame location which may also have changed + */ + + bool resizeFrame(FAR const struct nxgl_size_s *framesize, + FAR struct nxgl_point_s *framepos); + + /** + * Get the raw frame position (accounting for toolbar and frame) + * + * @param framepos Location to return the window frame position + */ + + bool getFramePosition(FAR struct nxgl_point_s *framepos); + + /** + * Set the raw frame position (accounting for toolbar and frame) + * + * @param framepos The new raw window position + */ + + bool setFramePosition(FAR const struct nxgl_point_s *framepos); + + /* Minimize (iconify) the window */ + + void iconify(void); + + /** + * De-iconify the window + */ + + void deIconify(void); + + /** + * Is the window iconified? + */ + + inline bool isIconified(void) + { + return m_iconified; + } + + /** + * Has the Icon moved? + */ + + inline bool hasIconMoved(void) + { + return m_iconMoved; + } + + /** + * Set Icon moved + */ + + inline void setIconMoved(bool moved) + { + m_iconMoved = moved; + } + + /** + * Get the size of the icon window associated with this application + * window. This is needed for placement of the icon on the background + * window. + * + * @param size Location to return the icon window size + */ + + inline bool getIconWindowSize(FAR struct nxgl_size_s *size) + { + return m_iconWin->getSize(size); + } + + /** + * Get the current position of the icon window associated with the + * application window. This is needed for placement of the icon on + * the background window. + * + * @param pos Location to return the icon window position + */ + + inline bool getIconWindowPosition(FAR struct nxgl_point_s *pos) + { + return m_iconWin->getPosition(pos); + } + + /** + * Set the new position of the icon window associated with the + * application window. This is needed for placement of the icon on the + * background window. + * + * @param pos The new location of the icon window + */ + + inline bool setIconWindowPosition(FAR const struct nxgl_point_s *pos) + { + return m_iconWin->setPosition(pos); + } + + /** + * Get zoom + */ + + inline uint16_t getZoom(void) + { + return m_zoom; + } + + /** + * Set zoom + * + * @param zoom The new zoom setting + */ + + inline void setZoom(uint16_t zoom) + { + m_zoom = zoom; + } + + /** + * Check for widget-related toolbar events, typically button presses. + * This is called by event handling logic for events that require + * detection of widget events. + */ + + inline bool pollToolbarEvents(void) + { + NXWidgets::CWidgetControl *control = m_toolbar->getWidgetControl(); + return control->pollEvents(); + } + + /** + * Handle WINDOW events. + * + * @param eventmsg. The received NxWidget WINDOW event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + + bool event(FAR struct SEventMsg *eventmsg); + }; +} + +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CWINDOW_HXX diff --git a/include/graphics/twm4nx/cwindowevent.hxx b/include/graphics/twm4nx/cwindowevent.hxx new file mode 100644 index 000000000..ab0a5266d --- /dev/null +++ b/include/graphics/twm4nx/cwindowevent.hxx @@ -0,0 +1,145 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/src/cwindowevent.hxx +// Shim to manage the interface between NX messages and NxWidgets +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// 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 __APPS_INCLUDE_GRAPHICS_TWM4NX_CWINDOWEVENT_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_CWINDOWEVENT_HXX + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include + +#include "graphics/nxwidgets/cwindoweventhandler.hxx" +#include "graphics/nxwidgets/cwidgetstyle.hxx" +#include "graphics/nxwidgets/cwidgetcontrol.hxx" +#include "graphics/twm4nx/twm4nx_widgetevents.hxx" +#include "graphics/twm4nx/ctwm4nx.hxx" + +///////////////////////////////////////////////////////////////////////////// +// Implementation Classes +///////////////////////////////////////////////////////////////////////////// + +#if defined(__cplusplus) + +namespace Twm4Nx +{ + /** + * The class CWindowEvent integrates the widget control with some special + * handling of mouse and keyboard inputs needs by NxWM. It use used + * in place of CWidgetControl whenever an NxWM window is created. + * + * CWindowEvent cohabitates with CWidgetControl only because it needs the + * CWidgetControl as an argument in its messaging. + */ + + class CWindowEvent : public NXWidgets::CWindowEventHandler, + public NXWidgets::CWidgetControl + { + private: + FAR CTwm4Nx *m_twm4nx; /**< Cached instance of CTwm4Nx */ + mqd_t m_eventq; /**< NxWidget event message queue */ + + /** + * Send the EVENT_MSG_POLL input event message to the Twm4Nx event loop. + */ + + void sendInputEvent(void); + + // Override CWidgetEventHandler virutal methods /////////////////////// + +#ifdef CONFIG_NX_XYINPUT + /** + * Handle an NX window mouse input event. + */ + + void handleMouseEvent(void); +#endif + +#ifdef CONFIG_NX_KBD + /** + * Handle a NX window keyboard input event. + */ + + void handleKeyboardEvent(void); +#endif + + /** + * Handle a NX window blocked event + * + * @param arg - User provided argument (see nx_block or nxtk_block) + */ + + void handleBlockedEvent(FAR void *arg); + + public: + + /** + * CWindowEvent Constructor + * + * @param twm4nx. The Twm4Nx session instance. + * @param style The default style that all widgets on this display + * should use. If this is not specified, the widget will use the + * values stored in the defaultCWidgetStyle object. + */ + + CWindowEvent(FAR CTwm4Nx *twm4nx, + FAR const NXWidgets::CWidgetStyle *style = + (const NXWidgets::CWidgetStyle *)NULL); + + /** + * CWindowEvent Destructor. + */ + + ~CWindowEvent(void); + + /** + * Handle MSG events. + * + * @param msg. The received system MSG event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + + static bool event(FAR struct SEventMsg *msg); + }; +} +#endif // __cplusplus + +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CWINDOWEVENT_HXX diff --git a/include/graphics/twm4nx/cwindowfactory.hxx b/include/graphics/twm4nx/cwindowfactory.hxx new file mode 100644 index 000000000..6c18ef232 --- /dev/null +++ b/include/graphics/twm4nx/cwindowfactory.hxx @@ -0,0 +1,194 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/include/cwindowfactory.hxx +// A collection of Window Helpers: Add a new window, put the titlebar and +// other stuff around the window +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Largely an original work but derives from TWM 1.0.10 in many ways: +// +// Copyright 1989,1998 The Open Group +// Copyright 1988 by Evans & Sutherland Computer Corporation, +// +// Please refer to apps/twm4nx/COPYING for detailed copyright information. +// +// 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 __APPS_INCLUDE_GRAPHICS_TWM4NX_CWINDOWFACTORY_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_CWINDOWFACTORY_HXX + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include + +#include "graphics/twm4nx/cwindow.hxx" + +///////////////////////////////////////////////////////////////////////////// +// Implementation Classes +///////////////////////////////////////////////////////////////////////////// + +namespace NXWidgets +{ + struct SRlePaletteBitmap; // Forward reference +} + +namespace Twm4Nx +{ + class CWindow; // Forward reference + class CIconMgr; // Forward reference + struct SWindowEntry; // Forward reference + + // For each window that is on the display, one of these structures + // is allocated and linked into a list. It is essentially just a + // container for a window. + + struct SWindow + { + FAR struct SWindow *flink; /**< Foward link tonext window */ + FAR struct SWindow *blink; /**< Backward link to previous window */ + FAR struct SWindowEntry *wentry; /**< Icon manager list entry (for list removal) */ + FAR CWindow *cwin; /**< Window object payload */ + }; + + /** + * The CWindowFactory class creates new window instances and manages some + * things that are common to all windows. + */ + + class CWindowFactory + { + private: + + CTwm4Nx *m_twm4nx; /**< Cached Twm4Nx session */ + struct nxgl_point_s m_winpos; /**< Position of next window created */ + FAR struct SWindow *m_windowHead; /**< List of all windows on the display */ + + /** + * Add a window container to the window list. + * + * @param win. The window container to be added to the list. + */ + + void addWindow(FAR struct SWindow *win); + + /** + * Remove a window container from the window list. + * + * @param win. The window container to be removed from the list. + */ + + void removeWindow(FAR struct SWindow *win); + + /** + * Find the window container that contains the specified window. + * + * @param cwin. The window whose container is needed. + * @return On success, the container of the specific window is returned; + * NULL is returned on failure. + */ + + FAR struct SWindow *findWindow(FAR CWindow *cwin); + + public: + + /** + * CWindowFactory Constructor + * + * @param twm4nx. Twm4Nx session + */ + + CWindowFactory(CTwm4Nx *twm4nx); + + /** + * CWindowFactory Destructor + */ + + ~CWindowFactory(void); + + /** + * Create a new window and add it to the window list. + * + * @param name The window name + * @param sbitmap The Icon bitmap + * @param isIconMgr Flag to tell if this is an icon manager window + * @param iconMgr Pointer to icon manager instance + * @param noToolbar True: Don't add Title Bar + * @return Reference to the allocated CWindow instance + */ + + FAR CWindow * + createWindow(FAR const char *name, + FAR const struct NXWidgets::SRlePaletteBitmap *sbitmap, + bool isIconMgr, FAR CIconMgr *iconMgr, bool noToolbar); + + /** + * Handle the EVENT_WINDOW_DELETE event. The logic sequence is as + * follows: + * + * 1. The TERMINATE button in pressed in the Window Toolbar + * 2. CWindowFactory::event receives the widget event, + * EVENT_WINDOW_TERMINATE and request to halt the NX Server + * messages queues. + * 3. The server responds with the EVENT_WINDOW_DELETE which is + * caught by this function. + * + * @param cwin The CWindow instance. This will be deleted and its + * associated container will be freed. + */ + + void destroyWindow(FAR CWindow *cwin); + + /** + * Return the head of the window list. + * + * @return The head of the window list. + */ + + inline FAR struct SWindow *windowHead(void) + { + return m_windowHead; + } + + /** + * Handle WINDOW events. + * + * @param msg. The received NxWidget WINDOW event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + + bool event(FAR struct SEventMsg *msg); + }; +} + +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CWINDOWFACTORY_HXX diff --git a/include/graphics/twm4nx/twm4nx_config.hxx b/include/graphics/twm4nx/twm4nx_config.hxx new file mode 100644 index 000000000..9a7580f80 --- /dev/null +++ b/include/graphics/twm4nx/twm4nx_config.hxx @@ -0,0 +1,455 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/include/twm4nx_config.hxx +// Twm4Nx configuration settings +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// 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 __APPS_INCLUDE_GRAPHICS_TWM4NX_TWM4NX_CONFIG_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_TWM4NX_CONFIG_HXX + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include + +#include "graphics/nxglyphs.hxx" +#include "graphics/nxwidgets/nxconfig.hxx" +#include "graphics/nxwidgets/crlepalettebitmap.hxx" + +///////////////////////////////////////////////////////////////////////////// +// Pre-Processor Definitions +///////////////////////////////////////////////////////////////////////////// + +// General Configuration //////////////////////////////////////////////////// + +/** + * Required settings: + * + * CONFIG_HAVE_CXX : C++ support is required + * CONFIG_NX : NX must enabled + * CONFIG_NXTERM=y : For NxTerm support + * CONFIG_SCHED_ONEXIT : Support for on_exit() + */ + +#ifndef CONFIG_HAVE_CXX +# error "C++ support is required (CONFIG_HAVE_CXX)" +#endif + +/** + * NX Multi-user support is required + */ + +#ifndef CONFIG_NX +# error "NX support is required (CONFIG_NX)" +#endif + +/** + * NxTerm support is (probably) required to support NxTWM terminals + */ + +#if defined(CONFIG_TWM4NX_NXTERM) && !defined(CONFIG_NXTERM) +# warning "NxTerm support may be needed (CONFIG_NXTERM)" +#endif + +/** + * on_exit() support is (probably) required. on_exit() is the normal + * mechanism used by Twm4Nx applications to clean-up on a application task + * exit. + */ + +#ifndef CONFIG_SCHED_ONEXIT +# warning "on_exit() support may be needed (CONFIG_SCHED_ONEXIT)" +#endif + +// Background /////////////////////////////////////////////////////////////// + +/** + * CONFIG_TWM4NX_DEFAULT_BACKGROUNDCOLOR - Normal background color. Default: + * MKRGB(148,189,215) + * CONFIG_TWM4NX_BACKGROUND_IMAGE - The name of the image to use in the + * background window. Default:NXWidgets::g_nuttxBitmap160x160 + */ + +#ifndef CONFIG_TWM4NX_BACKGROUND_IMAGE +# define CONFIG_TWM4NX_BACKGROUND_IMAGE NXWidgets::g_nuttxBitmap160x160 +#endif + +// Windows ////////////////////////////////////////////////////////////////// + +// Toolbar ///////////////////////////////////////////////////////////////// + +/** + * Toolbar Icons. The Title bar contains (from left to right): + * + * 1. Menu button + * 2. Window title (text) + * 3. Minimize (Iconify) button + * 4. Resize button + * 5. Delete button + * + * There is no focus indicator + */ + +#ifndef CONFIG_TWM4NX_MENU_IMAGE +# define CONFIG_TWM4NX_MENU_IMAGE NXWidgets::g_menuBitmap +#endif + +#ifndef CONFIG_TWM4NX_MINIMIZE_IMAGE +# define CONFIG_TWM4NX_MINIMIZE_IMAGE NXWidgets::g_minimizeBitmap +#endif + +#ifndef CONFIG_TWM4NX_RESIZE_IMAGE +# define CONFIG_TWM4NX_RESIZE_IMAGE NXWidgets::g_resizeBitmap +#endif + +#ifndef CONFIG_TWM4NX_TERMINATE_IMAGE +# define CONFIG_TWM4NX_TERMINATE_IMAGE NXWidgets::g_stopBitmap +#endif + +#ifndef CONFIG_TWM4NX_ICONMGR_IMAGE +# define CONFIG_TWM4NX_ICONMGR_IMAGE NXWidgets::g_nxiconBitmap +#endif + +// Spacing. Defaults values good at 75 and 100 DPI + +#ifndef CONFIG_TWM4NX_TOOLBAR_HSPACING +# define CONFIG_TWM4NX_TOOLBAR_HSPACING 8 +#endif + +#ifndef CONFIG_TWM4NX_ICONMGR_VSPACING +# define CONFIG_TWM4NX_FRAME_VSPACING 2 +#endif + +#ifndef CONFIG_TWM4NX_BUTTON_INDENT +# define CONFIG_TWM4NX_BUTTON_INDENT 1 +#endif + +#ifndef CONFIG_TWM4NX_ICONMGR_VSPACING +# define CONFIG_TWM4NX_ICONMGR_VSPACING 2 +#endif + +#ifndef CONFIG_TWM4NX_ICONMGR_HSPACING +# define CONFIG_TWM4NX_ICONMGR_HSPACING 2 +#endif + +// Menus //////////////////////////////////////////////////////////////////// + +/** + * CONFIG_TWM4NX_MENU_IMAGE. Menu image (see toolbar icons) + */ + +// Colors /////////////////////////////////////////////////////////////////// + +/* Colors *******************************************************************/ + +/** + * Color configuration + * + * CONFIG_TWM4NX_DEFAULT_BACKGROUNDCOLOR - Normal background color. Default: + * MKRGB(148,189,215) + * CONFIG_TWM4NX_DEFAULT_SELECTEDBACKGROUNDCOLOR - Select background color. + * Default: MKRGB(206,227,241) + * CONFIG_TWM4NX_DEFAULT_SHINEEDGECOLOR - Color of the bright edge of a border. + * Default: MKRGB(255,255,255) + * CONFIG_TWM4NX_DEFAULT_SHADOWEDGECOLOR - Color of the shadowed edge of a border. + * Default: MKRGB(0,0,0) + * CONFIG_TWM4NX_DEFAULT_FONTCOLOR - Default font color. Default: + * MKRGB(0,0,0) + * CONFIG_TWM4NX_TRANSPARENT_COLOR - The "transparent" color. Default: + * MKRGB(0,0,0) + */ + +/** + * Normal background color + */ + +#ifndef CONFIG_TWM4NX_DEFAULT_BACKGROUNDCOLOR +# define CONFIG_TWM4NX_DEFAULT_BACKGROUNDCOLOR MKRGB(148,189,215) +#endif + +/** + * Default selected background color + */ + +#ifndef CONFIG_TWM4NX_DEFAULT_SELECTEDBACKGROUNDCOLOR +# define CONFIG_TWM4NX_DEFAULT_SELECTEDBACKGROUNDCOLOR MKRGB(206,227,241) +#endif + +/** + * Border colors + */ + +#ifndef CONFIG_TWM4NX_DEFAULT_SHINEEDGECOLOR +# define CONFIG_TWM4NX_DEFAULT_SHINEEDGECOLOR MKRGB(248,248,248) +#endif + +#ifndef CONFIG_TWM4NX_DEFAULT_SHADOWEDGECOLOR +# define CONFIG_TWM4NX_DEFAULT_SHADOWEDGECOLOR MKRGB(35,58,73) +#endif + +/** + * The default font color + */ + +#ifndef CONFIG_TWM4NX_DEFAULT_FONTCOLOR +# define CONFIG_TWM4NX_DEFAULT_FONTCOLOR MKRGB(255,255,255) +#endif + +/** + * The transparent color + */ + +#ifndef CONFIG_TWM4NX_TRANSPARENT_COLOR +# define CONFIG_TWM4NX_TRANSPARENT_COLOR MKRGB(0,0,0) +#endif + +// Toolbar Configuration //////////////////////////////////////////////////// + +/** + * CONFIG_TWM4NX_TOOLBAR_HEIGHT. The height of the tool bar in each + * application window. At present, all icons are 21 or 42 pixels in height + * (depending on the setting of CONFIG_TWM4NX_LARGE_ICONS) and, hence require + * a task bar of at least that size. + */ + +#ifndef CONFIG_TWM4NX_TOOLBAR_HEIGHT +# define CONFIG_TWM4NX_TOOLBAR_HEIGHT \ + (CONFIG_TWM4NX_TASKBAR_ICONHEIGHT + 2 * CONFIG_TWM4NX_TASKBAR_HSPACING) +#endif + +/* CONFIG_TWM4NX_TOOLBAR_FONTID overrides the default Twm4Nx font selection */ + +#ifndef CONFIG_TWM4NX_TOOLBAR_FONTID +# define CONFIG_TWM4NX_TOOLBAR_FONTID CONFIG_TWM4NX_DEFAULT_FONTID +#endif + +// Background Image ////////////////////////////////////////////////////////// + +/** + * CONFIG_TWM4NX_BACKGROUND_IMAGE - The name of the image to use in the + * background window. Default:NXWidgets::g_nuttxBitmap160x160 + */ + +#ifndef CONFIG_TWM4NX_BACKGROUND_IMAGE +# define CONFIG_TWM4NX_BACKGROUND_IMAGE NXWidgets::g_nuttxBitmap160x160 +#endif + +// Cursor //////////////////////////////////////////////////////////////////// +// Cursor Images + +#ifndef CONFIG_TWM4NX_CURSOR_IMAGE // The normal cursor image +# define CONFIG_TWM4NX_CURSOR_IMAGE g_arrow1Cursor +#endif + +#ifndef CONFIG_TWM4NX_GBCURSOR_IMAGE // Grab cursor image +# define CONFIG_TWM4NX_GBCURSOR_IMAGE g_grabCursor +#endif + +#ifndef CONFIG_TWM4NX_WTCURSOR_IMAGE // Wait cursor image +# define CONFIG_TWM4NX_WTCURSOR_IMAGE g_waitCursor +#endif + +// Fonts ///////////////////////////////////////////////////////////////////// + +// Font IDs + +#ifndef CONFIG_TWM4NX_TITLE_FONTID +# define CONFIG_TWM4NX_TITLE_FONTID NXFONT_DEFAULT +#endif + +#ifndef CONFIG_TWM4NX_MENU_FONTID +# define CONFIG_TWM4NX_MENU_FONTID NXFONT_DEFAULT +#endif + +#ifndef CONFIG_TWM4NX_ICON_FONTID +# define CONFIG_TWM4NX_ICON_FONTID NXFONT_DEFAULT +#endif + +#ifndef CONFIG_TWM4NX_SIZE_FONTID +# define CONFIG_TWM4NX_SIZE_FONTID NXFONT_DEFAULT +#endif + +#ifndef CONFIG_TWM4NX_ICONMGR_SIZEFONTID +# define CONFIG_TWM4NX_ICONMGR_SIZEFONTID NXFONT_DEFAULT +#endif + +// Font Colors + +#ifndef CONFIG_TWM4NX_TITLE_FONTCOLOR +# define CONFIG_TWM4NX_TITLE_FONTCOLOR MKRGB(0,64,0) +#endif + +#ifndef CONFIG_TWM4NX_MENU_FONTCOLOR +# define CONFIG_TWM4NX_MENU_FONTCOLOR MKRGB(0,64,0) +#endif + +#ifndef CONFIG_TWM4NX_ICON_FONTCOLOR +# define CONFIG_TWM4NX_ICON_FONTCOLOR MKRGB(0,64,0) +#endif + +#ifndef CONFIG_TWM4NX_SIZE_FONTCOLOR +# define CONFIG_TWM4NX_SIZE_FONTCOLOR MKRGB(0,64,0) +#endif + +#ifndef CONFIG_TWM4NX_ICONMGR_FONTCOLOR +# define CONFIG_TWM4NX_ICONMGR_FONTCOLOR MKRGB(0,64,0) +#endif + +#ifndef CONFIG_TWM4NX_DEFAULT_FONTCOLOR +# define CONFIG_TWM4NX_DEFAULT_FONTCOLOR MKRGB(0,64,0) +#endif + +// NxTerm Window ///////////////////////////////////////////////////////////// + +/** + * NxTerm Window Configuration + * + * CONFIG_TWM4NX_NXTERM_PRIO - Priority of the NxTerm task. Default: + * SCHED_PRIORITY_DEFAULT. NOTE: This priority should be less than + * CONFIG_NXSTART_SERVERPRIO or else there may be data overrun errors. + * Such errors would most likely appear as duplicated rows of data on the + * display. + * CONFIG_TWM4NX_NXTERM_STACKSIZE - The stack size to use when starting the + * NxTerm task. Default: 2048 bytes. + * CONFIG_TWM4NX_NXTERM_WCOLOR - The color of the NxTerm window background. + * Default: MKRGB(192,192,192) + * CONFIG_TWM4NX_NXTERM_FONTCOLOR - The color of the fonts to use in the + * NxTerm window. Default: MKRGB(0,0,0) + * CONFIG_TWM4NX_NXTERM_FONTID - The ID of the font to use in the NxTerm + * window. Default: CONFIG_TWM4NX_DEFAULT_FONTID + * CONFIG_TWM4NX_NXTERM_ICON - The glyph to use as the NxTerm icon + */ + +#ifdef CONFIG_TWM4NX_NXTERM +# ifndef CONFIG_TWM4NX_NXTERM_PRIO +# define CONFIG_TWM4NX_NXTERM_PRIO SCHED_PRIORITY_DEFAULT +# endif + +# if CONFIG_NXSTART_SERVERPRIO <= CONFIG_TWM4NX_NXTERM_PRIO +# warning "CONFIG_NXSTART_SERVERPRIO <= CONFIG_TWM4NX_NXTERM_PRIO" +# warning" -- This can result in data overrun errors" +# endif + +# ifndef CONFIG_TWM4NX_NXTERM_STACKSIZE +# define CONFIG_TWM4NX_NXTERM_STACKSIZE 2048 +# endif + +# ifndef CONFIG_TWM4NX_NXTERM_WCOLOR +# define CONFIG_TWM4NX_NXTERM_WCOLOR CONFIG_TWM4NX_DEFAULT_BACKGROUNDCOLOR +# endif + +# ifndef CONFIG_TWM4NX_NXTERM_FONTCOLOR +# define CONFIG_TWM4NX_NXTERM_FONTCOLOR CONFIG_TWM4NX_DEFAULT_FONTCOLOR +# endif + +# ifndef CONFIG_TWM4NX_NXTERM_FONTID +# define CONFIG_TWM4NX_NXTERM_FONTID CONFIG_TWM4NX_DEFAULT_FONTID +# endif + + /** + * The NxTerm window glyph + */ + +# ifndef CONFIG_TWM4NX_NXTERM_ICON +# define CONFIG_TWM4NX_NXTERM_ICON NXWidgets::g_cmdBitmap +# endif +#endif + +// Input Devices ///////////////////////////////////////////////////////////// + +/** Common input device settings + * + * CONFIG_TWM4NX_INPUT_SIGNO - The realtime signal used to wake up the + * keyboard/mouse listener thread. Default: 6 + * CONFIG_TWM4NX_INPUT_LISTENERPRIO - Priority of the touchscreen listener + * thread. Default: (SCHED_PRIORITY_DEFAULT + 20) + * CONFIG_TWM4NX_INPUT_LISTENERSTACK - Input listener thread stack + * size. Default 1024 + */ + +#ifndef CONFIG_TWM4NX_INPUT_SIGNO +# define CONFIG_TWM4NX_INPUT_SIGNO 6 +#endif + +#ifndef CONFIG_TWM4NX_INPUT_LISTENERPRIO +# define CONFIG_TWM4NX_INPUT_LISTENERPRIO (SCHED_PRIORITY_DEFAULT + 20) +#endif + +#ifndef CONFIG_TWM4NX_INPUT_LISTENERSTACK +# define CONFIG_TWM4NX_INPUT_LISTENERSTACK 1024 +#endif + +// Mouse Input Device //////////////////////////////////////////////////////// + +/** + * Mouse device settings + * + * CONFIG_TWM4NX_MOUSE_DEVPATH - The full path to the mouse device. + * Default: "/dev/console" + * CONFIG_TWM4NX_MOUSE_USBHOST - Indicates the the mouse is attached via + * USB + * CONFIG_TWM4NX_MOUSE_BUFSIZE - The size of the mouse read data buffer. + * Default: sizeof(struct mouse_report_s) + */ + +#ifndef CONFIG_TWM4NX_MOUSE_DEVPATH +# define CONFIG_TWM4NX_MOUSE_DEVPATH "/dev/mouse0" +#endif + +#ifndef CONFIG_TWM4NX_MOUSE_BUFSIZE +# define CONFIG_TWM4NX_MOUSE_BUFSIZE sizeof(struct mouse_report_s) +#endif + +// Keyboard device /////////////////////////////////////////////////////////// + +/** + * Keyboard device settings + * + * CONFIG_TWM4NX_KEYBOARD_DEVPATH - The full path to the keyboard device. + * Default: "/dev/console" + * CONFIG_TWM4NX_KEYBOARD_USBHOST - Indicates the the keyboard is attached via + * USB + * CONFIG_TWM4NX_KEYBOARD_BUFSIZE - The size of the keyboard read data buffer. + * Default: 16 + */ + +#ifndef CONFIG_TWM4NX_KEYBOARD_DEVPATH +# define CONFIG_TWM4NX_KEYBOARD_DEVPATH "/dev/kbd0" +#endif + +#ifndef CONFIG_TWM4NX_KEYBOARD_BUFSIZE +# define CONFIG_TWM4NX_KEYBOARD_BUFSIZE 6 +#endif + +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_TWM4NX_CONFIG_HXX diff --git a/include/graphics/twm4nx/twm4nx_cursor.hxx b/include/graphics/twm4nx/twm4nx_cursor.hxx new file mode 100644 index 000000000..7f98d55d4 --- /dev/null +++ b/include/graphics/twm4nx/twm4nx_cursor.hxx @@ -0,0 +1,70 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/include/twm4nx_cursor.hxx +// Cursor-related definitions +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// 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 __APPS_GRAPHICS_TWM4NX_INCLUDE_TWM4NX_CURSOR_HXX +#define __APPS_GRAPHICS_TWM4NX_INCLUDE_TWM4NX_CURSOR_HXX + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "graphics/twm4nx/twm4nx_config.hxx" + +#ifdef CONFIG_NX_SWCURSOR + +///////////////////////////////////////////////////////////////////////////// +// Public Constant Data +///////////////////////////////////////////////////////////////////////////// + +namespace Twm4Nx +{ + extern const struct nx_cursorimage_s // Normal cursor + CONFIG_TWM4NX_CURSOR_IMAGE; + extern const struct nx_cursorimage_s // Grab button + CONFIG_TWM4NX_GBCURSOR_IMAGE; + extern const struct nx_cursorimage_s // Wait cursor + CONFIG_TWM4NX_WTCURSOR_IMAGE; +} + +///////////////////////////////////////////////////////////////////////////// +// Public Function Prototypes +///////////////////////////////////////////////////////////////////////////// + +#endif // CONFIG_NX_SWCURSOR +#endif // __APPS_GRAPHICS_TWM4NX_INCLUDE_TWM4NX_CURSOR_HXX diff --git a/include/graphics/twm4nx/twm4nx_widgetevents.hxx b/include/graphics/twm4nx/twm4nx_widgetevents.hxx new file mode 100644 index 000000000..58bedc1f5 --- /dev/null +++ b/include/graphics/twm4nx/twm4nx_widgetevents.hxx @@ -0,0 +1,215 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/include/twm4nx_widgetevents.hxx +// Twm4Nx Widget Event Handling +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// 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 __APPS_INCLUDE_GRAPHICS_TWM4NX_TWM4NX_WIDGETEVENTS_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_TWM4NX_WIDGETEVENTS_HXX + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include + +#include +#include "graphics/nxwidgets/cwindoweventhandler.hxx" + +///////////////////////////////////////////////////////////////////////////// +// Preprocessor Definitions +///////////////////////////////////////////////////////////////////////////// + +#define MAX_EVENT_PAYLOAD (64 - sizeof(uint16_t)) + +///////////////////////////////////////////////////////////////////////////// +// WidgetEvent +///////////////////////////////////////////////////////////////////////////// + +namespace NXWidgets +{ + class CNxTkWindow; // Forward reference +} + +namespace Twm4Nx +{ + class CWindow; // Forward reference + class CWindowEvent; // Forward reference + class CTwm4Nx; // Forward reference + + /////////////////////////////////////////////////////////////////////////// + // Public Types + /////////////////////////////////////////////////////////////////////////// + + /** + * This enumeration identifies the recipient of the event + */ + + enum EEventRecipient + { + EVENT_RECIPIENT_MSG = 0x0000, /**< Twm4Nx messenging event */ + EVENT_RECIPIENT_SYSTEM = 0x1000, /**< Twm4Nx system event */ + EVENT_RECIPIENT_ICONWIN = 0x2000, /**< Icon Window event */ + EVENT_RECIPIENT_ICONMGR = 0x3000, /**< Icon Manager event */ + EVENT_RECIPIENT_MENU = 0x4000, /**< Menu related event */ + EVENT_RECIPIENT_WINDOW = 0x5000, /**< Window related event */ + EVENT_RECIPIENT_TOOLBAR = 0x6000, /**< Toolbar related event */ + EVENT_RECIPIENT_BORDER = 0x7000, /**< Window border related event */ + EVENT_RECIPIENT_RESIZE = 0x8000, /**< Window resize event */ + EVENT_RECIPIENT_MASK = 0xf000, /**< Used to isolate recipient */ + }; + + /** + * Specific events include the recipient as part of the event ID encoding. + */ + + enum EEventID + { + // Recipient == MSG + + EVENT_MSG_POLL = 0x0000, /**< Poll widgets for events */ + + // Recipient == SYSTEM + + EVENT_SYSTEM_ERROR = 0x1000, /**< Report system error */ + EVENT_SYSTEM_EXIT = 0x1001, /**< Terminate the Twm4Nx session */ + + // Recipient == ICONWIN + + EVENT_ICONWIN_GRAB = 0x2000, /**< Click on toolbar (not toolbar buttons) */ + EVENT_ICONWIN_DRAG = 0x2001, /**< Drag window */ + EVENT_ICONWIN_UNGRAB = 0x2002, /**< Release click on toolbar */ + + // Recipient == ICONMGR + + EVENT_ICONMGR_FORWARD = 0x3000, /**< Forward in the window list */ + EVENT_ICONMGR_BACK = 0x3001, /**< Backward in the window list */ + EVENT_ICONMGR_UP = 0x3002, /**< Up one row */ + EVENT_ICONMGR_DOWN = 0x3003, /**< Down one row */ + EVENT_ICONMGR_LEFT = 0x3004, /**< Left one column */ + EVENT_ICONMGR_RIGHT = 0x3005, /**< Right one column */ + EVENT_ICONMGR_SHOWPARENT = 0x3006, /**< Raise Icon Manager parent window */ + EVENT_ICONMGR_HIDE = 0x3007, /**< Hide the Icon Manager */ + EVENT_ICONMGR_SORT = 0x3008, /**< Sort the Icon Manager */ + + // Recipient == MENU + + EVENT_MENU_IDENTIFY = 0x4001, /**< Describe the window */ + EVENT_MENU_VERSION = 0x4002, /**< Show the Twm4Nx version */ + EVENT_MENU_ICONIFY = 0x4003, /**< Tool bar minimize button pressed */ + EVENT_MENU_DEICONIFY = 0x4004, /**< Window icon pressed */ + EVENT_MENU_FUNCTION = 0x4005, /**< Perform function on unknown menu */ + EVENT_MENU_TITLE = 0x4006, /**< REVISIT: Really an action not an event */ + EVENT_MENU_ROOT = 0x4007, /**< REVISIT: Popup root menu */ + + // Recipient == WINDOW + + EVENT_WINDOW_FOCUS = 0x5000, /**< Enter modal state */ + EVENT_WINDOW_UNFOCUS = 0x5001, /**< Exit modal state */ + EVENT_WINDOW_RAISE = 0x5002, /**< Raise window to the top of the heirarchy */ + EVENT_WINDOW_LOWER = 0x5003, /**< Lower window to the bottom of the heirarchy */ + EVENT_WINDOW_DRAG = 0x5004, /**< Drag window */ + EVENT_WINDOW_POPUP = 0x5005, /**< De-iconify and raise window */ + EVENT_WINDOW_DELETE = 0x5006, /**< Delete window */ + + // Recipient == TOOLBAR + + EVENT_TOOLBAR_GRAB = 0x6000, /**< Click on title widget */ + EVENT_TOOLBAR_UNGRAB = 0x6001, /**< Release click on title widget */ + EVENT_TOOLBAR_MENU = 0x6002, /**< Toolbar menu button released */ + EVENT_TOOLBAR_MINIMIZE = 0x6003, /**< Toolbar minimize button released */ + EVENT_TOOLBAR_RESIZE = 0x6004, /**< Toolbar resize button released */ + EVENT_TOOLBAR_TERMINATE = 0x6005, /**< Toolbar delete button released */ + + // Recipient == BORDER + + // Recipient == RESIZE + + EVENT_RESIZE_START = 0x8000, /**< Start window resize */ + EVENT_RESIZE_VERTZOOM = 0x8001, /**< Zoom vertically only */ + EVENT_RESIZE_HORIZOOM = 0x8002, /**< Zoom horizontally only */ + EVENT_RESIZE_FULLZOOM = 0x8003, /**< Zoom both vertically and horizontally */ + EVENT_RESIZE_LEFTZOOM = 0x8004, /**< Zoom left only */ + EVENT_RESIZE_RIGHTZOOM = 0x8005, /**< Zoom right only */ + EVENT_RESIZE_TOPZOOM = 0x8006, /**< Zoom top only */ + EVENT_RESIZE_BOTTOMZOOM = 0x8007, /**< Zoom bottom only */ + }; + + // Contexts for button press events + + enum EButtonContext + { + EVENT_CONTEXT_WINDOW = 0, + EVENT_CONTEXT_TITLE, + EVENT_CONTEXT_ICON, + EVENT_CONTEXT_ROOT, + EVENT_CONTEXT_FRAME, + EVENT_CONTEXT_ICONMGR, + EVENT_CONTEXT_NAME, + EVENT_CONTEXT_IDENTIFY, + NUM_CONTEXTS + }; + + /** + * This type represents a generic message containing all possible, + * message-specific options (wasteful, but a lot easier). + */ + + struct SEventMsg + { + uint16_t eventID; /**< Encoded event ID */ + struct nxgl_point_s pos; /**< X/Y position */ + uint8_t context; /**< Button press context */ + bool pulldown; /**< Pull-down menu */ + FAR const char *action; /**< Menu action */ + FAR NXWidgets::CNxTkWindow *nxwin; /**< Raw NX window reference */ + FAR void *obj; /**< Window object (CWindow or CIconWin) */ + }; + + /** + * This is the alternative form of the message used on in + * CWindowEvent::event() + */ + + struct SNxEventMsg + { + uint16_t eventID; /**< Encoded event ID */ + FAR CWindowEvent *instance; /**< X/Y position */ + FAR struct SWindow *win; /**< Twm4NX window reference */ + }; +} + +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_TWM4NX_WIDGETEVENTS_HXX