Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmswindow.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2012 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
00031  **************************************************************************/
00032 
00033 #include "mmsgui/mmswindow.h"
00034 #include "mmsgui/mmschildwindow.h"
00035 #include "mmsgui/mmswidgets.h"
00036 #include "mmsgui/mmsborder.h"
00037 #include <math.h>
00038 #include <stdlib.h>
00039 #include <string.h>
00040 #include <fcntl.h>
00041 
00042 //#define DEBUG_LOCK_OUTPUT
00043 #ifdef DEBUG_LOCK_OUTPUT
00044 #include <sys/syscall.h>
00045 #define PRINT_LOCK(msg...) printf("%s %s - %d (%lu)\n", ((string)(msg)).c_str(),__FUNCTION__,__LINE__,(pid_t) syscall (SYS_gettid))
00046 #else
00047 #define PRINT_LOCK(msg...)
00048 #endif
00049 
00050 
00051 #include "mmscore/mmsinit.h"
00052 
00053 
00054 /* static variables */
00055 IMMSWindowManager   *MMSWindow::windowmanager = NULL;
00056 
00057 MMSImageManager     *MMSWindow::im1 = NULL;
00058 MMSFBLayer          *MMSWindow::im1_layer = NULL;
00059 MMSImageManager     *MMSWindow::im2 = NULL;
00060 MMSFBLayer          *MMSWindow::im2_layer = NULL;
00061 MMSFontManager      *MMSWindow::fm = NULL;
00062 
00063 MMSFBWindow *MMSWindow::fullscreen_root_window          = NULL;
00064 int         MMSWindow::fullscreen_root_window_use_count = 0;
00065 MMSFBWindow *MMSWindow::fullscreen_main_window          = NULL;
00066 int         MMSWindow::fullscreen_main_window_use_count = 0;
00067 
00068 // helper macros for horizontal stretchmode
00069 #define MMSFBWINDOW_CALC_STRETCH_W(w)               ((w->stretchLeft-25600)+(w->stretchRight-25600)+25600)
00070 #define MMSFBWINDOW_CALC_STRETCH_LEFT(x,w)          ((w->stretchLeft!=25600)?((((x)*w->stretchLeft*100+12800)/2560000)&~0x01):(x))
00071 #define MMSFBWINDOW_CALC_STRETCH_WIDTH(x,w)         ((MMSFBWINDOW_CALC_STRETCH_W(w)!=25600)?((((x)*MMSFBWINDOW_CALC_STRETCH_W(w)*100+12800)/2560000)&~0x01):(x))
00072 #define MMSFBWINDOW_CALC_STRETCH_WIDTH_REV(x,w)     ((MMSFBWINDOW_CALC_STRETCH_W(w)!=25600)?((((x)*25600+12800)/MMSFBWINDOW_CALC_STRETCH_W(w))&~0x01):(x))
00073 
00074 // helper macros for vertical stretchmode
00075 #define MMSFBWINDOW_CALC_STRETCH_H(w)               ((w->stretchUp-25600)+(w->stretchDown-25600)+25600)
00076 #define MMSFBWINDOW_CALC_STRETCH_UP(x,w)            ((w->stretchUp!=25600)?((((x)*w->stretchUp*100+12800)/2560000)&~0x01):(x))
00077 #define MMSFBWINDOW_CALC_STRETCH_HEIGHT(x,w)        ((MMSFBWINDOW_CALC_STRETCH_H(w)!=25600)?((((x)*MMSFBWINDOW_CALC_STRETCH_H(w)*100+12800)/2560000)&~0x01):(x))
00078 #define MMSFBWINDOW_CALC_STRETCH_HEIGHT_REV(x,w)    ((MMSFBWINDOW_CALC_STRETCH_H(w)!=25600)?((((x)*25600+12800)/MMSFBWINDOW_CALC_STRETCH_H(w))&~0x01):(x))
00079 
00080 
00081 #define MMSWINDOW_ANIM_MAX_OFFSET   30
00082 
00083 MMSWindow::MMSWindow() {
00084 
00085     this->TID = 0;
00086     this->Lock_cnt = 0;
00087 
00088     this->baseWindowClass = NULL;
00089     this->windowClass = NULL;
00090     this->initialized = false;
00091     this->precalcnav = false;
00092     this->parent = NULL;
00093     this->toplevel_parent = NULL;
00094 //this->im = NULL;
00095 //    this->fm = NULL;
00096     this->window = NULL;
00097     this->layer = NULL;
00098     this->surface = NULL;
00099     this->flags = MMSW_NONE;
00100     this->bgimage = NULL;
00101     this->bgimage_from_external = false;
00102     for (int i=0;i<MMSBORDER_IMAGE_NUM_SIZE;i++)
00103         this->borderimages[i] = NULL;
00104     bordergeomset = false;
00105 
00106     this->draw_setgeom = true;
00107 
00108     this->dxpix = 0;
00109     this->dypix = 0;
00110     this->geom.x = 0;
00111     this->geom.y = 0;
00112     this->geom.w = 0;
00113     this->geom.h = 0;
00114 
00115     this->focusedChildWin = 0;
00116 
00117     this->upArrowWidget    = NULL;
00118     this->downArrowWidget  = NULL;
00119     this->leftArrowWidget  = NULL;
00120     this->rightArrowWidget = NULL;
00121 
00122     this->initialArrowsDrawn = false;
00123 
00124     // init stretch mode, per default the windows will not be stretched by the window manager
00125     this->stretchmode = false;
00126     this->stretchLeft = 0;
00127     this->stretchUp = 0;
00128     this->stretchRight = 0;
00129     this->stretchDown = 0;
00130 
00131     this->always_on_top_index = 0;
00132 
00133     this->need_redraw = false;
00134 
00135     // initialize the callbacks
00136     onBeforeShow        = new sigc::signal<bool, MMSWindow*>::accumulated<bool_accumulator>;
00137     onAfterShow         = new sigc::signal<void, MMSWindow*, bool>;
00138     onBeforeHide        = new sigc::signal<bool, MMSWindow*, bool>::accumulated<bool_accumulator>;
00139     onHide              = new sigc::signal<void, MMSWindow*, bool>;
00140     onHandleInput       = new sigc::signal<bool, MMSWindow*, MMSInputEvent*>::accumulated<neg_bool_accumulator>;
00141     onBeforeHandleInput = new sigc::signal<bool, MMSWindow*, MMSInputEvent*>::accumulated<neg_bool_accumulator>;
00142     onDraw              = new sigc::signal<bool, MMSFBSurface*, bool>::accumulated<neg_bool_accumulator>;
00143 
00144     // initialize the animation callbacks
00145     this->onBeforeAnimation_connection  = this->pulser.onBeforeAnimation.connect(sigc::mem_fun(this, &MMSWindow::onBeforeAnimation));
00146     this->onAnimation_connection        = this->pulser.onAnimation.connect(sigc::mem_fun(this, &MMSWindow::onAnimation));
00147     this->onAfterAnimation_connection   = this->pulser.onAfterAnimation.connect(sigc::mem_fun(this, &MMSWindow::onAfterAnimation));
00148 }
00149 
00150 MMSWindow::~MMSWindow() {
00151     // wait until show/hide actions are finished
00152     PRINT_LOCK("mmsfb unlock");
00153     bool rc = mmsfb->unlock();
00154 
00155     while(this->action->getAction() != MMSWACTION_NONE)
00156         msleep(100);
00157 
00158     if(rc)
00159         mmsfb->lock();
00160 
00161     // hide the window if shown
00162     instantHide();
00163 
00164     // delete the callbacks
00165     if (onBeforeShow) delete onBeforeShow;
00166     if (onAfterShow) delete onAfterShow;
00167     if (onBeforeHide) delete onBeforeHide;
00168     if (onHide) delete onHide;
00169     if (onHandleInput) delete onHandleInput;
00170     if (onBeforeHandleInput) delete onBeforeHandleInput;
00171     if (onDraw) delete onDraw;
00172 
00173     // disconnect callbacks from pulser
00174     this->onBeforeAnimation_connection.disconnect();
00175     this->onAnimation_connection.disconnect();
00176     this->onAfterAnimation_connection.disconnect();
00177 
00178     // delete images, ...
00179     release();
00180 
00181     if (this->type != MMSWINDOWTYPE_CHILDWINDOW) {
00182         // remove normal window
00183         if (this->windowmanager)
00184             this->windowmanager->removeWindow(this);
00185     }
00186     else {
00187         // remove child window from parent
00188         if (this->parent)
00189             this->parent->removeChildWindow(this);
00190     }
00191 
00192     // delete children
00193     // i have to delete only the first widget because all others are children from it and will be implicitly deleted
00194     if (children.size()>0)
00195         delete children.at(0);
00196 
00197     // delete childwins
00198     for (unsigned int i = 0; i < childwins.size(); i++)
00199         delete childwins.at(i).window;
00200 
00201     // delete the rest :)
00202     delete this->action;
00203 //delete this->im;
00204 //delete this->fm;
00205 
00206     if (!((this->flags & MMSW_VIDEO)&&(!(this->flags & MMSW_USEGRAPHICSLAYER)))) {
00207         // surface is NOT the video layer surface
00208         // so delete the window/surface memory
00209         if (this->window) {
00210             // delete the mmsfbwindow/surface
00211             bool os;
00212             getOwnSurface(os);
00213             if (os) {
00214                 // own surface, so delete complete window
00215                 delete this->window;
00216             }
00217             else {
00218                 // delete sub-surface and decrease use counter
00219                 if (this->surface)
00220                     delete this->surface;
00221                 if (this->type == MMSWINDOWTYPE_ROOTWINDOW) {
00222                     if (this->fullscreen_root_window_use_count > 0)
00223                         this->fullscreen_root_window_use_count--;
00224                     if (this->fullscreen_root_window_use_count == 0)
00225                         if (this->fullscreen_root_window) {
00226                             // delete the fullscreen window for root window type because not used anymore
00227                             delete this->fullscreen_root_window;
00228                             this->fullscreen_root_window = NULL;
00229                         }
00230                 }
00231                 if (this->type == MMSWINDOWTYPE_MAINWINDOW) {
00232                     if (this->fullscreen_main_window_use_count > 0)
00233                         this->fullscreen_main_window_use_count--;
00234                     if (this->fullscreen_main_window_use_count == 0)
00235                         if (this->fullscreen_main_window) {
00236                             // delete the fullscreen window for main window type because not used anymore
00237                             delete this->fullscreen_main_window;
00238                             this->fullscreen_main_window = NULL;
00239                         }
00240                 }
00241             }
00242         }
00243         else {
00244             // delete surface (e.g. child window surface)
00245             if (this->surface)
00246                 delete this->surface;
00247         }
00248     }
00249 }
00250 
00251 MMSWINDOWTYPE MMSWindow::getType() {
00252     return this->type;
00253 }
00254 
00255 bool MMSWindow::create(string dx, string dy, string w, string h, MMSALIGNMENT alignment, MMSWINDOW_FLAGS flags,
00256                        bool *own_surface, bool *backbuffer) {
00257     /* save flags */
00258     this->flags = flags;
00259 
00260     /* set theme values */
00261     if (dx != "")
00262         setDx(dx, false, false);
00263     if (dy != "")
00264         setDy(dy, false, false);
00265     if (w != "")
00266         setWidth(w, false, false);
00267     if (h != "")
00268         setHeight(h, false, false);
00269     if (alignment != MMSALIGNMENT_NOTSET)
00270         setAlignment(alignment, false, false);
00271     if (own_surface)
00272         setOwnSurface(*own_surface);
00273     if (backbuffer)
00274         setBackBuffer(*backbuffer);
00275 
00276     this->action = new MMSWindowAction(this);
00277     this->firstfocusset = false;
00278     this->focusedwidget=NULL;
00279 
00280     this->navigateUpWindow    = NULL;
00281     this->navigateDownWindow  = NULL;
00282     this->navigateLeftWindow  = NULL;
00283     this->navigateRightWindow = NULL;
00284 
00285     this->buttonpress_widget = NULL;
00286     this->buttonpress_childwin = NULL;
00287 
00288     if (!this->parent) {
00289         /* normal parent window, check the flags and get the right layer */
00290         if ((mmsfbmanager.getLayerCount()<2)&&(this->flags & MMSW_VIDEO)) {
00291             DEBUGMSG("MMSGUI", "use video window on graphics layer");
00292             this->flags = (MMSWINDOW_FLAGS)(this->flags | MMSW_USEGRAPHICSLAYER);
00293         }
00294 
00295         if ((this->flags & MMSW_VIDEO)&&(!(this->flags & MMSW_USEGRAPHICSLAYER))) {
00296             DEBUGMSG("MMSGUI", "get the video layer");
00297             this->layer = mmsfbmanager.getVideoLayer();
00298         } else {
00299             DEBUGMSG("MMSGUI", "get the grapics layer");
00300             this->layer = mmsfbmanager.getGraphicsLayer();
00301         }
00302     }
00303     else {
00304         /* child window, use the flags and the layer from my parent */
00305         DEBUGMSG("MMSGUI", "use layer from parent window");
00306         this->flags = this->parent->flags;
00307         this->layer = this->parent->layer;
00308 
00309         // searching the right toplevel parent
00310         this->toplevel_parent = this->getParent(true);
00311     }
00312 
00313     DEBUGMSG("MMSGUI", "got flags: ");
00314     if (this->flags) {
00315         if (this->flags & MMSW_VIDEO)
00316             DEBUGMSG("MMSGUI", " MMSW_VIDEO");
00317         if(this->flags & MMSW_USEGRAPHICSLAYER)
00318             DEBUGMSG("MMSGUI", " MMSW_USEGRAPHICSLAYER");
00319     }
00320     else
00321         DEBUGMSG("MMSGUI", " MMSW_NONE");
00322 
00323     // create static image manager
00324     if (!this->im1_layer) {
00325         this->im1 = new MMSImageManager(this->layer);
00326         this->im1_layer = this->layer;
00327         this->im = this->im1;
00328     }
00329     else {
00330         if (this->im1_layer == this->layer) {
00331             this->im = this->im1;
00332         }
00333         else {
00334             if (this->im2_layer == this->layer) {
00335                 this->im = this->im2;
00336             }
00337             else {
00338                 this->im2 = new MMSImageManager(this->layer);
00339                 this->im2_layer = this->layer;
00340                 this->im = this->im2;
00341             }
00342         }
00343     }
00344 
00345     // create static font manager
00346     if (!this->fm)
00347         this->fm = new MMSFontManager();
00348 
00349     // set some attributes
00350     this->shown=false;
00351     this->willshow=false;
00352     this->willhide=false;
00353 
00354     buffered_shown = false;
00355 
00356     // resize/create the window
00357     if (this->windowmanager)
00358         resize();
00359 
00360     bool initial_load = false;
00361     getInitialLoad(initial_load);
00362     if (initial_load) {
00363         // init window (e.g. load images, fonts, ...)
00364         init();
00365     }
00366 
00367     return true;
00368 }
00369 
00370 bool MMSWindow::create(string w, string h, MMSALIGNMENT alignment, MMSWINDOW_FLAGS flags, bool *own_surface,
00371                        bool *backbuffer) {
00372     return create("", "", w, h, alignment, flags, own_surface, backbuffer);
00373 }
00374 
00375 
00376 
00377 bool MMSWindow::resize(bool refresh) {
00378     int wdesc_posx, wdesc_posy, wdesc_width, wdesc_height;
00379     string dx, dy, width, height;
00380 
00381 
00382     DEBUGMSG("MMSGUI", "resize... flags: " + iToStr(this->flags));
00383 
00384     if (this->layer == NULL) {
00385         DEBUGMSG("MMSGUI", "have no layer... returning");
00386         return false;
00387     }
00388 
00389     if (!this->parent) {
00390         /* normal parent window */
00391 
00392         /* check if we have a video window and should use the video layer */
00393         if ((this->flags & MMSW_VIDEO)&&(!(this->flags & MMSW_USEGRAPHICSLAYER))) {
00394             if (!this->surface) {
00395                 DEBUGMSG("MMSGUI", "have a video window, use the layer surface");
00396                 this->layer->getSurface(&this->surface);
00397                 DEBUGMSG("MMSGUI", "after layer->getSurface() (surface = 0x%x)", this->surface);
00398                 if (this->windowmanager)
00399                     this->windowmanager->addWindow(this);
00400 
00401                 this->geom.x = 0;
00402                 this->geom.y = 0;
00403                 this->layer->getResolution(&this->geom.w, &this->geom.h);
00404                 this->innerGeom = this->geom;
00405                 DEBUGMSG("MMSGUI", "resolution: %d x %d", this->geom.w, this->geom.h);
00406             }
00407             else
00408                 DEBUGMSG("MMSGUI", "cannot resize the layer surface");
00409 
00410             return true;
00411         }
00412 
00413         if (!this->windowmanager) {
00414             DEBUGMSG("MMSGUI", "have no windowmanager... returning");
00415             return false;
00416         }
00417 
00418         /* get the screen width and height */
00419         this->layer->getResolution(&this->vrect.w, &this->vrect.h);
00420         DEBUGMSG("MMSGUI", "got screen %dx%d", this->vrect.w, this->vrect.h);
00421 
00422         if (this->flags & MMSW_VIDEO) {
00423             /* for video windows use full screen */
00424             this->vrect.x = 0;
00425             this->vrect.y = 0;
00426         }
00427         else
00428             /* other windows uses visible rectangle settings from windowmanager */
00429             this->vrect = this->windowmanager->getVRect();
00430 
00431         DEBUGMSG("MMSGUI", "use screen area %d, %d, %d, %d", this->vrect.x, this->vrect.x, this->vrect.w, this->vrect.h);
00432     }
00433     else {
00434         /* child window */
00435 
00436         /* get the parent width and height */
00437         this->vrect.x = (this->parent->geom.w - this->parent->innerGeom.w) / 2;
00438         this->vrect.y = (this->parent->geom.h - this->parent->innerGeom.h) / 2;
00439         this->vrect.w = this->parent->innerGeom.w;
00440         this->vrect.h = this->parent->innerGeom.h;
00441 //        logger.writeLog("got inner size from parent " + iToStr(vrect.w) + "x" + iToStr(vrect.h));
00442     }
00443 
00444     /* calculate the window position */
00445     /* first try with xpos */
00446     if (!getDx(dx)) dx = "";
00447     if (getPixelFromSizeHint(&wdesc_posx, dx, vrect.w, 0) == false) {
00448         if (getPixelFromSizeHint(&wdesc_posx, dx, 10000, 0) == false) {
00449             DEBUGMSG("MMSGUI", "window dx %s is wrong, using 0px", dx.c_str());
00450             myWindowClass.setDx("0px");
00451             wdesc_posx = 0;
00452         }
00453     }
00454     /* ypos */
00455     if (!getDy(dy)) dy = "";
00456     if (getPixelFromSizeHint(&wdesc_posy, dy, vrect.h, wdesc_posx) == false) {
00457         if (getPixelFromSizeHint(&wdesc_posy, dy, 10000, wdesc_posx) == false) {
00458             DEBUGMSG("MMSGUI", "window dy %s is wrong, using 0px", dy.c_str());
00459             myWindowClass.setDy("0px");
00460             wdesc_posy = 0;
00461         }
00462     }
00463     /* second try with xpos (because of "<factor>$") */
00464     if (!getDx(dx)) dx = "";
00465     if (getPixelFromSizeHint(&wdesc_posx, dx, vrect.w, wdesc_posy) == false) {
00466         if (getPixelFromSizeHint(&wdesc_posx, dx, 10000, wdesc_posy) == false) {
00467             DEBUGMSG("MMSGUI", "window dx %s is wrong, using 0px", dx.c_str());
00468             myWindowClass.setDx("0px");
00469             wdesc_posx = 0;
00470         }
00471     }
00472 
00473     /* save the real dx / dy */
00474     this->dxpix = wdesc_posx;
00475     this->dypix = wdesc_posy;
00476 
00477     DEBUGMSG("MMSGUI", "dx: %d, dy: %d", this->dxpix, this->dypix);
00478 
00479     /* calculate the window size */
00480     if (!getWidth(width)) width = "";
00481     if (getPixelFromSizeHint(&wdesc_width, width, vrect.w, 0) == false) {
00482         if (getPixelFromSizeHint(&wdesc_width, width, 10000, 0) == false) {
00483             DEBUGMSG("MMSGUI", "window width %s is wrong, using %d px", width.c_str(), vrect.w);
00484             myWindowClass.setWidth(iToStr(vrect.w) + "px");
00485             wdesc_width = vrect.w;
00486         }
00487     }
00488     if (!getHeight(height)) height = "";
00489     if (getPixelFromSizeHint(&wdesc_height, height, vrect.h, 0) == false) {
00490         if (getPixelFromSizeHint(&wdesc_height, height, 10000, 0) == false) {
00491             DEBUGMSG("MMSGUI", "window height %s is wrong, using %d px", height.c_str(), vrect.h);
00492             myWindowClass.setHeight(iToStr(vrect.h) + "px");
00493             wdesc_height = vrect.h;
00494         }
00495     }
00496 
00497     DEBUGMSG("MMSGUI", "window resolution: %d x %d", wdesc_width, wdesc_height);
00498 
00499     if ((wdesc_width == 0)&&(wdesc_height == 0)) {
00500         /* bad values */
00501         DEBUGMSG("MMSGUI", "window width " + width + " is wrong, using " + iToStr(vrect.w) + "px");
00502         myWindowClass.setWidth(iToStr(vrect.w) + "px");
00503         wdesc_width = vrect.w;
00504         DEBUGMSG("MMSGUI", "window height " + height + " is wrong, using " + iToStr(vrect.h) + "px");
00505         myWindowClass.setHeight(iToStr(vrect.h) + "px");
00506         wdesc_height = vrect.h;
00507     }
00508     else {
00509         if (wdesc_width == 0) {
00510             /* it seems that width should be a factor of height */
00511             getPixelFromSizeHint(&wdesc_width, width, vrect.w, wdesc_height);
00512         }
00513         else {
00514             /* it seems that height should be a factor of width */
00515             getPixelFromSizeHint(&wdesc_height, height, vrect.h, wdesc_width);
00516         }
00517     }
00518 
00519     /* adjust a little bit */
00520     unsigned int margin;
00521     if (!getMargin(margin))
00522         margin = 0;
00523     wdesc_posx+= vrect.x;
00524     wdesc_posy+= vrect.y;
00525     wdesc_width-= margin*2;
00526     wdesc_height-= margin*2;
00527 
00528     /* work with alignment */
00529     MMSALIGNMENT alignment;
00530     if (!getAlignment(alignment)) alignment = MMSALIGNMENT_CENTER;
00531     switch (alignment) {
00532         case MMSALIGNMENT_CENTER:
00533             wdesc_posx+= (vrect.w - wdesc_width) / 2;
00534             wdesc_posy+= (vrect.h - wdesc_height) / 2;
00535             break;
00536         case MMSALIGNMENT_LEFT:
00537             wdesc_posy+= (vrect.h - wdesc_height) / 2;
00538             break;
00539         case MMSALIGNMENT_RIGHT:
00540             wdesc_posx+= (vrect.w - wdesc_width);
00541             wdesc_posy+= (vrect.h - wdesc_height) / 2;
00542             break;
00543         case MMSALIGNMENT_TOP_CENTER:
00544             wdesc_posx+= (vrect.w - wdesc_width) / 2;
00545             break;
00546         case MMSALIGNMENT_TOP_LEFT:
00547             break;
00548         case MMSALIGNMENT_TOP_RIGHT:
00549             wdesc_posx+= (vrect.w - wdesc_width);
00550             break;
00551         case MMSALIGNMENT_BOTTOM_CENTER:
00552             wdesc_posx+= (vrect.w - wdesc_width) / 2;
00553             wdesc_posy+= (vrect.h - wdesc_height);
00554             break;
00555         case MMSALIGNMENT_BOTTOM_LEFT:
00556             wdesc_posy+= (vrect.h - wdesc_height);
00557             break;
00558         case MMSALIGNMENT_BOTTOM_RIGHT:
00559             wdesc_posx+= (vrect.w - wdesc_width);
00560             wdesc_posy+= (vrect.h - wdesc_height);
00561             break;
00562         default:
00563             break;
00564     }
00565 
00566     // use even pos/size because of pixelformats like YV12
00567     wdesc_posx   &= 0xfffffffe;
00568     wdesc_posy   &= 0xfffffffe;
00569     wdesc_width  &= 0xfffffffe;
00570     wdesc_height &= 0xfffffffe;
00571 
00572     int oldx = this->geom.x;
00573     int oldy = this->geom.y;
00574     this->geom.x = wdesc_posx;
00575     this->geom.y = wdesc_posy;
00576     int oldw = this->geom.w;
00577     int oldh = this->geom.h;
00578     this->geom.w = wdesc_width;
00579     this->geom.h = wdesc_height;
00580     unsigned int borderMargin;
00581     if (!getBorderMargin(borderMargin))
00582         borderMargin = 0;
00583     unsigned int borderThickness;
00584     if (!getBorderThickness(borderThickness))
00585         borderThickness = 0;
00586     unsigned int dz = borderMargin + borderThickness;
00587     innerGeom.x = dz;
00588     innerGeom.y = dz;
00589     innerGeom.w = this->geom.w - 2*dz;
00590     innerGeom.h = this->geom.h - 2*dz;
00591 
00592 
00593     if (!this->parent) {
00594         // normal parent window
00595         if (!this->window) {
00596             // create window
00597 
00598             // own surface?
00599             bool os;
00600             getOwnSurface(os);
00601 
00602             if (!(this->flags & MMSW_VIDEO)) {
00603                 // no video window, use alpha
00604                 if ((os) || ((this->type == MMSWINDOWTYPE_ROOTWINDOW) && (!this->fullscreen_root_window))
00605                          || ((this->type == MMSWINDOWTYPE_MAINWINDOW) && (!this->fullscreen_main_window))) {
00606 
00607                     if ((!os) && ((this->type == MMSWINDOWTYPE_ROOTWINDOW) || (this->type == MMSWINDOWTYPE_MAINWINDOW))) {
00608                         // create full screen window
00609                         wdesc_posx = 0;
00610                         wdesc_posy = 0;
00611                         this->layer->getResolution(&wdesc_width, &wdesc_height);
00612                     }
00613 
00614                     // window should have own surface, backbuffer requested?
00615                     bool backbuffer = false;
00616                     getBackBuffer(backbuffer);
00617                     if (backbuffer) {
00618                         DEBUGMSG("MMSGUI", "creating window (" + iToStr(wdesc_posx) + ","
00619                                                             + iToStr(wdesc_posy) + ","
00620                                                             + iToStr(wdesc_width) + ","
00621                                                             + iToStr(wdesc_height)
00622                                                             + ") with alphachannel and backbuffer");
00623                         this->layer->createWindow(&(this->window),
00624                                                   wdesc_posx, wdesc_posy, wdesc_width, wdesc_height,
00625                                                   MMSFB_PF_NONE, true, 1);
00626                     }
00627                     else {
00628                         DEBUGMSG("MMSGUI", "creating window (" + iToStr(wdesc_posx) + ","
00629                                                             + iToStr(wdesc_posy) + ","
00630                                                             + iToStr(wdesc_width) + ","
00631                                                             + iToStr(wdesc_height)
00632                                                             + ") with alphachannel, no backbuffer");
00633                         this->layer->createWindow(&(this->window),
00634                                                   wdesc_posx, wdesc_posy, wdesc_width, wdesc_height,
00635                                                   MMSFB_PF_NONE, true, 0);
00636                     }
00637 
00638                     DEBUGMSG("MMSGUI", "window created (0x%x)", this->window);
00639 
00640                     // window should not be visible at this time
00641                     this->window->setOpacity(0);
00642                 }
00643 
00644                 if (!os) {
00645                     if (this->type == MMSWINDOWTYPE_ROOTWINDOW) {
00646                         if (!this->fullscreen_root_window)
00647                             this->fullscreen_root_window = this->window;
00648                         else
00649                             this->window = this->fullscreen_root_window;
00650                         this->fullscreen_root_window_use_count++;
00651                     }
00652                     else
00653                     if (this->type == MMSWINDOWTYPE_MAINWINDOW) {
00654                         if (!this->fullscreen_main_window)
00655                             this->fullscreen_main_window = this->window;
00656                         else
00657                             this->window = this->fullscreen_main_window;
00658                         this->fullscreen_main_window_use_count++;
00659                     }
00660                 }
00661             }
00662             else {
00663                 // video window, do not use alpha
00664                 bool backbuffer = false;
00665                 getBackBuffer(backbuffer);
00666                 if (backbuffer) {
00667                     DEBUGMSG("MMSGUI", "creating video window (" + iToStr(wdesc_posx) + ","
00668                                                               + iToStr(wdesc_posy) + ","
00669                                                               + iToStr(wdesc_width) + ","
00670                                                               + iToStr(wdesc_height)
00671                                                               + ") with backbuffer, no alphachannel");
00672                     this->layer->createWindow(&(this->window),
00673                                               wdesc_posx, wdesc_posy, wdesc_width, wdesc_height,
00674                                               MMSFB_PF_NONE, false, 1);
00675                 }
00676                 else {
00677                     DEBUGMSG("MMSGUI", "creating video window (" + iToStr(wdesc_posx) + ","
00678                                                               + iToStr(wdesc_posy) + ","
00679                                                               + iToStr(wdesc_width) + ","
00680                                                               + iToStr(wdesc_height)
00681                                                               + "), no alphachannel, no backbuffer");
00682                     this->layer->createWindow(&(this->window),
00683                                               wdesc_posx, wdesc_posy, wdesc_width, wdesc_height,
00684                                               MMSFB_PF_NONE, false, 0);
00685                 }
00686 
00687                 DEBUGMSG("MMSGUI", "video window created (0x%x)", this->window);
00688 
00689                 // window should not be visible at this time
00690                 this->window->setOpacity(0);
00691 
00692                 // video windows should have own surfaces
00693                 setOwnSurface(true);
00694             }
00695 
00696             // get window surface
00697             this->window->getSurface(&(this->surface));
00698 
00699             if ((this->window == this->fullscreen_root_window) || (this->window == this->fullscreen_main_window)) {
00700                 // get subsurface
00701                 DEBUGMSG("MMSGUI", "window has no own surface, get subsurface of shared full screen window");
00702                 this->surface = this->surface->getSubSurface(&this->geom);
00703             }
00704 
00705 
00706             // normal window
00707             DEBUGMSG("MMSGUI", "setting blitting flags for window");
00708             this->surface->lock();
00709             this->surface->setBlittingFlags(MMSFB_BLIT_BLEND_ALPHACHANNEL);
00710             this->surface->unlock();
00711 
00712             /* set the window to bottom */
00713 //            this->window->lowerToBottom();
00714 
00715             // add window to managers list
00716             if (this->windowmanager) {
00717                 DEBUGMSG("MMSGUI", "adding window to window manager");
00718                 this->windowmanager->addWindow(this);
00719             }
00720         }
00721         else {
00722             // change the window (new size/pos)
00723             bool os;
00724             getOwnSurface(os);
00725             if (os) {
00726                 // own surface
00727                 int px,py;
00728                 this->window->getPosition(&px, &py);
00729                 if ((this->geom.x != px)||(this->geom.y != py)) {
00730                     DEBUGMSG("MMSGUI", "repositioning window (" + iToStr(this->geom.x) + "," + iToStr(this->geom.y) + ")");
00731                     this->window->moveTo(this->geom.x, this->geom.y);
00732                 }
00733                 int w,h;
00734                 this->window->getSize(&w, &h);
00735                 if ((this->geom.w != w)||(this->geom.h != h)) {
00736                     DEBUGMSG("MMSGUI", "resizing window (" + iToStr(this->geom.w) + "x" + iToStr(this->geom.h) + ")");
00737                     this->window->resize(this->geom.w, this->geom.h);
00738                 }
00739             }
00740             else {
00741                 // working with subsurface
00742                 DEBUGMSG("MMSGUI", "re-positioning/-sizing window subsurface (" + iToStr(this->geom.x) + "," + iToStr(this->geom.y) + ","
00743                                                                         + iToStr(this->geom.w) + "," + iToStr(this->geom.h) + ")");
00744                 this->surface->lock();
00745                 this->surface->setSubSurface(&this->geom);
00746                 this->surface->unlock();
00747             }
00748         }
00749     }
00750     else {
00751         /* child window */
00752         if (!this->surface) {
00753             /* create surface for child window */
00754             /* get layers pixelformat */
00755             MMSFBSurfacePixelFormat pixelformat;
00756             this->layer->getPixelFormat(&pixelformat);
00757 
00758             bool os;
00759             getOwnSurface(os);
00760             if (os) {
00761                 bool backbuffer = false;
00762                 getBackBuffer(backbuffer);
00763                 if (backbuffer) {
00764                     DEBUGMSG("MMSGUI", "creating surface for child window (" + iToStr(wdesc_posx) + ","
00765                                                                           + iToStr(wdesc_posy) + ","
00766                                                                           + iToStr(wdesc_width) + ","
00767                                                                           + iToStr(wdesc_height)
00768                                                                           + ") with pixelformat " + getMMSFBPixelFormatString(pixelformat)
00769                                                                           + " (alphachannel and backbuffer)");
00770 
00771                     this->layer->createSurface(&(this->surface),
00772                                               wdesc_width, wdesc_height, MMSFB_PF_NONE, 1);
00773                 }
00774                 else {
00775                     DEBUGMSG("MMSGUI", "creating surface for child window (" + iToStr(wdesc_posx) + ","
00776                                                                           + iToStr(wdesc_posy) + ","
00777                                                                           + iToStr(wdesc_width) + ","
00778                                                                           + iToStr(wdesc_height)
00779                                                                           + ") with pixelformat " + getMMSFBPixelFormatString(pixelformat)
00780                                                                           + " (alphachannel, no backbuffer)");
00781 
00782                     this->layer->createSurface(&(this->surface),
00783                                               wdesc_width, wdesc_height, MMSFB_PF_NONE, 0);
00784                 }
00785             }
00786             else {
00787                 DEBUGMSG("MMSGUI", "creating sub surface for child window (" + iToStr(wdesc_posx) + ","
00788                                                                           + iToStr(wdesc_posy) + ","
00789                                                                           + iToStr(wdesc_width) + ","
00790                                                                           + iToStr(wdesc_height)
00791                                                                           + ") with pixelformat " + getMMSFBPixelFormatString(pixelformat)
00792                                                                           + " (use alpha)");
00793 
00794                 MMSFBRectangle rect;
00795 
00796                 rect.x = wdesc_posx;
00797                 rect.y = wdesc_posy;
00798                 rect.w = wdesc_width;
00799                 rect.h = wdesc_height;
00800                 this->surface = this->parent->surface->getSubSurface(&rect);
00801             }
00802 
00803             this->surface->lock();
00804             this->surface->setBlittingFlags(MMSFB_BLIT_BLEND_ALPHACHANNEL);
00805             this->surface->unlock();
00806 
00807             /* set the window to bottom */
00808 //            this->window->lowerToBottom();
00809 
00810             /* add window to parents childwins list */
00811 //printf("%x->resize(), this->%x->addChildwindow(%x)\n", this, this->parent, this);
00812             this->parent->addChildWindow(this);
00813         }
00814         else {
00815             /* change the surface (new size/pos) */
00816             if   ((this->geom.x != oldx)||(this->geom.y != oldy)
00817                 ||(this->geom.w != oldw)||(this->geom.h != oldh)) {
00818                 DEBUGMSG("MMSGUI", "re-positioning/-sizing child window (" + iToStr(this->geom.x) + "," + iToStr(this->geom.y) + ","
00819                                                                         + iToStr(this->geom.w) + "," + iToStr(this->geom.h) + ")");
00820                 this->parent->setChildWindowRegion(this, refresh);
00821             }
00822         }
00823     }
00824 
00825     DEBUGMSG("MMSGUI", "resizing done");
00826 
00827     return true;
00828 }
00829 
00830 
00831 void MMSWindow::lock() {
00832     // which window is to lock?
00833     MMSWindow *tolock = this;
00834     if (this->toplevel_parent)
00835         tolock = this->toplevel_parent;
00836     else
00837     if (this->parent)
00838         tolock = this->parent;
00839 
00840     if (tolock->surface)
00841         tolock->surface->lock();
00842 
00843 /*    if (tolock->Lock.trylock() == 0) {
00844         // I have got the lock the first time
00845         tolock->TID = pthread_self();
00846         tolock->Lock_cnt = 1;
00847     }
00848     else {
00849         if ((tolock->TID == pthread_self())&&(tolock->Lock_cnt > 0)) {
00850             // I am the thread which has already locked this window
00851             tolock->Lock_cnt++;
00852         }
00853         else {
00854             // another thread has already locked this window, waiting for...
00855             tolock->Lock.lock();
00856             tolock->TID = pthread_self();
00857             tolock->Lock_cnt = 1;
00858         }
00859     }
00860     */
00861 
00862 /*
00863     if (this->Lock.trylock() == 0) {
00864         // I have got the lock the first time
00865         this->TID = pthread_self();
00866         this->Lock_cnt = 1;
00867     }
00868     else {
00869         if ((this->TID == pthread_self())&&(this->Lock_cnt > 0)) {
00870             // I am the thread which has already locked this window
00871             this->Lock_cnt++;
00872         }
00873         else {
00874             // another thread has already locked this window, waiting for...
00875             this->Lock.lock();
00876             this->TID = pthread_self();
00877             this->Lock_cnt = 1;
00878         }
00879     }
00880     */
00881 }
00882 
00883 void MMSWindow::unlock() {
00884     // which window is to lock?
00885     MMSWindow *tolock = this;
00886     if (this->toplevel_parent)
00887         tolock = this->toplevel_parent;
00888     else
00889     if (this->parent)
00890         tolock = this->parent;
00891 
00892     if (tolock->surface)
00893         tolock->surface->unlock();
00894 
00895 /*  if (tolock->TID != pthread_self())
00896         return;
00897     if(tolock->Lock_cnt==0)
00898         return;
00899     tolock->Lock_cnt--;
00900     if (tolock->Lock_cnt == 0)
00901         tolock->Lock.unlock();
00902 */
00903 
00904 /*
00905     if (this->TID != pthread_self())
00906         return;
00907     if(this->Lock_cnt==0)
00908         return;
00909     this->Lock_cnt--;
00910     if (this->Lock_cnt == 0)
00911         this->Lock.unlock();
00912 */
00913 }
00914 
00915 
00916 string MMSWindow::getName() {
00917     return this->name;
00918 }
00919 
00920 void MMSWindow::setName(string name) {
00921     this->name = name;
00922 }
00923 
00924 MMSWindow* MMSWindow::findWindow(string name) {
00925     MMSWindow *window;
00926 
00927     if (name == "") {
00928         // empty name
00929         return NULL;
00930     }
00931 
00932     if (name == this->name) {
00933         // it's me
00934         return this;
00935     }
00936 
00937     // first, my own childwins
00938     for (unsigned int i = 0; i < childwins.size(); i++)
00939         if (childwins.at(i).window->getName() == name)
00940             return childwins.at(i).window;
00941 
00942     // second, call search method of my childwins
00943     for (unsigned int i = 0; i < childwins.size(); i++)
00944         if ((window = childwins.at(i).window->findWindow(name)))
00945             return window;
00946 
00947     return NULL;
00948 }
00949 
00950 MMSWindow* MMSWindow::getLastWindow() {
00951     if (this->childwins.size() > 0)
00952         return this->childwins.at(this->childwins.size()-1).window;
00953     return NULL;
00954 }
00955 
00956 bool MMSWindow::addChildWindow(MMSWindow *childwin) {
00957     if (childwin->getType()!=MMSWINDOWTYPE_CHILDWINDOW)
00958         return false;
00959 
00960     // per default childwins are not focused
00961     CHILDWINS cw;
00962     cw.window = childwin;
00963     cw.region.x1 = childwin->geom.x;
00964     cw.region.y1 = childwin->geom.y;
00965     cw.region.x2 = childwin->geom.x + childwin->geom.w - 1         ;//+20;
00966     cw.region.y2 = childwin->geom.y + childwin->geom.h - 1         ;//+20;
00967     cw.opacity = 0;
00968     cw.oldopacity = 0;
00969     cw.focusedWidget = 0;
00970     cw.special_blit = false;
00971 
00972     // insert child window into stack
00973     lock();
00974     bool aot = false;
00975     childwin->getAlwaysOnTop(aot);
00976     if (!aot) {
00977         // normal stack position, insert window before windows with "always on top" flag
00978         this->childwins.insert(this->childwins.begin() + this->always_on_top_index, cw);
00979         this->always_on_top_index++;
00980     }
00981     else {
00982         // window with "always on top" flag, add it to the end of list
00983         this->childwins.push_back(cw);
00984     }
00985     unlock();
00986 
00987     return true;
00988 }
00989 
00990 
00991 
00992 bool MMSWindow::removeChildWindow(MMSWindow *childwin) {
00993     if (childwin->getType()!=MMSWINDOWTYPE_CHILDWINDOW)
00994         return false;
00995 
00996     // remove child window from stack
00997     lock();
00998     for (unsigned int i = 0; i < this->childwins.size(); i++) {
00999         if (childwins.at(i).window == childwin) {
01000             // remove window from stack
01001             this->childwins.erase(this->childwins.begin()+i);
01002             bool aot = false;
01003             childwin->getAlwaysOnTop(aot);
01004             if (!aot) {
01005                 // normal stack position, decrease the index for "always on top" windows
01006                 this->always_on_top_index--;
01007             }
01008 
01009             int childwinsize = this->childwins.size()-1;
01010             if ((this->focusedChildWin > childwinsize) && (childwinsize >= 0))
01011                 this->focusedChildWin = childwinsize;
01012 
01013             unlock();
01014             return true;
01015         }
01016     }
01017     unlock();
01018 
01019     return false;
01020 }
01021 
01022 
01023 bool MMSWindow::setChildWindowOpacity(MMSWindow *childwin, unsigned char opacity, bool refresh) {
01024     if (childwin->getType()!=MMSWINDOWTYPE_CHILDWINDOW)
01025         return false;
01026 
01027     // find child window and set the opacity
01028     lock();
01029     for (unsigned int i = 0; i < this->childwins.size(); i++) {
01030         if (this->childwins.at(i).window == childwin) {
01031             this->childwins.at(i).oldopacity = this->childwins.at(i).opacity;
01032             this->childwins.at(i).opacity = opacity;
01033             if (refresh) {
01034                 PRINT_LOCK("call flipWindow");
01035                 flipWindow(childwin, NULL, MMSFB_FLIP_NONE, false, true);
01036                 PRINT_LOCK("end flipWindow");
01037             }
01038             unlock();
01039             return true;
01040         }
01041     }
01042     unlock();
01043     return false;
01044 }
01045 
01046 bool MMSWindow::setChildWindowRegion(MMSWindow *childwin, bool refresh) {
01047 
01048     if (childwin->getType()!=MMSWINDOWTYPE_CHILDWINDOW)
01049         return false;
01050 
01051     lock();
01052     for (unsigned int i = 0; i < this->childwins.size(); i++) {
01053         if (this->childwins.at(i).window == childwin) {
01054             // get old region
01055             MMSFBRegion *currregion = &this->childwins.at(i).region;
01056             MMSFBRegion oldregion = *currregion;
01057 
01058             if   ((oldregion.x1 != childwin->geom.x)
01059                 ||(oldregion.y1 != childwin->geom.y)
01060                 ||(oldregion.x2 - oldregion.x1 + 1 != childwin->geom.w)
01061                 ||(oldregion.y2 - oldregion.y1 + 1 != childwin->geom.h)
01062                 ||(childwin->stretchmode)) {
01063 
01064                 // calc new pos
01065                 currregion->x1 = childwin->geom.x;
01066                 currregion->y1 = childwin->geom.y;
01067                 currregion->x2 = childwin->geom.x + childwin->geom.w - 1;
01068                 currregion->y2 = childwin->geom.y + childwin->geom.h - 1;
01069 
01070                 if (childwin->stretchmode) {
01071                     currregion->x1 = childwin->geom.x - (MMSFBWINDOW_CALC_STRETCH_LEFT(childwin->geom.w, childwin) - childwin->geom.w);
01072                     currregion->y1 = childwin->geom.y - (MMSFBWINDOW_CALC_STRETCH_UP(childwin->geom.h, childwin) - childwin->geom.h);
01073                     currregion->x2 = currregion->x1 + MMSFBWINDOW_CALC_STRETCH_WIDTH(childwin->geom.w, childwin) - 1;
01074                     currregion->y2 = currregion->y1 + MMSFBWINDOW_CALC_STRETCH_HEIGHT(childwin->geom.h, childwin) - 1;
01075                 }
01076 
01077                 bool os;
01078                 childwin->getOwnSurface(os);
01079                 if (os) {
01080                     if   ((oldregion.x2 - oldregion.x1 + 1 != childwin->geom.w)
01081                         ||(oldregion.y2 - oldregion.y1 + 1 != childwin->geom.h)) {
01082                         // resize surface
01083                         childwin->surface->lock();
01084                         childwin->surface->resize(childwin->geom.w, childwin->geom.h);
01085                         childwin->surface->unlock();
01086 
01087                         // call resize recursive for new regions of my child windows
01088                         for (unsigned int j = 0; j < childwin->childwins.size(); j++) {
01089                             childwin->childwins.at(j).window->resize(false);
01090                         }
01091                     }
01092                 }
01093                 else {
01094                     // working with sub surface
01095                     childwin->surface->lock();
01096                     childwin->surface->setSubSurface(&(childwin->geom));
01097                     childwin->surface->unlock();
01098 
01099                     // call resize recursive for new regions of my child windows
01100                     for (unsigned int j = 0; j < childwin->childwins.size(); j++) {
01101                         childwin->childwins.at(j).window->resize(false);
01102                     }
01103                 }
01104 
01105                 // recursive calls should stop here
01106                 if (!refresh) {
01107                     unlock();
01108                     return true;
01109                 }
01110 
01111                 // draw at new pos
01112                 PRINT_LOCK("call flipWindow");
01113                 flipWindow(childwin, NULL, MMSFB_FLIP_NONE, false, false);
01114                 PRINT_LOCK("end flipWindow");
01115 
01116                 // redraw the old rects
01117                 if (oldregion.y1 < currregion->y1) {
01118                     // redraw above
01119                     MMSFBRegion region;
01120                     region = oldregion;
01121                     if (region.y2 >= currregion->y1)
01122                         region.y2 = currregion->y1 - 1;
01123 
01124                     region.x1-= currregion->x1;
01125                     region.x2-= currregion->x1;
01126                     region.y1-=currregion->y1;
01127                     region.y2-=currregion->y1;
01128                     PRINT_LOCK("call flipWindow");
01129                     flipWindow(childwin, &region, MMSFB_FLIP_NONE, false, false);
01130                     PRINT_LOCK("end flipWindow");
01131                 }
01132                 if (oldregion.y2 > currregion->y2) {
01133                     // redraw below
01134                     MMSFBRegion region;
01135                     region = oldregion;
01136                     if (region.y1 <= currregion->y2)
01137                         region.y1 = currregion->y2 + 1;
01138 
01139                     region.x1-= currregion->x1;
01140                     region.x2-= currregion->x1;
01141                     region.y1-=currregion->y1;
01142                     region.y2-=currregion->y1;
01143                     PRINT_LOCK("call flipWindow");
01144                     flipWindow(childwin, &region, MMSFB_FLIP_NONE, false, false);
01145                     PRINT_LOCK("end flipWindow");
01146                 }
01147                 if (oldregion.x1 < currregion->x1) {
01148                     // redraw left side
01149                     MMSFBRegion region;
01150                     region = oldregion;
01151                     if  ((region.y2 >= currregion->y1)
01152                        &&(region.y1 <= currregion->y2)) {
01153                         if (region.x2 >= currregion->x1)
01154                             region.x2 = currregion->x1 - 1;
01155 
01156                         region.y1 = 0;
01157                         region.y2 = currregion->y2 - currregion->y1;
01158                         region.x1-=currregion->x1;
01159                         region.x2-=currregion->x1;
01160                         PRINT_LOCK("call flipWindow");
01161                         flipWindow(childwin, &region, MMSFB_FLIP_NONE, false, false);
01162                         PRINT_LOCK("end flipWindow");
01163                     }
01164                 }
01165                 if (oldregion.x2 > currregion->x2) {
01166                     // redraw right side
01167                     MMSFBRegion region;
01168                     region = oldregion;
01169                     if  ((region.y2 >= currregion->y1)
01170                        &&(region.y1 <= currregion->y2)) {
01171                         if (region.x1 <= currregion->x2)
01172                             region.x1 = currregion->x2 + 1;
01173 
01174                         region.y1 = 0;
01175                         region.y2 = currregion->y2 - currregion->y1;
01176                         region.x1-=currregion->x1;
01177                         region.x2-=currregion->x1;
01178                         PRINT_LOCK("call flipWindow");
01179                         flipWindow(childwin, &region, MMSFB_FLIP_NONE, false, false);
01180                         PRINT_LOCK("end flipWindow");
01181                     }
01182                 }
01183             }
01184 
01185             unlock();
01186             return true;
01187         }
01188     }
01189 
01190     unlock();
01191     return false;
01192 }
01193 
01194 bool MMSWindow::moveChildWindow(MMSWindow *childwin, int x, int y, bool refresh) {
01195 
01196     if (childwin->getType()!=MMSWINDOWTYPE_CHILDWINDOW)
01197         return false;
01198 
01199     childwin->geom.x = x;
01200     childwin->geom.y = y;
01201 
01202     return setChildWindowRegion(childwin, refresh);
01203 }
01204 
01205 void MMSWindow::drawChildWindows(MMSFBSurface *dst_surface, MMSFBRegion *region, int offsX, int offsY) {
01206     MMSFBRegion       pw_region;
01207 
01208     if (region == NULL) {
01209         // complete surface
01210         pw_region.x1 = 0;
01211         pw_region.y1 = 0;
01212         pw_region.x2 = this->geom.w - 1;
01213         pw_region.y2 = this->geom.h - 1;
01214     }
01215     else {
01216         // only a region
01217         pw_region = *region;
01218     }
01219 
01220 //printf("   *MMSWindow::drawChildWindows() - %s, %d,%d,%d,%d\n", name.c_str(),pw_region.x1,pw_region.y1,pw_region.x2,pw_region.y2);
01221 
01222     // draw all affected child windows
01223     for (unsigned int i = 0; i < this->childwins.size(); i++) {
01224         CHILDWINS *cw = &(this->childwins.at(i));
01225         MMSFBRegion *myregion = &(cw->region);
01226 
01227         // window pointer set?
01228         if (!cw->window)
01229             continue;
01230 
01231         // if the window has no opacity then continue
01232         if (!cw->opacity)
01233             continue;
01234 
01235         if (!((myregion->x2 < pw_region.x1)||(myregion->y2 < pw_region.y1)
01236             ||(myregion->x1 > pw_region.x2)||(myregion->y1 > pw_region.y2))) {
01237 
01238             // the window is affected
01239             // calc source and destination
01240             MMSFBRectangle src_rect;
01241             int dst_x = pw_region.x1;
01242             int dst_y = pw_region.y1;
01243 
01244             src_rect.x = pw_region.x1 - myregion->x1;
01245             if (src_rect.x < 0) {
01246                 dst_x-= src_rect.x;
01247                 src_rect.x = 0;
01248             }
01249 
01250             src_rect.y = pw_region.y1 - myregion->y1;
01251             if (src_rect.y < 0) {
01252                 dst_y-= src_rect.y;
01253                 src_rect.y = 0;
01254             }
01255 
01256             src_rect.w = myregion->x2 - myregion->x1 + 1 - src_rect.x;
01257             if (myregion->x2 > pw_region.x2)
01258                 src_rect.w-= myregion->x2 - pw_region.x2;
01259 
01260             src_rect.h = myregion->y2 - myregion->y1 + 1 - src_rect.y;
01261             if (myregion->y2 > pw_region.y2)
01262                 src_rect.h-= myregion->y2 - pw_region.y2;
01263 
01264             if (cw->window->stretchmode) {
01265                 src_rect.x = MMSFBWINDOW_CALC_STRETCH_WIDTH_REV(src_rect.x, cw->window);
01266                 src_rect.y = MMSFBWINDOW_CALC_STRETCH_HEIGHT_REV(src_rect.y, cw->window);
01267                 src_rect.w = MMSFBWINDOW_CALC_STRETCH_WIDTH_REV(src_rect.w , cw->window);
01268                 src_rect.h = MMSFBWINDOW_CALC_STRETCH_HEIGHT_REV(src_rect.h, cw->window);
01269             }
01270 
01271             // own surface?
01272             bool os = true;
01273             cw->window->getOwnSurface(os);
01274 
01275             if (os) {
01276                 // own surface
01277                 // for this we support the opacity attribute and the stretch feature
01278 
01279                 // check if we have to do the "special blit"
01280                 // "special blit" means that we have to call draw() for the window and it's childwindows
01281                 // origin is the need_redraw flag which is set for example by targetLangChanged()
01282                 bool special_blit = cw->window->need_redraw;
01283 
01284                 if (!special_blit) {
01285                     if (cw->opacity < 255) {
01286                         // opacity calculation requested
01287                         // check if at least one child window with opacity > 0 does exists
01288                         for (unsigned int c = 0; c < cw->window->childwins.size(); c++) {
01289                             if (cw->window->childwins.at(c).opacity) {
01290                                 // childwindow is shown
01291                                 special_blit = true;
01292                                 break;
01293                             }
01294                         }
01295                     }
01296                     else
01297                     if (cw->window->stretchmode) {
01298                         // should be stretched
01299                         // check if at least one child window with opacity > 0 does exists
01300                         for (unsigned int c = 0; c < cw->window->childwins.size(); c++) {
01301                             if (cw->window->childwins.at(c).opacity) {
01302                                 // childwindow is shown
01303                                 special_blit = true;
01304                                 break;
01305                             }
01306                         }
01307                     }
01308                 }
01309 
01310                 if (!special_blit) {
01311                     // now we have to find childwindows with own_surface="false"
01312                     for (unsigned int c = 0; c < cw->window->childwins.size(); c++) {
01313                         if (cw->window->childwins.at(c).opacity) {
01314                             // childwindow is shown
01315                             bool os = true;
01316                             cw->window->childwins.at(c).window->getOwnSurface(os);
01317                             if (!os) {
01318                                 // childwindow has no own surface
01319                                 special_blit = true;
01320                                 break;
01321                             }
01322                         }
01323                     }
01324                 }
01325 
01326                 if ((!special_blit) && (cw->special_blit)) {
01327                     // currently special blit is not requested
01328                     // but the blit beforehand has "destroy" the window surface
01329                     // so we have to redraw the window
01330                     // note: drawing proceeds on the surface of parent window
01331                     // note: draw() has to clear the window surface!
01332                     cw->window->draw(false, &src_rect, true);
01333                 }
01334                 cw->special_blit = special_blit;
01335 
01336                 dst_surface->lock();
01337                 cw->window->surface->lock();
01338 
01339                 if (special_blit) {
01340                     // special mode
01341                     // we MUST draw (the background) to the surface of this window
01342                     // then we MUST draw the window stack if the child windows to the surface of this window
01343                     // afterwards we MUST blit/stretch the result to the dst_surface
01344 
01345                     // direct draw
01346                     // note: drawing proceeds on the surface of parent window
01347                     // note: draw() has to clear the window surface!
01348                     cw->window->draw(false, &src_rect, true);
01349 
01350                     // draw the children of this child, let child windows draw to my surface
01351                     MMSFBRegion reg;
01352                     reg.x1 = src_rect.x;
01353                     reg.y1 = src_rect.y;
01354                     reg.x2 = src_rect.x + src_rect.w - 1;
01355                     reg.y2 = src_rect.y + src_rect.h - 1;
01356                     if(cw->window) {
01357                         cw->window->drawChildWindows(cw->window->surface, &reg,
01358                                                      reg.x1, reg.y1);
01359                     }
01360 
01361                     if (cw->opacity < 255) {
01362                         // set the blitting flags and color
01363                         dst_surface->setBlittingFlags((MMSFBBlittingFlags) (MMSFB_BLIT_BLEND_ALPHACHANNEL|MMSFB_BLIT_BLEND_COLORALPHA));
01364                         dst_surface->setColor(0, 0, 0, cw->opacity);
01365                     }
01366                     else {
01367                         // set the blitting flags
01368                         dst_surface->setBlittingFlags((MMSFBBlittingFlags) MMSFB_BLIT_BLEND_ALPHACHANNEL);
01369                     }
01370 
01371                     // blit window front buffer to destination surface
01372                     if (!cw->window->stretchmode) {
01373                         // normal blit if stretch mode is off
01374 //DO WE NEED THE OFFSET???
01375 //                      dst_surface->blit(cw->window->surface, &src_rect, dst_x + offsX, dst_y + offsY);
01376 
01377                         dst_surface->blit(cw->window->surface, &src_rect, dst_x, dst_y);
01378                     }
01379                     else {
01380                         // stretch the window to the parent surface
01381 //DO WE NEED THE OFFSET???
01382 /*                      MMSFBRectangle dr = MMSFBRectangle(
01383                                                 dst_x + offsX,
01384                                                 dst_y + offsY,
01385                                                 MMSFBWINDOW_CALC_STRETCH_WIDTH(src_rect.w, cw->window),
01386                                                 MMSFBWINDOW_CALC_STRETCH_HEIGHT(src_rect.h, cw->window));*/
01387                         MMSFBRectangle dr = MMSFBRectangle(
01388                                                 dst_x,
01389                                                 dst_y,
01390                                                 MMSFBWINDOW_CALC_STRETCH_WIDTH(src_rect.w, cw->window),
01391                                                 MMSFBWINDOW_CALC_STRETCH_HEIGHT(src_rect.h, cw->window));
01392                         dst_surface->stretchBlit(cw->window->surface, &src_rect, &dr);
01393                     }
01394                 }
01395                 else {
01396                     // we can blit the surface of this window directly to the dst_surface
01397                     if (cw->opacity < 255) {
01398                         // set the blitting flags and color
01399                         dst_surface->setBlittingFlags((MMSFBBlittingFlags) (MMSFB_BLIT_BLEND_ALPHACHANNEL|MMSFB_BLIT_BLEND_COLORALPHA));
01400                         dst_surface->setColor(0, 0, 0, cw->opacity);
01401                     }
01402                     else {
01403                         // set the blitting flags
01404                         dst_surface->setBlittingFlags((MMSFBBlittingFlags) MMSFB_BLIT_BLEND_ALPHACHANNEL);
01405                     }
01406 
01407                     // blit window front buffer to destination surface
01408                     if (!cw->window->stretchmode) {
01409                         // normal blit if stretch mode is off
01410                         dst_surface->blit(cw->window->surface, &src_rect, dst_x + offsX, dst_y + offsY);
01411                     }
01412                     else {
01413                         // stretch the window to the parent surface
01414                         MMSFBRectangle dr = MMSFBRectangle(
01415                                                 dst_x + offsX,
01416                                                 dst_y + offsY,
01417                                                 MMSFBWINDOW_CALC_STRETCH_WIDTH(src_rect.w, cw->window),
01418                                                 MMSFBWINDOW_CALC_STRETCH_HEIGHT(src_rect.h, cw->window));
01419                         dst_surface->stretchBlit(cw->window->surface, &src_rect, &dr);
01420                     }
01421 
01422                     // draw the children of this child, let child windows draw to the surface of my parent
01423                     MMSFBRegion reg;
01424                     reg.x1 = src_rect.x;
01425                     reg.y1 = src_rect.y;
01426                     reg.x2 = src_rect.x + src_rect.w - 1;
01427                     reg.y2 = src_rect.y + src_rect.h - 1;
01428                     if(cw->window) {
01429                         cw->window->drawChildWindows(dst_surface, &reg,
01430                                                      dst_x + offsX - reg.x1, dst_y + offsY - reg.y1);
01431                     }
01432                 }
01433 
01434                 cw->window->surface->unlock();
01435                 dst_surface->unlock();
01436             }
01437             else {
01438                 // no own surface
01439                 // for this we DO NOT support the stretch feature!!!
01440                 if (cw->window->stretchmode) {
01441                     printf("DISKO: Cannot stretch the window '%s' which has no own surface!\n",
01442                             cw->window->name.c_str());
01443                 }
01444 
01445                 // direct draw
01446                 // note: drawing proceeds on the surface of parent window
01447                 cw->window->draw(false, &src_rect, false, cw->opacity);
01448 
01449                 // draw the children of this child, let child windows draw to the surface of my parent
01450                 MMSFBRegion reg;
01451                 reg.x1 = src_rect.x;
01452                 reg.y1 = src_rect.y;
01453                 reg.x2 = src_rect.x + src_rect.w - 1;
01454                 reg.y2 = src_rect.y + src_rect.h - 1;
01455                 if(cw->window) {
01456                     cw->window->drawChildWindows(dst_surface, &reg,
01457                                                  dst_x + offsX - reg.x1, dst_y + offsY - reg.y1);
01458                 }
01459             }
01460         }
01461     }
01462 }
01463 
01464 
01465 
01466 bool MMSWindow::flipWindow(MMSWindow *win, MMSFBRegion *region, MMSFBFlipFlags flags,
01467                            bool flipChildSurface, bool locked) {
01468     MMSFBSurface    *pw_surface;
01469     MMSFBRegion       pw_region;
01470 
01471     // stop parallel processing
01472     if (!locked)
01473 //PUP        flipLock.lock();
01474         lock();
01475 
01476     if (!win) win = this;
01477     if (win->getType()!=MMSWINDOWTYPE_CHILDWINDOW) {
01478         // normal parent window
01479         pw_surface = win->surface;
01480         if (region == NULL) {
01481             // complete surface
01482             pw_region.x1 = 0;
01483             pw_region.y1 = 0;
01484             pw_region.x2 = win->geom.w - 1;
01485             pw_region.y2 = win->geom.h - 1;
01486         }
01487         else {
01488             // only a region
01489             pw_region = *region;
01490         }
01491     }
01492     else {
01493         // child window
01494         int z = -1;
01495         for (unsigned int i = 0; i < this->childwins.size(); i++) {
01496             if (this->childwins.at(i).window == win) {
01497                 // child window found, flip it
01498                 if (flipChildSurface) {
01499                     bool os;
01500                     win->getOwnSurface(os);
01501                     if (os) {
01502                         // the child window has an own surface which we have to flip
01503                         // if the child window has NO own surface, the window will be redrawed by the parent automatically
01504                         win->surface->lock();
01505                         PRINT_LOCK("call flip");
01506                         win->surface->flip(region);
01507                         PRINT_LOCK("end flip");
01508                         win->surface->unlock();
01509                     }
01510                 }
01511 
01512                 // return if parent window is not shown
01513                 if ((win->parent->isShown()==false)&&(win->parent->willshow==false)) {
01514                     // unlock
01515                     if (!locked)
01516 //PUP                        flipLock.unlock();
01517                         unlock();
01518                     return true;
01519                 }
01520 
01521                 // return if opacity is zero
01522                 if ((this->childwins.at(i).opacity==0)&&(this->childwins.at(i).oldopacity==0)) {
01523                     // unlock
01524                     if (!locked)
01525 //PUP                        flipLock.unlock();
01526                         unlock();
01527                     return true;
01528                 }
01529 
01530                 // return if the child window is out of the visible parent region
01531                 if   ((win->geom.x >= win->parent->geom.w) || (win->geom.y >= win->parent->geom.h)
01532                     ||(win->geom.x + win->geom.w <= 0) || (win->geom.y + win->geom.h <= 0)) {
01533                     // unlock
01534                     if (!locked)
01535 //PUP                        flipLock.unlock();
01536                         unlock();
01537                     return true;
01538                 }
01539 
01540                 this->childwins.at(i).oldopacity = this->childwins.at(i).opacity;
01541 
01542                 // get parents surface and break loop
01543                 pw_surface = win->parent->surface;
01544                 z = i;
01545                 break;
01546             }
01547         }
01548 
01549         // window found?
01550         if (z < 0) {
01551             // not found
01552             if (!locked)
01553 //PUP                flipLock.unlock();
01554                 unlock();
01555 
01556             return false;
01557         }
01558 
01559         // calculate the affected region on the parent surface
01560         MMSFBRegion *myregion = &(this->childwins.at(z).region);
01561         if (region == NULL) {
01562             // complete surface
01563             pw_region = *myregion;
01564         }
01565         else {
01566             // only a region
01567             pw_region.x1 = myregion->x1 + region->x1;
01568             pw_region.y1 = myregion->y1 + region->y1;
01569             pw_region.x2 = myregion->x1 + region->x2;
01570             pw_region.y2 = myregion->y1 + region->y2;
01571         }
01572 
01573         // redraw the region within parent window
01574         MMSFBRectangle rect;
01575         rect.x = pw_region.x1;
01576         rect.y = pw_region.y1;
01577         rect.w = pw_region.x2 - pw_region.x1 + 1;
01578         rect.h = pw_region.y2 - pw_region.y1 + 1;
01579 
01580 
01581         if (this->parent == NULL) {
01582             // i am the top level parent
01583             this->draw(true, &rect);
01584         } else {
01585             // i am also a child, call recursive to the top level parent
01586             PRINT_LOCK("call flipWindow");
01587             bool ret = this->parent->flipWindow(win->parent, &pw_region, flags, false, false);
01588             PRINT_LOCK("end flipWindow");
01589 
01590             // unlock
01591             if (!locked)
01592 //PUP                flipLock.unlock();
01593                 unlock();
01594 
01595             // stop here, because the drawing of child windows is initiated by the top level parent window
01596             return ret;
01597         }
01598 
01599     }
01600 
01601     // here we are a top level parent window
01602     // child windows are not allowed here!!!
01603 
01604     // lock
01605 //PUP    pw_surface->lock();
01606 //    lock();
01607 
01608 
01609     // draw all affected child windows
01610     drawChildWindows(pw_surface, &pw_region);
01611 
01612     // do the flip
01613     pw_surface->lock();
01614     pw_surface->flip(&pw_region);
01615     pw_surface->unlock();
01616 
01617     // unlock
01618 //PUP    pw_surface->unlock();
01619 //    unlock();
01620 
01621     // unlock
01622     if (!locked)
01623 //PUP        flipLock.unlock();
01624         unlock();
01625 
01626     return false;
01627 }
01628 
01629 
01630 void MMSWindow::removeFocusFromChildWindow() {
01631     /* check something */
01632     if (!this->parent) return;
01633     if ((this->parent->focusedChildWin < 0) || (this->parent->focusedChildWin >= this->parent->childwins.size())) return;
01634     if (this->parent->childwins.at(this->parent->focusedChildWin).window != this) return;
01635 
01636     // searching for other childwin to get the focus
01637     // first we are searching for focusable widgets
01638     // if nothing found, we use a shown window and set the input focus to it
01639     for (int retry = 0; retry <= 1; retry++) {
01640         for (int i = (int)this->parent->childwins.size()-1; i >= 0; i--) {
01641             if (i == (int)this->parent->focusedChildWin) continue;
01642             MMSWindow *w = this->parent->childwins.at(i).window;
01643             if (!w->isShown()) continue;
01644 
01645             if (!retry) {
01646                 // first time: check if there are focusable widgets
01647                 if (!w->getNumberOfFocusableWidgets())
01648                     if (!w->getNumberOfFocusableChildWins())
01649                         continue;
01650             }
01651 
01652             // okay, i have the focus, remove it
01653             this->parent->removeChildWinFocus();
01654 
01655             // set the new focused childwin
01656             this->parent->focusedChildWin = i;
01657             this->parent->restoreChildWinFocus();
01658             return;
01659         }
01660     }
01661 
01662 //TODO: it must be possible, that there is no focused childwin (-1)
01663 }
01664 
01665 
01666 void MMSWindow::loadArrowWidgets() {
01667     /* searching root parent */
01668     MMSWindow *tmp = this;
01669     while (tmp->parent) tmp = tmp->parent;
01670 
01671     bool    b;
01672     string  s;
01673 
01674     /* connect arrow widgets */
01675     if (!this->upArrowWidget)
01676         if (getUpArrow(s))
01677             if (s != "")
01678                 if ((this->upArrowWidget = tmp->findWidget(s))) {
01679                     if (!this->upArrowWidget->getSelectable(b))
01680                         this->upArrowWidget = NULL;
01681                     else
01682                         if (!b)
01683                             this->upArrowWidget = NULL;
01684                 }
01685 
01686     if (!this->downArrowWidget)
01687         if (getDownArrow(s))
01688             if (s != "")
01689                 if ((this->downArrowWidget = tmp->findWidget(s))) {
01690                     if (!this->downArrowWidget->getSelectable(b))
01691                         this->downArrowWidget = NULL;
01692                     else
01693                         if (!b)
01694                             this->downArrowWidget = NULL;
01695                 }
01696 
01697     if (!this->leftArrowWidget)
01698         if (getLeftArrow(s))
01699             if (s != "")
01700                 if ((this->leftArrowWidget = tmp->findWidget(s))) {
01701                     if (!this->leftArrowWidget->getSelectable(b))
01702                         this->leftArrowWidget = NULL;
01703                     else
01704                         if (!b)
01705                             this->leftArrowWidget = NULL;
01706                 }
01707 
01708     if (!this->rightArrowWidget)
01709         if (getRightArrow(s))
01710             if (s != "")
01711                 if ((this->rightArrowWidget = tmp->findWidget(s))) {
01712                     if (!this->rightArrowWidget->getSelectable(b))
01713                         this->rightArrowWidget = NULL;
01714                     else
01715                         if (!b)
01716                             this->rightArrowWidget = NULL;
01717                 }
01718 }
01719 
01720 
01721 void MMSWindow::getArrowWidgetStatus(ARROW_WIDGET_STATUS *setarrows) {
01722 
01723     if (this->focusedwidget) {
01724         /* for my widgets */
01725         setarrows->up=(this->focusedwidget->canNavigateUp());
01726         setarrows->down=(this->focusedwidget->canNavigateDown());
01727         setarrows->left=(this->focusedwidget->canNavigateLeft());
01728         setarrows->right=(this->focusedwidget->canNavigateRight());
01729 
01730         /* check my window navigation */
01731         if (!setarrows->up)
01732             setarrows->up=(getNavigateUpWindow());
01733         if (!setarrows->down)
01734             setarrows->down=(getNavigateDownWindow());
01735         if (!setarrows->left)
01736             setarrows->left=(getNavigateLeftWindow());
01737         if (!setarrows->right)
01738             setarrows->right=(getNavigateRightWindow());
01739     }
01740     else {
01741         /* for my focused child window */
01742         if (!childwins.empty()) {
01743             try {
01744                 MMSWindow *fWin = childwins.at(this->focusedChildWin).window;
01745 
01746                 /* get all the states (my own and all children) */
01747                 fWin->getArrowWidgetStatus(setarrows);
01748             } catch (std::exception&) {
01749                 return;
01750             }
01751 
01752             /* check my window navigation */
01753             if (!setarrows->up)
01754                 setarrows->up=(getNavigateUpWindow());
01755             if (!setarrows->down)
01756                 setarrows->down=(getNavigateDownWindow());
01757             if (!setarrows->left)
01758                 setarrows->left=(getNavigateLeftWindow());
01759             if (!setarrows->right)
01760                 setarrows->right=(getNavigateRightWindow());
01761 
01762         }
01763     }
01764 }
01765 
01766 void MMSWindow::switchArrowWidgets() {
01767     preCalcNaviLock.lock();
01768 
01769     /* connect arrow widgets */
01770     loadArrowWidgets();
01771 
01772     /* get the new state of the arrows */
01773     ARROW_WIDGET_STATUS setarrows;
01774     memset(&setarrows, 0, sizeof(ARROW_WIDGET_STATUS));
01775 
01776     /* get all the states (my own and all children) */
01777     getArrowWidgetStatus(&setarrows);
01778 
01779     /* switch arrow widgets */
01780     if (this->upArrowWidget) {
01781         if (setarrows.up)
01782             this->upArrowWidget->setSelected(true);
01783         else
01784             this->upArrowWidget->setSelected(false);
01785     }
01786 
01787     if (this->downArrowWidget) {
01788         if (setarrows.down)
01789             this->downArrowWidget->setSelected(true);
01790         else
01791             this->downArrowWidget->setSelected(false);
01792     }
01793 
01794     if (this->leftArrowWidget) {
01795         if (setarrows.left)
01796             this->leftArrowWidget->setSelected(true);
01797         else
01798             this->leftArrowWidget->setSelected(false);
01799     }
01800 
01801     if (this->rightArrowWidget) {
01802         if (setarrows.right)
01803             this->rightArrowWidget->setSelected(true);
01804         else
01805             this->rightArrowWidget->setSelected(false);
01806     }
01807 
01808     /* recursive to my parents */
01809     if (this->parent)
01810         this->parent->switchArrowWidgets();
01811 
01812     preCalcNaviLock.unlock();
01813 }
01814 
01815 
01816 bool MMSWindow::flip(void) {
01817     if (getType()==MMSWINDOWTYPE_CHILDWINDOW) {
01818         PRINT_LOCK("call flipWindow");
01819         this->parent->flipWindow(this);
01820         PRINT_LOCK("end flipWindow");
01821     }
01822     else {
01823         this->surface->lock();
01824         PRINT_LOCK("call flip");
01825         this->surface->flip();
01826         PRINT_LOCK("end flip");
01827         this->surface->unlock();
01828     }
01829     return true;
01830 }
01831 
01832 MMSFBLayer *MMSWindow::getLayer() {
01833     return this->layer;
01834 }
01835 
01836 MMSFBSurface *MMSWindow::getSurface() {
01837     return this->surface;
01838 }
01839 
01840 MMSWindow *MMSWindow::getParent(bool toplevel) {
01841     if (!toplevel)
01842         return this->parent;
01843     if (!this->parent)
01844         return NULL;
01845     MMSWindow *pw = this->parent->getParent(toplevel);
01846     if (pw)
01847         return pw;
01848     return this->parent;
01849 }
01850 
01851 
01852 void MMSWindow::recalculateChildren() {
01853     if(!this->children.empty()) {
01854         this->children.at(0)->setGeometry(this->innerGeom);
01855     }
01856 
01857     /* pre-calculate the navigation */
01858     preCalcNavigation();
01859 }
01860 
01861 
01862 
01863 bool MMSWindow::initnav() {
01864 
01865     // get my four windows to which I have to navigate
01866     if (this->parent) {
01867         string s;
01868         if (getNavigateUp(s))
01869             this->navigateUpWindow = this->parent->findWindow(s);
01870         if (getNavigateDown(s))
01871             this->navigateDownWindow = this->parent->findWindow(s);
01872         if (getNavigateRight(s))
01873             this->navigateRightWindow = this->parent->findWindow(s);
01874         if (getNavigateLeft(s))
01875             this->navigateLeftWindow = this->parent->findWindow(s);
01876     }
01877 
01878     // pre-calculate the navigation
01879     preCalcNavigation();
01880 
01881     return true;
01882 }
01883 
01884 bool MMSWindow::init() {
01885 
01886     if (this->initialized) {
01887         // already initialized
01888         return true;
01889     }
01890 
01891     // load images
01892     string path, name;
01893 
01894     if (!this->bgimage_from_external) {
01895         if (!getBgImagePath(path)) path = "";
01896         if (!getBgImageName(name)) name = "";
01897         this->bgimage = this->im->getImage(path, name);
01898     }
01899 
01900     if (!getBorderImagePath(path)) path = "";
01901     for (int i=0;i<MMSBORDER_IMAGE_NUM_SIZE;i++) {
01902         if (!getBorderImageNames((MMSBORDER_IMAGE_NUM)i, name)) name = "";
01903         this->borderimages[i] = this->im->getImage(path, name);
01904     }
01905 
01906     this->initialized = true;
01907     return true;
01908 }
01909 
01910 bool MMSWindow::release() {
01911 
01912     if (!this->initialized) {
01913         // not initialized
01914         return true;
01915     }
01916 
01917     // release all images
01918     if (!this->bgimage_from_external) {
01919         this->im->releaseImage(this->bgimage);
01920         this->bgimage = NULL;
01921     }
01922 
01923     for (int i=0;i<MMSBORDER_IMAGE_NUM_SIZE;i++) {
01924         this->im->releaseImage(this->borderimages[i]);
01925         this->borderimages[i] = NULL;
01926     }
01927 
01928     this->initialized = false;
01929     return true;
01930 }
01931 
01932 
01933 void MMSWindow::draw(bool toRedrawOnly, MMSFBRectangle *rect2update, bool clear, unsigned char opacity) {
01934 
01935     // reset "need redraw" flag
01936     this->need_redraw = false;
01937 
01938     // init window (e.g. load images, fonts, ...)
01939     init();
01940 
01941     // lock
01942     lock();
01943     this->surface->lock();
01944 
01945     if (rect2update) {
01946         /* use a small rectangle */
01947         MMSFBRegion clip;
01948         clip.x1 = rect2update->x;
01949         clip.y1 = rect2update->y;
01950         clip.x2 = rect2update->x + rect2update->w - 1;
01951         clip.y2 = rect2update->y + rect2update->h - 1;
01952         this->surface->setClip(&clip);
01953     }
01954 
01955     if (!this->onDraw->emit(this->surface, clear)) {
01956         // nothing drawn by callback(s), so we have to do it
01957 
01958         // draw background
01959         MMSFBColor bgcolor;
01960         getBgColor(bgcolor);
01961         if (this->bgimage) {
01962             this->bgimage->lock();
01963             // clear all or a part of the surface
01964             if (clear) {
01965                 if ((bgcolor.a && bgcolor.a != 255) || opacity != 255 || !this->bgimage->isOpaque()) {
01966                     this->surface->clear();
01967                 }
01968             }
01969 
01970             // prepare for blitting
01971             this->surface->setBlittingFlagsByBrightnessAlphaAndOpacityAndSource(
01972                                     255, (bgcolor.a)?bgcolor.a:255, opacity, this->bgimage);
01973 
01974             // draw background with bgimage
01975             this->surface->stretchBlit(this->bgimage, NULL, &(this->innerGeom));
01976             this->bgimage->unlock();
01977         }
01978         else
01979         if (bgcolor.a) {
01980             // clear all or a part of the surface
01981             if (clear) {
01982                 if (bgcolor.a != 255 || opacity != 255) {
01983                     this->surface->clear();
01984                 }
01985             }
01986 
01987             // prepare for drawing
01988             this->surface->setDrawingColorAndFlagsByBrightnessAndOpacity(bgcolor, 255, opacity);
01989 
01990             // draw window background
01991             this->surface->fillRectangle(this->innerGeom.x, this->innerGeom.y, this->innerGeom.w, this->innerGeom.h);
01992         }
01993         else {
01994             // clear all or a part of the surface
01995             if (clear) {
01996                 this->surface->clear();
01997             }
01998         }
01999 
02000         // draw children
02001         bool backgroundFilled = true;
02002         if(!this->children.empty()) {
02003             if (opacity != 255) {
02004                 printf("DISKO: Window %s drawn with opacity %d, but widgets will be drawn with full opacity!\n",
02005                         name.c_str(), opacity);
02006             }
02007 
02008             if (this->draw_setgeom) {
02009 //printf(">>>>>>>>>>>>>>>AAAAAAAAAAAAAA>>>>>>>>>>>>>>>\n");
02010 
02011                 if (!this->children.at(0)->content_size_initialized) {
02012                     // first time, init content size an geometry
02013                     this->children.at(0)->setGeometry(this->innerGeom);
02014                     this->children.at(0)->initContentSize();
02015                 }
02016 
02017                 this->children.at(0)->setGeometry(this->innerGeom);
02018 
02019 //printf("<<<<<<<<<<<<<<<AAAAAAAAAAAAAA>>>>>>>>>>>>>>>\n");
02020                 this->draw_setgeom = false;
02021             }
02022             this->children.at(0)->drawchildren(toRedrawOnly, &backgroundFilled, rect2update);
02023         }
02024     }
02025 
02026     // reset the clip
02027     this->surface->setClip(NULL);
02028 
02029     this->surface->unlock();
02030     // unlock
02031 //PUP    this->surface->unlock();
02032     unlock();
02033 
02034     // draw border
02035     if (!toRedrawOnly)
02036         drawMyBorder(opacity);
02037 }
02038 
02039 void MMSWindow::drawMyBorder(unsigned char opacity) {
02040     unsigned int borderThickness;
02041     if (!getBorderThickness(borderThickness))
02042         borderThickness = 0;
02043     bool borderRCorners;
02044     if (!getBorderRCorners(borderRCorners))
02045         borderRCorners = false;
02046     MMSFBColor c;
02047 
02048     getBorderColor(c);
02049     drawBorder(borderThickness, borderRCorners, this->borderimages,
02050                this->bordergeom, &(this->bordergeomset), this->surface,
02051                0, 0, this->geom.w, this->geom.h, c, this->im, 255, opacity);
02052 }
02053 
02054 
02055 bool MMSWindow::show() {
02056 
02057     PRINT_LOCK("mmsfb unlock");
02058     bool rc = mmsfb->unlock();
02059     // the window will be hidden in a few seconds (hideAction thread is running), wait for it
02060     while (this->willhide)
02061         msleep(100);
02062 
02063     while(1) {
02064         // check if the window is shown
02065         if(this->shown) {
02066             // call onAfterShow callback with already shown flag
02067             this->onAfterShow->emit(this, true);
02068             return true;
02069         }
02070 
02071         // check if the window will already be shown
02072         if (this->willshow) {
02073             msleep(100);
02074             continue;
02075         }
02076         break;
02077     }
02078 
02079     if(rc)
02080         mmsfb->lock();
02081 
02082     // start the show process
02083     this->willshow = true;
02084 
02085     // call onBeforeShow callback
02086     if (!this->onBeforeShow->emit(this)) {
02087         // a callback returns false, break the show process
02088         this->willshow = false;
02089         return false;
02090     }
02091 
02092 
02093     switch (getType()) {
02094     case MMSWINDOWTYPE_MAINWINDOW:
02095         // hide all main and popup windows
02096         // root windows will be hidden during the show animation, see beforeShowAction()
02097         if (this->windowmanager) {
02098             this->windowmanager->hideAllPopupWindows(true);
02099             this->windowmanager->hideAllMainWindows();
02100         }
02101         break;
02102     case MMSWINDOWTYPE_CHILDWINDOW:
02103         if (this->parent) {
02104             if (!this->parent->isShown(true)) {
02105                 // not really visible, break the show process
02106                 this->buffered_shown = true;
02107                 this->setFirstFocus();
02108                 this->shown = true;
02109                 this->willshow = false;
02110                 this->onAfterShow->emit(this, false);
02111                 return true;
02112             }
02113         }
02114         break;
02115     default:
02116         break;
02117     }
02118 
02119 
02120 
02121 /*    if (this->action->isRunning())
02122         this->action->cancelBroadcast.emit(this->getType());
02123     this->action->setAction(MMSWACTION_SHOW);
02124     this->action->start();*/
02125 
02126     //////////
02127 
02128     // do the animation in a separate thread...
02129     this->pulser.setStepsPerSecond(MMSWINDOW_ANIM_MAX_OFFSET * 4);
02130     this->pulser.setMaxOffset(MMSWINDOW_ANIM_MAX_OFFSET, MMSPULSER_SEQ_LOG_SOFT_END, MMSWINDOW_ANIM_MAX_OFFSET / 2);
02131     this->pulser_mode = MMSWINDOW_PULSER_MODE_SHOW;
02132     this->pulser.start(false, true);
02133 
02134 
02135     ////////////
02136 
02137 
02138     return true;
02139 }
02140 
02141 
02142 /////////////////////
02143 void MMSWindow::showBufferedShown() {
02144     unsigned int cws = childwins.size();
02145     if (!cws) {
02146         /* pre-calculate the navigation */
02147 /*        if (this->parent) {
02148             this->parent->preCalcNavigation();
02149             this->switchArrowWidgets();
02150         }*/
02151     }
02152 
02153 //printf("show4-0 - %s\n", name.c_str());
02154 
02155     lock();
02156 
02157     for (unsigned int i = 0; i < childwins.size(); i++) {
02158         MMSWindow *w = childwins.at(i).window;
02159 
02160         if (w->shown) {
02161             if (!w->buffered_shown) {
02162                 // it is not the first time, so one draw is enough
02163                 // do it only for child windows with own surfaces
02164                 bool os;
02165                 w->getOwnSurface(os);
02166                 if (os) {
02167                     w->draw();
02168                     PRINT_LOCK("call flipWindow");
02169                     w->parent->flipWindow(w);
02170                     PRINT_LOCK("end flipWindow");
02171                 }
02172             }
02173             else {
02174                 // buffered shown, first time called
02175                 w->draw();
02176                 w->draw();
02177 
02178                 if (!w->precalcnav) {
02179                     // init window (e.g. pre-calc navigation ...)
02180                     w->initnav();
02181                     w->precalcnav = true;
02182                 }
02183 
02184                 if (!w->initialArrowsDrawn) {
02185                     // set the arrow widgets
02186                     w->initialArrowsDrawn = true;
02187                     w->switchArrowWidgets();
02188                 }
02189 
02190                 // flip only child windows with own surfaces
02191                 bool os;
02192                 w->getOwnSurface(os);
02193                 if (os) {
02194                     PRINT_LOCK("call flipWindow");
02195                     w->parent->flipWindow(w);
02196                     PRINT_LOCK("end flipWindow");
02197                 }
02198 
02199                 if ((w->parent)||((!w->parent)&&(w->window))) {
02200                     unsigned int opacity;
02201                     if (!w->getOpacity(opacity)) opacity = 255;
02202 
02203                     // set final opacity
02204                     w->parent->setChildWindowOpacity(w, opacity);
02205                 }
02206 
02207                 // first time finished
02208                 w->buffered_shown = false;
02209 
02210                 // go recursive to the child windows
02211                 w->showBufferedShown();
02212             }
02213         }
02214     }
02215 
02216     unlock();
02217 }
02218 
02219 
02220 
02221 bool MMSWindow::raiseToTop(int zlevel) {
02222 
02223     lock();
02224 
02225     if (!this->parent) {
02226         // normal parent window, set the window to top
02227         if (this->window) {
02228             bool ret = this->window->raiseToTop(zlevel);
02229             unlock();
02230             return ret;
02231         }
02232         unlock();
02233         return false;
02234     }
02235 
02236     // child window, change the childwins vector
02237     for (unsigned int i = 0; i < this->parent->childwins.size(); i++) {
02238         if (this->parent->childwins.at(i).window == this) {
02239             // child window found, move it to the end of the vector
02240             if (i + 1 < this->parent->childwins.size()) {
02241                 // not at the end, moving it
02242                 CHILDWINS cw = this->parent->childwins.at(i);
02243                 this->parent->childwins.erase(this->parent->childwins.begin()+i);
02244                 bool aot = false;
02245                 this->getAlwaysOnTop(aot);
02246                 if (!aot) {
02247                     // normal stack position, move window before windows with "always on top" flag
02248                     this->parent->childwins.insert(this->parent->childwins.begin() + this->parent->always_on_top_index - 1, cw);
02249 
02250                     if (i < this->parent->always_on_top_index) {
02251                         // window is already in the "normal" area
02252                         if (this->parent->focusedChildWin == i) {
02253                             // focused child window is raised
02254                             this->parent->focusedChildWin = this->parent->always_on_top_index - 1;
02255                         }
02256                         else {
02257                             if (this->parent->focusedChildWin < this->parent->always_on_top_index) {
02258                                 if (this->parent->focusedChildWin > i) {
02259                                     // the focused window will not be changed here!!!
02260                                     this->parent->focusedChildWin--;
02261                                 }
02262                             }
02263                         }
02264                     }
02265                     else {
02266                         // window is switched to "normal" area
02267                         this->parent->always_on_top_index++;
02268                         if (this->parent->focusedChildWin == i) {
02269                             // focused child window is raised
02270                             this->parent->focusedChildWin = this->parent->always_on_top_index - 1;
02271                         }
02272                         else {
02273                             if (this->parent->focusedChildWin >= this->parent->always_on_top_index) {
02274                                 if (this->parent->focusedChildWin < i) {
02275                                     // the focused window will not be changed here!!!
02276                                     this->parent->focusedChildWin++;
02277                                 }
02278                             }
02279                         }
02280                     }
02281 
02282                     // index to the child window
02283                     i = this->parent->always_on_top_index - 1;
02284                 }
02285                 else {
02286                     // window with "always on top" flag, move it to the end of list
02287                     this->parent->childwins.push_back(cw);
02288 
02289                     if (i >= this->parent->always_on_top_index) {
02290                         // window is already in the "always on top" area
02291                         if (this->parent->focusedChildWin == i) {
02292                             // focused child window is raised
02293                             this->parent->focusedChildWin = this->parent->childwins.size() - 1;
02294                         }
02295                         else {
02296                             if (this->parent->focusedChildWin > i) {
02297                                 // the focused window will not be changed here!!!
02298                                 this->parent->focusedChildWin--;
02299                             }
02300                         }
02301                     }
02302                     else {
02303                         // window is switched to "always on top" area
02304                         this->parent->always_on_top_index--;
02305                         if (this->parent->focusedChildWin == i) {
02306                             // focused child window is raised
02307                             this->parent->focusedChildWin = this->parent->childwins.size() - 1;
02308                         }
02309                         else {
02310                             if (this->parent->focusedChildWin > i) {
02311                                 // the focused window will not be changed here!!!
02312                                 this->parent->focusedChildWin--;
02313                             }
02314                         }
02315                     }
02316 
02317                     // index to the child window
02318                     i = this->parent->childwins.size() - 1;
02319                 }
02320 
02321                 // redraw the window stack if child window and parent is shown
02322                 if ((this->parent->childwins.at(i).window->shown)&&(this->parent->shown)) {
02323                     PRINT_LOCK("call flipWindow");
02324                     this->parent->flipWindow(this->parent->childwins.at(i).window, NULL, MMSFB_FLIP_NONE, false, true);
02325                     PRINT_LOCK("end flipWindow");
02326                 }
02327 
02328             }
02329 
02330             unlock();
02331             return true;
02332         }
02333     }
02334     unlock();
02335     return false;
02336 }
02337 
02338 bool MMSWindow::lowerToBottom() {
02339     if (!this->parent) {
02340         // normal parent window, set the window to bottom
02341         if (this->window) {
02342             return this->window->lowerToBottom();
02343         }
02344         return false;
02345     }
02346 
02347     // child window, change the childwins vector
02348     lock();
02349     for (unsigned int i = 0; i < this->parent->childwins.size(); i++) {
02350         if (this->parent->childwins.at(i).window == this) {
02351             // child window found, move it to the beginning of the vector
02352             if (i > 0) {
02353                 // not at the beginning, moving it
02354                 CHILDWINS cw = this->parent->childwins.at(i);
02355                 this->parent->childwins.erase(this->parent->childwins.begin()+i);
02356 
02357                 bool aot = false;
02358                 this->getAlwaysOnTop(aot);
02359                 if (!aot) {
02360                     // normal stack position, move window to the beginning of the list
02361                     this->parent->childwins.insert(this->parent->childwins.begin(), cw);
02362 
02363                     if (this->parent->focusedChildWin < i) {
02364                         // the focused window will not be changed here!!!
02365                         this->parent->focusedChildWin++;
02366                     }
02367 
02368                     // index to the child window
02369                     i = 0;
02370                 }
02371                 else {
02372                     // window with "always on top" flag, move window before all windows with "always on top" flag
02373                     this->parent->childwins.insert(this->parent->childwins.begin() + this->parent->always_on_top_index, cw);
02374 
02375                     if (this->parent->focusedChildWin >= this->parent->always_on_top_index) {
02376                         if (this->parent->focusedChildWin < i) {
02377                             // the focused window will not be changed here!!!
02378                             this->parent->focusedChildWin++;
02379                         }
02380                     }
02381 
02382                     // index to the child window
02383                     i = this->parent->always_on_top_index;
02384                 }
02385 
02386                 // redraw the window stack if child window and parent is shown
02387                 if ((this->parent->childwins.at(i).window->shown)&&(this->parent->shown)) {
02388                     PRINT_LOCK("call flipWindow");
02389                     this->parent->flipWindow(this->parent->childwins.at(i).window, NULL, MMSFB_FLIP_NONE, false, true);
02390                     PRINT_LOCK("end flipWindow");
02391                 }
02392             }
02393 
02394             unlock();
02395             return true;
02396         }
02397     }
02398     unlock();
02399     return false;
02400 }
02401 
02402 bool MMSWindow::moveTo(int x, int y, bool refresh) {
02403     x&= ~0x01;
02404     y&= ~0x01;
02405     if (!this->parent) {
02406         bool os;
02407         getOwnSurface(os);
02408         if (os) {
02409             // own surface
02410             this->window->moveTo(x, y);
02411         }
02412         else {
02413             // root, main, popup window with shared surface
02414             static bool firsttime = true;
02415             if (firsttime) {
02416                 printf("DISKO: Moving window (%s) with own_surface=\"false\" is not recommended.\n",
02417                         (this->name=="")?"noname":this->name.c_str());
02418                 firsttime = false;
02419             }
02420 
02421             this->surface->lock();
02422             // clear
02423             this->surface->clear();
02424             PRINT_LOCK("call flip");
02425             this->surface->flip();
02426             PRINT_LOCK("end flip");
02427 
02428             // move subsurface
02429             this->surface->moveTo(x, y);
02430             this->surface->unlock();
02431 
02432             // move visible rectangle
02433             MMSFBRectangle vrect;
02434             if (this->window->getVisibleRectangle(&vrect)) {
02435                 vrect.x = x;
02436                 vrect.y = y;
02437                 this->window->setVisibleRectangle(&vrect);
02438             }
02439 
02440             // refresh (redraw) window
02441             this->refresh();
02442         }
02443     }
02444     else {
02445         // this is a child window
02446         this->parent->moveChildWindow(this, x, y, refresh);
02447     }
02448 
02449     return true;
02450 }
02451 
02452 
02453 bool MMSWindow::stretch(double left, double up, double right, double down) {
02454     bool ret = true;
02455 
02456     // TODO: currently we work for child windows only
02457     if (!parent) return false;
02458 
02459     // reset stretch mode
02460     this->stretchmode = false;
02461     this->stretchLeft = (int)(left * 256);
02462     this->stretchUp   = (int)(up * 256);
02463     this->stretchRight= (int)(right * 256);
02464     this->stretchDown = (int)(down * 256);
02465 
02466     if ((left != 100)||(right != 100)||(up != 100)||(down != 100)) {
02467         if ((((left-100)+(right-100)+100) > 0) && (((up-100)+(down-100)+100) > 0)) {
02468             // values accepted
02469             this->stretchmode = true;
02470         }
02471         else {
02472             // wrong inputs
02473             ret = false;
02474         }
02475     }
02476 
02477     // re-calculate the window region and return
02478     parent->setChildWindowRegion(this, true);
02479     return ret;
02480 }
02481 
02482 bool MMSWindow::onBeforeAnimation(MMSPulser *pulser) {
02483     bool rc = false;
02484     mmsfb->lock();
02485     switch (this->pulser_mode) {
02486     case MMSWINDOW_PULSER_MODE_SHOW:
02487         PRINT_LOCK("enter beforeShowAction");
02488         rc = beforeShowAction(pulser);
02489         PRINT_LOCK("leave beforeShowAction");
02490         PRINT_LOCK("mmsfb unlock");
02491         mmsfb->unlock();
02492         return rc;
02493     case MMSWINDOW_PULSER_MODE_HIDE:
02494         rc = beforeHideAction(pulser);
02495         PRINT_LOCK("mmsfb unlock");
02496         mmsfb->unlock();
02497         return rc;
02498     }
02499 
02500     PRINT_LOCK("mmsfb unlock");
02501     mmsfb->unlock();
02502 
02503     return false;
02504 }
02505 
02506 bool MMSWindow::onAnimation(MMSPulser *pulser) {
02507     mmsfb->lock();
02508     bool rc = false;
02509     switch (this->pulser_mode) {
02510     case MMSWINDOW_PULSER_MODE_SHOW:
02511         PRINT_LOCK("enter showAction");
02512         rc = showAction(pulser);
02513         PRINT_LOCK("leave showAction");
02514         PRINT_LOCK("mmsfb unlock");
02515         mmsfb->unlock();
02516         return rc;
02517     case MMSWINDOW_PULSER_MODE_HIDE:
02518         rc = hideAction(pulser);
02519         PRINT_LOCK("mmsfb unlock");
02520         mmsfb->unlock();
02521         return rc;
02522     }
02523     PRINT_LOCK("mmsfb unlock");
02524     mmsfb->unlock();
02525     return false;
02526 }
02527 
02528 void MMSWindow::onAfterAnimation(MMSPulser *pulser) {
02529     mmsfb->lock();
02530 
02531     switch (this->pulser_mode) {
02532     case MMSWINDOW_PULSER_MODE_SHOW:
02533         PRINT_LOCK("enter afterShowAction");
02534         afterShowAction(pulser);
02535         PRINT_LOCK("leave afterShowAction");
02536         break;
02537     case MMSWINDOW_PULSER_MODE_HIDE:
02538         afterHideAction(pulser);
02539         break;
02540     }
02541 
02542     PRINT_LOCK("mmsfb unlock");
02543     mmsfb->unlock();
02544 }
02545 
02546 bool MMSWindow::beforeShowAction(MMSPulser *pulser) {
02547     if(shown==true) {
02548         // call onAfterShow callback with already shown flag
02549         this->onAfterShow->emit(this, true);
02550         this->willshow=false;
02551         return false;
02552     }
02553 
02554     // set the first focused widget, if not set and if window can get the focus
02555     this->setFirstFocus();
02556 
02557     if (getType() == MMSWINDOWTYPE_CHILDWINDOW) {
02558         if ((int)this->parent->focusedChildWin >= 0) {
02559             MMSWindow *fw = this->parent->childwins.at(this->parent->focusedChildWin).window;
02560             if ((fw != this) && (!fw->isShown())) {
02561                 // focused child window is not shown!
02562                 // so set focus to this window
02563                 setFocus();
02564             }
02565         }
02566     }
02567 
02568     PRINT_LOCK("try to lock beforeshow");
02569     // lock during draw
02570     lock();
02571     PRINT_LOCK("got lock beforeshow");
02572 
02573     // optimized shown
02574     showBufferedShown();
02575 
02576     // check if all of its parents are shown
02577     bool really_shown = true;
02578     if (this->parent)
02579         really_shown = this->parent->isShown(true);
02580 
02581 
02582     if (getType() == MMSWINDOWTYPE_ROOTWINDOW) {
02583         // hide the current root window
02584         if (this->windowmanager) {
02585             this->windowmanager->hideAllRootWindows(true);
02586             this->windowmanager->lowerToBottom(this);
02587         }
02588         else {
02589             lowerToBottom();
02590         }
02591     }
02592     else {
02593         // bring all other windows in foreground
02594         if (!this->parent) {
02595             // normal parent window (main or popup)
02596             if (this->windowmanager) {
02597                 PRINT_LOCK("call raiseToTop");
02598                 this->windowmanager->raiseToTop(this);
02599             }
02600             else {
02601                 PRINT_LOCK("call raiseToTop");
02602                 raiseToTop(0);
02603             }
02604         }
02605         else {
02606             // change the z-order of child windows?
02607             bool staticzorder = false;
02608             this->parent->getStaticZOrder(staticzorder);
02609             if (!staticzorder) {
02610                 PRINT_LOCK("call raiseToTop");
02611                 raiseToTop(0);
02612             }
02613         }
02614     }
02615 
02616     if ((getType() == MMSWINDOWTYPE_ROOTWINDOW) || (getType() == MMSWINDOWTYPE_MAINWINDOW)) {
02617         bool os;
02618         getOwnSurface(os);
02619         if (!os) {
02620             if (this->window) {
02621                 // we are working with a subsurface of a fullscreen window
02622                 this->window->setVisibleRectangle(&this->geom);
02623             }
02624         }
02625     }
02626 
02627     // draw complete window two times!!! *********************************
02628     // two times are needed because if window is not shown (shown=false) *
02629     // refreshFromChild does not work!!! -> but the second call to draw  *
02630     // uses the current settings from all childs                         *
02631     draw();
02632     draw();
02633     //********************************************************************
02634 
02635     if (!this->precalcnav) {
02636         // init window (e.g. pre-calc navigation ...)
02637         initnav();
02638         this->precalcnav = true;
02639     }
02640 
02641     if (!this->initialArrowsDrawn) {
02642         // set the arrow widgets
02643         this->initialArrowsDrawn = true;
02644         switchArrowWidgets();
02645     }
02646 
02647     // make it visible
02648     if (!this->parent) {
02649         PRINT_LOCK("call flipWindow");
02650         flipWindow(this);
02651         PRINT_LOCK("end flipWindow");
02652     }
02653     else {
02654         PRINT_LOCK("call flipWindow");
02655         this->parent->flipWindow(this);
02656         PRINT_LOCK("end flipWindow");
02657     }
02658 
02659     // drawing finished, unlock
02660     unlock();
02661 
02662     if (this->window) {
02663         // show window (normally the opacity is 0 here)
02664         this->window->show();
02665     }
02666 
02667     // window is shown (important to set it before animation!!!)
02668     shown=true;
02669 
02670     // per default only main or root windows can get inputs
02671     // popup windows can get inputs if the modal mode is set
02672     // child windows get the inputs from the parent main, root or popup window
02673     if (this->windowmanager) {
02674         switch (getType()) {
02675             case MMSWINDOWTYPE_MAINWINDOW:
02676             case MMSWINDOWTYPE_ROOTWINDOW:
02677                 this->windowmanager->setToplevelWindow(this);
02678                 break;
02679             case MMSWINDOWTYPE_POPUPWINDOW: {
02680                 bool modal;
02681                 if (getModal(modal)) {
02682                     if (modal)
02683                         this->windowmanager->setToplevelWindow(this);
02684                 }
02685                 break;
02686             }
02687             default:
02688                 break;
02689         }
02690     }
02691 
02692     // check if window or parent are correctly initialized
02693     if (!((this->parent)||((!this->parent)&&(this->window)))) {
02694         // no, do not start the animation
02695         afterShowAction(NULL);
02696         return false;
02697     }
02698 
02699     // init animation values
02700     if (!getOpacity(this->anim_opacity)) this->anim_opacity = 255;
02701     this->anim_rect = getGeometry();
02702     if (!getFadeIn(this->anim_fade)) this->anim_fade = false;
02703     if (!getMoveIn(this->anim_move)) this->anim_move = MMSDIRECTION_NOTSET;
02704 
02705     if ((!really_shown)||((!this->anim_fade)&&(this->anim_move==MMSDIRECTION_NOTSET))) {
02706         // nothing to animate, set values which are valid after the animation
02707         afterShowAction(pulser);
02708         return false;
02709     }
02710 
02711     // calculate the steps
02712     int steps = MMSWINDOW_ANIM_MAX_OFFSET;
02713     switch (this->anim_move) {
02714         case MMSDIRECTION_LEFT:
02715             this->anim_move_step = (vrect.w - this->anim_rect.x + vrect.x) / (steps+1);
02716             break;
02717         case MMSDIRECTION_RIGHT:
02718             this->anim_move_step = (this->anim_rect.w - vrect.x + this->anim_rect.x) / (steps+1);
02719             break;
02720         case MMSDIRECTION_UP:
02721             this->anim_move_step = (vrect.h - this->anim_rect.y + vrect.y) / (steps+1);
02722             break;
02723         case MMSDIRECTION_DOWN:
02724             this->anim_move_step = (this->anim_rect.h - vrect.y + this->anim_rect.y) / (steps+1);
02725             break;
02726         default:
02727             break;
02728     }
02729 
02730     if (this->anim_fade)
02731         this->anim_opacity_step = this->anim_opacity / (steps+1);
02732 
02733     return true;
02734 }
02735 
02736 
02737 bool MMSWindow::showAction(MMSPulser *pulser) {
02738 
02739     PRINT_LOCK("enter ShowAction");
02740 
02741     // do the animation
02742     double offs = MMSWINDOW_ANIM_MAX_OFFSET - pulser->getOffset();
02743 
02744 //printf("111111111111111 %f %d\n", offs, pulser->getOnAnimationCounter());
02745 
02746     // move it
02747     switch (this->anim_move) {
02748         case MMSDIRECTION_LEFT:
02749             moveTo((int)(this->anim_rect.x + offs * this->anim_move_step) & ~0x01, this->anim_rect.y);
02750             break;
02751         case MMSDIRECTION_RIGHT:
02752             moveTo((int)(this->anim_rect.x - offs * this->anim_move_step) & ~0x01, this->anim_rect.y);
02753             break;
02754         case MMSDIRECTION_UP:
02755             moveTo(this->anim_rect.x, (int)(this->anim_rect.y + offs * this->anim_move_step) & ~0x01);
02756             break;
02757         case MMSDIRECTION_DOWN:
02758             moveTo(this->anim_rect.x, (int)(this->anim_rect.y - offs * this->anim_move_step) & ~0x01);
02759             break;
02760         default:
02761             break;
02762     }
02763 
02764     if (this->anim_fade) {
02765         // fade it
02766         if (!parent)
02767             this->window->setOpacity(this->anim_opacity - offs * this->anim_opacity_step);
02768         else
02769             this->parent->setChildWindowOpacity(this, this->anim_opacity - offs * this->anim_opacity_step);
02770     }
02771     else
02772     if (pulser->getOnAnimationCounter() == 0) {
02773         // no fade animation and called for the first time, set the opacity
02774         if (!parent)
02775             this->window->setOpacity(this->anim_opacity);
02776         else
02777             this->parent->setChildWindowOpacity(this, this->anim_opacity);
02778     }
02779 
02780     PRINT_LOCK("leave ShowAction");
02781 
02782     return true;
02783 }
02784 
02785 void MMSWindow::afterShowAction(MMSPulser *pulser) {
02786     PRINT_LOCK("enter afterShowAction");
02787 
02788     if (pulser) {
02789         // animation finished
02790         // set final position
02791         if (this->anim_move != MMSDIRECTION_NOTSET) {
02792             moveTo(this->anim_rect.x, this->anim_rect.y);
02793         }
02794 
02795         // set final opacity
02796         if (!this->parent) {
02797             this->window->setOpacity(this->anim_opacity);
02798         }
02799         else {
02800             this->parent->setChildWindowOpacity(this, this->anim_opacity);
02801         }
02802     }
02803 
02804     // do the rest...
02805     this->willshow=false;
02806 
02807     if (getType() == MMSWINDOWTYPE_CHILDWINDOW) {
02808         //TODO: if no focused childwin, then i should get the focused back
02809 
02810         // pre-calculate the navigation
02811         if (this->parent) {
02812             this->parent->preCalcNavigation();
02813             this->switchArrowWidgets();
02814         }
02815     }
02816 
02817     // call onAfterShow callback without already shown flag
02818     this->onAfterShow->emit(this, false);
02819 
02820     PRINT_LOCK("leave afterShowAction");
02821 }
02822 
02823 bool MMSWindow::beforeHideAction(MMSPulser *pulser) {
02824     if (shown==false) {
02825         this->willhide = false;
02826         return false;
02827     }
02828 
02829     // check if all of its parents are shown
02830     bool really_shown = this->isShown(true);
02831 
02832     if (!this->parent)
02833         if (this->windowmanager)
02834             this->windowmanager->removeWindowFromToplevel(this);
02835 
02836     if (getType() == MMSWINDOWTYPE_CHILDWINDOW) {
02837         // remove the focus from me
02838         removeFocusFromChildWindow();
02839     }
02840 
02841     // check if window or parent are correctly initialized
02842     if (!((this->parent)||((!this->parent)&&(this->window)))) {
02843         // no, check if i have the surface from layer
02844         if (this->surface) {
02845             this->surface->lock();
02846             // clear it
02847             this->surface->clear();
02848             PRINT_LOCK("call flip");
02849             this->surface->flip();
02850             PRINT_LOCK("end flip");
02851             this->surface->unlock();
02852         }
02853         afterHideAction(NULL);
02854         return false;
02855     }
02856 
02857     // init animation values
02858     if (!getOpacity(this->anim_opacity)) this->anim_opacity = 255;
02859     this->anim_rect = getGeometry();
02860     if (!getFadeOut(this->anim_fade)) this->anim_fade = false;
02861     if (!getMoveOut(this->anim_move)) this->anim_move = MMSDIRECTION_NOTSET;
02862 
02863     if ((!really_shown)||((!this->anim_fade)&&(this->anim_move==MMSDIRECTION_NOTSET))) {
02864         // nothing to animate, set values which are valid after the animation
02865         afterHideAction(pulser);
02866         return false;
02867     }
02868 
02869     // calculate the steps
02870     int steps = MMSWINDOW_ANIM_MAX_OFFSET;
02871     switch (this->anim_move) {
02872         case MMSDIRECTION_LEFT:
02873             this->anim_move_step = (this->anim_rect.w - vrect.x + this->anim_rect.x) / (steps+1);
02874             break;
02875         case MMSDIRECTION_RIGHT:
02876             this->anim_move_step = (vrect.w - this->anim_rect.x + vrect.x) / (steps+1);
02877             break;
02878         case MMSDIRECTION_UP:
02879             this->anim_move_step = (this->anim_rect.h - vrect.y + this->anim_rect.y) / (steps+1);
02880             break;
02881         case MMSDIRECTION_DOWN:
02882             this->anim_move_step = (vrect.h - this->anim_rect.y + vrect.y) / (steps+1);
02883             break;
02884         default:
02885             break;
02886     }
02887 
02888     if (this->anim_fade)
02889         this->anim_opacity_step = this->anim_opacity / (steps+1);
02890 
02891     return true;
02892 }
02893 
02894 bool MMSWindow::hideAction(MMSPulser *pulser) {
02895 
02896     // do the animation
02897     double offs = pulser->getOffset();
02898 
02899 //printf("2222222222222 %f %d\n", offs, pulser->getOnAnimationCounter());
02900 
02901 
02902     // move it
02903     switch (this->anim_move) {
02904         case MMSDIRECTION_LEFT:
02905             moveTo((int)(this->anim_rect.x - offs * this->anim_move_step) & ~0x01, this->anim_rect.y);
02906             break;
02907         case MMSDIRECTION_RIGHT:
02908             moveTo((int)(this->anim_rect.x + offs * this->anim_move_step) & ~0x01, this->anim_rect.y);
02909             break;
02910         case MMSDIRECTION_UP:
02911             moveTo(this->anim_rect.x, (int)(this->anim_rect.y - offs * this->anim_move_step) & ~0x01);
02912             break;
02913         case MMSDIRECTION_DOWN:
02914             moveTo(this->anim_rect.x, (int)(this->anim_rect.y + offs * this->anim_move_step) & ~0x01);
02915             break;
02916         default:
02917             break;
02918     }
02919 
02920     if (this->anim_fade) {
02921         // fade it
02922         if (!parent)
02923             this->window->setOpacity(this->anim_opacity - offs * this->anim_opacity_step);
02924         else
02925             this->parent->setChildWindowOpacity(this, this->anim_opacity - offs * this->anim_opacity_step);
02926     }
02927     else
02928     if (pulser->getOnAnimationCounter() == 0) {
02929         // no fade animation and called for the first time, set the opacity
02930         if (!parent)
02931             this->window->setOpacity(this->anim_opacity);
02932         else
02933             this->parent->setChildWindowOpacity(this, this->anim_opacity);
02934     }
02935 
02936     return true;
02937 }
02938 
02939 void MMSWindow::afterHideAction(MMSPulser *pulser) {
02940     if (pulser) {
02941         // animation finished
02942         // set final opacity
02943         if (!this->parent) {
02944             this->window->setOpacity(0);
02945             this->window->hide();
02946         }
02947         else {
02948             this->parent->setChildWindowOpacity(this, 0);
02949         }
02950 
02951         // restore position
02952         if (this->anim_move != MMSDIRECTION_NOTSET) {
02953             moveTo(this->anim_rect.x, this->anim_rect.y);
02954         }
02955     }
02956 
02957     // do the rest...
02958     shown=false;
02959     willhide=false;
02960 
02961     if (getType() == MMSWINDOWTYPE_CHILDWINDOW) {
02962         // pre-calculate the navigation
02963         if (this->parent) {
02964             this->parent->preCalcNavigation();
02965             switchArrowWidgets();
02966         }
02967     }
02968 
02969     //TODO: release images...
02970     release();
02971 }
02972 
02973 bool MMSWindow::hide(bool goback, bool wait) {
02974     //give the other threads a chance to do their part
02975     PRINT_LOCK("mmsfb unlock");
02976     bool rc = mmsfb->unlock();
02977     /* the window will be shown in a few seconds (showAction thread is running), wait for it */
02978     while (this->willshow)
02979         msleep(100);
02980 
02981     while(1) {
02982         /* check if the window is shown */
02983         if(!this->shown)
02984             return true;
02985         /* check if the window will already be hidden */
02986         if (this->willhide) {
02987             msleep(100);
02988             continue;
02989         }
02990         break;
02991     }
02992 
02993     //back to locking if applicable
02994     if(rc)
02995         mmsfb->lock();
02996 
02997     /* starting hide process */
02998     this->willhide = true;
02999 
03000     /* call onBeforeHide callback */
03001     if (!this->onBeforeHide->emit(this, goback)) {
03002         /* a callback returns false, break the hide process */
03003         this->willhide = false;
03004         return false;
03005     }
03006 
03007 /*
03008     if (this->action->isRunning())
03009         this->action->cancelBroadcast.emit(this->getType());
03010     this->action->setAction(MMSWACTION_HIDE);
03011     this->action->start();
03012 
03013     if (wait) {
03014         int c = 0;
03015         while ((this->action->getAction()==MMSWACTION_HIDE) && c < 20) { msleep(100); c++; }
03016     }
03017 */
03018 
03019     // do the animation in a separate thread...
03020     this->pulser.setStepsPerSecond(MMSWINDOW_ANIM_MAX_OFFSET * 4);
03021     this->pulser.setMaxOffset(MMSWINDOW_ANIM_MAX_OFFSET, MMSPULSER_SEQ_LOG_SOFT_START,  MMSWINDOW_ANIM_MAX_OFFSET / 2);
03022 //  this->pulser.setMaxOffset(MMSWINDOW_ANIM_MAX_OFFSET, MMSPULSER_SEQ_LOG_SOFT_END,    MMSWINDOW_ANIM_MAX_OFFSET / 2);
03023 //  this->pulser.setMaxOffset(MMSWINDOW_ANIM_MAX_OFFSET, MMSPULSER_SEQ_LINEAR);
03024 //  this->pulser.setMaxOffset(MMSWINDOW_ANIM_MAX_OFFSET, MMSPULSER_SEQ_LINEAR_DESC);
03025 //  this->pulser.setMaxOffset(MMSWINDOW_ANIM_MAX_OFFSET, MMSPULSER_SEQ_LOG_DESC_SOFT_START, MMSWINDOW_ANIM_MAX_OFFSET / 2);
03026 //  this->pulser.setMaxOffset(MMSWINDOW_ANIM_MAX_OFFSET, MMSPULSER_SEQ_LOG_DESC_SOFT_END,   MMSWINDOW_ANIM_MAX_OFFSET / 2);
03027 //  this->pulser.setMaxOffset(MMSWINDOW_ANIM_MAX_OFFSET, MMSPULSER_SEQ_LOG_SOFT_START_AND_END);
03028     this->pulser_mode = MMSWINDOW_PULSER_MODE_HIDE;
03029     this->pulser.start(!wait, true);
03030 
03031 
03032     // call onHide callback
03033     this->onHide->emit(this, goback);
03034 
03035     return true;
03036 }
03037 
03038 /*
03039 bool MMSWindow::hideAction(bool *stopaction) {
03040     bool    saction = *stopaction;
03041 
03042     if(shown==false)
03043         return !saction;
03044 
03045     // check if all of its parents are shown
03046     bool really_shown = this->isShown(true);
03047 
03048     if (!this->parent)
03049         if (this->windowmanager)
03050             this->windowmanager->removeWindowFromToplevel(this);
03051 
03052     if (getType() == MMSWINDOWTYPE_CHILDWINDOW) {
03053         // remove the focus from me
03054         removeFocusFromChildWindow();
03055     }
03056 /////////////////
03057     if ((this->parent)||((!this->parent)&&(this->window))) {
03058         unsigned int opacity;
03059         if (!getOpacity(opacity)) opacity = 255;
03060         MMSFBRectangle rect = getGeometry();
03061 
03062         bool fadeout;
03063         if (!getFadeOut(fadeout)) fadeout = false;
03064         MMSDIRECTION moveout;
03065         if (!getMoveOut(moveout)) moveout = MMSDIRECTION_NOTSET;
03066 
03067         if ((really_shown)&&((fadeout)||(moveout!=MMSDIRECTION_NOTSET))) {
03068             // little animation
03069             int steps = 3;
03070             unsigned int opacity_step;
03071             int move_step;
03072 
03073             switch (moveout) {
03074                 case MMSDIRECTION_LEFT:
03075                     move_step = (rect.w-vrect.x+rect.x) / (steps+1);
03076                     break;
03077                 case MMSDIRECTION_RIGHT:
03078                     move_step = (vrect.w-rect.x+vrect.x) / (steps+1);
03079                     break;
03080                 case MMSDIRECTION_UP:
03081                     move_step = (rect.h-vrect.y+rect.y) / (steps+1);
03082                     break;
03083                 case MMSDIRECTION_DOWN:
03084                     move_step = (vrect.h-rect.y+vrect.y) / (steps+1);
03085                     break;
03086                 default:
03087                     break;
03088             }
03089 
03090             if (fadeout)
03091                 opacity_step = opacity / (steps+1);
03092 
03093             for (int i = 1; i <= steps; i++) {
03094 
03095                 // start time stamp
03096                 unsigned int start_ts = getMTimeStamp();
03097 
03098                 switch (moveout) {
03099                     case MMSDIRECTION_LEFT:
03100                         moveTo((rect.x - i * move_step) & ~0x01, rect.y);
03101                         break;
03102                     case MMSDIRECTION_RIGHT:
03103                         moveTo((rect.x + i * move_step) & ~0x01, rect.y);
03104                         break;
03105                     case MMSDIRECTION_UP:
03106                         moveTo(rect.x, (rect.y - i * move_step) & ~0x01);
03107                         break;
03108                     case MMSDIRECTION_DOWN:
03109                         moveTo(rect.x, (rect.y + i * move_step) & ~0x01);
03110                         break;
03111                     default:
03112                         break;
03113                 }
03114 
03115                 if (fadeout) {
03116                     if (!parent)
03117                         this->window->setOpacity(opacity - i * opacity_step);
03118                     else
03119                         this->parent->setChildWindowOpacity(this, opacity - i * opacity_step);
03120                 }
03121 
03122                 if (*stopaction) {
03123                     saction=true;
03124                     break;
03125                 }
03126 
03127                 // end time stamp
03128                 unsigned int end_ts = getMTimeStamp();
03129 
03130                 // sleeping a little...
03131                 msleep(getFrameDelay(start_ts, end_ts));
03132 
03133             }
03134         }
03135 ///ddd
03136         if (!parent) {
03137             // set final opacity
03138             this->window->setOpacity(0);
03139             this->window->hide();
03140         }
03141         else {
03142             // set final opacity
03143             this->parent->setChildWindowOpacity(this, 0);
03144         }
03145 
03146         // restore position
03147         if (moveout!=MMSDIRECTION_NOTSET)
03148             moveTo(rect.x, rect.y);
03149     }
03150     else {
03151         // check if i have the surface from layer
03152         if (this->surface) {
03153             // clear it
03154             this->surface->clear();
03155             this->surface->flip();
03156         }
03157     }
03158 ///////////
03159 
03160     shown=false;
03161     willhide=false;
03162 
03163     if (getType() == MMSWINDOWTYPE_CHILDWINDOW) {
03164         // pre-calculate the navigation
03165         if (this->parent) {
03166             this->parent->preCalcNavigation();
03167             switchArrowWidgets();
03168         }
03169     }
03170 
03171     *stopaction=false;
03172 
03173     return !saction;
03174 }*/
03175 
03176 void MMSWindow::waitUntilShown() {
03177     //ensure that a show action can take place
03178     PRINT_LOCK("mmsfb unlock");
03179     bool rc = mmsfb->unlock();
03180 
03181     while ((!isShown())||(willshow))
03182         msleep(10);
03183 
03184     //ensure that a show action can take place
03185     if(rc)
03186         mmsfb->lock();
03187 }
03188 
03189 void MMSWindow::waitUntilHidden() {
03190     //ensure that a show action can take place
03191     PRINT_LOCK("mmsfb unlock");
03192     bool rc = mmsfb->unlock();
03193 
03194     while ((isShown())||(willhide))
03195         msleep(10);
03196 
03197     //ensure that a show action can take place
03198     if(rc)
03199         mmsfb->lock();
03200 }
03201 
03202 void MMSWindow::add(MMSWidget *child) {
03203 
03204     /* prevent duplicate items */
03205     for(unsigned int i = 0; i < this->children.size(); i++) {
03206         if(children.at(i)->getId() == child->getId())
03207             return;
03208     }
03209 
03210     /* add to the children vector */
03211     lock();
03212     this->children.push_back(child);
03213     unlock();
03214 }
03215 
03216 void MMSWindow::remove(MMSWidget *child) {
03217     /* remove from children vector */
03218     for(unsigned int i = 0; i < this->children.size(); i++) {
03219         if(children.at(i) == child) {
03220             this->children.erase(this->children.begin()+i);
03221             return;
03222         }
03223     }
03224 }
03225 
03226 
03227 void MMSWindow::refreshFromChild(MMSWidget *child, MMSFBRectangle *rect2update, bool check_shown) {
03228     MMSFBRegion     region;
03229     MMSFBRectangle  flip_rect;
03230 
03231     // use own surface?
03232     // note: os=false must ONLY be set, if this window is a child window!!!
03233     bool os = true;
03234     if (this->type == MMSWINDOWTYPE_CHILDWINDOW)
03235         getOwnSurface(os);
03236 
03237     if (check_shown) {
03238         // it makes sense that we skip all drawing requests here, if this window OR one of its parents are not shown
03239         if (!isShown(true)) {
03240             DEBUGMSG("MMSGUI", "MMSWindow->refreshFromChild() skipped because window is not shown");
03241             return;
03242         }
03243     }
03244 
03245     // lock drawing
03246 //PUP    this->drawLock.lock();
03247     lock();
03248 
03249 
03250     // calculate region
03251     MMSFBRectangle rect;
03252     MMSWidget *c = child;
03253     if ((!c)&&(!children.empty()))
03254         c = children.at(0);
03255     if (c) {
03256         if (!rect2update) {
03257             rect = c->getGeometry();
03258             if (c->isDrawable()) {
03259                 unsigned int childmargin;
03260                 if (!c->getMargin(childmargin))
03261                     childmargin = 0;
03262                 rect.x+=childmargin;
03263                 rect.y+=childmargin;
03264                 rect.w-=2*childmargin;
03265                 rect.h-=2*childmargin;
03266             }
03267         }
03268         else
03269             rect = *rect2update;
03270 
03271         // check x/y
03272         if (rect.x < this->innerGeom.x) {
03273             rect.w-= this->innerGeom.x - rect.x;
03274             rect.x = this->innerGeom.x;
03275         }
03276         if (rect.y < this->innerGeom.y) {
03277             rect.h-= this->innerGeom.y - rect.y;
03278             rect.y = this->innerGeom.y;
03279         }
03280 
03281         // valid rectangle?
03282         if ((rect.w <= 0)||(rect.h <= 0)) {
03283             unlock();
03284             return;
03285         }
03286 
03287         // check width/height
03288         if (rect.x + rect.w > this->innerGeom.x + this->innerGeom.w)
03289             rect.w = this->innerGeom.w - rect.x;
03290         if (rect.y + rect.h > this->innerGeom.y + this->innerGeom.h)
03291             rect.h = this->innerGeom.h - rect.y;
03292 
03293         // valid rectangle?
03294         if ((rect.w <= 0)||(rect.h <= 0)) {
03295             unlock();
03296             return;
03297         }
03298 
03299         // save src rectangle for separate flip() call
03300         flip_rect = rect;
03301 
03302         if (stretchmode) {
03303             // adjust the destination rectangle
03304             rect.x = MMSFBWINDOW_CALC_STRETCH_WIDTH(rect.x, this);
03305             rect.y = MMSFBWINDOW_CALC_STRETCH_HEIGHT(rect.y, this);
03306             rect.w = MMSFBWINDOW_CALC_STRETCH_WIDTH(rect.w, this);
03307             rect.h = MMSFBWINDOW_CALC_STRETCH_HEIGHT(rect.h, this);
03308         }
03309     }
03310     else {
03311         // update complete inner geom
03312         rect = this->innerGeom;
03313 
03314         // save src rectangle for separate flip() call
03315         flip_rect = rect;
03316     }
03317 
03318     if(child) {
03319         // draw only childs of this child
03320         if (os)
03321             child->drawchildren();
03322     }
03323     else {
03324         // draw only some parts of the window
03325         if (os)
03326             draw(true, (rect2update)?&flip_rect:NULL);
03327     }
03328 
03329     // set region
03330     region.x1 = rect.x;
03331     region.x2 = rect.x+rect.w-1;
03332     region.y1 = rect.y;
03333     region.y2 = rect.y+rect.h-1;
03334 
03335 //    logger.writeLog("flip the region (x1,y1,x2,y2) (" +
03336 //        iToStr(region.x1) + "," + iToStr(region.y1) + "," + iToStr(region.x2) + "," + iToStr(region.y2) +")");
03337 
03338     if (!bordergeomset)
03339         // border geom is not set -> draw the border
03340         drawMyBorder();
03341     else {
03342         // draw the border if it is in the flipping region
03343         bool htdb = false;
03344 
03345         // check if border should be drawn
03346         if (!htdb)
03347             htdb = ((bordergeom[0].x + bordergeom[0].w > region.x1)
03348                   &&(bordergeom[0].y + bordergeom[0].h > region.y1));
03349         if (!htdb)
03350             htdb = (bordergeom[1].y + bordergeom[1].h > region.y1);
03351         if (!htdb)
03352             htdb = ((bordergeom[2].x <= region.x2)
03353                   &&(bordergeom[2].y + bordergeom[2].h > region.y1));
03354         if (!htdb)
03355             htdb = (bordergeom[3].x <= region.x2);
03356         if (!htdb)
03357             htdb = ((bordergeom[4].x <= region.x2)
03358                   &&(bordergeom[4].y <= region.y2));
03359         if (!htdb)
03360             htdb = (bordergeom[5].y <= region.y2);
03361         if (!htdb)
03362             htdb = ((bordergeom[6].x + bordergeom[6].w > region.x1)
03363                   &&(bordergeom[6].y <= region.y2));
03364         if (!htdb)
03365             htdb = (bordergeom[7].x + bordergeom[7].w > region.x1);
03366 
03367         if (htdb) {
03368             // I have to draw the border
03369             DEBUGMSG("MMSGUI", "draw window border");
03370             drawMyBorder();
03371         }
03372     }
03373 
03374     // flip region
03375     if (!this->parent) {
03376         PRINT_LOCK("call flipWindow");
03377         flipWindow(this, &region, MMSFB_FLIP_ONSYNC);
03378         PRINT_LOCK("end flipWindow");
03379     }
03380     else {
03381         if (!stretchmode) {
03382             // normal flip
03383             PRINT_LOCK("call flipWindow");
03384             this->parent->flipWindow(this, &region, MMSFB_FLIP_ONSYNC);
03385             PRINT_LOCK("end flipWindow");
03386         }
03387         else {
03388             // flip src region and call flipWindow with stretched region
03389             MMSFBRegion rg;
03390             rg.x1 = flip_rect.x;
03391             rg.x2 = flip_rect.x + flip_rect.w-1;
03392             rg.y1 = flip_rect.y;
03393             rg.y2 = flip_rect.y + flip_rect.h-1;
03394             this->surface->lock();
03395             PRINT_LOCK("call flip");
03396             this->surface->flip(&rg);
03397             PRINT_LOCK("end flip");
03398             this->surface->unlock();
03399             PRINT_LOCK("call flipWindow");
03400             this->parent->flipWindow(this, &region, MMSFB_FLIP_ONSYNC, false);
03401             PRINT_LOCK("end flipWindow");
03402         }
03403     }
03404 
03405     // unlock drawing
03406 //PUP    this->drawLock.unlock();
03407     unlock();
03408 }
03409 
03410 void MMSWindow::refresh(MMSFBRegion *region) {
03411 
03412     if (!isShown(true)) {
03413         // drawing skipped because window is or it's parents are not shown
03414         return;
03415     }
03416 
03417     // lock drawing
03418 //PUP    this->drawLock.lock();
03419     lock();
03420 
03421     // draw window
03422     setWidgetGeometryOnNextDraw();
03423     if (region) {
03424         // draw a region
03425         MMSFBRectangle rect2update;
03426         rect2update.x = region->x1;
03427         rect2update.y = region->y1;
03428         rect2update.w = region->x2 - region->x1 + 1;
03429         rect2update.h = region->y2 - region->y1 + 1;
03430         draw(false, &rect2update);
03431     }
03432     else {
03433         // draw whole window
03434         draw();
03435     }
03436 
03437     // make it visible
03438     if (!this->parent) {
03439         PRINT_LOCK("call flipWindow");
03440         flipWindow(this, region);
03441         PRINT_LOCK("end flipWindow");
03442     }
03443     else {
03444         PRINT_LOCK("call flipWindow");
03445         this->parent->flipWindow(this, region);
03446         PRINT_LOCK("end flipWindow");
03447     }
03448 
03449     // unlock drawing
03450 //PUP    this->drawLock.unlock();
03451     unlock();
03452 }
03453 
03454 
03455 void MMSWindow::setFocusedWidget(MMSWidget *child, bool set, bool switchfocus, bool refresh) {
03456 //printf("XXX: setFocusedWidget for window %s %x set = %d, switchfocus = %d\n", name.c_str(), this, set, switchfocus);
03457     if (set) {
03458         if (switchfocus) {
03459  //         printf(">>> %x, %x\n", this->focusedwidget, child);
03460             if (child != this->focusedwidget) {
03461                 if (this->focusedwidget)
03462                     this->focusedwidget->setFocus(false, refresh);
03463             }
03464             if (child) {
03465                 if (!child->isFocused()) {
03466                     child->setFocus(true, refresh);
03467                 }
03468             }
03469         }
03470         this->focusedwidget = child;
03471         this->firstfocusset = true;
03472     }
03473     else {
03474         if (child)
03475             if (child->isFocused()) {
03476                 if (switchfocus) {
03477 //                  child->focused = false; ////////////////////////
03478                     child->setFocus(false, refresh);
03479                 }
03480                 this->focusedwidget = NULL;
03481                 this->firstfocusset = false;
03482             }
03483     }
03484 
03485     switchArrowWidgets();
03486 }
03487 
03488 bool MMSWindow::setFirstFocus(bool cw) {
03489 //printf("XXX: setFirstFocus1 to %s %x\n", name.c_str(), this);
03490 
03491 
03492     // per default only main or root windows can get inputs
03493     // popup windows can get inputs if the modal mode is set
03494     // child windows get the inputs from the parent main, root or popup window
03495     switch (getType()) {
03496         case MMSWINDOWTYPE_MAINWINDOW:
03497         case MMSWINDOWTYPE_ROOTWINDOW:
03498             break;
03499         case MMSWINDOWTYPE_POPUPWINDOW: {
03500             bool modal;
03501             if (getModal(modal)) {
03502                 if (modal)
03503                     this->windowmanager->setToplevelWindow(this);
03504             }
03505             break;
03506         }
03507         case MMSWINDOWTYPE_CHILDWINDOW:
03508             if (!cw) return false;
03509 //printf ("parent->focusedChildWin %d\n", parent->focusedChildWin);
03510 //printf ("parent->focusedwidget %d\n", this->focusedwidget);
03511             break;
03512         default:
03513             return false;
03514     }
03515 
03516 //printf("XXX: setFirstFocus2 to %s\n", name.c_str());
03517     DEBUGMSG("MMSGUI", "MMSWindow: setFirstFocus to " + getName());
03518 
03519     if (this->firstfocusset) {
03520 //printf("XXX: setFirstFocus2.2 to %s\n", name.c_str());
03521         DEBUGMSG("MMSGUI", "MMSWindow: focus already set");
03522         return true;
03523     }
03524     this->firstfocusset = true;
03525     bool b;
03526 
03527 //printf("XXX: setFirstFocus3 to %s\n", name.c_str());
03528 
03529     if(this->children.empty()) {
03530         bool found = false;
03531 
03532         for (unsigned int j = 0; j < this->childwins.size(); j++) {
03533             MMSWindow *w = this->childwins.at(j).window;
03534             if (!w->shown && !w->willshow) {
03535 //printf("XXX: setFirstFocus3.1 to %s -> childwin %s %d %d %d\n", name.c_str(), w->name.c_str(), w->buffered_shown, w->shown, w->willshow);
03536                 continue;
03537             }
03538 
03539 //printf("XXX: setFirstFocus4 to %s -> childwin %s\n", name.c_str(), w->name.c_str());
03540 
03541             if (w->getNumberOfFocusableWidgets()) {
03542 //printf("XXX: setFirstFocus5 to %s -> childwin %s %d\n", name.c_str(), w->name.c_str(), j);
03543                 /* widgets found which can be focused */
03544                 this->focusedChildWin = j;
03545                 found = true;
03546                 if (!w->firstfocusset) {
03547 //printf("XXX: setFirstFocus6 to %s -> childwin %s\n", name.c_str(), w->name.c_str());
03548                     for(unsigned int i=0;i<w->children.size();i++) {
03549                         if(w->children.at(i)->getFocusable(b))
03550                             if (b) {
03551                                 DEBUGMSG("MMSGUI", "MMSWindow: set focus to child nr " + iToStr(i));
03552                                 string inputmode = "";
03553                                 w->children.at(i)->getInputModeEx(inputmode);
03554                                 if (strToUpr(inputmode) != "CLICK") {
03555 //printf("XXX: setFirstFocus7 to %s -> childwin %s\n", name.c_str(), w->name.c_str());
03556                                     w->children.at(i)->setFocus(true, false);
03557                                 }
03558                                 else {
03559                                     w->children.at(i)->setFocus(false, false);
03560                                 }
03561                                 w->firstfocusset = true;
03562                                 this->childwins.at(j).focusedWidget = i;
03563                                 return true;
03564                             }
03565                     }
03566                 }
03567                 break;
03568             }
03569             else
03570             if (w->getNumberOfFocusableChildWins()) {
03571                 /* child windows found which have focusable widgets */
03572                 this->focusedChildWin = j;
03573                 found = true;
03574                 if (!w->firstfocusset) {
03575                     for(unsigned int i=0;i<w->childwins.size();i++) {
03576                         if (w->childwins.at(i).window->setFirstFocus(true))
03577                             return true;
03578                     }
03579                 }
03580                 break;
03581             }
03582         }
03583 
03584         if (found) {
03585             static bool again;
03586 
03587             if (!again) {
03588                  int fd = open( "/dev/kmsg", O_WRONLY );
03589 
03590                  if (fd >= 0) {
03591                       char msg[] = "MMSWindow::setFirstFocus() found first focus\n";
03592 
03593                       write( fd, msg, sizeof(msg) );
03594                       close( fd );
03595                  }
03596 
03597                  if (getenv( "MMS_EXIT_ON_FIRST_FOCUS" ))
03598                      exit(0);
03599 
03600                  again = true;
03601             }
03602             return true;
03603         }
03604 
03605         DEBUGMSG("MMSGUI", "MMSWindow: no children to focus for window " + getName());
03606         return false;
03607     }
03608 
03609 
03610     for(unsigned int i=0;i<this->children.size();i++) {
03611         if(this->children.at(i)->getFocusable(b))
03612             if (b) {
03613                 DEBUGMSG("MMSGUI", "MMSWindow: set focus to child nr " + iToStr(i));
03614                 string inputmode = "";
03615                 this->children.at(i)->getInputModeEx(inputmode);
03616                 if (strToUpr(inputmode) != "CLICK")
03617                     this->children.at(i)->setFocus(true);
03618                 return true;
03619             }
03620     }
03621 
03622     DEBUGMSG("MMSGUI", "MMSWindow: no children to focus for window " + getName());
03623     return false;
03624 }
03625 
03626 
03627 
03628 #define MAXDGCODE   999999
03629 
03630 /* a lower return value is better than an higher value */
03631 double MMSWindow::calculateDistGradCode_Up(MMSFBRectangle currPos, MMSFBRectangle candPos) {
03632 
03633     MMSFB_BREAK();
03634 
03635     /* check if candidate is over the current widget */
03636     if (candPos.y >= currPos.y)
03637         /* no */
03638         return MAXDGCODE;
03639 
03640     /* create some vector points */
03641     double w1 = (double)candPos.x;                          // left border to left border
03642            w1-= (double)currPos.x;
03643     double w2 = (double)candPos.x + (double)candPos.w - 1;  // right border to right border
03644            w2-= (double)currPos.x + (double)currPos.w - 1;
03645     double w3 = (double)candPos.x + ((double)candPos.w / 2);// middle to middle
03646            w3-= (double)currPos.x + ((double)currPos.w / 2);
03647     double h  = (double)candPos.y + ((double)candPos.h / 2);// height
03648            h -= (double)currPos.y + ((double)currPos.h / 2);
03649 
03650     /* if the candidate is direct over the current widget and candidate width is equal or greater */
03651     if ((w1 - (double)currPos.w / 2 <= 0) && (w2 + (double)currPos.w / 2 >= 0)) {
03652         /* then set the gradient of the middle vector to zero */
03653         w3 = 0;
03654 
03655         /* set smallest possible height */
03656         h = 0 - ((double)currPos.y - ((double)candPos.y + (double)candPos.h - 1));
03657     }
03658 
03659     /* check if correct quadrant */
03660     if (h >= 0)
03661         return MAXDGCODE;
03662 
03663     /* get absolute values */
03664     w1 = fabs(w1);
03665     w2 = fabs(w2);
03666     w3 = fabs(w3);
03667     h  = fabs(h);
03668 
03669     /* temporary storage for distance */
03670     double dist;
03671 
03672     /* temporary result storage */
03673     double dgcode1, dgcode2;
03674 
03675     /* work with left vector */
03676     dist = sqrt(w1*w1 + h*h);
03677     if (w1 <= h) {
03678         /* calc the gradient and the result code */
03679         double grad = w1 / h;
03680         dgcode1 = dist / (1 - grad);
03681     }
03682     else
03683         /* the grad is higher than 1 and will be ignored */
03684         dgcode1 = MAXDGCODE-MAXDGCODE/2+dist;
03685 
03686     /* work with right vector */
03687     dist = sqrt(w2*w2 + h*h);
03688     if (w2 <= h) {
03689         /* calc the gradient and the result code */
03690         double grad = w2 / h;
03691         dgcode2 = dist / (1 - grad);
03692     }
03693     else
03694         /* the grad is higher than 1 and will be ignored */
03695         dgcode2 = MAXDGCODE-MAXDGCODE/2+dist;
03696 
03697     /* take the smallest value */
03698     if (dgcode1 > dgcode2)
03699         dgcode1 = dgcode2;
03700 
03701     /* work with middle vector */
03702     dist = sqrt(w3*w3 + h*h);
03703     if (w3 <= h) {
03704         /* calc the gradient and the result code */
03705         double grad = w3 / h;
03706         dgcode2 = dist / (1 - grad);
03707     }
03708     else
03709         /* the grad is higher than 1 and will be ignored */
03710         dgcode2 = MAXDGCODE-MAXDGCODE/2+dist;
03711 
03712     /* return with the smallest value */
03713     if (dgcode1 < dgcode2)
03714         return dgcode1;
03715 
03716     /* return the result */
03717     return dgcode2;
03718 }
03719 
03720 
03721 /* a lower return value is better than an higher value */
03722 double MMSWindow::calculateDistGradCode_Down(MMSFBRectangle currPos, MMSFBRectangle candPos) {
03723 
03724     /* check if candidate is under the current widget */
03725     if (candPos.y + candPos.h - 1 <= currPos.y + currPos.h - 1)
03726         /* no */
03727         return MAXDGCODE;
03728 
03729     /* create some vector points */
03730     double w1 = (double)candPos.x;                          // left border to left border
03731            w1-= (double)currPos.x;
03732     double w2 = (double)candPos.x + (double)candPos.w - 1;  // right border to right border
03733            w2-= (double)currPos.x + (double)currPos.w - 1;
03734     double w3 = (double)candPos.x + ((double)candPos.w / 2);// middle to middle
03735            w3-= (double)currPos.x + ((double)currPos.w / 2);
03736     double h  = (double)candPos.y + ((double)candPos.h / 2);// height
03737            h -= (double)currPos.y + ((double)currPos.h / 2);
03738 
03739     /* if the candidate is direct under the current widget and candidate width is equal or greater */
03740     if ((w1 - (double)currPos.w / 2 <= 0) && (w2 + (double)currPos.w / 2 >= 0)) {
03741         /* then set the gradient of the middle vector to zero */
03742         w3 = 0;
03743 
03744         /* set smallest possible height */
03745         h = (double)candPos.y - ((double)currPos.y + (double)currPos.h - 1);
03746     }
03747 
03748     /* check if correct quadrant */
03749     if (h <= 0)
03750         return MAXDGCODE;
03751 
03752     /* get absolute values */
03753     w1 = fabs(w1);
03754     w2 = fabs(w2);
03755     w3 = fabs(w3);
03756     h  = fabs(h);
03757 
03758     /* temporary storage for distance */
03759     double dist;
03760 
03761     /* temporary result storage */
03762     double dgcode1, dgcode2;
03763 
03764     /* work with left vector */
03765     dist = sqrt(w1*w1 + h*h);
03766     if (w1 <= h) {
03767         /* calc the gradient and the result code */
03768         double grad = w1 / h;
03769         dgcode1 = dist / (1 - grad);
03770     }
03771     else
03772         /* the grad is higher than 1 and will be ignored */
03773         dgcode1 = MAXDGCODE-MAXDGCODE/2+dist;
03774 
03775     /* work with right vector */
03776     dist = sqrt(w2*w2 + h*h);
03777     if (w2 <= h) {
03778         /* calc the gradient and the result code */
03779         double grad = w2 / h;
03780         dgcode2 = dist / (1 - grad);
03781     }
03782     else
03783         /* the grad is higher than 1 and will be ignored */
03784         dgcode2 = MAXDGCODE-MAXDGCODE/2+dist;
03785 
03786     /* take the smallest value */
03787     if (dgcode1 > dgcode2)
03788         dgcode1 = dgcode2;
03789 
03790     /* work with middle vector */
03791     dist = sqrt(w3*w3 + h*h);
03792     if (w3 <= h) {
03793         /* calc the gradient and the result code */
03794         double grad = w3 / h;
03795         dgcode2 = dist / (1 - grad);
03796     }
03797     else
03798         /* the grad is higher than 1 and will be ignored */
03799         dgcode2 = MAXDGCODE-MAXDGCODE/2+dist;
03800 
03801     /* return with the smallest value */
03802     if (dgcode1 < dgcode2)
03803         return dgcode1;
03804 
03805     /* return the result */
03806     return dgcode2;
03807 }
03808 
03809 
03810 /* a lower return value is better than an higher value */
03811 double MMSWindow::calculateDistGradCode_Left(MMSFBRectangle currPos, MMSFBRectangle candPos) {
03812 
03813     /* check if candidate is left of the current widget */
03814     if (candPos.x >= currPos.x)
03815         return MAXDGCODE;
03816 
03817     /* create some vector points */
03818     double h1 = (double)candPos.y;                          // top border to top border
03819            h1-= (double)currPos.y;
03820     double h2 = (double)candPos.y + (double)candPos.h - 1;  // bottom border to bottom border
03821            h2-= (double)currPos.y + (double)currPos.h - 1;
03822     double h3 = (double)candPos.y + ((double)candPos.h / 2);// middle to middle
03823            h3-= (double)currPos.y + ((double)currPos.h / 2);
03824     double w  = (double)candPos.x + ((double)candPos.w / 2);// width
03825            w -= (double)currPos.x + ((double)currPos.w / 2);
03826 
03827     /* if the candidate is direct left of the current widget and candidate width is equal or greater */
03828     if ((h1 - (double)currPos.h / 2 <= 0) && (h2 + (double)currPos.h / 2 >= 0)) {
03829         /* then set the gradient of the middle vector to zero */
03830         h3 = 0;
03831 
03832         /* set smallest possible width */
03833         w = 0-((double)currPos.x - ((double)candPos.x + (double)candPos.w - 1));
03834     }
03835 
03836     /* check if correct quadrant */
03837     if (w >= 0)
03838         return MAXDGCODE;
03839 
03840     /* get absolute values */
03841     h1 = fabs(h1);
03842     h2 = fabs(h2);
03843     h3 = fabs(h3);
03844     w  = fabs(w);
03845 
03846     /* temporary storage for distance */
03847     double dist;
03848 
03849     /* temporary result storage */
03850     double dgcode1, dgcode2;
03851 
03852     /* work with top vector */
03853     dist = sqrt(h1*h1 + w*w);
03854     if (h1 <= w) {
03855         /* calc the gradient and the result code */
03856         double grad = h1 / w;
03857         dgcode1 = dist / (1 - grad);
03858     }
03859     else
03860         /* the grad is higher than 1 and will be ignored */
03861         dgcode1 = MAXDGCODE-MAXDGCODE/2+dist;
03862 
03863     /* work with bottom vector */
03864     dist = sqrt(h2*h2 + w*w);
03865     if (h2 <= w) {
03866         /* calc the gradient and the result code */
03867         double grad = h2 / w;
03868         dgcode2 = dist / (1 - grad);
03869     }
03870     else
03871         /* the grad is higher than 1 and will be ignored */
03872         dgcode2 = MAXDGCODE-MAXDGCODE/2+dist;
03873 
03874     /* take the smallest value */
03875     if (dgcode1 > dgcode2)
03876         dgcode1 = dgcode2;
03877 
03878     /* work with middle vector */
03879     dist = sqrt(h3*h3 + w*w);
03880     if (h3 <= w) {
03881         /* calc the gradient and the result code */
03882         double grad = h3 / w;
03883         dgcode2 = dist / (1 - grad);
03884     }
03885     else
03886         /* the grad is higher than 1 and will be ignored */
03887         dgcode2 = MAXDGCODE-MAXDGCODE/2+dist;
03888 
03889     /* return with the smallest value */
03890     if (dgcode1 < dgcode2)
03891         return dgcode1;
03892 
03893     /* return the result */
03894     return dgcode2;
03895 }
03896 
03897 
03898 /* a lower return value is better than an higher value */
03899 double MMSWindow::calculateDistGradCode_Right(MMSFBRectangle currPos, MMSFBRectangle candPos) {
03900 
03901     /* check if candidate is right of the current widget */
03902     if (candPos.x + candPos.w - 1 <= currPos.x + currPos.w - 1)
03903         return MAXDGCODE;
03904 
03905     /* create some vector points */
03906     double h1 = (double)candPos.y;                          // top border to top border
03907            h1-= (double)currPos.y;
03908     double h2 = (double)candPos.y + (double)candPos.h - 1;  // bottom border to bottom border
03909            h2-= (double)currPos.y + (double)currPos.h - 1;
03910     double h3 = (double)candPos.y + ((double)candPos.h / 2);// middle to middle
03911            h3-= (double)currPos.y + ((double)currPos.h / 2);
03912     double w  = (double)candPos.x + ((double)candPos.w / 2);// width
03913            w -= (double)currPos.x + ((double)currPos.w / 2);
03914 
03915     /* if the candidate is direct right of the current widget and candidate width is equal or greater */
03916     if ((h1 - (double)currPos.h / 2 <= 0) && (h2 + (double)currPos.h / 2 >= 0)) {
03917         /* then set the gradient of the middle vector to zero */
03918         h3 = 0;
03919 
03920         /* set smallest possible width */
03921         w = (double)candPos.x - ((double)currPos.x + (double)currPos.w - 1);
03922     }
03923 
03924     /* check if correct quadrant */
03925     if (w <= 0)
03926         return MAXDGCODE;
03927 
03928     /* get absolute values */
03929     h1 = fabs(h1);
03930     h2 = fabs(h2);
03931     h3 = fabs(h3);
03932     w  = fabs(w);
03933 
03934     /* temporary storage for distance */
03935     double dist;
03936 
03937     /* temporary result storage */
03938     double dgcode1, dgcode2;
03939 
03940     /* work with top vector */
03941     dist = sqrt(h1*h1 + w*w);
03942     if (h1 <= w) {
03943         /* calc the gradient and the result code */
03944         double grad = h1 / w;
03945         dgcode1 = dist / (1 - grad);
03946     }
03947     else
03948         /* the grad is higher than 1 and will be ignored */
03949         dgcode1 = MAXDGCODE-MAXDGCODE/2+dist;
03950 
03951     /* work with bottom vector */
03952     dist = sqrt(h2*h2 + w*w);
03953     if (h2 <= w) {
03954         /* calc the gradient and the result code */
03955         double grad = h2 / w;
03956         dgcode2 = dist / (1 - grad);
03957     }
03958     else
03959         /* the grad is higher than 1 and will be ignored */
03960         dgcode2 = MAXDGCODE-MAXDGCODE/2+dist;
03961 
03962     /* take the smallest value */
03963     if (dgcode1 > dgcode2)
03964         dgcode1 = dgcode2;
03965 
03966     /* work with middle vector */
03967     dist = sqrt(h3*h3 + w*w);
03968     if (h3 <= w) {
03969         /* calc the gradient and the result code */
03970         double grad = h3 / w;
03971         dgcode2 = dist / (1 - grad);
03972     }
03973     else
03974         /* the grad is higher than 1 and will be ignored */
03975         dgcode2 = MAXDGCODE-MAXDGCODE/2+dist;
03976 
03977     /* return with the smallest value */
03978     if (dgcode1 < dgcode2)
03979         return dgcode1;
03980 
03981     /* return the result */
03982     return dgcode2;
03983 }
03984 
03985 
03986 bool MMSWindow::handleNavigationForWidgets(MMSInputEvent *inputevent) {
03987     MMSWidget *candidate = NULL;
03988 
03989     /* if no focused widget then return */
03990     if (!this->focusedwidget)
03991         return false;
03992 
03993     if (inputevent->type == MMSINPUTEVENTTYPE_KEYPRESS) {
03994         /* keyboard inputs */
03995 
03996         /* check if widget names for navigation are set to the focused widget */
03997         switch (inputevent->key) {
03998             case MMSKEY_CURSOR_DOWN:
03999                 candidate = this->focusedwidget->getNavigateDownWidget();
04000                 break;
04001             case MMSKEY_CURSOR_UP:
04002                 candidate = this->focusedwidget->getNavigateUpWidget();
04003                 break;
04004             case MMSKEY_CURSOR_RIGHT:
04005                 candidate = this->focusedwidget->getNavigateRightWidget();
04006                 break;
04007             case MMSKEY_CURSOR_LEFT:
04008                 candidate = this->focusedwidget->getNavigateLeftWidget();
04009                 break;
04010 
04011             default:
04012                 break;
04013         }
04014     }
04015     else {
04016         /* other inputs */
04017     }
04018 
04019     if (candidate) {
04020         /* i found a new widget */
04021         if (candidate->getId() != this->focusedwidget->getId()) {
04022             /* different from current focus */
04023             this->focusedwidget->setFocus(false);
04024             candidate->setFocus(true, true, inputevent);
04025             return true;
04026         }
04027     }
04028 
04029     return false;
04030 }
04031 
04032 
04033 
04034 void MMSWindow::removeChildWinFocus() {
04035     if (this->childwins.size() > this->focusedChildWin) {
04036 
04037         /* get the focused childwin */
04038         MMSWindow *fWin = this->childwins.at(this->focusedChildWin).window;
04039 
04040         if (!fWin->children.empty()) {
04041             /* save focused widget from current window and remove the focus */
04042             for(unsigned int i=0;i<fWin->children.size();i++) {
04043                 if(fWin->children.at(i)->isFocused()) {
04044                     try {
04045                         childwins.at(this->focusedChildWin).focusedWidget = i;
04046                     } catch (std::exception&) {
04047                     }
04048                     fWin->children.at(i)->setFocus(false);
04049 
04050                     /* set the arrow widgets */
04051                     fWin->switchArrowWidgets();
04052 
04053                     break;
04054                 }
04055             }
04056         }
04057         else {
04058             /* recursive to my focused childwin */
04059             fWin->removeChildWinFocus();
04060         }
04061     }
04062 }
04063 
04064 bool MMSWindow::restoreChildWinFocus(MMSInputEvent *inputevent) {
04065 
04066     if (this->childwins.size() > this->focusedChildWin) {
04067 
04068         /* get the focused childwin */
04069         MMSWindow *fWin = this->childwins.at(this->focusedChildWin).window;
04070 
04071         /* check if something to focus */
04072         if (!fWin->getNumberOfFocusableWidgets())
04073             if (!fWin->getNumberOfFocusableChildWins())
04074                 return false;
04075 
04076         if (!fWin->children.empty()) {
04077             /* restore focused widget to candidate window */
04078             bool b;
04079             if (!fWin->children.at(this->childwins.at(this->focusedChildWin).focusedWidget)->getFocusable(b))
04080                 b = false;
04081 
04082             if (b) {
04083                 string inputmode = "";
04084                 fWin->children.at(this->childwins.at(this->focusedChildWin).focusedWidget)->getInputModeEx(inputmode);
04085                 if (strToUpr(inputmode) != "CLICK") {
04086                     fWin->children.at(this->childwins.at(this->focusedChildWin).focusedWidget)->setFocus(true, true, inputevent);
04087                 }
04088             }
04089             else {
04090                 /* last focusable widget is not focusable anymore, search other widget to focus */
04091                 for(unsigned int i=0;i<fWin->children.size();i++) {
04092                     if(fWin->children.at(i)->getFocusable(b))
04093                         if (b) {
04094                             this->childwins.at(this->focusedChildWin).focusedWidget = i;
04095 
04096                             string inputmode = "";
04097                             fWin->children.at(i)->getInputModeEx(inputmode);
04098                             if (strToUpr(inputmode) != "CLICK") {
04099                                 fWin->children.at(i)->setFocus(true, true, inputevent);
04100                             }
04101 
04102                             break;
04103                         }
04104                 }
04105             }
04106 
04107             /* set the arrow widgets */
04108             fWin->switchArrowWidgets();
04109         }
04110         else {
04111             /* recursive to my focused childwin */
04112             if (!fWin->restoreChildWinFocus(inputevent)) {
04113 
04114                 /* nothing to focus, searching for other childwin */
04115                 for(unsigned int i = 0; i < fWin->childwins.size(); i++) {
04116                     if (i == fWin->focusedChildWin)
04117                         continue;
04118 
04119                     /* found */
04120                     fWin->focusedChildWin = i;
04121 
04122                     /* next try */
04123                     if (fWin->restoreChildWinFocus(inputevent))
04124                         /* okay */
04125                         return true;
04126                     else
04127                         /* try with next */
04128                         continue;
04129                 }
04130 
04131                 /* no childwin found, reset the focus to the first childwin */
04132                 fWin->focusedChildWin = 0;
04133                 return false;
04134             }
04135         }
04136     }
04137 
04138     return true;
04139 }
04140 
04141 
04142 void MMSWindow::setFocus() {
04143 
04144 //printf("MMSWindow::setFocus %08x, %s\n", this, name.c_str());
04145 
04146     // i do only work for child windows
04147     if (!this->parent) return;
04148 
04149     // check if focusable
04150     bool focusable = false;
04151     getFocusable(focusable);
04152     if (!focusable) return;
04153 
04154     // searching me
04155     int me = -1;
04156     for (unsigned int i = 0; i < this->parent->childwins.size(); i++)
04157         if (this->parent->childwins.at(i).window == this) {
04158             me = i;
04159             break;
04160         }
04161 
04162 //printf("setFocus2 %s\n", name.c_str());
04163 
04164     // found within parents list?
04165     if (me < 0) return;
04166 
04167 //printf("setFocus3 %s, %d, %d, parent = %s\n", name.c_str(), this->parent->focusedChildWin, me, this->parent->name.c_str());
04168 
04169     // check if shown
04170     if (!this->isShown() && !this->willshow) {
04171         this->show();
04172         this->waitUntilShown();
04173     }
04174 
04175     // currently focused child window?
04176     if ((int)this->parent->focusedChildWin == me) return;
04177 
04178 //printf("setFocus4 %s\n", name.c_str());
04179 
04180     // save focused widget from current window and remove the focus
04181     this->parent->removeChildWinFocus();
04182 
04183     // i am the new focused window
04184     this->parent->focusedChildWin = me;
04185 
04186     // restore focused widget to candidate window
04187     this->parent->restoreChildWinFocus();
04188 
04189     // change the z-order of child windows?
04190     bool staticzorder = false;
04191     this->parent->getStaticZOrder(staticzorder);
04192     if (!staticzorder) {
04193         PRINT_LOCK("call raiseToTop");
04194         raiseToTop(0);
04195     }
04196 }
04197 
04198 bool MMSWindow::getFocus(bool checkparents) {
04199     // check if i am a child window
04200     if (!this->parent) {
04201         if (windowmanager->getToplevelWindow() == this)
04202             return true;
04203         else
04204             return false;
04205     }
04206 
04207     // search me
04208     int me = -1;
04209     for (unsigned int i = 0; i < this->parent->childwins.size(); i++)
04210         if (this->parent->childwins.at(i).window == this) {
04211             me = i;
04212             break;
04213         }
04214 
04215     // i have found me within my parents list
04216     if (me < 0) return false;
04217 
04218     // i am the currently focused child window?
04219     if ((int)this->parent->focusedChildWin == me) {
04220         if (checkparents)
04221             return this->parent->getFocus(checkparents);
04222         else
04223             return true;
04224     }
04225     else
04226         return false;
04227 }
04228 
04229 bool MMSWindow::handleNavigationForChildWins(MMSInputEvent *inputevent) {
04230     MMSWindow *candidate = NULL;
04231     int cand=-1;
04232 
04233     /* check if I have child windows */
04234     if (!(this->childwins.size() > this->focusedChildWin))
04235         return false;
04236 
04237     /* get access to the focused child window */
04238     MMSWindow *fWin = this->childwins.at(this->focusedChildWin).window;
04239 
04240     if (inputevent->type == MMSINPUTEVENTTYPE_KEYPRESS) {
04241         /* keyboard inputs */
04242 
04243         /* check if window names for navigation are set to the focused child window */
04244         switch (inputevent->key) {
04245             case MMSKEY_CURSOR_DOWN:
04246                 candidate = fWin->getNavigateDownWindow();
04247                 break;
04248             case MMSKEY_CURSOR_UP:
04249                 candidate = fWin->getNavigateUpWindow();
04250                 break;
04251             case MMSKEY_CURSOR_RIGHT:
04252                 candidate = fWin->getNavigateRightWindow();
04253                 break;
04254             case MMSKEY_CURSOR_LEFT:
04255                 candidate = fWin->getNavigateLeftWindow();
04256                 break;
04257 
04258             default:
04259                 break;
04260         }
04261     }
04262     else {
04263         /* other inputs */
04264 
04265     }
04266 
04267     if (candidate) {
04268         /* check if candidate has something to focus */
04269         if (!candidate->getNumberOfFocusableWidgets())
04270             if (!candidate->getNumberOfFocusableChildWins())
04271                 return false;
04272 
04273         /* i found a new window */
04274         if (candidate != fWin) {
04275             /* different from current focus */
04276             for(unsigned int i = 0; i < this->childwins.size(); i++) {
04277                 if (childwins.at(i).window == candidate) {
04278                     cand = i;
04279                     break;
04280                 }
04281             }
04282             if (cand < 0)
04283                 return false;
04284 
04285             /* save focused widget from current window and remove the focus */
04286             removeChildWinFocus();
04287 
04288             /* new focused window */
04289             this->focusedChildWin = cand;
04290 
04291             /* restore focused widget to candidate window */
04292             restoreChildWinFocus(inputevent);
04293 
04294             return true;
04295         }
04296     }
04297 
04298     return false;
04299 }
04300 
04301 
04302 void MMSWindow::preCalcNavigation() {
04303 
04304     preCalcNaviLock.lock();
04305 
04306     if (!this->children.empty()) {
04307         /* for each focusable widget */
04308         for(unsigned int k = 0; k < this->children.size(); k++) {
04309             /* simulate that this widget has the focus */
04310             MMSWidget *fwidget = children.at(k);
04311             bool    b;
04312             string  s;
04313 
04314             if (!fwidget->getFocusable(b))
04315                 continue;
04316             if (!b)
04317                 continue;
04318 
04319             /* for up, down, left right keys */
04320             for(unsigned int j = 0; j < 4; j++) {
04321                 MMSKeySymbol key = MMSKEY_NULL;
04322                 switch (j) {
04323                     case 0:
04324                         key = MMSKEY_CURSOR_UP;
04325                         break;
04326                     case 1:
04327                         key = MMSKEY_CURSOR_DOWN;
04328                         break;
04329                     case 2:
04330                         key = MMSKEY_CURSOR_LEFT;
04331                         break;
04332                     case 3:
04333                         key = MMSKEY_CURSOR_RIGHT;
04334                         break;
04335                 }
04336 
04337                 /* searching for next widget to become the focus */
04338                 MMSFBRectangle fGeom = fwidget->getGeometry();
04339                 MMSWidget *candidate = NULL;
04340                 double dgcode = MAXDGCODE;
04341 
04342                 for(unsigned int i = 0; i < this->children.size(); i++) {
04343                     /* get widget */
04344                     MMSWidget *widget = children.at(i);
04345 
04346                     /* not for already focused widget */
04347                     if (i != k) {
04348                         /* its not the already focused one */
04349                         if (widget->getFocusable(b))
04350                             if (b) {
04351                                 /* basically it can be focused */
04352                                 MMSFBRectangle wGeom = widget->getGeometry();
04353                                 double cand_dgcode = MAXDGCODE;
04354 
04355                                 if (key == MMSKEY_CURSOR_DOWN)
04356                                     cand_dgcode = calculateDistGradCode_Down(fGeom, wGeom);
04357                                 else
04358                                 if (key == MMSKEY_CURSOR_UP)
04359                                     cand_dgcode = calculateDistGradCode_Up(fGeom, wGeom);
04360                                 else
04361                                 if (key == MMSKEY_CURSOR_RIGHT)
04362                                     cand_dgcode = calculateDistGradCode_Right(fGeom, wGeom);
04363                                 else
04364                                 if (key == MMSKEY_CURSOR_LEFT)
04365                                     cand_dgcode = calculateDistGradCode_Left(fGeom, wGeom);
04366 
04367                                 /* new candidate? */
04368                                 if (cand_dgcode < dgcode) {
04369                                     /* yes, make it to my new candidate */
04370                                     candidate = widget;
04371                                     dgcode = cand_dgcode;
04372                                 }
04373                             }
04374                     }
04375                 }
04376 
04377                 if (candidate) {
04378                     /* i found a new widget */
04379                     if (key == MMSKEY_CURSOR_DOWN) {
04380                         if (!fwidget->getNavigateDown(s))
04381                             fwidget->setNavigateDownWidget(candidate);
04382                         else
04383                             if (s == "")
04384                                 fwidget->setNavigateDownWidget(candidate);
04385                     } else
04386                     if (key == MMSKEY_CURSOR_UP) {
04387                         if (!fwidget->getNavigateUp(s))
04388                             fwidget->setNavigateUpWidget(candidate);
04389                         else
04390                             if (s == "")
04391                                 fwidget->setNavigateUpWidget(candidate);
04392                     } else
04393                     if (key == MMSKEY_CURSOR_RIGHT) {
04394                         if (!fwidget->getNavigateRight(s))
04395                             fwidget->setNavigateRightWidget(candidate);
04396                         else
04397                             if (s == "")
04398                                 fwidget->setNavigateRightWidget(candidate);
04399                     } else
04400                     if (key == MMSKEY_CURSOR_LEFT) {
04401                         if (!fwidget->getNavigateLeft(s))
04402                             fwidget->setNavigateLeftWidget(candidate);
04403                         else
04404                             if (s == "")
04405                                 fwidget->setNavigateLeftWidget(candidate);
04406                     }
04407                 }
04408             }
04409         }
04410     }
04411     else {
04412         /* no widgets, work for child windows */
04413         /* for each child window which have focusable widgets or child windows */
04414         for(unsigned int k = 0; k < this->childwins.size(); k++) {
04415             /* simulate that this window has the focus */
04416             MMSWindow *fWin = this->childwins.at(k).window;
04417 
04418             /* only for visible windows */
04419             if (!fWin->isShown())
04420                 continue;
04421 
04422             /* search for shown parent */
04423             MMSWindow *p = this->parent;
04424             while (p) {
04425                 if (!p->parent) {
04426                     p = NULL;
04427                     break;
04428                 }
04429                 if (!p->isShown())
04430                     break;
04431                 p = p->parent;
04432             }
04433             if (p)
04434                 continue;
04435 
04436             /* check if i have something to focus */
04437             if (!fWin->getNumberOfFocusableWidgets())
04438                 if (!fWin->getNumberOfFocusableChildWins())
04439                     continue;
04440 
04441             /* for up, down, left right keys */
04442             for(unsigned int j = 0; j < 4; j++) {
04443                 MMSKeySymbol key = MMSKEY_NULL;
04444                 switch (j) {
04445                     case 0:
04446                         key = MMSKEY_CURSOR_UP;
04447                         break;
04448                     case 1:
04449                         key = MMSKEY_CURSOR_DOWN;
04450                         break;
04451                     case 2:
04452                         key = MMSKEY_CURSOR_LEFT;
04453                         break;
04454                     case 3:
04455                         key = MMSKEY_CURSOR_RIGHT;
04456                         break;
04457                 }
04458 
04459 
04460                 /* searching for child window to become the focus */
04461                 MMSFBRectangle fGeom;
04462                 fGeom.x = fWin->geom.x;
04463                 fGeom.y = fWin->geom.y;
04464                 fGeom.w = fWin->geom.w;
04465                 fGeom.h = fWin->geom.h;
04466                 MMSWindow *candidate = NULL;
04467                 double dgcode = MAXDGCODE;
04468 
04469                 for(unsigned int i = 0; i < this->childwins.size(); i++) {
04470                     /* get window */
04471                     MMSWindow *window = childwins.at(i).window;
04472 
04473                     /* only for visible windows */
04474                     if (!window->isShown())
04475                         continue;
04476 
04477                     /* not for already focused window */
04478                     if (i != k) {
04479                         /* its not the already focused one */
04480                         int fwd = window->getNumberOfFocusableWidgets();
04481                         int fwn = window->getNumberOfFocusableChildWins();
04482                         if ((fwd>0)||(fwn>0)) {
04483                             /* basically it can be focused */
04484                             MMSFBRectangle wGeom;
04485                             wGeom.x = window->geom.x;
04486                             wGeom.y = window->geom.y;
04487                             wGeom.w = window->geom.w;
04488                             wGeom.h = window->geom.h;
04489                             double cand_dgcode = MAXDGCODE;
04490 
04491                             if (key == MMSKEY_CURSOR_DOWN)
04492                                 cand_dgcode = calculateDistGradCode_Down(fGeom, wGeom);
04493                             else
04494                             if (key == MMSKEY_CURSOR_UP)
04495                                 cand_dgcode = calculateDistGradCode_Up(fGeom, wGeom);
04496                             else
04497                             if (key == MMSKEY_CURSOR_RIGHT)
04498                                 cand_dgcode = calculateDistGradCode_Right(fGeom, wGeom);
04499                             else
04500                             if (key == MMSKEY_CURSOR_LEFT)
04501                                 cand_dgcode = calculateDistGradCode_Left(fGeom, wGeom);
04502 
04503                             /* new candidate? */
04504                             if (cand_dgcode < dgcode) {
04505                                 /* yes, make it to my new candidate */
04506                                 candidate = window;
04507                                 dgcode = cand_dgcode;
04508 
04509                                 if (fwn>0) {
04510                                     preCalcNaviLock.unlock();
04511                                     window->preCalcNavigation();
04512                                     preCalcNaviLock.lock();
04513                                 }
04514                             }
04515                         }
04516                     }
04517                 }
04518 
04519                 /* i found a new window */
04520                 if (key == MMSKEY_CURSOR_DOWN) {
04521                     string s;
04522                     if (!fWin->getNavigateDown(s)) s = "";
04523                     if (s == "")
04524                         fWin->setNavigateDownWindow(candidate);
04525                 } else
04526                 if (key == MMSKEY_CURSOR_UP) {
04527                     string s;
04528                     if (!fWin->getNavigateUp(s)) s = "";
04529                     if (s == "")
04530                         fWin->setNavigateUpWindow(candidate);
04531                 } else
04532                 if (key == MMSKEY_CURSOR_RIGHT) {
04533                     string s;
04534                     if (!fWin->getNavigateRight(s)) s = "";
04535                     if (s == "")
04536                         fWin->setNavigateRightWindow(candidate);
04537                 } else
04538                 if (key == MMSKEY_CURSOR_LEFT) {
04539                     string s;
04540                     if (!fWin->getNavigateLeft(s)) s = "";
04541                     if (s == "")
04542                         fWin->setNavigateLeftWindow(candidate);
04543                 }
04544             }
04545         }
04546     }
04547 
04548     preCalcNaviLock.unlock();
04549 }
04550 
04551 
04552 bool MMSWindow::handleInput(MMSInputEvent *inputevent) {
04553     bool ret = true;
04554     bool navigate = false;
04555 
04556     if (this->shown == false) {
04557         return false;
04558     }
04559 
04560 /*
04561     printf("111111111111111111111> %08x %s\n", this, name.c_str());
04562     getWindowManager()->printStack();
04563     printf("111111111111111111111<\n");
04564 */
04565         //check childwindows
04566         if(this->childwins.empty()) {
04567             if(onBeforeHandleInput->emit(this,inputevent)) {
04568                 return true;
04569             }
04570         } else {
04571             try {
04572                 if(onBeforeHandleInput->emit(this->childwins.at(this->focusedChildWin).window,inputevent)) {
04573                     return true;
04574                 }
04575             } catch(std::exception&) {
04576                 return true;
04577             }
04578         }
04579 /*
04580     printf("22222222222222222>\n");
04581     getWindowManager()->printStack();
04582     printf("22222222222222222<\n");
04583 */
04584         if (inputevent->type == MMSINPUTEVENTTYPE_KEYPRESS) {
04585             // keyboard inputs
04586             try {
04587                 if(this->focusedwidget != NULL) {
04588                     this->focusedwidget->handleInput(inputevent);
04589 
04590                     switch(inputevent->key) {
04591                         case MMSKEY_CURSOR_DOWN:
04592                         case MMSKEY_CURSOR_LEFT:
04593                         case MMSKEY_CURSOR_RIGHT:
04594                         case MMSKEY_CURSOR_UP:
04595                             // set the arrow widgets
04596                             switchArrowWidgets();
04597                             break;
04598                         default:
04599                             break;
04600                     }
04601 
04602                     return true;
04603                 }
04604                 else
04605                 if (this->childwins.size() > this->focusedChildWin) {
04606                     // get the focus to my focused child window
04607 //                  logger.writeLog("try to execute input on childwindow");
04608                     if (!this->childwins.at(this->focusedChildWin).window->handleInput(inputevent)) {
04609                         // childwin cannot navigate further, so try to find the next childwin
04610                         bool modal = false;
04611                         ((MMSChildWindow*)this->childwins.at(this->focusedChildWin).window)->getModal(modal);
04612                         if (!modal)
04613                             // currently focused child window is NOT marked as modal, so try to change the focus
04614                             this->handleNavigationForChildWins(inputevent);
04615 
04616                         return false;
04617                     }
04618 
04619                     // set the arrow widgets
04620                     switchArrowWidgets();
04621 
04622                     return true;
04623                 }
04624                 else {
04625                     //throw MMSWidgetError(1,"navigate");
04626                      navigate=true;
04627                 }
04628 
04629             } catch (MMSWidgetError &err) {
04630                 if(err.getCode() == 1) {
04631                     printf("missed navigation exception 1\n");
04632                     navigate=true;
04633                 }
04634             }
04635             if(navigate) {
04636                 /* test if navigation must be done */
04637                 ret = true;
04638                 switch(inputevent->key) {
04639                     /* handle navigation */
04640                     case MMSKEY_CURSOR_DOWN:
04641                     case MMSKEY_CURSOR_LEFT:
04642                     case MMSKEY_CURSOR_RIGHT:
04643                     case MMSKEY_CURSOR_UP:
04644 //                          logger.writeLog("widget threw a exception so try to navigate");
04645                         ret = this->handleNavigationForWidgets(inputevent);
04646 
04647                         /* set the arrow widgets */
04648                         switchArrowWidgets();
04649 
04650                         break;
04651                     default:
04652                         /* input is no navigation */
04653                         ret = false;
04654                         break;
04655                 }
04656 
04657                 /* call handle input callback */
04658                 onHandleInput->emit(this, inputevent);
04659             }
04660 
04661         }
04662         else
04663         if (inputevent->type == MMSINPUTEVENTTYPE_KEYRELEASE) {
04664             /* call handle input callback */
04665             onHandleInput->emit(this, inputevent);
04666         }
04667         else
04668         if (inputevent->type == MMSINPUTEVENTTYPE_BUTTONPRESS) {
04669             // button pressed
04670             try {
04671                 if (this->children.size()) {
04672                     // searching for the right widget to get the focus
04673                     int posx = inputevent->posx;
04674                     int posy = inputevent->posy;
04675                     bool b;
04676                     for (unsigned int j = 0; j < this->children.size(); j++) {
04677                         MMSWidget *w = this->children.at(j);
04678                         if (!w->getClickable(b))
04679                             continue;
04680                         if (!b)
04681                             continue;
04682                         if (!w->isActivated())
04683                             continue;
04684 
04685                         MMSFBRectangle rect = this->children.at(j)->getGeometry();
04686                         if ((posx >= rect.x)&&(posy >= rect.y)
04687                           &&(posx < rect.x + rect.w)&&(posy < rect.y + rect.h)) {
04688                             // this is the widget under the pointer
04689                             string inputmode = "";
04690                             w->getInputModeEx(inputmode);
04691                             if (strToUpr(inputmode) != "CLICK") {
04692                                 // e.g. remote control
04693                                 w->getFocusable(b);
04694                                 if ((b)&&(w != this->focusedwidget)) {
04695                                     // set focus to this widget
04696                                     DEBUGMSG("MMSGUI", "try to change focus");
04697 
04698                                     // set focused widget
04699                                     setFocusedWidget(w, true, true, true);
04700                                 }
04701 
04702                                 DEBUGMSG("MMSGUI", "try to execute input on widget");
04703                                 this->buttonpress_widget = w;
04704                                 this->buttonpress_widget->handleInput(inputevent);
04705                             }
04706                             else {
04707                                 // e.g. touch
04708                                 w->getFocusable(b);
04709                                 if (b) {
04710                                     if (w != this->focusedwidget) {
04711                                         // set focus to this widget
04712                                         DEBUGMSG("MMSGUI", "try to change focus");
04713                                     }
04714 
04715                                     // set focused widget
04716                                     // note, that we do not refresh the screen, because widget::handleInput() was
04717                                     // called which will do this task
04718                                     setFocusedWidget(w, true, true, false);
04719                                 }
04720 
04721                                 DEBUGMSG("MMSGUI", "try to execute input on widget");
04722                                 this->buttonpress_widget = w;
04723                                 this->buttonpress_widget->handleInput(inputevent);
04724                             }
04725 
04726 
04727                             // set the arrow widgets
04728                             switchArrowWidgets();
04729 
04730                             return true;
04731                         }
04732                     }
04733 
04734                     // no widget found
04735                     this->buttonpress_widget = NULL;
04736 
04737                     // call handle input callback
04738                     onHandleInput->emit(this, inputevent);
04739                     return true;
04740                     //throw MMSWidgetError(1,"no focusable widget found");
04741                 }
04742                 else
04743                 if (this->childwins.size() > this->focusedChildWin) {
04744                     bool modal = false;
04745                     if (this->childwins.at(this->focusedChildWin).window->isShown())
04746                         this->childwins.at(this->focusedChildWin).window->getModal(modal);
04747 
04748                     if (!modal) {
04749                         /* searching for the right childwin to get the focus */
04750                         int posx = inputevent->posx;
04751                         int posy = inputevent->posy;
04752     //                  for (unsigned int j = 0; j < this->childwins.size(); j++) {
04753                         for (int j = (int)this->childwins.size()-1; j >= 0; j--) {
04754                             // get access to the window
04755                             MMSWindow *window = this->childwins.at(j).window;
04756 
04757                             // shown?
04758                             if (!window->isShown()) {
04759                                 // no, ignoring it
04760                                 continue;
04761                             }
04762 
04763                             // focusable?
04764                             bool focusable = false;
04765                             window->getFocusable(focusable);
04766                             if (!focusable) {
04767                                 // no, ignoring it
04768                                 continue;
04769                             }
04770 
04771                             // check if the window is under the pointer
04772                             MMSFBRectangle rect = window->getGeometry();
04773                             if ((posx >= rect.x)&&(posy >= rect.y)
04774                               &&(posx < rect.x + rect.w)&&(posy < rect.y + rect.h)) {
04775                                 // this is the childwin under the pointer
04776                                 if (!window->getFocus()) {
04777     //                              bool modal = false;
04778     //                              ((MMSChildWindow*)this->childwins.at(this->focusedChildWin).window)->getModal(modal);
04779     //                              if (modal)
04780                                         // currently focused child window is marked as modal, so do not change the focus
04781     //                                  continue;
04782 
04783                                     if (window->getNumberOfFocusableWidgets(true)>0)
04784                                     {
04785                                         /* set focus to this childwin */
04786                                         DEBUGMSG("MMSGUI", "try to change focus");
04787                                         window->setFocus();
04788                                     }
04789                                 }
04790 
04791                                 // normalize the pointer position
04792                                 inputevent->posx-=rect.x;
04793                                 inputevent->posy-=rect.y;
04794 
04795                                 DEBUGMSG("MMSGUI", "try to execute input on childwin");
04796                                 this->buttonpress_childwin = window;
04797                                 window->handleInput(inputevent);
04798 
04799                                 // set the arrow widgets
04800                                 switchArrowWidgets();
04801 
04802                                 return true;
04803                             }
04804                         }
04805 
04806                         // no childwin found
04807                         this->buttonpress_childwin = NULL;
04808                         throw MMSWidgetError(1,"no focusable childwin found");
04809                     }
04810                     else {
04811                         // modal window is active
04812                         //int posx = inputeventset->at(i).posx;
04813                         //int posy = inputeventset->at(i).posy;
04814                         MMSFBRectangle rect = this->childwins.at(this->focusedChildWin).window->getGeometry();
04815 
04816                         inputevent->posx-=rect.x;
04817                         inputevent->posy-=rect.y;
04818 
04819                         DEBUGMSG("MMSGUI", "try to execute input on childwin");
04820                         this->buttonpress_childwin = this->childwins.at(this->focusedChildWin).window;
04821                         this->childwins.at(this->focusedChildWin).window->handleInput(inputevent);
04822 
04823                         // set the arrow widgets
04824                         switchArrowWidgets();
04825 
04826                         return true;
04827                     }
04828                 }
04829                 else {
04830                     //throw MMSWidgetError(1,"navigate, buttonpress");
04831                     navigate=true;
04832                 }
04833 
04834             } catch (MMSWidgetError &err) {
04835                 if(err.getCode() == 1) {
04836                     printf("missed navigation exception 2\n");
04837                     navigate=true;
04838                 }
04839             }
04840             if(navigate) {
04841                 /* test if navigation must be done */
04842                 ret = true;
04843 
04844                 /* call handle input callback */
04845                 onHandleInput->emit(this, inputevent);
04846             }
04847 
04848         }
04849         else
04850         if   ((inputevent->type == MMSINPUTEVENTTYPE_BUTTONRELEASE)
04851             ||(inputevent->type == MMSINPUTEVENTTYPE_AXISMOTION)) {
04852             /* button released */
04853             try {
04854                 if (this->children.size()) {
04855                     // window with widgets
04856                     if (this->buttonpress_widget) {
04857                         DEBUGMSG("MMSGUI", "try to execute input on widget");
04858                         this->buttonpress_widget->handleInput(inputevent);
04859 
04860                         if (inputevent->type == MMSINPUTEVENTTYPE_BUTTONRELEASE)
04861                             this->buttonpress_widget = NULL;
04862 
04863                         // set the arrow widgets
04864                         switchArrowWidgets();
04865 
04866                         return true;
04867                     }
04868                     else {
04869                         return false;
04870                     }
04871                 }
04872                 else
04873                 if (this->childwins.size() > this->focusedChildWin) {
04874                     // window with childwindows
04875                     if (this->buttonpress_childwin) {
04876                         /* normalize the pointer position */
04877                         MMSFBRectangle rect = this->buttonpress_childwin->getGeometry();
04878                         inputevent->posx-=rect.x;
04879                         inputevent->posy-=rect.y;
04880 
04881                         DEBUGMSG("MMSGUI", "try to execute input on childwin");
04882                         bool rc = this->buttonpress_childwin->handleInput(inputevent);
04883 
04884                         if (inputevent->type == MMSINPUTEVENTTYPE_BUTTONRELEASE)
04885                             this->buttonpress_childwin = NULL;
04886 
04887                         // set the arrow widgets
04888                         switchArrowWidgets();
04889 
04890                         return rc;
04891                     }
04892                     else {
04893                         return false;
04894                     }
04895                 }
04896                 else {
04897 //                  throw MMSWidgetError(1,"navigate, buttonrelease");
04898 
04899                     // window without widgets and childwindows, e.g. video/flash windows
04900 
04901                     // call handle input callback
04902                     return onHandleInput->emit(this, inputevent);
04903                 }
04904 
04905             } catch (MMSWidgetError &err) {
04906                 if(err.getCode() == 1) {
04907                     /* test if navigation must be done */
04908                     ret = true;
04909 
04910                     /* call handle input callback */
04911                     onHandleInput->emit(this, inputevent);
04912                 }
04913             }
04914         }
04915 
04916     return ret;
04917 }
04918 
04919 MMSFBRectangle MMSWindow::getGeometry() {
04920     return this->geom;
04921 }
04922 
04923 MMSFBRectangle MMSWindow::getRealGeometry() {
04924     /* childwin? */
04925     if (!this->parent)
04926         return this->geom;
04927 
04928     /* yes */
04929     MMSFBRectangle r1,r2;
04930     r1 = this->geom;
04931     r2 = this->parent->getRealGeometry();
04932     r1.x+=r2.x;
04933     r1.y+=r2.y;
04934     return r1;
04935 }
04936 
04937 
04938 MMSWidget *MMSWindow::getFocusedWidget() {
04939     return this->focusedwidget;
04940 }
04941 
04942 int MMSWindow::getNumberOfFocusableWidgets(bool cw) {
04943     int     cnt = 0;
04944     bool    b;
04945 
04946     if (!children.empty()) {
04947         for (unsigned int i = 0; i < children.size(); i++)
04948             if (children.at(i)->getFocusable(b))
04949                 if (b)
04950                     cnt++;
04951     }
04952     else {
04953         if (cw) {
04954             for (unsigned int i = 0; i < childwins.size(); i++)
04955                 cnt += childwins.at(i).window->getNumberOfFocusableWidgets(cw);
04956         }
04957     }
04958 
04959     return cnt;
04960 }
04961 
04962 int MMSWindow::getNumberOfFocusableChildWins() {
04963     int cnt = 0;
04964 
04965     for (unsigned int i = 0; i < childwins.size(); i++)
04966         if (childwins.at(i).window->getNumberOfFocusableWidgets()>0)
04967             cnt++;
04968         else
04969             cnt+=childwins.at(i).window->getNumberOfFocusableChildWins();
04970 
04971     return cnt;
04972 }
04973 
04974 
04975 void MMSWindow::setWindowManager(IMMSWindowManager *wm) {
04976     if (this->windowmanager != wm) {
04977         DEBUGMSG("MMSGUI", "windowmanager != wm");
04978         /* set new window manager */
04979         if (this->windowmanager != NULL) {
04980             DEBUGMSG("MMSGUI", "windowmanager != NULL");
04981             this->windowmanager = wm;
04982             /* and add the window to it */
04983             if (this->windowmanager) {
04984                 DEBUGMSG("MMSGUI", "windowmanager->addWindow");
04985                 this->windowmanager->addWindow(this);
04986             }
04987         }
04988         else {
04989             this->windowmanager = wm;
04990             DEBUGMSG("MMSGUI", "resize");
04991             this->resize();
04992         }
04993     }
04994 }
04995 
04996 bool MMSWindow::isShown(bool checkparents, bool checkopacity) {
04997     if (!this->shown) return false;
04998     if (this->buffered_shown) return false;
04999     if (checkopacity) {
05000         unsigned int opacity;
05001         this->getOpacity(opacity);
05002         if (!opacity) return false;
05003     }
05004     if ((checkparents)&&(this->parent)) return this->parent->isShown(true, checkopacity);
05005     return true;
05006 }
05007 
05008 
05009 
05010 bool MMSWindow::willHide() {
05011     return this->willhide;
05012 }
05013 
05014 void MMSWindow::instantShow() {
05015     unsigned int opacity;
05016     if (!getOpacity(opacity)) opacity = 255;
05017 
05018     if (!parent) {
05019         /* normal window */
05020         if (this->window) {
05021             this->window->show();
05022             this->window->setOpacity(opacity);
05023         }
05024     }
05025     else {
05026         /* child window */
05027         this->parent->setChildWindowOpacity(this, opacity);
05028     }
05029 }
05030 
05031 void MMSWindow::instantHide() {
05032     if (!parent) {
05033         // normal window
05034         if (this->windowmanager)
05035             this->windowmanager->removeWindowFromToplevel(this);
05036         if (isShown())
05037             if (this->window) {
05038                 this->window->setOpacity(0);
05039                 this->window->hide();
05040             }
05041     }
05042     else {
05043         // child window
05044         if (isShown()) {
05045             removeFocusFromChildWindow();
05046             this->parent->setChildWindowOpacity(this, 0);
05047         }
05048     }
05049 }
05050 
05051 
05052 void MMSWindow::setWidgetGeometryOnNextDraw() {
05053     this->draw_setgeom = true;
05054 }
05055 
05056 void MMSWindow::targetLangChanged(MMSLanguage lang, bool refresh) {
05057     // for all child windows
05058     for (unsigned int i = 0; i < this->childwins.size(); i++) {
05059         this->childwins.at(i).window->targetLangChanged(lang, false);
05060     }
05061 
05062     // for my own children (widgets)
05063     for (unsigned int i = 0; i < this->children.size(); i++)
05064         switch (this->children.at(i)->getType()) {
05065         case MMSWIDGETTYPE_LABEL:
05066             ((MMSLabelWidget *)this->children.at(i))->targetLangChanged(lang);
05067             break;
05068         case MMSWIDGETTYPE_TEXTBOX:
05069             ((MMSTextBoxWidget *)this->children.at(i))->targetLangChanged(lang);
05070             break;
05071         case MMSWIDGETTYPE_INPUT:
05072             ((MMSInputWidget *)this->children.at(i))->targetLangChanged(lang);
05073             break;
05074         default:
05075             break;
05076         }
05077 
05078     // window needs to be redrawn
05079     // this is especially required for child windows with own_surface="true"
05080     this->need_redraw = true;
05081 
05082     // refresh it
05083     if (refresh) {
05084         this->refresh();
05085     }
05086 }
05087 
05088 void MMSWindow::themeChanged(string &themeName, bool refresh) {
05089     // for all child windows
05090     for (unsigned int i = 0; i < this->childwins.size(); i++) {
05091         this->childwins.at(i).window->themeChanged(themeName, false);
05092     }
05093 
05094     // for my own children (widgets)
05095     for (unsigned int i = 0; i < this->children.size(); i++) {
05096         this->children.at(i)->themeChanged(themeName);
05097     }
05098 
05099     // delete images, ...
05100     release();
05101 
05102     // refresh it
05103     if (refresh)
05104         this->refresh();
05105 }
05106 
05107 
05108 
05109 MMSWidget* MMSWindow::findWidget(string name) {
05110     MMSWidget *widget;
05111 
05112     if (name == "") {
05113         // empty name
05114         return NULL;
05115     }
05116 
05117     // for all child windows
05118     for (unsigned int i = 0; i < childwins.size(); i++)
05119         if ((widget = childwins.at(i).window->findWidget(name)))
05120             return widget;
05121 
05122     // for my own children (widgets)
05123     for (unsigned int i = 0; i < children.size(); i++)
05124         if (children.at(i)->getName() == name)
05125             return children.at(i);
05126 
05127     return NULL;
05128 }
05129 
05130 MMSWidget* MMSWindow::findWidgetType(MMSWIDGETTYPE type) {
05131     MMSWidget *widget;
05132 
05133     /* for all child windows */
05134     for (unsigned int i = 0; i < childwins.size(); i++)
05135         if ((widget = childwins.at(i).window->findWidgetType(type)))
05136             return widget;
05137 
05138     /* first, my own children */
05139     for (unsigned int i = 0; i < children.size(); i++)
05140         if (children.at(i)->getType() == type)
05141             return children.at(i);
05142 
05143     /* second, call search method of my children */
05144     for (unsigned int i = 0; i < children.size(); i++)
05145         if ((widget = children.at(i)->findWidgetType(type)))
05146             return widget;
05147 
05148     return NULL;
05149 }
05150 
05151 MMSWidget* MMSWindow::findWidgetAndType(string name, MMSWIDGETTYPE type) {
05152     MMSWidget *widget;
05153 
05154     if ((widget = findWidget(name))) {
05155         // root widget found, find child widget with type
05156         if (widget->getType() == type) {
05157             // found root widget has the correct type
05158             return widget;
05159         }
05160         else {
05161             // find the type within root's children
05162             return widget->findWidgetType(type);
05163         }
05164     }
05165 
05166     return NULL;
05167 }
05168 
05169 MMSWidget* MMSWindow::operator[](string name) {
05170     MMSWidget *widget;
05171 
05172     if (name.empty()) {
05173         if (children.size() > 0)
05174             return children.at(0);
05175     }
05176 
05177     if ((widget = findWidget(name)))
05178         return widget;
05179 
05180     throw MMSWidgetError(1, "widget " + name + " not found");
05181 }
05182 
05183 
05184 MMSWindow *MMSWindow::getNavigateUpWindow() {
05185     return navigateUpWindow;
05186 }
05187 
05188 MMSWindow *MMSWindow::getNavigateDownWindow() {
05189     return navigateDownWindow;
05190 }
05191 
05192 MMSWindow *MMSWindow::getNavigateLeftWindow() {
05193     return navigateLeftWindow;
05194 }
05195 
05196 MMSWindow *MMSWindow::getNavigateRightWindow() {
05197     return navigateRightWindow;
05198 }
05199 
05200 void MMSWindow::setNavigateUpWindow(MMSWindow *upWindow) {
05201     navigateUpWindow = upWindow;
05202 }
05203 
05204 void MMSWindow::setNavigateDownWindow(MMSWindow *downWindow) {
05205     navigateDownWindow = downWindow;
05206 }
05207 
05208 void MMSWindow::setNavigateRightWindow(MMSWindow *rightWindow) {
05209     navigateRightWindow = rightWindow;
05210 }
05211 
05212 void MMSWindow::setNavigateLeftWindow(MMSWindow *leftWindow) {
05213     navigateLeftWindow = leftWindow;
05214 }
05215 
05216 
05217 
05218 unsigned int MMSWindow::printStack(char *buffer, int space) {
05219     char *ptr = buffer + space;
05220     int cnt;
05221 
05222     // name of window
05223     if (!this->name.empty())
05224         cnt = sprintf(ptr, "%s", this->name.c_str());
05225     else
05226         cnt = sprintf(ptr, "<noname>");
05227     if (cnt > 32 - space) cnt = 32 - space;
05228     ptr[cnt] = ' ';
05229     ptr+=33 - space;
05230 
05231     // this ptr
05232     cnt = sprintf(ptr, "%08x", this);
05233     ptr[cnt] = ' ';
05234     ptr+=9;
05235 
05236     // shown/focused state
05237     if (this->isShown()) {
05238         if (!this->isShown(true, true)) {
05239             if (!this->getFocus(true))
05240                 cnt = sprintf(ptr, "shown");
05241             else
05242                 cnt = sprintf(ptr, "shown/focus");
05243         }
05244         else {
05245             if (!this->getFocus(true))
05246                 cnt = sprintf(ptr, "visible");
05247             else
05248                 cnt = sprintf(ptr, "visible/focus");
05249         }
05250     }
05251     else {
05252         if (!this->getFocus(true))
05253             cnt = sprintf(ptr, "hidden");
05254         else
05255             cnt = sprintf(ptr, "hidden/focus");
05256     }
05257     ptr[cnt] = ' ';
05258     ptr+=14;
05259 
05260     // opacity
05261     unsigned int opacity;
05262     getOpacity(opacity);
05263     cnt = sprintf(ptr, "%02x", opacity);
05264     ptr[cnt] = ' ';
05265     ptr+=8;
05266 
05267     // opacity
05268     bool ownsurface;
05269     getOwnSurface(ownsurface);
05270     cnt = sprintf(ptr, "%s", (ownsurface)?"true":"false");
05271     ptr[cnt] = ' ';
05272     ptr+=12;
05273 
05274     // line feed
05275     cnt = sprintf(ptr, "\n");
05276     ptr[cnt] = ' ';
05277     ptr+= cnt;
05278 
05279     // through child windows, from top to bottom
05280     for (unsigned int i = this->childwins.size(); i > 0; i--) {
05281         ptr += this->childwins.at(i-1).window->printStack(ptr, space + 1);
05282     }
05283 
05284     return (unsigned int)(ptr - buffer);
05285 }
05286 
05287 
05288 /***********************************************/
05289 /* begin of theme access methods (get methods) */
05290 /***********************************************/
05291 
05292 #define GETWINDOW(x,y) \
05293     if (this->myWindowClass.is##x()) return myWindowClass.get##x(y); \
05294     else if ((windowClass)&&(windowClass->is##x())) return windowClass->get##x(y); \
05295     else return baseWindowClass->get##x(y);
05296 
05297 
05298 bool MMSWindow::getAlignment(MMSALIGNMENT &alignment) {
05299     GETWINDOW(Alignment, alignment);
05300 }
05301 
05302 bool MMSWindow::getDx(string &dx) {
05303     GETWINDOW(Dx, dx);
05304 }
05305 
05306 int MMSWindow::getDxPix() {
05307     return this->dxpix;
05308 }
05309 
05310 bool MMSWindow::getDy(string &dy) {
05311     GETWINDOW(Dy, dy);
05312 }
05313 
05314 int MMSWindow::getDyPix() {
05315     return this->dypix;
05316 }
05317 
05318 bool MMSWindow::getWidth(string &width) {
05319     GETWINDOW(Width, width);
05320 }
05321 
05322 bool MMSWindow::getHeight(string &height) {
05323     GETWINDOW(Height, height);
05324 }
05325 
05326 bool MMSWindow::getBgColor(MMSFBColor &bgcolor) {
05327     GETWINDOW(BgColor, bgcolor);
05328 }
05329 
05330 bool MMSWindow::getBgImagePath(string &bgimagepath) {
05331     GETWINDOW(BgImagePath, bgimagepath);
05332 }
05333 
05334 bool MMSWindow::getBgImageName(string &bgimagename) {
05335     GETWINDOW(BgImageName, bgimagename);
05336 }
05337 
05338 bool MMSWindow::getOpacity(unsigned int &opacity) {
05339     GETWINDOW(Opacity, opacity);
05340 }
05341 
05342 bool MMSWindow::getFadeIn(bool &fadein) {
05343     GETWINDOW(FadeIn, fadein);
05344 }
05345 
05346 bool MMSWindow::getFadeOut(bool &fadeout) {
05347     GETWINDOW(FadeOut, fadeout);
05348 }
05349 
05350 bool MMSWindow::getDebug(bool &debug) {
05351     GETWINDOW(Debug, debug);
05352 }
05353 
05354 bool MMSWindow::getMargin(unsigned int &margin) {
05355     GETWINDOW(Margin, margin);
05356 }
05357 
05358 bool MMSWindow::getUpArrow(string &uparrow) {
05359     GETWINDOW(UpArrow, uparrow);
05360 }
05361 
05362 bool MMSWindow::getDownArrow(string &downarrow) {
05363     GETWINDOW(DownArrow, downarrow);
05364 }
05365 
05366 bool MMSWindow::getLeftArrow(string &leftarrow) {
05367     GETWINDOW(LeftArrow, leftarrow);
05368 }
05369 
05370 bool MMSWindow::getRightArrow(string &rightarrow) {
05371     GETWINDOW(RightArrow, rightarrow);
05372 }
05373 
05374 bool MMSWindow::getNavigateUp(string &navigateup) {
05375     GETWINDOW(NavigateUp, navigateup);
05376 }
05377 
05378 bool MMSWindow::getNavigateDown(string &navigatedown) {
05379     GETWINDOW(NavigateDown, navigatedown);
05380 }
05381 
05382 bool MMSWindow::getNavigateLeft(string &navigateleft) {
05383     GETWINDOW(NavigateLeft, navigateleft);
05384 }
05385 
05386 bool MMSWindow::getNavigateRight(string &navigateright) {
05387     GETWINDOW(NavigateRight, navigateright);
05388 }
05389 
05390 bool MMSWindow::getOwnSurface(bool &ownsurface) {
05391     GETWINDOW(OwnSurface, ownsurface);
05392 }
05393 
05394 bool MMSWindow::getMoveIn(MMSDIRECTION &movein) {
05395     GETWINDOW(MoveIn, movein);
05396 }
05397 
05398 bool MMSWindow::getMoveOut(MMSDIRECTION &moveout) {
05399     GETWINDOW(MoveOut, moveout);
05400 }
05401 
05402 bool MMSWindow::getModal(bool &modal) {
05403     GETWINDOW(Modal, modal);
05404 }
05405 
05406 bool MMSWindow::getStaticZOrder(bool &staticzorder) {
05407     GETWINDOW(StaticZOrder, staticzorder);
05408 }
05409 
05410 bool MMSWindow::getAlwaysOnTop(bool &alwaysontop) {
05411     GETWINDOW(AlwaysOnTop, alwaysontop);
05412 }
05413 
05414 bool MMSWindow::getFocusable(bool &focusable) {
05415     GETWINDOW(Focusable, focusable);
05416 }
05417 
05418 bool MMSWindow::getBackBuffer(bool &backbuffer) {
05419     GETWINDOW(BackBuffer, backbuffer);
05420 }
05421 
05422 bool MMSWindow::getInitialLoad(bool &initialload) {
05423     GETWINDOW(InitialLoad, initialload);
05424 }
05425 
05426 
05427 #define GETBORDER(x,y) \
05428     if (this->myWindowClass.border.is##x()) return myWindowClass.border.get##x(y); \
05429     else if ((windowClass)&&(windowClass->border.is##x())) return windowClass->border.get##x(y); \
05430     else return baseWindowClass->border.get##x(y);
05431 
05432 #define GETBORDER_IMAGES(x,p,y) \
05433     if (this->myWindowClass.border.is##x()) return myWindowClass.border.get##x(p,y); \
05434     else if ((windowClass)&&(windowClass->border.is##x())) return windowClass->border.get##x(p,y); \
05435     else return baseWindowClass->border.get##x(p,y);
05436 
05437 
05438 bool MMSWindow::getBorderColor(MMSFBColor &color) {
05439     GETBORDER(Color, color);
05440 }
05441 
05442 bool MMSWindow::getBorderImagePath(string &imagepath) {
05443     GETBORDER(ImagePath, imagepath);
05444 }
05445 
05446 bool MMSWindow::getBorderImageNames(MMSBORDER_IMAGE_NUM num, string &imagename) {
05447     GETBORDER_IMAGES(ImageNames, num, imagename);
05448 }
05449 
05450 bool MMSWindow::getBorderThickness(unsigned int &thickness) {
05451     GETBORDER(Thickness, thickness);
05452 }
05453 
05454 bool MMSWindow::getBorderMargin(unsigned int &margin) {
05455     GETBORDER(Margin, margin);
05456 }
05457 
05458 bool MMSWindow::getBorderRCorners(bool &rcorners) {
05459     GETBORDER(RCorners, rcorners);
05460 }
05461 
05462 /***********************************************/
05463 /* begin of theme access methods (set methods) */
05464 /***********************************************/
05465 
05466 void MMSWindow::setAlignment(MMSALIGNMENT alignment, bool refresh, bool resize) {
05467     myWindowClass.setAlignment(alignment);
05468     if (resize)
05469         this->resize();
05470     if (refresh)
05471         this->refresh();
05472 }
05473 
05474 void MMSWindow::setDx(string dx, bool refresh, bool resize) {
05475     myWindowClass.setDx(dx);
05476     if (resize)
05477         this->resize();
05478     if (refresh)
05479         this->refresh();
05480 }
05481 
05482 void MMSWindow::setDxPix(int dx, bool refresh, bool resize) {
05483     string s = iToStr(dx) + "px";
05484     setDx(s, refresh, resize);
05485 }
05486 
05487 void MMSWindow::setDy(string dy, bool refresh, bool resize) {
05488     myWindowClass.setDy(dy);
05489     if (resize)
05490         this->resize();
05491     if (refresh)
05492         this->refresh();
05493 }
05494 
05495 void MMSWindow::setDyPix(int dy, bool refresh, bool resize) {
05496     string s = iToStr(dy) + "px";
05497     setDy(s, refresh, resize);
05498 }
05499 
05500 void MMSWindow::setWidth(string width, bool refresh, bool resize) {
05501     myWindowClass.setWidth(width);
05502     if (resize)
05503         this->resize();
05504     if (refresh)
05505         this->refresh();
05506 }
05507 
05508 void MMSWindow::setHeight(string height, bool refresh, bool resize) {
05509     myWindowClass.setHeight(height);
05510     if (resize)
05511         this->resize();
05512     if (refresh)
05513         this->refresh();
05514 }
05515 
05516 void MMSWindow::setBgColor(MMSFBColor bgcolor, bool refresh) {
05517     myWindowClass.setBgColor(bgcolor);
05518     if (refresh)
05519         this->refresh();
05520 }
05521 
05522 void MMSWindow::setBgImagePath(string bgimagepath, bool load, bool refresh) {
05523     myWindowClass.setBgImagePath(bgimagepath);
05524     if (!this->bgimage_from_external) {
05525         if (this->initialized) {
05526             if (load) {
05527                 im->releaseImage(this->bgimage);
05528                 string path, name;
05529                 if (!getBgImagePath(path)) path = "";
05530                 if (!getBgImageName(name)) name = "";
05531                 this->bgimage = im->getImage(path, name);
05532             }
05533             if (refresh)
05534                 this->refresh();
05535         }
05536     }
05537 }
05538 
05539 void MMSWindow::setBgImageName(string bgimagename, bool load, bool refresh) {
05540     myWindowClass.setBgImageName(bgimagename);
05541     if (!this->bgimage_from_external) {
05542         if (this->initialized) {
05543             if (load) {
05544                 im->releaseImage(this->bgimage);
05545                 string path, name;
05546                 if (!getBgImagePath(path)) path = "";
05547                 if (!getBgImageName(name)) name = "";
05548                 this->bgimage = im->getImage(path, name);
05549             }
05550             if (refresh)
05551                 this->refresh();
05552         }
05553     }
05554 }
05555 
05556 
05557 void MMSWindow::setBgImage(MMSFBSurface *bgimage, bool refresh) {
05558     if (!this->bgimage_from_external) {
05559         if (this->initialized) {
05560             im->releaseImage(this->bgimage);
05561             this->bgimage = NULL;
05562         }
05563     }
05564 
05565     // set external pointer to bgimage
05566     this->bgimage = bgimage;
05567     this->bgimage_from_external = true;
05568 
05569     if (refresh)
05570         this->refresh();
05571 }
05572 
05573 
05574 void MMSWindow::setOpacity(unsigned int opacity, bool refresh) {
05575     unsigned int op = 0;
05576 
05577     getOpacity(op);
05578 
05579     if (op == opacity)
05580         return;
05581 
05582     myWindowClass.setOpacity(opacity);
05583 
05584     if (!this->parent) {
05585         if (this->window)
05586             this->window->setOpacity(opacity);
05587     }
05588     else {
05589         this->parent->setChildWindowOpacity(this, opacity, refresh);
05590     }
05591 }
05592 
05593 void MMSWindow::setFadeIn(bool fadein) {
05594     myWindowClass.setFadeIn(fadein);
05595 }
05596 
05597 void MMSWindow::setFadeOut(bool fadeout) {
05598     myWindowClass.setFadeOut(fadeout);
05599 }
05600 
05601 void MMSWindow::setDebug(bool debug, bool refresh) {
05602     myWindowClass.setDebug(debug);
05603     if (refresh)
05604         this->refresh();
05605 }
05606 
05607 void MMSWindow::setMargin(unsigned int margin, bool refresh, bool resize) {
05608     myWindowClass.setMargin(margin);
05609     if (resize)
05610         this->resize();
05611     if (refresh)
05612         this->refresh();
05613 }
05614 
05615 void MMSWindow::setUpArrow(string uparrow, bool refresh) {
05616     myWindowClass.setUpArrow(uparrow);
05617     upArrowWidget = NULL;
05618     if (refresh)
05619         this->refresh();
05620 }
05621 
05622 void MMSWindow::setDownArrow(string downarrow, bool refresh) {
05623     myWindowClass.setDownArrow(downarrow);
05624     downArrowWidget = NULL;
05625     if (refresh)
05626         this->refresh();
05627 }
05628 
05629 void MMSWindow::setLeftArrow(string leftarrow, bool refresh) {
05630     myWindowClass.setLeftArrow(leftarrow);
05631     leftArrowWidget = NULL;
05632     if (refresh)
05633         this->refresh();
05634 }
05635 
05636 void MMSWindow::setRightArrow(string rightarrow, bool refresh) {
05637     myWindowClass.setRightArrow(rightarrow);
05638     rightArrowWidget = NULL;
05639     if (refresh)
05640         this->refresh();
05641 }
05642 
05643 void MMSWindow::setNavigateUp(string navigateup) {
05644     myWindowClass.setNavigateUp(navigateup);
05645     this->navigateUpWindow = NULL;
05646     if ((this->parent)&&(navigateup!=""))
05647         this->navigateUpWindow = this->parent->findWindow(navigateup);
05648 }
05649 
05650 void MMSWindow::setNavigateDown(string navigatedown) {
05651     myWindowClass.setNavigateDown(navigatedown);
05652     this->navigateDownWindow = NULL;
05653     if ((this->parent)&&(navigatedown!=""))
05654         this->navigateDownWindow = this->parent->findWindow(navigatedown);
05655 }
05656 
05657 void MMSWindow::setNavigateLeft(string navigateleft) {
05658     myWindowClass.setNavigateLeft(navigateleft);
05659     this->navigateLeftWindow = NULL;
05660     if ((this->parent)&&(navigateleft!=""))
05661         this->navigateLeftWindow = this->parent->findWindow(navigateleft);
05662 }
05663 
05664 void MMSWindow::setNavigateRight(string navigateright) {
05665     myWindowClass.setNavigateRight(navigateright);
05666     this->navigateRightWindow = NULL;
05667     if ((this->parent)&&(navigateright!=""))
05668         this->navigateRightWindow = this->parent->findWindow(navigateright);
05669 }
05670 
05671 void MMSWindow::setOwnSurface(bool ownsurface) {
05672     myWindowClass.setOwnSurface(ownsurface);
05673 }
05674 
05675 void MMSWindow::setMoveIn(MMSDIRECTION movein) {
05676     myWindowClass.setMoveIn(movein);
05677 }
05678 
05679 void MMSWindow::setMoveOut(MMSDIRECTION moveout) {
05680     myWindowClass.setMoveOut(moveout);
05681 }
05682 
05683 void MMSWindow::setModal(bool modal) {
05684     myWindowClass.setModal(modal);
05685 }
05686 
05687 void MMSWindow::setStaticZOrder(bool staticzorder) {
05688     myWindowClass.setStaticZOrder(staticzorder);
05689 }
05690 
05691 void MMSWindow::setAlwaysOnTop(bool alwaysontop) {
05692     // get current status
05693     bool aot = false;
05694     this->getAlwaysOnTop(aot);
05695 
05696     // status change?
05697     if (aot == alwaysontop)
05698         return;
05699 
05700     // set value
05701     lock();
05702     myWindowClass.setAlwaysOnTop(alwaysontop);
05703 
05704     // raise the window to the top of "normal" or "always on top" area in the childwins list
05705     PRINT_LOCK("call raiseToTop");
05706     raiseToTop();
05707 
05708     unlock();
05709 }
05710 
05711 void MMSWindow::setFocusable(bool focusable) {
05712     myWindowClass.setFocusable(focusable);
05713 }
05714 
05715 void MMSWindow::setBackBuffer(bool backbuffer) {
05716     myWindowClass.setBackBuffer(backbuffer);
05717 }
05718 
05719 void MMSWindow::setInitialLoad(bool initialload) {
05720     myWindowClass.setInitialLoad(initialload);
05721 }
05722 
05723 void MMSWindow::setBorderColor(MMSFBColor color, bool refresh) {
05724     myWindowClass.border.setColor(color);
05725     if (refresh)
05726         this->refresh();
05727 }
05728 
05729 void MMSWindow::setBorderImagePath(string imagepath, bool load, bool refresh) {
05730     myWindowClass.border.setImagePath(imagepath);
05731     if (this->initialized) {
05732         if (load) {
05733             string path, name;
05734             if (!getBorderImagePath(path)) path = "";
05735             for (int i=0;i<MMSBORDER_IMAGE_NUM_SIZE;i++) {
05736                 im->releaseImage(this->borderimages[i]);
05737                 if (!getBorderImageNames((MMSBORDER_IMAGE_NUM)i, name)) name = "";
05738                 this->borderimages[i] = im->getImage(path, name);
05739             }
05740         }
05741         if (refresh)
05742             this->refresh();
05743     }
05744 }
05745 
05746 void MMSWindow::setBorderImageNames(string imagename_1, string imagename_2, string imagename_3, string imagename_4,
05747                                     string imagename_5, string imagename_6, string imagename_7, string imagename_8,
05748                                     bool load, bool refresh) {
05749     myWindowClass.border.setImageNames(imagename_1, imagename_2, imagename_3, imagename_4,
05750                                        imagename_5, imagename_6, imagename_7, imagename_8);
05751     if (this->initialized) {
05752         if (load) {
05753             string path, name;
05754             if (!getBorderImagePath(path)) path = "";
05755             for (int i=0;i<MMSBORDER_IMAGE_NUM_SIZE;i++) {
05756                 im->releaseImage(this->borderimages[i]);
05757                 if (!getBorderImageNames((MMSBORDER_IMAGE_NUM)i, name)) name = "";
05758                 this->borderimages[i] = im->getImage(path, name);
05759             }
05760         }
05761         if (refresh)
05762             this->refresh();
05763     }
05764 }
05765 
05766 void MMSWindow::setBorderThickness(unsigned int thickness, bool refresh, bool resize) {
05767     myWindowClass.border.setThickness(thickness);
05768     if (resize)
05769         this->resize();
05770     if (refresh)
05771         this->refresh();
05772 }
05773 
05774 void MMSWindow::setBorderMargin(unsigned int margin, bool refresh, bool resize) {
05775     myWindowClass.border.setMargin(margin);
05776     if (resize)
05777         this->resize();
05778     if (refresh)
05779         this->refresh();
05780 }
05781 
05782 void MMSWindow::setBorderRCorners(bool rcorners, bool refresh) {
05783     myWindowClass.border.setRCorners(rcorners);
05784     if (refresh)
05785         this->refresh();
05786 }
05787 
05788 void MMSWindow::updateFromThemeClass(MMSWindowClass *themeClass) {
05789 
05790     MMSALIGNMENT    a;
05791     bool            b;
05792     MMSFBColor      c;
05793     MMSDIRECTION    d;
05794     string          s;
05795     unsigned int    u;
05796 
05797     if (themeClass->getAlignment(a))
05798         setAlignment(a, false, false);
05799     if (themeClass->getDx(s))
05800         setDx(s, false, false);
05801     if (themeClass->getDy(s))
05802         setDy(s, false, false);
05803     if (themeClass->getWidth(s))
05804         setWidth(s, false, false);
05805     if (themeClass->getHeight(s))
05806         setHeight(s, false, false);
05807     if (themeClass->getBgColor(c))
05808         setBgColor(c, false);
05809     if (themeClass->getBgImagePath(s))
05810         setBgImagePath(s, true, false);
05811     if (themeClass->getBgImageName(s))
05812         setBgImageName(s, true, false);
05813     if (themeClass->getOpacity(u))
05814         setOpacity(u, false);
05815     if (themeClass->getFadeIn(b))
05816         setFadeIn(b);
05817     if (themeClass->getFadeOut(b))
05818         setFadeOut(b);
05819     if (themeClass->getDebug(b))
05820         setDebug(b, false);
05821     if (themeClass->getMargin(u))
05822         setMargin(u, false, false);
05823     if (themeClass->getUpArrow(s))
05824         setUpArrow(s, false);
05825     if (themeClass->getDownArrow(s))
05826         setDownArrow(s, false);
05827     if (themeClass->getLeftArrow(s))
05828         setLeftArrow(s, false);
05829     if (themeClass->getRightArrow(s))
05830         setRightArrow(s, false);
05831     if (themeClass->getNavigateUp(s))
05832         setNavigateUp(s);
05833     if (themeClass->getNavigateDown(s))
05834         setNavigateDown(s);
05835     if (themeClass->getNavigateLeft(s))
05836         setNavigateLeft(s);
05837     if (themeClass->getNavigateRight(s))
05838         setNavigateRight(s);
05839     if (themeClass->getOwnSurface(b))
05840         setOwnSurface(b);
05841     if (themeClass->getMoveIn(d))
05842         setMoveIn(d);
05843     if (themeClass->getMoveOut(d))
05844         setMoveOut(d);
05845     if (themeClass->getModal(b))
05846         setModal(b);
05847     if (themeClass->getStaticZOrder(b))
05848         setStaticZOrder(b);
05849     if (themeClass->getAlwaysOnTop(b))
05850         setAlwaysOnTop(b);
05851     if (themeClass->getFocusable(b))
05852         setFocusable(b);
05853     if (themeClass->getBackBuffer(b))
05854         setBackBuffer(b);
05855     if (themeClass->getInitialLoad(b))
05856         setInitialLoad(b);
05857     if (themeClass->border.getColor(c))
05858         setBorderColor(c, false);
05859     if (themeClass->border.getImagePath(s))
05860         setBorderImagePath(s, true, false);
05861     if (themeClass->border.isImageNames()) {
05862         string s[8];
05863         themeClass->border.getImageNames(MMSBORDER_IMAGE_NUM_TOP_LEFT, s[0]);
05864         themeClass->border.getImageNames(MMSBORDER_IMAGE_NUM_TOP, s[1]);
05865         themeClass->border.getImageNames(MMSBORDER_IMAGE_NUM_TOP_RIGHT, s[2]);
05866         themeClass->border.getImageNames(MMSBORDER_IMAGE_NUM_RIGHT, s[3]);
05867         themeClass->border.getImageNames(MMSBORDER_IMAGE_NUM_BOTTOM_RIGHT, s[4]);
05868         themeClass->border.getImageNames(MMSBORDER_IMAGE_NUM_BOTTOM, s[5]);
05869         themeClass->border.getImageNames(MMSBORDER_IMAGE_NUM_BOTTOM_LEFT, s[6]);
05870         themeClass->border.getImageNames(MMSBORDER_IMAGE_NUM_LEFT, s[7]);
05871         setBorderImageNames(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], true, false);
05872     }
05873     if (themeClass->border.getThickness(u))
05874         setBorderThickness(u, false, false);
05875     if (themeClass->border.getMargin(u))
05876         setBorderMargin(u, false, false);
05877     if (themeClass->border.getRCorners(b))
05878         setBorderRCorners(b, false);
05879 
05880     /* resize window and refresh */
05881     resize();
05882     refresh();
05883 }
05884 
05885 /***********************************************/
05886 /* end of theme access methods                 */
05887 /***********************************************/

Generated by doxygen