GRSISort
Created by P.C. Bender
Developement Team: P.C. Bender, R. Dunlop, V. Bildstein
An extension of the ROOT analysis Framework
grsixx.cxx
Go to the documentation of this file.
1 
2 //////////////////////////////////////////////////////////////////////////
3 // //
4 // GRSIxx //
5 // //
6 // X11 based routines used to display the splash screen for grsisort. //
7 // //
8 // //
9 //////////////////////////////////////////////////////////////////////////
10 
11 #include "Globals.h"
12 #include "GVersion.h"
13 
14 #include "RConfigure.h"
15 
16 #include <cstdio>
17 #include <unistd.h>
18 #include <cstdlib>
19 #include <cstring>
20 #include <pwd.h>
21 #include <sys/types.h>
22 #include <X11/Xlib.h>
23 #include <X11/xpm.h>
24 
25 #include "Rtypes.h"
26 
27 #if defined(R__AIX) || defined(R__SOLARIS)
28 #include <sys/select.h>
29 #endif
30 #include <ctime>
31 #include <sys/time.h>
32 
33 #include "TSystem.h"
34 
35 static Display* gDisplay = nullptr;
36 static Window gLogoWindow = 0;
37 static Pixmap gLogoPixmap = 0;
38 static Pixmap gCreditsPixmap = 0;
39 static GC gGC = nullptr;
40 static XFontStruct* gFont = nullptr;
41 static bool gDone = false;
42 static bool gMayPopdown = false;
43 static bool gAbout = false;
44 static unsigned int gWidth = 0;
45 static unsigned int gHeight = 0;
46 static int gStayUp = 4000; // 4 seconds
47 static XRectangle gCreditsRect = {15, 155, 285, 130}; // clip rect in logo
48 static unsigned int gCreditsWidth = gCreditsRect.width / 2; // credits pixmap size
49 static unsigned int gCreditsHeight = 0;
50 
51 static struct timeval gPopupTime;
52 
53 static const char* gConception[] = {"P. C. Bender", nullptr};
54 
55 static const char* gLeadDevelopers[] = {"P. C. Bender", "R. Dunlop", nullptr};
56 
57 // static const char *gRootDevelopers[] = {
58 // 0
59 //};
60 //
61 // static const char *gCintDevelopers[] = {
62 // 0
63 //};
64 //
65 // static const char *gRootDocumentation[] = {
66 // 0
67 //};
68 
69 static const char* gKeyContributors[] = {"V. Bildstein", "D. Miller", nullptr};
70 
71 static char** gContributors = nullptr;
72 
73 static bool StayUp(int milliSec)
74 {
75  // Returns false if milliSec milliseconds have passed since logo
76  // was popped up, true otherwise.
77 
78  struct timeval ctv, dtv, tv, ptv = gPopupTime;
79 
80  tv.tv_sec = milliSec / 1000;
81  tv.tv_usec = (milliSec % 1000) * 1000;
82 
83  gettimeofday(&ctv, nullptr);
84  if((dtv.tv_usec = ctv.tv_usec - ptv.tv_usec) < 0) {
85  dtv.tv_usec += 1000000;
86  ptv.tv_sec++;
87  }
88  dtv.tv_sec = ctv.tv_sec - ptv.tv_sec;
89 
90  if((ctv.tv_usec = tv.tv_usec - dtv.tv_usec) < 0) {
91  ctv.tv_usec += 1000000;
92  dtv.tv_sec++;
93  }
94  ctv.tv_sec = tv.tv_sec - dtv.tv_sec;
95 
96  return ctv.tv_sec >= 0;
97 }
98 
99 static void Sleep(int milliSec)
100 {
101  // Sleep for specified amount of milli seconds.
102 
103  // get current time
104  struct timeval tv;
105 
106  tv.tv_sec = milliSec / 1000;
107  tv.tv_usec = (milliSec % 1000) * 1000;
108 
109  select(0, nullptr, nullptr, nullptr, &tv);
110 }
111 
112 static Pixmap GetRootLogo()
113 {
114  // Get logo from xpm file.
115 
116  Pixmap logo = 0;
117  Screen* xscreen = XDefaultScreenOfDisplay(gDisplay);
118  if(xscreen == nullptr) {
119  return logo;
120  }
121 
122  int depth = PlanesOfScreen(xscreen);
123 
124  XWindowAttributes win_attr;
125  XGetWindowAttributes(gDisplay, gLogoWindow, &win_attr);
126 
127  XpmAttributes attr;
128  attr.valuemask = XpmVisual | XpmColormap | XpmDepth;
129  attr.visual = win_attr.visual;
130  attr.colormap = win_attr.colormap;
131  attr.depth = win_attr.depth;
132 
133 #ifdef XpmColorKey // Not available in XPM 3.2 and earlier
134  attr.valuemask |= XpmColorKey;
135  if(depth > 4) {
136  attr.color_key = XPM_COLOR;
137  } else if(depth > 2) {
138  attr.color_key = XPM_GRAY4;
139  } else if(depth > 1) {
140  attr.color_key = XPM_GRAY;
141  } else if(depth == 1) {
142  attr.color_key = XPM_MONO;
143  } else {
144  attr.valuemask &= ~XpmColorKey;
145  }
146 
147 #endif // defined(XpmColorKey)
148  std::string file;
149  file.append(getenv("GRSISYS"));
150  file.append("/libraries/TGRSIint/grsisplash_bw.xpm");
151 
152  int ret = XpmReadFileToPixmap(gDisplay, gLogoWindow, const_cast<char*>(file.c_str()), &logo, nullptr, &attr);
153  XpmFreeAttributes(&attr);
154 
155  if(ret == XpmSuccess || ret == XpmColorError) {
156  return logo;
157  }
158 
159  std::cout<<"rootx xpm error: "<<XpmGetErrorString(ret)<<std::endl;
160 
161  if(logo != 0u) {
162  XFreePixmap(gDisplay, logo);
163  }
164  logo = 0;
165 
166  return logo;
167 }
168 
169 static void ReadContributors()
170 {
171  // Read the file $ROOTSYS/README/CREDITS for the names of the
172  // contributors.
173 
174  char buf[2048];
175 #ifdef ROOTDOCDIR
176  snprintf(buf, sizeof(buf), "%s/CREDITS", ROOTDOCDIR);
177 #else
178  snprintf(buf, sizeof(buf), "%s/README/CREDITS", getenv("ROOTSYS"));
179 #endif
180 
181  gContributors = nullptr;
182 
183  FILE* f = fopen(buf, "r");
184  if(f == nullptr) {
185  return;
186  }
187 
188  int cnt = 0;
189  while(fgets(buf, sizeof(buf), f) != nullptr) {
190  if(strncmp(buf, "N: ", 3) == 0) {
191  cnt++;
192  }
193  }
194  gContributors = new char*[cnt + 1];
195 
196  cnt = 0;
197  rewind(f);
198  while(fgets(buf, sizeof(buf), f) != nullptr) {
199  if(strncmp(buf, "N: ", 3) == 0) {
200  int len = strlen(buf);
201  buf[len - 1] = 0; // remove \n
202  len -= 3; // remove "N: "
203  gContributors[cnt] = new char[len];
204  strncpy(gContributors[cnt], buf + 3, len);
205  cnt++;
206  }
207  }
208  gContributors[cnt] = nullptr;
209 
210  fclose(f);
211 }
212 
213 static void DrawVersion()
214 {
215  // Draw version string.
216 
217  char version[80];
218  sprintf(version, "Version %s", GRSI_RELEASE);
219 
220  XDrawString(gDisplay, gLogoWindow, gGC, 15, gHeight - 20, version, strlen(version));
221 }
222 
223 static void DrawROOTCredit()
224 {
225  // Draw version string.
226 
227  char version[80];
228  sprintf(version, "A ROOT based package");
229 
230  XDrawString(gDisplay, gLogoWindow, gGC, 15, gHeight - 35, version, strlen(version));
231 }
232 
233 static int DrawCreditItem(const char* creditItem, const char** members, int y, bool draw)
234 {
235  // Draw credit item.
236 
237  char credit[1024];
238  int i;
239  int lineSpacing = gFont->max_bounds.ascent + gFont->max_bounds.descent;
240 
241  strlcpy(credit, creditItem, sizeof(credit));
242  for(i = 0; (members != nullptr) && (members[i] != nullptr); i++) {
243  if(i != 0) {
244  strlcat(credit, ", ", sizeof(credit));
245  }
246  if(XTextWidth(gFont, credit, strlen(credit)) + XTextWidth(gFont, members[i], strlen(members[i])) >
247  static_cast<int>(gCreditsWidth)) {
248  if(draw) {
249  XDrawString(gDisplay, gCreditsPixmap, gGC, 0, y, credit, strlen(credit));
250  }
251  y += lineSpacing;
252  strlcpy(credit, " ", sizeof(credit));
253  }
254  strlcat(credit, members[i], sizeof(credit));
255  }
256  if(draw) {
257  XDrawString(gDisplay, gCreditsPixmap, gGC, 0, y, credit, strlen(credit));
258  }
259 
260  return y;
261 }
262 
263 static int DrawCredits(bool draw, bool)
264 {
265  /// Draw credits. If draw is true draw credits,
266  /// otherwise just return size of all credit text.
267 
268  if(gFont == nullptr) {
269  return 150; // size not important no text will be drawn anyway
270  }
271 
272  int lineSpacing = gFont->max_bounds.ascent + gFont->max_bounds.descent;
273  int y = lineSpacing;
274 
275  y = DrawCreditItem("Conception: ", gConception, y, draw);
276 
277  y += 2 * lineSpacing - 1;
278 
279  y = DrawCreditItem("Lead Developers: ", gLeadDevelopers, y, draw);
280 
281  y += 2 * lineSpacing - 1; // special layout tweak
282 
283  y = DrawCreditItem("Key Contributions: ", gKeyContributors, y, draw);
284 
285  y += 2 * lineSpacing - 1; // special layout tweak
286 
287  y += 10;
288  return y;
289 }
290 
291 void ScrollCredits(int ypos)
292 {
293  XRectangle crect[1];
294  crect[0] = gCreditsRect;
295  XSetClipRectangles(gDisplay, gGC, 0, 0, crect, 1, Unsorted);
296 
298  gCreditsRect.y);
299 
300  XSetClipMask(gDisplay, gGC, None);
301 }
302 
303 void PopupLogo(bool about)
304 {
305  // Popup logo, waiting till ROOT is ready to run.
306  gDisplay = XOpenDisplay("");
307  if(gDisplay == nullptr) {
308  return;
309  }
310 
311  gAbout = about;
312 
313  Pixel back, fore;
314  int screen = DefaultScreen(gDisplay);
315 
316  back = WhitePixel(gDisplay, screen);
317  fore = BlackPixel(gDisplay, screen);
318 
319  gLogoWindow = XCreateSimpleWindow(gDisplay, DefaultRootWindow(gDisplay), -100, -100, 50, 50, 0, fore, back);
320 
322 
323  if(gLogoPixmap == 0u) {
324  XCloseDisplay(gDisplay);
325  gDisplay = nullptr;
326  return;
327  }
328 
329  Window root;
330  int x, y;
331  unsigned int bw, depth;
332  XGetGeometry(gDisplay, gLogoPixmap, &root, &x, &y, &gWidth, &gHeight, &bw, &depth);
333 
334  Screen* xscreen = XDefaultScreenOfDisplay(gDisplay);
335 
336  if(xscreen == nullptr) {
337  XCloseDisplay(gDisplay);
338  gDisplay = nullptr;
339  return;
340  }
341  x = (WidthOfScreen(xscreen) - gWidth) / 2;
342  y = (HeightOfScreen(xscreen) - gHeight) / 2;
343 
344  XMoveResizeWindow(gDisplay, gLogoWindow, x, y, gWidth, gHeight);
345  XSync(gDisplay, False); // make sure move & resize is done before mapping
346 
347  unsigned long valmask;
348  XSetWindowAttributes xswa;
349  valmask = CWBackPixmap | CWOverrideRedirect;
350  xswa.background_pixmap = gLogoPixmap;
351  xswa.override_redirect = True;
352  XChangeWindowAttributes(gDisplay, gLogoWindow, valmask, &xswa);
353 
354  gGC = XCreateGC(gDisplay, gLogoWindow, 0, nullptr);
355  gFont = XLoadQueryFont(gDisplay, "-adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-iso8859-1");
356  if(gFont == nullptr) {
357  std::cout<<"Couldn't find font \"-adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-iso8859-1\","<<std::endl
358  <<"trying \"fixed\". Please fix your system so helvetica can be found, "<<std::endl
359  <<"this font typically is in the rpm (or pkg equivalent) package "<<std::endl
360  <<"XFree86-[75,100]dpi-fonts or fonts-xorg-[75,100]dpi."<<std::endl;
361  gFont = XLoadQueryFont(gDisplay, "fixed");
362  if(gFont == nullptr) {
363  std::cout<<"Also couln't find font \"fixed\", your system is terminally misconfigured."<<std::endl;
364  }
365  }
366  if(gFont != nullptr) {
367  XSetFont(gDisplay, gGC, gFont->fid);
368  }
369  XSetForeground(gDisplay, gGC, fore);
370  XSetBackground(gDisplay, gGC, back);
371 
372  if(about) {
374  }
375 
376  gCreditsHeight = DrawCredits(false, about) + gCreditsRect.height + 50;
378  XSetForeground(gDisplay, gGC, back);
379  XFillRectangle(gDisplay, gCreditsPixmap, gGC, 0, 0, gCreditsWidth, gCreditsHeight);
380  XSetForeground(gDisplay, gGC, fore);
381  DrawCredits(true, about);
382 
383  XSelectInput(gDisplay, gLogoWindow, ButtonPressMask | ExposureMask);
384 
385  XMapRaised(gDisplay, gLogoWindow);
386 
387  gettimeofday(&gPopupTime, nullptr);
388 }
389 
390 void WaitLogo()
391 {
392  // Main event loop waiting till time arrives to pop down logo
393  // or when forced by button press event.
394 
395  if(gDisplay == nullptr) {
396  return;
397  }
398 
399  int ypos = 0;
400  bool stopScroll = false;
401 
402  ScrollCredits(ypos);
403  DrawVersion();
404  DrawROOTCredit();
405  XFlush(gDisplay);
406 
407  while(!gDone) {
408  gSystem->Sleep(3500);
409  break;
410 
411  XEvent event;
412  if(XCheckMaskEvent(gDisplay, ButtonPressMask | ExposureMask, &event) != 0) {
413  switch(event.type) {
414  case Expose:
415  if(event.xexpose.count == 0) {
416  ScrollCredits(ypos);
417  DrawVersion();
418  }
419  break;
420  case ButtonPress:
421  if(gAbout && event.xbutton.button == 3) {
422  stopScroll = !stopScroll;
423  } else {
424  gDone = true;
425  }
426  break;
427  default: break;
428  }
429  }
430 
431  Sleep(100);
432 
433  if(!gAbout && !StayUp(gStayUp) && gMayPopdown) {
434  gDone = true;
435  }
436 
437  if(gAbout && !stopScroll) {
438  if(ypos == 0) {
439  Sleep(2000);
440  }
441  ypos++;
442  if(ypos > static_cast<int>(gCreditsHeight - gCreditsRect.height - 50)) {
443  ypos = -int(gCreditsRect.height);
444  }
445  ScrollCredits(ypos);
446  XFlush(gDisplay);
447  }
448  }
449 
450  if(gLogoWindow != 0u) {
451  XUnmapWindow(gDisplay, gLogoWindow);
452  XDestroyWindow(gDisplay, gLogoWindow);
453  gLogoWindow = 0;
454  }
455  if(gLogoPixmap != 0u) {
456  XFreePixmap(gDisplay, gLogoPixmap);
457  gLogoPixmap = 0;
458  }
459  if(gCreditsPixmap != 0u) {
460  XFreePixmap(gDisplay, gCreditsPixmap);
461  gCreditsPixmap = 0;
462  }
463  if(gFont != nullptr) {
464  XFreeFont(gDisplay, gFont);
465  gFont = nullptr;
466  }
467  if(gGC != nullptr) {
468  XFreeGC(gDisplay, gGC);
469  gGC = nullptr;
470  }
471  if(gDisplay != nullptr) {
472  XSync(gDisplay, False);
473  XCloseDisplay(gDisplay);
474  gDisplay = nullptr;
475  }
476 }
477 
479 {
480  // ROOT is ready to run, may pop down the logo if stay up time expires.
481 
482  gMayPopdown = true;
483 }
484 
486 {
487  // Close connection to X server (called by child).
488 
489  if(gDisplay != nullptr) {
490  close(ConnectionNumber(gDisplay));
491  }
492 }
static unsigned int gHeight
Definition: grsixx.cxx:45
static unsigned int gCreditsWidth
Definition: grsixx.cxx:48
static void DrawVersion()
Definition: grsixx.cxx:213
static char ** gContributors
Definition: grsixx.cxx:71
static Window gLogoWindow
Definition: grsixx.cxx:36
static XRectangle gCreditsRect
Definition: grsixx.cxx:47
static XFontStruct * gFont
Definition: grsixx.cxx:40
static bool StayUp(int milliSec)
Definition: grsixx.cxx:73
static void DrawROOTCredit()
Definition: grsixx.cxx:223
static bool gDone
Definition: grsixx.cxx:41
#define GRSI_RELEASE
Definition: GVersion.h:4
void WaitLogo()
Definition: grsixx.cxx:390
static void ReadContributors()
Definition: grsixx.cxx:169
static const char * gKeyContributors[]
Definition: grsixx.cxx:69
void PopupLogo(bool about)
Definition: grsixx.cxx:303
static int DrawCredits(bool draw, bool)
Definition: grsixx.cxx:263
static Pixmap gCreditsPixmap
Definition: grsixx.cxx:38
static Pixmap gLogoPixmap
Definition: grsixx.cxx:37
static int DrawCreditItem(const char *creditItem, const char **members, int y, bool draw)
Definition: grsixx.cxx:233
static unsigned int gCreditsHeight
Definition: grsixx.cxx:49
void ScrollCredits(int ypos)
Definition: grsixx.cxx:291
static const char * gLeadDevelopers[]
Definition: grsixx.cxx:55
static void Sleep(int milliSec)
Definition: grsixx.cxx:99
static bool gMayPopdown
Definition: grsixx.cxx:42
static GC gGC
Definition: grsixx.cxx:39
static int gStayUp
Definition: grsixx.cxx:46
static const char * gConception[]
Definition: grsixx.cxx:53
void PopdownLogo()
Definition: grsixx.cxx:478
static bool gAbout
Definition: grsixx.cxx:43
void CloseDisplay()
Definition: grsixx.cxx:485
static Display * gDisplay
Definition: grsixx.cxx:35
static unsigned int gWidth
Definition: grsixx.cxx:44
static struct timeval gPopupTime
Definition: grsixx.cxx:51
static Pixmap GetRootLogo()
Definition: grsixx.cxx:112