From da2cae2e72a7302bb9771df5d8d76796fca5faf9 Mon Sep 17 00:00:00 2001 From: Fons Rademakers <Fons.Rademakers@cern.ch> Date: Thu, 8 Jan 2004 23:06:52 +0000 Subject: [PATCH] uses new splash screen. Screen does not need modification anymore for each new minor release. Version is printed over it and taken from the ROOT_RELEASE define. All core developers are credited. When called as "root -a" the credit text scrolls and shows names of all people in CREDITS file. The "About ROOT..." menu items in the Help menus of TCanvas, TBrowser and TTreeViewer call "root -a &" and show the scrolling credits. To close splash screen click with mouse in it. Not yet tested on display with < 255 colors so some tuning might be needed for these old enviroments. git-svn-id: http://root.cern.ch/svn/root/trunk@7869 27541ba8-7e3a-0410-8455-c3a389f83636 --- rootx/src/rootx.cxx | 39 ++-- rootx/src/rootxx.cxx | 447 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 387 insertions(+), 99 deletions(-) diff --git a/rootx/src/rootx.cxx b/rootx/src/rootx.cxx index 851de8b40cf..904a3157142 100644 --- a/rootx/src/rootx.cxx +++ b/rootx/src/rootx.cxx @@ -1,4 +1,4 @@ -// @(#)root/rootx:$Name: $:$Id: rootx.cxx,v 1.10 2003/07/27 08:05:07 brun Exp $ +// @(#)root/rootx:$Name: $:$Id: rootx.cxx,v 1.11 2003/10/13 18:20:18 rdm Exp $ // Author: Fons Rademakers 19/02/98 ////////////////////////////////////////////////////////////////////////// @@ -78,14 +78,14 @@ #define ROOTBINARY "root.exe" #endif -extern void PopupLogo(); +extern void PopupLogo(bool); +extern void WaitLogo(); extern void PopdownLogo(); extern void CloseDisplay(); static STRUCT_UTMP *gUtmpContents; -static int gBatch = 0; -static int gNoLogo = 0; +static bool gNoLogo = false; static int GetErrno() @@ -233,7 +233,7 @@ static void SigUsr1(int) { // When we get SIGUSR1 from child (i.e. ROOT) then pop down logo. - if (!gBatch) + if (!gNoLogo) PopdownLogo(); } @@ -293,24 +293,38 @@ int main(int argc, char **argv) } #endif - // In batch mode don't show splash screen + // In batch mode don't show splash screen, idem for no logo mode, + // in about mode show always splash screen + bool batch = false, about = false; int i; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-?") || !strncmp(argv[i], "-h", 2)) { PrintUsage(argv[0]); return 1; } - if (!strcmp(argv[i], "-b")) gBatch = 1; - if (!strcmp(argv[i], "-l")) gNoLogo = 1; + if (!strcmp(argv[i], "-b")) batch = true; + if (!strcmp(argv[i], "-l")) gNoLogo = true; + if (!strcmp(argv[i], "-a")) about = true; + } + if (batch) + gNoLogo = true; + if (about) { + batch = false; + gNoLogo = false; } - if (!gBatch) { + if (!batch) { SetDisplay(); if (!getenv("DISPLAY")) { fprintf(stderr, "%s: can't figure out DISPLAY, set it manually\n", argv[0]); return 1; } - if (!gNoLogo) PopupLogo(); + if (about) { + PopupLogo(true); + WaitLogo(); + return 0; + } else if (!gNoLogo) + PopupLogo(false); } // Ignore SIGINT and SIGQUIT. Install handler for SIGUSR1. @@ -350,8 +364,11 @@ int main(int argc, char **argv) if ((childpid = fork()) < 0) { fprintf(stderr, "%s: error forking child\n", argv[0]); return 1; - } else if (childpid > 0) + } else if (childpid > 0) { + if (!gNoLogo) + WaitLogo(); WaitChild(childpid); + } // Continue with child... diff --git a/rootx/src/rootxx.cxx b/rootx/src/rootxx.cxx index 3f7570dac03..99ef45626e9 100644 --- a/rootx/src/rootxx.cxx +++ b/rootx/src/rootxx.cxx @@ -1,4 +1,4 @@ -// @(#)root/rootx:$Name: $:$Id: rootxx.cxx,v 1.1.1.1 2000/05/16 17:00:48 rdm Exp $ +// @(#)root/rootx:$Name: $:$Id: rootxx.cxx,v 1.2 2001/06/22 16:10:21 rdm Exp $ // Author: Fons Rademakers 19/02/98 ////////////////////////////////////////////////////////////////////////// @@ -10,8 +10,16 @@ // // ////////////////////////////////////////////////////////////////////////// +#ifdef HAVE_CONFIG +#include "config.h" +#endif + #include <stdio.h> #include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <pwd.h> +#include <sys/types.h> #include <X11/Xlib.h> #include "RConfig.h" @@ -23,55 +31,98 @@ #include <time.h> #include <sys/time.h> -#ifdef XpmVersion -#ifndef XpmSuccess -#define XpmSuccess 0 -#endif -#ifndef XpmColorError -#define XpmColorError 1 -#endif -#endif - -// X bitmaps -#include "rootlogo_xbm.h" -#ifdef XpmVersion -#include "rootlogo_xpm.h" -#endif - - -static Display *gDisplay = 0; -static Window gLogoWindow = 0; -static Pixmap gLogoPixmap = 0; +static Display *gDisplay = 0; +static Window gLogoWindow = 0; +static Pixmap gLogoPixmap = 0; +static Pixmap gCreditsPixmap = 0; +static GC gGC = 0; +static XFontStruct *gFont = 0; +static bool gDone = false; +static bool gMayPopdown = false; +static bool gAbout = false; +static unsigned int gWidth = 0; +static unsigned int gHeight = 0; +static int gStayUp = 4000; // 4 seconds +static XRectangle gCreditsRect = { 15, 155, 285, 130 }; // clip rect in logo +static unsigned int gCreditsWidth = gCreditsRect.width; // credits pixmap size +static unsigned int gCreditsHeight = 0; static struct timeval gPopupTime; - - -static void StayUp(int milliSec) +static const char *gConception[] = { + "Rene Brun", + "Fons Rademakers", + 0 +}; + +static const char *gRootDevelopers[] = { + "Ilka Antcheva", + "Maarten Ballintijn", + "Bertrand Bellenot", + "Rene Brun", + "Philippe Canal", + "Olivier Couet", + "Gerardo Ganis", + "Eddy Offermann", + "Valeriy Onuchin", + "Fons Rademakers", + 0 +}; + +static const char *gCintDevelopers[] = { + "Masaharu Goto", + 0 +}; + +static const char *gRootDocumentation[] = { + "Ilka Antcheva", + "Susan Panachek", + 0 +}; + +static char **gContributors = 0; + + + +static bool StayUp(int milliSec) { - // Make sure milliSec milliseconds have passed since logo was popped up. + // Returns false if milliSec milliseconds have passed since logo + // was popped up, true otherwise. - // get current time - struct timeval ctv, dtv, tv; + struct timeval ctv, dtv, tv, ptv = gPopupTime; tv.tv_sec = milliSec / 1000; tv.tv_usec = (milliSec % 1000) * 1000; gettimeofday(&ctv, 0); - if ((dtv.tv_usec = ctv.tv_usec - gPopupTime.tv_usec) < 0) { + if ((dtv.tv_usec = ctv.tv_usec - ptv.tv_usec) < 0) { dtv.tv_usec += 1000000; - gPopupTime.tv_sec++; + ptv.tv_sec++; } - dtv.tv_sec = ctv.tv_sec - gPopupTime.tv_sec; + dtv.tv_sec = ctv.tv_sec - ptv.tv_sec; if ((ctv.tv_usec = tv.tv_usec - dtv.tv_usec) < 0) { - tv.tv_usec += 1000000; + ctv.tv_usec += 1000000; dtv.tv_sec++; } ctv.tv_sec = tv.tv_sec - dtv.tv_sec; - if (ctv.tv_sec < 0) return; - select(0, 0, 0, 0, &ctv); + if (ctv.tv_sec < 0) return false; + + return true; +} + +static void Sleep(int milliSec) +{ + // Sleep for specified amount of milli seconds. + + // get current time + struct timeval tv; + + tv.tv_sec = milliSec / 1000; + tv.tv_usec = (milliSec % 1000) * 1000; + + select(0, 0, 0, 0, &tv); } static Pixel Color(const char *name) @@ -88,76 +139,214 @@ static Pixel Color(const char *name) static Pixmap GetRootLogo() { + // Get logo from xpm file. + Pixmap logo = 0; int depth = PlanesOfScreen(XDefaultScreenOfDisplay(gDisplay)); -#ifdef XpmVersion - if (depth > 1) { - XWindowAttributes win_attr; - XGetWindowAttributes(gDisplay, gLogoWindow, &win_attr); + XWindowAttributes win_attr; + XGetWindowAttributes(gDisplay, gLogoWindow, &win_attr); - XpmAttributes attr; - attr.valuemask = XpmVisual | XpmColormap | XpmDepth; - attr.visual = win_attr.visual; - attr.colormap = win_attr.colormap; - attr.depth = win_attr.depth; + XpmAttributes attr; + attr.valuemask = XpmVisual | XpmColormap | XpmDepth; + attr.visual = win_attr.visual; + attr.colormap = win_attr.colormap; + attr.depth = win_attr.depth; #ifdef XpmColorKey // Not available in XPM 3.2 and earlier - attr.valuemask |= XpmColorKey; - if (depth > 4) - attr.color_key = XPM_COLOR; - else if (depth > 2) - attr.color_key = XPM_GRAY4; - else if (depth > 1) - attr.color_key = XPM_GRAY; - else if (depth == 1) - attr.color_key = XPM_MONO; - else - attr.valuemask &= ~XpmColorKey; + attr.valuemask |= XpmColorKey; + if (depth > 4) + attr.color_key = XPM_COLOR; + else if (depth > 2) + attr.color_key = XPM_GRAY4; + else if (depth > 1) + attr.color_key = XPM_GRAY; + else if (depth == 1) + attr.color_key = XPM_MONO; + else + attr.valuemask &= ~XpmColorKey; #endif // defined(XpmColorKey) - int ret = XpmCreatePixmapFromData(gDisplay, gLogoWindow, - (char **)rootlogo, &logo, - (Pixmap *)0, &attr); - XpmFreeAttributes(&attr); + char file[2048]; +#ifdef ROOTICONPATH + sprintf(file, "%s/Splash.xpm", ROOTICONPATH); +#else + sprintf(file, "%s/icons/Splash.xpm", getenv("ROOTSYS")); +#endif + int ret = XpmReadFileToPixmap(gDisplay, gLogoWindow, + file, &logo, 0, &attr); + XpmFreeAttributes(&attr); + + if (ret == XpmSuccess || ret == XpmColorError) + return logo; + + printf("rootx xpm error: %s\n", XpmGetErrorString(ret)); + + if (logo) XFreePixmap(gDisplay, logo); + logo = 0; + + return logo; +} + +static void ReadContributors() +{ + // Read the file $ROOTSYS/README/CREDITS for the names of the + // contributors. + + char buf[2048]; +#ifdef ROOTDOCDIR + sprintf(buf, "%s/CREDITS", ROOTDOCDIR); +#else + sprintf(buf, "%s/README/CREDITS", getenv("ROOTSYS")); +#endif + + gContributors = 0; - if (ret == XpmSuccess || ret == XpmColorError) - return logo; + FILE *f = fopen(buf, "r"); + if (!f) return; - if (logo) - XFreePixmap(gDisplay, logo); - logo = 0; + int cnt = 0; + while (fgets(buf, sizeof(buf), f)) { + if (!strncmp(buf, "N: ", 3)) { + cnt++; + } + } + gContributors = new char*[cnt+1]; + + cnt = 0; + rewind(f); + while (fgets(buf, sizeof(buf), f)) { + if (!strncmp(buf, "N: ", 3)) { + int len = strlen(buf); + buf[len-1] = 0; // remove \n + len -= 3; // remove "N: " + gContributors[cnt] = new char[len]; + strncpy(gContributors[cnt], buf+3, len); + cnt++; + } } + gContributors[cnt] = 0; -#endif // defined(XpmVersion) + fclose(f); +} - if (depth > 4) - logo = XCreatePixmapFromBitmapData(gDisplay, gLogoWindow, - rootlogo_bits, - rootlogo_width, rootlogo_height, - Color("brown"), - Color("white"), - depth); - else { - int screen = DefaultScreen(gDisplay); - logo = XCreatePixmapFromBitmapData(gDisplay, gLogoWindow, - rootlogo_bits, - rootlogo_width, rootlogo_height, - BlackPixel(gDisplay, screen), - WhitePixel(gDisplay, screen), - depth); +static void DrawVersion() +{ + // Draw version string. + + char version[80]; + sprintf(version, "Version %s", ROOT_RELEASE); + + XDrawString(gDisplay, gLogoWindow, gGC, 15, gHeight - 15, version, + strlen(version)); +} + +static int DrawCreditItem(const char *creditItem, const char **members, + int y, bool draw) +{ + // Draw credit item. + + char credit[1024]; + int i; + int lineSpacing = gFont->max_bounds.ascent + gFont->max_bounds.descent; + + strcpy(credit, creditItem); + for (i = 0; members && members[i]; i++) { + if (i) strcat(credit, ", "); + if (XTextWidth(gFont, credit, strlen(credit)) + + XTextWidth(gFont, members[i], strlen(members[i])) > (int) gCreditsWidth) { + if (draw) + XDrawString(gDisplay, gCreditsPixmap, gGC, 0, y, credit, strlen(credit)); + y += lineSpacing; + strcpy(credit, " "); + } + strcat(credit, members[i]); } - return logo; + if (draw) + XDrawString(gDisplay, gCreditsPixmap, gGC, 0, y, credit, strlen(credit)); + + return y; +} + +static int DrawCredits(bool draw, bool extended) +{ + // Draw credits. If draw is true draw credits, + // otherwise just return size of all credit text. + // If extended is true draw or returns size for extended full + // credits list. + + int lineSpacing = gFont->max_bounds.ascent + gFont->max_bounds.descent; + int y = 2*lineSpacing; + + y = DrawCreditItem("Conception: ", gConception, y, draw); + + y += 2*lineSpacing; + + y = DrawCreditItem("Engineering: ", gRootDevelopers, y, draw); + + y += 2*lineSpacing; + + y = DrawCreditItem("CINT C/C++ Intepreter: ", gCintDevelopers, y, draw); + + y += 2*lineSpacing; + + y = DrawCreditItem("Documentation: ", gRootDocumentation, y, draw); + + if (extended && gContributors) { + y += 2*lineSpacing; + y = DrawCreditItem("Contributors: ", (const char **)gContributors, y, draw); + + y += 2*lineSpacing; + y = DrawCreditItem("Special thanks to the neglected families and friends", 0, y, draw); + y += lineSpacing; + y = DrawCreditItem("of the aforementioned persons.", 0, y, draw); + + y += 2*lineSpacing; + y = DrawCreditItem("Our sincere thanks and apologies to anyone who deserves", 0, y, draw); + y += lineSpacing; + y = DrawCreditItem("credit but fails to appear in this list.", 0, y, draw); + + struct passwd *pwd = getpwuid(getuid()); + if (pwd) { + char *name = new char [strlen(pwd->pw_gecos)+1]; + strcpy(name, pwd->pw_gecos); + char *s = strchr(name, ','); + if (s) *s = 0; + char line[1024]; + sprintf(line, "Extra special thanks go to %s,", name); + delete [] name; + y += 2*lineSpacing; + y = DrawCreditItem(line, 0, y, draw); + y += lineSpacing; + y = DrawCreditItem("one of our favorite users.", 0, y, draw); + } + } + + return y; +} + +void ScrollCredits(int ypos) +{ + XRectangle crect[1]; + crect[0] = gCreditsRect; + XSetClipRectangles(gDisplay, gGC, 0, 0, crect, 1, Unsorted); + + XCopyArea(gDisplay, gCreditsPixmap, gLogoWindow, gGC, + 0, ypos, gCreditsWidth, gCreditsHeight, gCreditsRect.x, gCreditsRect.y); + + XSetClipMask(gDisplay, gGC, None); } -void PopupLogo() +void PopupLogo(bool about) { // Popup logo, waiting till ROOT is ready to run. gDisplay = XOpenDisplay(""); if (!gDisplay) return; + gAbout = about; + Pixel back, fore; int screen = DefaultScreen(gDisplay); @@ -168,17 +357,23 @@ void PopupLogo() -100, -100, 50, 50, 0, fore, back); gLogoPixmap = GetRootLogo(); + if (!gLogoPixmap) { + XCloseDisplay(gDisplay); + gDisplay = 0; + return; + } Window root; int x, y; - unsigned int w, h, bw, depth; - XGetGeometry(gDisplay, gLogoPixmap, &root, &x, &y, &w, &h, &bw, &depth); + unsigned int bw, depth; + XGetGeometry(gDisplay, gLogoPixmap, &root, &x, &y, &gWidth, &gHeight, + &bw, &depth); Screen *xscreen = XDefaultScreenOfDisplay(gDisplay); - x = (WidthOfScreen(xscreen) - w) / 2; - y = (HeightOfScreen(xscreen) - h) / 2; + x = (WidthOfScreen(xscreen) - gWidth) / 2; + y = (HeightOfScreen(xscreen) - gHeight) / 2; - XMoveResizeWindow(gDisplay, gLogoWindow, x, y, w, h); + XMoveResizeWindow(gDisplay, gLogoWindow, x, y, gWidth, gHeight); XSync(gDisplay, False); // make sure move & resize is done before mapping unsigned long valmask; @@ -188,17 +383,74 @@ void PopupLogo() xswa.override_redirect = True; XChangeWindowAttributes(gDisplay, gLogoWindow, valmask, &xswa); + gGC = XCreateGC(gDisplay, gLogoWindow, 0, 0); + gFont = XLoadQueryFont(gDisplay, "-adobe-helvetica-medium-r-*-*-10-*-*-*-*-*-iso8859-1"); + XSetFont(gDisplay, gGC, gFont->fid); + XSetForeground(gDisplay, gGC, fore); + XSetBackground(gDisplay, gGC, back); + + if (about) + ReadContributors(); + + gCreditsHeight = DrawCredits(false, about) + gCreditsRect.height + 50; + gCreditsPixmap = XCreatePixmap(gDisplay, gLogoWindow, gCreditsWidth, gCreditsHeight, depth); + XSetForeground(gDisplay, gGC, back); + XFillRectangle(gDisplay, gCreditsPixmap, gGC, 0, 0, gCreditsWidth, gCreditsHeight); + XSetForeground(gDisplay, gGC, fore); + DrawCredits(true, about); + + XSelectInput(gDisplay, gLogoWindow, ButtonPressMask | ExposureMask); + XMapRaised(gDisplay, gLogoWindow); - XSync(gDisplay, False); gettimeofday(&gPopupTime, 0); } -void PopdownLogo() +void WaitLogo() { - // Pop down the logo. ROOT is ready to run. + // Main event loop waiting till time arrives to pop down logo + // or when forced by button press event. - StayUp(4000); + if (!gDisplay) return; + + int ypos = 0; + + ScrollCredits(ypos); + DrawVersion(); + XFlush(gDisplay); + + while (!gDone) { + XEvent event; + if (XCheckMaskEvent(gDisplay, ButtonPressMask | ExposureMask, &event)) { + switch (event.type) { + case Expose: + if (event.xexpose.count == 0) { + ScrollCredits(ypos); + DrawVersion(); + } + break; + case ButtonPress: + gDone = true; + break; + default: + break; + } + } + + Sleep(100); + + if (!gAbout && !StayUp(gStayUp) && gMayPopdown) + gDone = true; + + if (gAbout) { + if (ypos == 0) Sleep(2000); + ypos++; + if (ypos > (int) (gCreditsHeight - gCreditsRect.height - 50)) + ypos = -int(gCreditsRect.height); + ScrollCredits(ypos); + XFlush(gDisplay); + } + } if (gLogoWindow) { XUnmapWindow(gDisplay, gLogoWindow); @@ -209,6 +461,18 @@ void PopdownLogo() XFreePixmap(gDisplay, gLogoPixmap); gLogoPixmap = 0; } + if (gCreditsPixmap) { + XFreePixmap(gDisplay, gCreditsPixmap); + gCreditsPixmap = 0; + } + if (gFont) { + XFreeFont(gDisplay, gFont); + gFont = 0; + } + if (gGC) { + XFreeGC(gDisplay, gGC); + gGC = 0; + } if (gDisplay) { XSync(gDisplay, False); XCloseDisplay(gDisplay); @@ -216,6 +480,13 @@ void PopdownLogo() } } +void PopdownLogo() +{ + // ROOT is ready to run, may pop down the logo if stay up time expires. + + gMayPopdown = true; +} + void CloseDisplay() { // Close connection to X server (called by child). -- GitLab