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