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

Generated by doxygen