rootxx.cxx

Go to the documentation of this file.
00001 // @(#)root/rootx:$Id: rootxx.cxx 35849 2010-09-28 15:41:16Z rdm $
00002 // Author: Fons Rademakers   19/02/98
00003 
00004 //////////////////////////////////////////////////////////////////////////
00005 //                                                                      //
00006 // Rootxx                                                               //
00007 //                                                                      //
00008 // X11 based routines used to display the splash screen for rootx,      //
00009 // the root front-end program.                                          //
00010 //                                                                      //
00011 //////////////////////////////////////////////////////////////////////////
00012 
00013 #include "RConfigure.h"
00014 
00015 #include <stdio.h>
00016 #include <unistd.h>
00017 #include <stdlib.h>
00018 #include <string.h>
00019 #include <pwd.h>
00020 #include <sys/types.h>
00021 #include <X11/Xlib.h>
00022 #include <X11/xpm.h>
00023 
00024 #include "Rtypes.h"
00025 
00026 #if defined(R__AIX) || defined(R__SOLARIS)
00027 #   include <sys/select.h>
00028 #endif
00029 #include <time.h>
00030 #include <sys/time.h>
00031 
00032 static Display     *gDisplay       = 0;
00033 static Window       gLogoWindow    = 0;
00034 static Pixmap       gLogoPixmap    = 0;
00035 static Pixmap       gCreditsPixmap = 0;
00036 static GC           gGC            = 0;
00037 static XFontStruct *gFont          = 0;
00038 static bool         gDone          = false;
00039 static bool         gMayPopdown    = false;
00040 static bool         gAbout         = false;
00041 static unsigned int gWidth         = 0;
00042 static unsigned int gHeight        = 0;
00043 static int          gStayUp        = 4000;   // 4 seconds
00044 static XRectangle   gCreditsRect   = { 15, 155, 285, 130 }; // clip rect in logo
00045 static unsigned int gCreditsWidth  = gCreditsRect.width; // credits pixmap size
00046 static unsigned int gCreditsHeight = 0;
00047 
00048 static struct timeval gPopupTime;
00049 
00050 static const char *gConception[] = {
00051    "Rene Brun",
00052    "Fons Rademakers",
00053    0
00054 };
00055 
00056 static const char *gLeadDevelopers[] = {
00057    "Rene Brun",
00058    "Philippe Canal",
00059    "Fons Rademakers",
00060    0
00061 };
00062 
00063 static const char *gRootDevelopers[] = {
00064    "Bertrand Bellenot",
00065    "Olivier Couet",
00066    "Gerardo Ganis",
00067    "Andrei Gheata",
00068    "Lorenzo Moneta",
00069    "Axel Naumann",
00070    "Paul Russo",
00071    "Matevz Tadel",
00072    0
00073 };
00074 
00075 static const char *gCintDevelopers[] = {
00076    "Masaharu Goto",
00077    0
00078 };
00079 
00080 static const char *gRootDocumentation[] = {
00081    "Ilka Antcheva",
00082    0
00083 };
00084 
00085 static char **gContributors = 0;
00086 
00087 
00088 
00089 static bool StayUp(int milliSec)
00090 {
00091    // Returns false if milliSec milliseconds have passed since logo
00092    // was popped up, true otherwise.
00093 
00094    struct timeval ctv, dtv, tv, ptv = gPopupTime;
00095 
00096    tv.tv_sec  = milliSec / 1000;
00097    tv.tv_usec = (milliSec % 1000) * 1000;
00098 
00099    gettimeofday(&ctv, 0);
00100    if ((dtv.tv_usec = ctv.tv_usec - ptv.tv_usec) < 0) {
00101       dtv.tv_usec += 1000000;
00102       ptv.tv_sec++;
00103    }
00104    dtv.tv_sec = ctv.tv_sec - ptv.tv_sec;
00105 
00106    if ((ctv.tv_usec = tv.tv_usec - dtv.tv_usec) < 0) {
00107       ctv.tv_usec += 1000000;
00108       dtv.tv_sec++;
00109    }
00110    ctv.tv_sec = tv.tv_sec - dtv.tv_sec;
00111 
00112    if (ctv.tv_sec < 0) return false;
00113 
00114    return true;
00115 }
00116 
00117 static void Sleep(int milliSec)
00118 {
00119    // Sleep for specified amount of milli seconds.
00120 
00121    // get current time
00122    struct timeval tv;
00123 
00124    tv.tv_sec  = milliSec / 1000;
00125    tv.tv_usec = (milliSec % 1000) * 1000;
00126 
00127    select(0, 0, 0, 0, &tv);
00128 }
00129 
00130 static Pixmap GetRootLogo()
00131 {
00132    // Get logo from xpm file.
00133 
00134    Pixmap logo = 0;
00135    int depth = PlanesOfScreen(XDefaultScreenOfDisplay(gDisplay));
00136 
00137    XWindowAttributes win_attr;
00138    XGetWindowAttributes(gDisplay, gLogoWindow, &win_attr);
00139 
00140    XpmAttributes attr;
00141    attr.valuemask    = XpmVisual | XpmColormap | XpmDepth;
00142    attr.visual       = win_attr.visual;
00143    attr.colormap     = win_attr.colormap;
00144    attr.depth        = win_attr.depth;
00145 
00146 #ifdef XpmColorKey              // Not available in XPM 3.2 and earlier
00147    attr.valuemask |= XpmColorKey;
00148    if (depth > 4)
00149       attr.color_key = XPM_COLOR;
00150    else if (depth > 2)
00151       attr.color_key = XPM_GRAY4;
00152    else if (depth > 1)
00153       attr.color_key = XPM_GRAY;
00154    else if (depth == 1)
00155       attr.color_key = XPM_MONO;
00156    else
00157       attr.valuemask &= ~XpmColorKey;
00158 
00159 #endif // defined(XpmColorKey)
00160 
00161    char file[2048];
00162 #ifdef ROOTICONPATH
00163    snprintf(file, sizeof(file), "%s/Splash.xpm", ROOTICONPATH);
00164 #else
00165    snprintf(file, sizeof(file), "%s/icons/Splash.xpm", getenv("ROOTSYS"));
00166 #endif
00167    int ret = XpmReadFileToPixmap(gDisplay, gLogoWindow,
00168                                  file, &logo, 0, &attr);
00169    XpmFreeAttributes(&attr);
00170 
00171    if (ret == XpmSuccess || ret == XpmColorError)
00172       return logo;
00173 
00174    printf("rootx xpm error: %s\n", XpmGetErrorString(ret));
00175 
00176    if (logo) XFreePixmap(gDisplay, logo);
00177    logo = 0;
00178 
00179    return logo;
00180 }
00181 
00182 static void ReadContributors()
00183 {
00184    // Read the file $ROOTSYS/README/CREDITS for the names of the
00185    // contributors.
00186 
00187    char buf[2048];
00188 #ifdef ROOTDOCDIR
00189    snprintf(buf, sizeof(buf), "%s/CREDITS", ROOTDOCDIR);
00190 #else
00191    snprintf(buf, sizeof(buf), "%s/README/CREDITS", getenv("ROOTSYS"));
00192 #endif
00193 
00194    gContributors = 0;
00195 
00196    FILE *f = fopen(buf, "r");
00197    if (!f) return;
00198 
00199    int cnt = 0;
00200    while (fgets(buf, sizeof(buf), f)) {
00201       if (!strncmp(buf, "N: ", 3)) {
00202          cnt++;
00203       }
00204    }
00205    gContributors = new char*[cnt+1];
00206 
00207    cnt = 0;
00208    rewind(f);
00209    while (fgets(buf, sizeof(buf), f)) {
00210       if (!strncmp(buf, "N: ", 3)) {
00211          int len = strlen(buf);
00212          buf[len-1] = 0;    // remove \n
00213          len -= 3;          // remove "N: "
00214          gContributors[cnt] = new char[len];
00215          strncpy(gContributors[cnt], buf+3, len);
00216          cnt++;
00217       }
00218    }
00219    gContributors[cnt] = 0;
00220 
00221    fclose(f);
00222 }
00223 
00224 static void DrawVersion()
00225 {
00226    // Draw version string.
00227 
00228    char version[80];
00229    sprintf(version, "Version %s", ROOT_RELEASE);
00230 
00231    XDrawString(gDisplay, gLogoWindow, gGC, 15, gHeight - 15, version,
00232                strlen(version));
00233 }
00234 
00235 static int DrawCreditItem(const char *creditItem, const char **members,
00236                           int y, bool draw)
00237 {
00238    // Draw credit item.
00239 
00240    char credit[1024];
00241    int i;
00242    int lineSpacing = gFont->max_bounds.ascent + gFont->max_bounds.descent;
00243 
00244    strlcpy(credit, creditItem, sizeof(credit));
00245    for (i = 0; members && members[i]; i++) {
00246       if (i) strcat(credit, ", ");
00247       if (XTextWidth(gFont, credit, strlen(credit)) +
00248           XTextWidth(gFont, members[i], strlen(members[i])) > (int) gCreditsWidth) {
00249          if (draw)
00250             XDrawString(gDisplay, gCreditsPixmap, gGC, 0, y, credit, strlen(credit));
00251          y += lineSpacing;
00252          strcpy(credit, "   ");
00253       }
00254       strcat(credit, members[i]);
00255    }
00256    if (draw)
00257       XDrawString(gDisplay, gCreditsPixmap, gGC, 0, y, credit, strlen(credit));
00258 
00259    return y;
00260 }
00261 
00262 static int DrawCredits(bool draw, bool extended)
00263 {
00264    // Draw credits. If draw is true draw credits,
00265    // otherwise just return size of all credit text.
00266    // If extended is true draw or returns size for extended full
00267    // credits list.
00268 
00269    if (!gFont) return 150;  // size not important no text will be drawn anyway
00270 
00271    int lineSpacing = gFont->max_bounds.ascent + gFont->max_bounds.descent;
00272    int y = lineSpacing;
00273 
00274    y = DrawCreditItem("Conception: ", gConception, y, draw);
00275 
00276    y += 2*lineSpacing;
00277 
00278    y = DrawCreditItem("Lead Developers: ", gLeadDevelopers, y, draw);
00279 
00280    y += 2*lineSpacing - 1;  // special layout tweak
00281 
00282    y = DrawCreditItem("Core Engineering: ", gRootDevelopers, y, draw);
00283 
00284    y += 2*lineSpacing - 1;  // to just not cut the bottom of the "p"
00285 
00286    y = DrawCreditItem("CINT C/C++ Intepreter: ", gCintDevelopers, y, draw);
00287 
00288    y += 2*lineSpacing;
00289 
00290    y = DrawCreditItem("Documentation: ", gRootDocumentation, y, draw);
00291 
00292    if (extended && gContributors) {
00293       y += 2*lineSpacing;
00294       y = DrawCreditItem("Contributors: ", (const char **)gContributors, y, draw);
00295 
00296       y += 2*lineSpacing;
00297       y = DrawCreditItem("Our sincere thanks and apologies to anyone who deserves", 0, y, draw);
00298       y += lineSpacing;
00299       y = DrawCreditItem("credit but fails to appear in this list.", 0, y, draw);
00300 
00301       struct passwd *pwd = getpwuid(getuid());
00302       if (pwd) {
00303          char *name = new char [strlen(pwd->pw_gecos)+1];
00304          strcpy(name, pwd->pw_gecos);
00305          char *s = strchr(name, ',');
00306          if (s) *s = 0;
00307          char line[1024];
00308          if (strlen(name))
00309             snprintf(line, sizeof(line), "Extra special thanks go to %s,", name);
00310          else
00311             snprintf(line, sizeof(line), "Extra special thanks go to %s,", pwd->pw_name);
00312          delete [] name;
00313          y += 2*lineSpacing;
00314          y = DrawCreditItem(line, 0, y, draw);
00315          y += lineSpacing;
00316          y = DrawCreditItem("one of our favorite users.", 0, y, draw);
00317       }
00318    }
00319 
00320    return y;
00321 }
00322 
00323 void ScrollCredits(int ypos)
00324 {
00325    XRectangle crect[1];
00326    crect[0] = gCreditsRect;
00327    XSetClipRectangles(gDisplay, gGC, 0, 0, crect, 1, Unsorted);
00328 
00329    XCopyArea(gDisplay, gCreditsPixmap, gLogoWindow, gGC,
00330              0, ypos, gCreditsWidth, gCreditsHeight, gCreditsRect.x, gCreditsRect.y);
00331 
00332    XSetClipMask(gDisplay, gGC, None);
00333 }
00334 
00335 void PopupLogo(bool about)
00336 {
00337    // Popup logo, waiting till ROOT is ready to run.
00338 
00339    gDisplay = XOpenDisplay("");
00340    if (!gDisplay) return;
00341 
00342    gAbout = about;
00343 
00344    Pixel back, fore;
00345    int screen = DefaultScreen(gDisplay);
00346 
00347    back = WhitePixel(gDisplay, screen);
00348    fore = BlackPixel(gDisplay, screen);
00349 
00350    gLogoWindow = XCreateSimpleWindow(gDisplay, DefaultRootWindow(gDisplay),
00351                                      -100, -100, 50, 50, 0, fore, back);
00352 
00353    gLogoPixmap = GetRootLogo();
00354    if (!gLogoPixmap) {
00355       XCloseDisplay(gDisplay);
00356       gDisplay = 0;
00357       return;
00358    }
00359 
00360    Window root;
00361    int x, y;
00362    unsigned int bw, depth;
00363    XGetGeometry(gDisplay, gLogoPixmap, &root, &x, &y, &gWidth, &gHeight,
00364                 &bw, &depth);
00365 
00366    Screen *xscreen = XDefaultScreenOfDisplay(gDisplay);
00367    x = (WidthOfScreen(xscreen) - gWidth) / 2;
00368    y = (HeightOfScreen(xscreen) - gHeight) / 2;
00369 
00370    XMoveResizeWindow(gDisplay, gLogoWindow, x, y, gWidth, gHeight);
00371    XSync(gDisplay, False);   // make sure move & resize is done before mapping
00372 
00373    unsigned long valmask;
00374    XSetWindowAttributes xswa;
00375    valmask = CWBackPixmap | CWOverrideRedirect;
00376    xswa.background_pixmap = gLogoPixmap;
00377    xswa.override_redirect = True;
00378    XChangeWindowAttributes(gDisplay, gLogoWindow, valmask, &xswa);
00379 
00380    gGC = XCreateGC(gDisplay, gLogoWindow, 0, 0);
00381    gFont = XLoadQueryFont(gDisplay, "-adobe-helvetica-medium-r-*-*-10-*-*-*-*-*-iso8859-1");
00382    if (!gFont) {
00383       printf("Couldn't find font \"-adobe-helvetica-medium-r-*-*-10-*-*-*-*-*-iso8859-1\",\n"
00384              "trying \"fixed\". Please fix your system so helvetica can be found, \n"
00385              "this font typically is in the rpm (or pkg equivalent) package \n"
00386              "XFree86-[75,100]dpi-fonts or fonts-xorg-[75,100]dpi.\n");
00387       gFont = XLoadQueryFont(gDisplay, "fixed");
00388       if (!gFont)
00389          printf("Also couln't find font \"fixed\", your system is terminally misconfigured.\n");
00390    }
00391    if (gFont)
00392       XSetFont(gDisplay, gGC, gFont->fid);
00393    XSetForeground(gDisplay, gGC, fore);
00394    XSetBackground(gDisplay, gGC, back);
00395 
00396    if (about)
00397       ReadContributors();
00398 
00399    gCreditsHeight = DrawCredits(false, about) + gCreditsRect.height + 50;
00400    gCreditsPixmap = XCreatePixmap(gDisplay, gLogoWindow, gCreditsWidth, gCreditsHeight, depth);
00401    XSetForeground(gDisplay, gGC, back);
00402    XFillRectangle(gDisplay, gCreditsPixmap, gGC, 0, 0, gCreditsWidth, gCreditsHeight);
00403    XSetForeground(gDisplay, gGC, fore);
00404    DrawCredits(true, about);
00405 
00406    XSelectInput(gDisplay, gLogoWindow, ButtonPressMask | ExposureMask);
00407 
00408    XMapRaised(gDisplay, gLogoWindow);
00409 
00410    gettimeofday(&gPopupTime, 0);
00411 }
00412 
00413 void WaitLogo()
00414 {
00415    // Main event loop waiting till time arrives to pop down logo
00416    // or when forced by button press event.
00417 
00418    if (!gDisplay) return;
00419 
00420    int ypos = 0;
00421    bool stopScroll = false;
00422 
00423    ScrollCredits(ypos);
00424    DrawVersion();
00425    XFlush(gDisplay);
00426 
00427    while (!gDone) {
00428       XEvent event;
00429       if (XCheckMaskEvent(gDisplay, ButtonPressMask | ExposureMask, &event)) {
00430          switch (event.type) {
00431             case Expose:
00432                if (event.xexpose.count == 0) {
00433                   ScrollCredits(ypos);
00434                   DrawVersion();
00435                }
00436                break;
00437             case ButtonPress:
00438                if (gAbout && event.xbutton.button == 3)
00439                   stopScroll = stopScroll ? false : true;
00440                else
00441                   gDone = true;
00442                break;
00443             default:
00444                break;
00445          }
00446       }
00447 
00448       Sleep(100);
00449 
00450       if (!gAbout && !StayUp(gStayUp) && gMayPopdown)
00451          gDone = true;
00452 
00453       if (gAbout && !stopScroll) {
00454          if (ypos == 0) Sleep(2000);
00455          ypos++;
00456          if (ypos > (int) (gCreditsHeight - gCreditsRect.height - 50))
00457             ypos = -int(gCreditsRect.height);
00458          ScrollCredits(ypos);
00459          XFlush(gDisplay);
00460       }
00461    }
00462 
00463    if (gLogoWindow) {
00464       XUnmapWindow(gDisplay, gLogoWindow);
00465       XDestroyWindow(gDisplay, gLogoWindow);
00466       gLogoWindow = 0;
00467    }
00468    if (gLogoPixmap) {
00469       XFreePixmap(gDisplay, gLogoPixmap);
00470       gLogoPixmap = 0;
00471    }
00472    if (gCreditsPixmap) {
00473       XFreePixmap(gDisplay, gCreditsPixmap);
00474       gCreditsPixmap = 0;
00475    }
00476    if (gFont) {
00477       XFreeFont(gDisplay, gFont);
00478       gFont = 0;
00479    }
00480    if (gGC) {
00481       XFreeGC(gDisplay, gGC);
00482       gGC = 0;
00483    }
00484    if (gDisplay) {
00485       XSync(gDisplay, False);
00486       XCloseDisplay(gDisplay);
00487       gDisplay = 0;
00488    }
00489 }
00490 
00491 void PopdownLogo()
00492 {
00493    // ROOT is ready to run, may pop down the logo if stay up time expires.
00494 
00495    gMayPopdown = true;
00496 }
00497 
00498 void CloseDisplay()
00499 {
00500    // Close connection to X server (called by child).
00501 
00502    if (gDisplay)
00503       close(ConnectionNumber(gDisplay));
00504 }

Generated on Tue Jul 5 15:14:37 2011 for ROOT_528-00b_version by  doxygen 1.5.1