NXWidgets: cstartwindow.cxx Source File

NXWidgets 1.19

cstartwindow.cxx
Go to the documentation of this file.
1 /********************************************************************************************
2 * NxWidgets/nxwm/src/cstartwindow.cxx
3 *
4 * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
5 * Author: Gregory Nutt <gnutt@nuttx.org>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name NuttX, NxWidgets, nor the names of its contributors
18 * me be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *
34 ********************************************************************************************/
35
36 /********************************************************************************************
37 * Included Files
38 ********************************************************************************************/
39
40 #include <nuttx/config.h>
41
42 #include <cstdlib>
43 #include <cfcntl>
44 #include <csched>
45 #include <cerrno>
46
47 #include "cwidgetcontrol.hxx"
48
49 #include "nxwmconfig.hxx"
50 #include "nxwmglyphs.hxx"
51 #include "ctaskbar.hxx"
52 #include "cstartwindow.hxx"
53
54 /********************************************************************************************
55 * Pre-Processor Definitions
56 ********************************************************************************************/
57
58 /********************************************************************************************
59 * Global Data
60 ********************************************************************************************/
61
62 /**
63 * The well-known name for the Start Window's message queue.
64 */
65
66 FAR const char *NxWM::g_startWindowMqName = CONFIG_NXWM_STARTWINDOW_MQNAME;
67
68 /********************************************************************************************
69 * CStartWindow Method Implementations
70 ********************************************************************************************/
71
72 extern const struct NXWidgets::SRlePaletteBitmap CONFIG_NXWM_STARTWINDOW_ICON;
73
74 using namespace NxWM;
75
76 /**
77 * CStartWindow Constructor
78 *
79 * @param taskbar. A pointer to the parent task bar instance
80 * @param window. The window to be used by this application.
81 */
82
83 CStartWindow::CStartWindow(CTaskbar *taskbar, CApplicationWindow *window)
84 {
85 // Save the constructor data
86
87 m_taskbar = taskbar;
88 m_window = window;
89
90 // Add our personalized window label
91
92 NXWidgets::CNxString myName = getName();
93 window->setWindowLabel(myName);
94
95 // Add our callbacks to the application window
96
97 window->registerCallbacks(static_cast<IApplicationCallback *>(this));
98 }
99
100 /**
101 * CStartWindow Constructor
102 */
103
104 CStartWindow::~CStartWindow(void)
105 {
106 // There would be a problem if we were stopped with the start window task
107 // running... that should never happen but we'll check anyway:
108
109 stop();
110
111 // Although we didn't create it, we are responsible for deleting the
112 // application window
113
114 delete m_window;
115
116 // Then stop and delete all applications
117
118 removeAllApplications();
119 }
120
121 /**
122 * Each implementation of IApplication must provide a method to recover
123 * the contained IApplicationWindow instance.
124 */
125
126 IApplicationWindow *CStartWindow::getWindow(void) const
127 {
128 return static_cast<IApplicationWindow*>(m_window);
129 }
130
131 /**
132 * Get the icon associated with the application
133 *
134 * @return An instance if IBitmap that may be used to rend the
135 * application's icon. This is an new IBitmap instance that must
136 * be deleted by the caller when it is no long needed.
137 */
138
139 NXWidgets::IBitmap *CStartWindow::getIcon(void)
140 {
141 NXWidgets::CRlePaletteBitmap *bitmap =
142 new NXWidgets::CRlePaletteBitmap(&CONFIG_NXWM_STARTWINDOW_ICON);
143
144 return bitmap;
145 }
146
147 /**
148 * Get the name string associated with the application
149 *
150 * @return A copy if CNxString that contains the name of the application.
151 */
152
153 NXWidgets::CNxString CStartWindow::getName(void)
154 {
155 return NXWidgets::CNxString("Start Window");
156 }
157
158 /**
159 * Start the application.
160 *
161 * @return True if the application was successfully started.
162 */
163
164 bool CStartWindow::run(void)
165 {
166 return true;
167 }
168
169 /**
170 * Stop the application.
171 */
172
173 void CStartWindow::stop(void)
174 {
175 }
176
177 /**
178 * Destroy the application and free all of its resources. This method
179 * will initiate blocking of messages from the NX server. The server
180 * will flush the window message queue and reply with the blocked
181 * message. When the block message is received by CWindowMessenger,
182 * it will send the destroy message to the start window task which
183 * will, finally, safely delete the application.
184 */
185
186 void CStartWindow::destroy(void)
187 {
188 // What are we doing? This should never happen because the start
189 // window task is persistent!
190
191 // Block any further window messages
192
193 m_window->block(this);
194
195 // Make sure that the application is stopped
196
197 stop();
198 }
199
200 /**
201 * The application window is hidden (either it is minimized or it is
202 * maximized, but not at the top of the hierarchy
203 */
204
205 void CStartWindow::hide(void)
206 {
207 // Disable drawing and events on all icons
208
209 for (int i = 0; i < m_slots.size(); i++)
210 {
211 NXWidgets::CImage *image = m_slots.at(i).image;
212 image->disableDrawing();
213 image->setRaisesEvents(false);
214 }
215 }
216
217 /**
218 * Redraw the entire window. The application has been maximized or
219 * otherwise moved to the top of the hiearchy
220 */
221
222 void CStartWindow::redraw(void)
223 {
224 // Recover the NXTK window instance contained in the application window
225
226 NXWidgets::INxWindow *window = m_window->getWindow();
227
228 // Get the widget control associated with the NXTK window
229
230 NXWidgets::CWidgetControl *control = window->getWidgetControl();
231
232 // Get the graphics port for drawing on the widget control
233
234 NXWidgets::CGraphicsPort *port = control->getGraphicsPort();
235
236 // Get the size of the application window
237
238 struct nxgl_size_s windowSize;
239 if (!window->getSize(&windowSize))
240 {
241 return;
242 }
243
244 // Fill the entire window with the background color
245
246 port->drawFilledRect(0, 0, windowSize.w, windowSize.h,
247 CONFIG_NXWM_DEFAULT_BACKGROUNDCOLOR);
248
249 // Begin adding icons in the upper left corner
250
251 struct nxgl_point_s iconPos;
252 iconPos.x = CONFIG_NXWM_STARTWINDOW_HSPACING;
253 iconPos.y = CONFIG_NXWM_STARTWINDOW_VSPACING;
254
255 // Add each icon in the list of applications
256
257 for (int i = 0; i < m_slots.size(); i++)
258 {
259 // Get the icon associated with this application
260
261 NXWidgets::CImage *image = m_slots.at(i).image;
262
263 // Disable drawing of the icon image; disable events from the icon
264
265 image->disableDrawing();
266 image->setRaisesEvents(false);
267
268 // Get the size of the icon image
269
270 NXWidgets::CRect rect;
271 image->getPreferredDimensions(rect);
272
273 // Center the image in the region defined by the maximum icon size
274
275 struct nxgl_point_s imagePos;
276 imagePos.x = iconPos.x;
277 imagePos.y = iconPos.y;
278
279 if (rect.getWidth() < m_iconSize.w)
280 {
281 imagePos.x += ((m_iconSize.w - rect.getWidth()) >> 1);
282 }
283
284 if (rect.getHeight() < m_iconSize.h)
285 {
286 imagePos.y += ((m_iconSize.h - rect.getHeight()) >> 1);
287 }
288
289 // Set the position of the icon bitmap
290
291 image->moveTo(imagePos.x, imagePos.y);
292
293 // Then re-draw the icon at the new position
294
295 image->enableDrawing();
296 image->redraw();
297 image->setRaisesEvents(true);
298
299 // Advance the next icon position to the left
300
301 iconPos.x += m_iconSize.w + CONFIG_NXWM_TASKBAR_HSPACING;
302
303 // If there is insufficient space on on this row for the next
304 // max-sized icon, then advance to the next row
305
306 if (iconPos.x + m_iconSize.w >= windowSize.w)
307 {
308 iconPos.x = CONFIG_NXWM_STARTWINDOW_HSPACING;
309 iconPos.y += m_iconSize.h + CONFIG_NXWM_TASKBAR_VSPACING;
310
311 // Don't try drawing past the bottom of the window
312
313 if (iconPos.y >= windowSize.w)
314 {
315 break;
316 }
317 }
318 }
319 }
320
321 /**
322 * Report of this is a "normal" window or a full screen window. The
323 * primary purpose of this method is so that window manager will know
324 * whether or not it show draw the task bar.
325 *
326 * @return True if this is a full screen window.
327 */
328
329 bool CStartWindow::isFullScreen(void) const
330 {
331 return m_window->isFullScreen();
332 }
333
334 /**
335 * Add the application to the start window. The general sequence is:
336 *
337 * 1. Call IAppicationFactory::create to a new instance of the application
338 * 2. Call CStartWindow::addApplication to add the application to the
339 * start window.
340 *
341 * @param app. The new application to add to the start window
342 * @return true on success
343 */
344
345 bool CStartWindow::addApplication(IApplicationFactory *app)
346 {
347 // Recover the NXTK window instance contained in the application window
348
349 NXWidgets::INxWindow *window = m_window->getWindow();
350
351 // Get the widget control associated with the NXTK window
352
353 NXWidgets::CWidgetControl *control = window->getWidgetControl();
354
355 // Get the bitmap icon that goes with this application
356
357 NXWidgets::IBitmap *bitmap = app->getIcon();
358
359 // Create a CImage instance to manage the application icon
360
361 NXWidgets::CImage *image =
362 new NXWidgets::CImage(control, 0, 0, bitmap->getWidth(),
363 bitmap->getHeight(), bitmap, 0);
364 if (!image)
365 {
366 return false;
367 }
368
369 // Configure the image, disabling drawing for now
370
371 image->setBorderless(true);
372 image->disableDrawing();
373
374 // Register to get events from the mouse clicks on the image
375
376 image->addWidgetEventHandler(this);
377
378 // Add the application to end of the list of applications managed by
379 // the start window
380
381 struct SStartWindowSlot slot;
382 slot.app = app;
383 slot.image = image;
384 m_slots.push_back(slot);
385
386 // Re-calculate the icon bounding box
387
388 getIconBounds();
389 return true;
390 }
391
392 /**
393 * Simulate a mouse click or release on the icon at index. This method
394 * is only available during automated testing of NxWM.
395 *
396 * @param index. Selects the icon in the start window
397 * @param click. True to click and false to release
398 */
399
400 #if defined(CONFIG_NXWM_UNITTEST) && !defined(CONFIG_NXWM_TOUCHSCREEN)
401 void CStartWindow::clickIcon(int index, bool click)
402 {
403 if (index < m_slots.size())
404 {
405 // Get the image widget at this index
406
407 NXWidgets::CImage *image = m_slots.at(index).image;
408
409 // Get the size and position of the widget
410
411 struct nxgl_size_s imageSize;
412 image->getSize(imageSize);
413
414 struct nxgl_point_s imagePos;
415 image->getPos(imagePos);
416
417 // And click or release the image at its center
418
419 if (click)
420 {
421 image->click(imagePos.x + (imageSize.w >> 1),
422 imagePos.y + (imageSize.h >> 1));
423 }
424 else
425 {
426 image->release(imagePos.x + (imageSize.w >> 1),
427 imagePos.y + (imageSize.h >> 1));
428 }
429 }
430 }
431 #endif
432
433 /**
434 * Called when the window minimize button is pressed.
435 */
436
437 void CStartWindow::minimize(void)
438 {
439 m_taskbar->minimizeApplication(static_cast<IApplication*>(this));
440 }
441
442 /**
443 * Called when the window minimize close is pressed.
444 */
445
446 void CStartWindow::close(void)
447 {
448 // Do nothing... you can't close the start window!!!
449 }
450
451 /**
452 * Calculate the icon bounding box
453 */
454
455 void CStartWindow::getIconBounds(void)
456 {
457 // Visit each icon
458
459 struct nxgl_size_s maxSize;
460 maxSize.w = 0;
461 maxSize.h = 0;
462
463 for (int i = 0; i < m_slots.size(); i++)
464 {
465 // Get the icon associated with this application
466
467 NXWidgets::CImage *image = m_slots.at(i).image;
468
469 // Get the size of the icon image
470
471 NXWidgets::CRect rect;
472 image->getPreferredDimensions(rect);
473
474 // Keep the maximum height and width
475
476 if (rect.getWidth() > maxSize.h)
477 {
478 maxSize.w = rect.getWidth() ;
479 }
480
481 if (rect.getHeight() > maxSize.h)
482 {
483 maxSize.h = rect.getHeight();
484 }
485 }
486
487 // And save the new maximum size
488
489 m_iconSize.w = maxSize.w;
490 m_iconSize.h = maxSize.h;
491 }
492
493 /**
494 * Stop all applications
495 */
496
497 void CStartWindow::removeAllApplications(void)
498 {
499 // Stop all applications and remove them from the start window. Clearly, there
500 // are some ordering issues here... On an orderly system shutdown, disconnection
501 // should really occur priority to deleting instances
502
503 while (!m_slots.empty())
504 {
505 // Remove the application factory from the start menu
506
507 IApplicationFactory *app = m_slots.at(0).app;
508
509 // Now, delete the image and the application
510
511 delete app;
512 delete m_slots.at(0).image;
513
514 // And discard the data in this slot
515
516 m_slots.erase(0);
517 }
518 }
519
520 /**
521 * Handle a widget action event. For CImage, this is a mouse button pre-release event.
522 *
523 * @param e The event data.
524 */
525
526 void CStartWindow::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
527 {
528 // Was an ICON clicked?
529
530 for (int i = 0; i < m_slots.size(); i++)
531 {
532 // Is this the clicked icon?
533
534 NXWidgets::CImage *image = m_slots.at(i).image;
535 if (image->isClicked())
536 {
537 // Create a new copy of the application
538
539 IApplication *app = m_slots.at(i).app->create();
540 if (app)
541 {
542 // Start the new copy of the application
543
544 if (m_taskbar->startApplication(app, false))
545 {
546 // Then break out of the loop
547
548 break;
549 }
550 else
551 {
552 // If we cannot start the app. Destroy the instance we
553 // created and see what happens next. Could be interesting.
554
555 app->stop();
556 app->destroy();
557 }
558 }
559 }
560 }
561 }
562
NxWM::CStartWindow::handleActionEvent
void handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
Definition: cstartwindow.cxx:526
NxWM::CApplicationWindow
Definition: capplicationwindow.hxx:74
NxWM::CStartWindow::m_window
CApplicationWindow * m_window
Definition: cstartwindow.hxx:119
NXWidgets::CNxWidget::isClicked
bool isClicked(void) const
Definition: cnxwidget.hxx:560
NxWM::CStartWindow::minimize
void minimize(void)
Definition: cstartwindow.cxx:437
NxWM::CStartWindow::stop
void stop(void)
Definition: cstartwindow.cxx:173
cstartwindow.hxx
NXWidgets::CRect::getHeight
nxgl_coord_t getHeight(void) const
Definition: crect.hxx:204
NXWidgets::CWidgetControl::getGraphicsPort
CGraphicsPort * getGraphicsPort(void)
Definition: cwidgetcontrol.hxx:769
NXWidgets::CNxWidget::moveTo
bool moveTo(nxgl_coord_t x, nxgl_coord_t y)
Definition: cnxwidget.cxx:990
NXWidgets::CWidgetControl
Definition: cwidgetcontrol.hxx:95
NxWM::CStartWindow::isFullScreen
bool isFullScreen(void) const
Definition: cstartwindow.cxx:329
NxWM::IApplicationFactory
Definition: iapplication.hxx:218
NxWM::CStartWindow::hide
void hide(void)
Definition: cstartwindow.cxx:205
NXWidgets::CNxWidget::disableDrawing
void disableDrawing(void)
Definition: cnxwidget.hxx:908
NXWidgets::CNxWidget::setRaisesEvents
void setRaisesEvents(bool raises)
Definition: cnxwidget.hxx:887
NXWidgets::CRect::getWidth
nxgl_coord_t getWidth(void) const
Definition: crect.hxx:181
NxWM::IApplicationFactory::getIcon
virtual NXWidgets::IBitmap * getIcon(void)=0
NxWM::CTaskbar::startApplication
bool startApplication(IApplication *app, bool minimized)
Definition: ctaskbar.cxx:450
NxWM::CStartWindow::getIcon
NXWidgets::IBitmap * getIcon(void)
Definition: cstartwindow.cxx:139
NxWM::CStartWindow::getName
NXWidgets::CNxString getName(void)
Definition: cstartwindow.cxx:153
NXWidgets::CRlePaletteBitmap
Definition: crlepalettebitmap.hxx:100
CONFIG_NXWM_STARTWINDOW_ICON
const struct NXWidgets::SRlePaletteBitmap CONFIG_NXWM_STARTWINDOW_ICON
NXWidgets::IBitmap::getHeight
virtual const nxgl_coord_t getHeight(void) const =0
NxWM::CStartWindow::getWindow
IApplicationWindow * getWindow(void) const
Definition: cstartwindow.cxx:126
cwidgetcontrol.hxx
NxWM::CApplicationWindow::setWindowLabel
void setWindowLabel(NXWidgets::CNxString &appname)
Definition: capplicationwindow.cxx:475
NxWM::CStartWindow::SStartWindowSlot
Definition: cstartwindow.hxx:108
NxWM::CStartWindow::addApplication
bool addApplication(IApplicationFactory *app)
Definition: cstartwindow.cxx:345
NXWidgets::CImage::getPreferredDimensions
void getPreferredDimensions(CRect &rect) const
Definition: cimage.cxx:139
NxWM::CStartWindow::m_taskbar
CTaskbar * m_taskbar
Definition: cstartwindow.hxx:118
NXWidgets::CNxWidget::redraw
void redraw(void)
Definition: cnxwidget.cxx:483
NxWM::CStartWindow::getIconBounds
void getIconBounds(void)
Definition: cstartwindow.cxx:455
NxWM::IApplication::stop
virtual void stop(void)=0
NXWidgets::INxWindow::getSize
virtual bool getSize(FAR struct nxgl_size_s *pSize)=0
NXWidgets::CNxWidget::click
virtual bool click(nxgl_coord_t x, nxgl_coord_t y)
Definition: cnxwidget.cxx:630
NxWM::CTaskbar::minimizeApplication
bool minimizeApplication(IApplication *app)
Definition: ctaskbar.cxx:639
nxwmconfig.hxx
NXWidgets::CNxWidget::getPos
void getPos(struct nxgl_point_s &pos) const
Definition: cnxwidget.hxx:616
NxWM::CStartWindow::m_iconSize
struct nxgl_size_s m_iconSize
Definition: cstartwindow.hxx:121
NXWidgets::CNxWidget::addWidgetEventHandler
void addWidgetEventHandler(CWidgetEventHandler *eventHandler)
Definition: cnxwidget.hxx:854
NxWM::CStartWindow::CStartWindow
CStartWindow(CTaskbar *taskbar, CApplicationWindow *window)
Definition: cstartwindow.cxx:83
NxWM::CApplicationWindow::block
void block(IApplication *app)
Definition: capplicationwindow.cxx:457
nxwmglyphs.hxx
NxWM
Definition: capplicationwindow.hxx:66
NxWM::CStartWindow::close
void close(void)
Definition: cstartwindow.cxx:446
NXWidgets::CGraphicsPort::drawFilledRect
void drawFilledRect(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t width, nxgl_coord_t height, nxgl_mxpixel_t color)
Definition: cgraphicsport.cxx:280
NxWM::CStartWindow::redraw
void redraw(void)
Definition: cstartwindow.cxx:222
NxWM::CStartWindow::m_slots
TNxArray< struct SStartWindowSlot > m_slots
Definition: cstartwindow.hxx:120
NxWM::CTaskbar
Definition: ctaskbar.hxx:85
NxWM::CApplicationWindow::registerCallbacks
void registerCallbacks(IApplicationCallback *callback)
Definition: capplicationwindow.cxx:497
NXWidgets::CNxWidget::enableDrawing
void enableDrawing(void)
Definition: cnxwidget.hxx:917
NXWidgets::CNxWidget::getSize
void getSize(struct nxgl_size_s &size) const
Definition: cnxwidget.hxx:604
NxWM::CApplicationWindow::getWindow
NXWidgets::INxWindow * getWindow(void) const
Definition: capplicationwindow.cxx:434
NXWidgets::CWidgetEventArgs
Definition: cwidgeteventargs.hxx:127
NXWidgets::CRect
Definition: crect.hxx:101
NXWidgets::CImage
Definition: cimage.hxx:109
NxWM::IApplicationWindow
Definition: iapplicationwindow.hxx:95
NxWM::CStartWindow::destroy
void destroy(void)
Definition: cstartwindow.cxx:186
NxWM::g_startWindowMqName
FAR const char * g_startWindowMqName
Definition: cstartwindow.hxx:93
NxWM::IApplication
Definition: iapplication.hxx:70
NxWM::CStartWindow::run
bool run(void)
Definition: cstartwindow.cxx:164
NXWidgets::IBitmap::getWidth
virtual const nxgl_coord_t getWidth(void) const =0
NXWidgets::CNxString
Definition: cnxstring.hxx:121
NXWidgets::SRlePaletteBitmap
Definition: crlepalettebitmap.hxx:80
NXWidgets::INxWindow::getWidgetControl
virtual CWidgetControl * getWidgetControl(void) const =0
bitmap
static const NXWidgets::SRlePaletteBitmapEntry bitmap[]
Definition: glyph_mediaplayer24x24.cxx:85
NxWM::CStartWindow::SStartWindowSlot::app
IApplicationFactory * app
Definition: cstartwindow.hxx:110
ctaskbar.hxx
NxWM::IApplication::destroy
virtual void destroy(void)=0
NXWidgets::CNxWidget::release
bool release(nxgl_coord_t x, nxgl_coord_t y)
Definition: cnxwidget.cxx:771
NxWM::CStartWindow::clickIcon
void clickIcon(int index, bool click)
Definition: cstartwindow.cxx:401
NXWidgets::INxWindow
Definition: inxwindow.hxx:83
NXWidgets::IBitmap
Definition: ibitmap.hxx:103
NxWM::CStartWindow::SStartWindowSlot::image
NXWidgets::CImage * image
Definition: cstartwindow.hxx:111
NXWidgets::CNxWidget::setBorderless
void setBorderless(bool isBorderless)
Definition: cnxwidget.cxx:461
NXWidgets::CGraphicsPort
Definition: cgraphicsport.hxx:106
NxWM::CStartWindow::removeAllApplications
void removeAllApplications(void)
Definition: cstartwindow.cxx:497
NxWM::CApplicationWindow::isFullScreen
bool isFullScreen(void) const
Definition: capplicationwindow.cxx:488
NxWM::CStartWindow::~CStartWindow
~CStartWindow(void)
Definition: cstartwindow.cxx:104