File: | home/maarten/src/libreoffice/core/desktop/unx/source/splashx.c |
Warning: | line 259, column 15 Value stored to 'out' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | /* |
3 | * This file is part of the LibreOffice project. |
4 | * |
5 | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | */ |
9 | |
10 | #include <config_features.h> |
11 | #include "splashx.h" |
12 | |
13 | #if defined(ENABLE_QUICKSTART_LIBPNG1) && HAVE_FEATURE_UI1 |
14 | |
15 | #include <X11/Xlib.h> |
16 | #include <X11/Xatom.h> |
17 | #include <X11/Xutil.h> |
18 | |
19 | #ifdef USE_XINERAMA1 |
20 | #include <X11/extensions/Xinerama.h> |
21 | #endif |
22 | |
23 | #include <osl/endian.h> |
24 | #include <fcntl.h> |
25 | #include <stdint.h> |
26 | #include <stdio.h> |
27 | #include <stdlib.h> |
28 | #include <string.h> |
29 | #include <unistd.h> |
30 | |
31 | #include <png.h> |
32 | |
33 | #include <osl/process.h> |
34 | #include <osl/thread.h> |
35 | #include <rtl/bootstrap.h> |
36 | #include <rtl/ustrbuf.h> |
37 | |
38 | typedef struct { |
39 | unsigned char b, g, r; |
40 | } color_t; |
41 | |
42 | struct splash |
43 | { |
44 | Display* display; |
45 | int screen; |
46 | int depth; |
47 | int display_width; |
48 | int display_height; |
49 | int display_x_pos; |
50 | int display_y_pos; |
51 | Visual* visual; |
52 | |
53 | int width; |
54 | int height; |
55 | |
56 | Colormap color_map; |
57 | Window win; |
58 | GC gc; |
59 | //true when intro-highres loaded successfully |
60 | sal_Bool bHasHiDpiImage; |
61 | |
62 | // Progress bar values |
63 | // taken from desktop/source/splash/splash.cxx |
64 | int tlx; |
65 | int tly; |
66 | int barwidth; |
67 | int barheight; |
68 | int barspace; |
69 | color_t barcol; |
70 | color_t framecol; |
71 | |
72 | XColor barcolor; |
73 | XColor framecolor; |
74 | |
75 | unsigned char** bitmap_rows; |
76 | png_structp png_ptr; |
77 | png_infop info_ptr; |
78 | |
79 | }; |
80 | |
81 | #define WINDOW_WIDTH440 440 |
82 | #define WINDOW_HEIGHT299 299 |
83 | |
84 | #define PROGRESS_XOFFSET12 12 |
85 | #define PROGRESS_YOFFSET18 18 |
86 | #define PROGRESS_BARSPACE2 2 |
87 | |
88 | /* libpng-1.2.41 */ |
89 | #ifndef PNG_TRANSFORM_GRAY_TO_RGB0x2000 |
90 | # define PNG_TRANSFORM_GRAY_TO_RGB0x2000 0x2000 |
91 | #endif |
92 | |
93 | static int splash_load_bmp( struct splash* splash, const char *filename ) |
94 | { |
95 | FILE *file; |
96 | |
97 | if ( !(file = fopen( filename, "r" ) ) ) |
98 | return 0; |
99 | |
100 | splash->png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING"1.6.37", NULL((void*)0), NULL((void*)0), NULL((void*)0) ); |
101 | splash->info_ptr = png_create_info_struct(splash->png_ptr); |
102 | png_init_io( splash->png_ptr, file ); |
103 | |
104 | if( setjmp( png_jmpbuf( splash->png_ptr ) )_setjmp ((*png_set_longjmp_fn((splash->png_ptr), longjmp, ( sizeof (jmp_buf))))) ) |
105 | { |
106 | png_destroy_read_struct( &(splash->png_ptr), &(splash->info_ptr), NULL((void*)0) ); |
107 | fclose( file ); |
108 | return 0; |
109 | } |
110 | |
111 | png_read_png( splash->png_ptr, splash->info_ptr, |
112 | PNG_TRANSFORM_EXPAND0x0010 | PNG_TRANSFORM_STRIP_ALPHA0x0002 | |
113 | PNG_TRANSFORM_GRAY_TO_RGB0x2000 | PNG_TRANSFORM_BGR0x0080, NULL((void*)0)); |
114 | |
115 | splash->bitmap_rows = png_get_rows( splash->png_ptr, splash->info_ptr ); |
116 | splash->width = png_get_image_width( splash->png_ptr, splash->info_ptr ); |
117 | splash->height = png_get_image_height( splash->png_ptr, splash->info_ptr ); |
118 | |
119 | fclose( file ); |
120 | return 1; |
121 | } |
122 | |
123 | static void setup_color( int const val[3], color_t *col ) |
124 | { |
125 | if ( val[0] < 0 || val[1] < 0 || val[2] < 0 ) |
126 | return; |
127 | |
128 | #define CONVERT_COLOR( from,to ) if ( from < 0 ) to = 0; else if ( from > 255 ) to = 255; else to = from; |
129 | CONVERT_COLOR( val[0], col->r ); |
130 | CONVERT_COLOR( val[1], col->g ); |
131 | CONVERT_COLOR( val[2], col->b ); |
132 | #undef CONVERT_COLOR |
133 | } |
134 | |
135 | /* Fill 'array' with values of the key 'name'. |
136 | Its value is a comma delimited list of integers */ |
137 | static void get_bootstrap_value( int *array, int size, rtlBootstrapHandle handle, const char *name ) |
138 | { |
139 | rtl_uString *pKey = NULL((void*)0), *pValue = NULL((void*)0); |
140 | |
141 | /* get the value from the ini file */ |
142 | rtl_uString_newFromAscii( &pKey, name ); |
143 | rtl_bootstrap_get_from_handle( handle, pKey, &pValue, NULL((void*)0) ); |
144 | |
145 | /* the value is several numbers delimited by ',' - parse it */ |
146 | if ( rtl_uString_getLength( pValue ) > 0 ) |
147 | { |
148 | rtl_uString *pToken = NULL((void*)0); |
149 | int i = 0; |
150 | sal_Int32 nIndex = 0; |
151 | for ( ; ( nIndex >= 0 ) && ( i < size ); ++i ) |
152 | { |
153 | nIndex = rtl_uString_getToken( &pToken, pValue, 0, ',', nIndex ); |
154 | array[i] = rtl_ustr_toInt32( rtl_uString_getStr( pToken ), 10 ); |
155 | } |
156 | |
157 | rtl_uString_release( pToken ); |
158 | } |
159 | |
160 | /* cleanup */ |
161 | rtl_uString_release( pKey ); |
162 | rtl_uString_release( pValue ); |
163 | } |
164 | |
165 | // setup |
166 | static void splash_setup( struct splash* splash, int const barc[3], int const framec[3], int posx, int posy, int w, int h ) |
167 | { |
168 | if ( splash->width <= 500 ) |
169 | { |
170 | splash->barwidth = splash->width - ( 2 * PROGRESS_XOFFSET12 ); |
171 | splash->barheight = 6; |
172 | splash->tlx = PROGRESS_XOFFSET12; |
173 | splash->tly = splash->height - PROGRESS_YOFFSET18; |
174 | |
175 | splash->barcol.r = 0; |
176 | splash->barcol.g = 0; |
177 | splash->barcol.b = 128; |
178 | } |
179 | |
180 | if ( posx >= 0 ) |
181 | splash->tlx = posx; |
182 | if ( posy >= 0 ) |
183 | splash->tly = posy; |
184 | if ( w >= 0 ) |
185 | splash->barwidth = w; |
186 | if ( h >= 0 ) |
187 | splash->barheight = h; |
188 | |
189 | setup_color( barc, &(splash->barcol) ); |
190 | setup_color( framec, &(splash->framecol) ); |
191 | } |
192 | |
193 | // Universal shift: bits >= 0 - left, otherwise right |
194 | #define SHIFT( x, bits )( ( (bits) >= 0 )? ( (x) << (bits) ): ( (x) >> -(bits) ) ) ( ( (bits) >= 0 )? ( (x) << (bits) ): ( (x) >> -(bits) ) ) |
195 | |
196 | // Position of the highest bit (more or less integer log2) |
197 | static int HIGHEST_BIT( unsigned long x ) |
198 | { |
199 | int i = 0; |
200 | for ( ; x; ++i ) |
201 | x >>= 1; |
202 | |
203 | return i; |
204 | } |
205 | |
206 | // Number of bits set to 1 |
207 | static int BITS( unsigned long x ) |
208 | { |
209 | int i = 0; |
210 | for ( ; x; x >>= 1 ) |
211 | if ( x & 1UL ) |
212 | ++i; |
213 | |
214 | return i; |
215 | } |
216 | |
217 | // Set 'bitmap' as the background of our 'win' window |
218 | static void create_pixmap(struct splash* splash) |
219 | { |
220 | Pixmap pixmap; |
221 | GC pixmap_gc; |
222 | XGCValues values; |
223 | |
224 | if ( !splash->bitmap_rows ) |
225 | { |
226 | return; |
227 | } |
228 | pixmap = XCreatePixmap( splash->display, splash->win, splash->width, splash->height, splash->depth ); |
229 | |
230 | pixmap_gc = XCreateGC( splash->display, pixmap, 0/*value_mask*/, &values ); |
231 | |
232 | if ( splash->visual->class == TrueColor4 ) |
233 | { |
234 | const unsigned long red_mask = splash->visual->red_mask; |
235 | const unsigned long green_mask = splash->visual->green_mask; |
236 | const unsigned long blue_mask = splash->visual->blue_mask; |
237 | |
238 | const unsigned long red_delta_mask = ( 1UL << ( 8 - BITS( red_mask ) ) ) - 1; |
239 | const unsigned long green_delta_mask = ( 1UL << ( 8 - BITS( green_mask ) ) ) - 1; |
240 | const unsigned long blue_delta_mask = ( 1UL << ( 8 - BITS( blue_mask ) ) ) - 1; |
241 | |
242 | const int red_shift = HIGHEST_BIT( red_mask ) - 8; |
243 | const int green_shift = HIGHEST_BIT( green_mask ) - 8; |
244 | const int blue_shift = HIGHEST_BIT( blue_mask ) - 8; |
245 | |
246 | XImage* image = XCreateImage( splash->display, splash->visual, splash->depth, ZPixmap2, |
247 | 0, NULL((void*)0), splash->width, splash->height, 32, 0 ); |
248 | |
249 | const int bytes_per_line = image->bytes_per_line; |
250 | const int bpp = image->bits_per_pixel; |
251 | const int byte_order = image->byte_order; |
252 | #if defined OSL_LITENDIAN |
253 | const int machine_byte_order = LSBFirst0; |
254 | #else /* OSL_BIGENDIAN */ |
255 | const int machine_byte_order = MSBFirst1; |
256 | #endif |
257 | |
258 | char *data = malloc( splash->height * bytes_per_line ); |
259 | char *out = data; |
Value stored to 'out' during its initialization is never read | |
260 | image->data = data; |
261 | |
262 | // The following dithers & converts the color_t color to one |
263 | // acceptable for the visual |
264 | #define COPY_IN_OUT( pix_size, code ) \ |
265 | { \ |
266 | int x, y; \ |
267 | for ( y = 0; y < splash->height; ++y ) \ |
268 | { \ |
269 | unsigned long red_delta = 0, green_delta = 0, blue_delta = 0; \ |
270 | color_t *in = (color_t *)(splash->bitmap_rows[y]); \ |
271 | out = data + y * bytes_per_line; \ |
272 | for ( x = 0; x < splash->width; ++x, ++in ) \ |
273 | { \ |
274 | unsigned long red = in->r + red_delta; \ |
275 | unsigned long green = in->g + green_delta; \ |
276 | unsigned long blue = in->b + blue_delta; \ |
277 | unsigned long pixel = 0; \ |
278 | uint32_t tmp = 0; \ |
279 | (void) tmp; \ |
280 | red_delta = red & red_delta_mask; \ |
281 | green_delta = green & green_delta_mask; \ |
282 | blue_delta = blue & blue_delta_mask; \ |
283 | if ( red > 255 ) \ |
284 | red = 255; \ |
285 | if ( green > 255 ) \ |
286 | green = 255; \ |
287 | if ( blue > 255 ) \ |
288 | blue = 255; \ |
289 | pixel = \ |
290 | ( SHIFT( red, red_shift )( ( (red_shift) >= 0 )? ( (red) << (red_shift) ): ( ( red) >> -(red_shift) ) ) & red_mask ) | \ |
291 | ( SHIFT( green, green_shift )( ( (green_shift) >= 0 )? ( (green) << (green_shift) ): ( (green) >> -(green_shift) ) ) & green_mask ) | \ |
292 | ( SHIFT( blue, blue_shift )( ( (blue_shift) >= 0 )? ( (blue) << (blue_shift) ): ( (blue) >> -(blue_shift) ) ) & blue_mask ); \ |
293 | code \ |
294 | } \ |
295 | } \ |
296 | } |
297 | |
298 | if ( bpp == 32 ) |
299 | { |
300 | if ( machine_byte_order == byte_order ) |
301 | COPY_IN_OUT( 4, *( (uint32_t *)out ) = (uint32_t)pixel; out += 4; ) |
302 | else |
303 | COPY_IN_OUT( 4, tmp = pixel; |
304 | *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 3 ); |
305 | *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) + 2 ); |
306 | *( (uint8_t *)out + 2 ) = *( (uint8_t *)(&tmp) + 1 ); |
307 | *( (uint8_t *)out + 3 ) = *( (uint8_t *)(&tmp) ); |
308 | out += 4; ) |
309 | } |
310 | else if ( bpp == 24 ) |
311 | { |
312 | if (machine_byte_order == byte_order) |
313 | { |
314 | #if defined OSL_LITENDIAN |
315 | COPY_IN_OUT( 3, memcpy(out, &pixel, sizeof (color_t)); out += 3; ) |
316 | #else /* OSL_BIGENDIAN */ |
317 | COPY_IN_OUT( 3, tmp = pixel; |
318 | *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 1 ); |
319 | *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) + 2 ); |
320 | *( (uint8_t *)out + 2 ) = *( (uint8_t *)(&tmp) + 3 ); |
321 | out += 3; ) |
322 | #endif |
323 | } |
324 | else |
325 | COPY_IN_OUT( 3, tmp = pixel; |
326 | *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 3 ); |
327 | *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) + 2 ); |
328 | *( (uint8_t *)out + 2 ) = *( (uint8_t *)(&tmp) + 1 ); |
329 | out += 3; ) |
330 | } |
331 | else if ( bpp == 16 ) |
332 | { |
333 | if ( machine_byte_order == byte_order ) |
334 | COPY_IN_OUT( 2, *( (uint16_t *)out ) = (uint16_t)pixel; out += 2; ) |
335 | else |
336 | COPY_IN_OUT( 2, tmp = pixel; |
337 | *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 1 ); |
338 | *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) ); |
339 | out += 2; ); |
340 | } |
341 | else if ( bpp == 8 ) |
342 | { |
343 | COPY_IN_OUT( 1, *( (uint8_t *)out ) = (uint8_t)pixel; ++out; ) |
344 | } |
345 | else |
346 | { |
347 | fprintf( stderrstderr, "Unsupported depth: %d bits per pixel.\n", bpp ); |
348 | XFreeGC( splash->display, pixmap_gc ); |
349 | XFreePixmap( splash->display, pixmap ); |
350 | XDestroyImage( image )((*((image)->f.destroy_image))((image))); |
351 | return; |
352 | } |
353 | |
354 | #undef COPY_IN_OUT |
355 | |
356 | XPutImage( splash->display, pixmap, pixmap_gc, image, 0, 0, 0, 0, splash->width, splash->height ); |
357 | XDestroyImage( image )((*((image)->f.destroy_image))((image))); |
358 | } |
359 | |
360 | XSetWindowBackgroundPixmap( splash->display, splash->win, pixmap ); |
361 | |
362 | XFreeGC( splash->display, pixmap_gc ); |
363 | XFreePixmap( splash->display, pixmap ); |
364 | } |
365 | |
366 | // The old method of hiding the window decorations |
367 | static void suppress_decorations_motif(struct splash* splash) |
368 | { |
369 | struct |
370 | { |
371 | unsigned long flags, functions, decorations; |
372 | long input_mode; |
373 | } mwmhints; |
374 | |
375 | Atom a = XInternAtom( splash->display, "_MOTIF_WM_HINTS", False0 ); |
376 | |
377 | mwmhints.flags = 15; // functions, decorations, input_mode, status |
378 | mwmhints.functions = 2; // ? |
379 | mwmhints.decorations = 0; |
380 | mwmhints.input_mode = 0; |
381 | |
382 | XChangeProperty( splash->display, splash->win, a, a, 32, |
383 | PropModeReplace0, (unsigned char*)&mwmhints, 5 ); |
384 | } |
385 | |
386 | // This is a splash, set it as such. |
387 | // If it fails, just hide the decorations... |
388 | static void suppress_decorations(struct splash* splash) |
389 | { |
390 | Atom atom_type = XInternAtom( splash->display, "_NET_WM_WINDOW_TYPE", True1 ); |
391 | Atom atom_splash = XInternAtom( splash->display, "_NET_WM_WINDOW_TYPE_SPLASH", True1 ); |
392 | |
393 | if ( atom_type != None0L && atom_splash != None0L ) |
394 | XChangeProperty( splash->display, splash->win, atom_type, XA_ATOM((Atom) 4), 32, |
395 | PropModeReplace0, (unsigned char*)&atom_splash, 1 ); |
396 | //else |
397 | suppress_decorations_motif(splash); // FIXME: Unconditional until Metacity/compiz's SPLASH handling is fixed |
398 | } |
399 | |
400 | /** |
401 | * Connects to the display and initializes splash with the screen details |
402 | * |
403 | * @return Success: 1; Failure: 0 |
404 | */ |
405 | static int splash_init_display( struct splash* splash, int argc, char** argv ) |
406 | { |
407 | char *display_name = NULL((void*)0); |
408 | int i; |
409 | #ifdef USE_XINERAMA1 |
410 | int n_xinerama_screens = 1; |
411 | XineramaScreenInfo* p_screens = NULL((void*)0); |
412 | #endif |
413 | |
414 | for ( i = 0; i < argc; i++ ) |
415 | { |
416 | if ( !strcmp( argv[i], "-display" ) || !strcmp( argv[i], "--display" ) ) |
417 | { |
418 | display_name = ( i + 1 < argc )? argv[i+1]: NULL((void*)0); |
419 | } |
420 | } |
421 | |
422 | if ( !display_name ) |
423 | { |
424 | display_name = getenv( "DISPLAY" ); |
425 | } |
426 | // init display |
427 | splash->display = XOpenDisplay( display_name ); |
428 | if ( !splash->display ) |
429 | { |
430 | fprintf( stderrstderr, "Failed to open display\n" ); |
431 | return 0; |
432 | } |
433 | |
434 | // create the window |
435 | splash->screen = DefaultScreen( splash->display )(((_XPrivDisplay)(splash->display))->default_screen); |
436 | splash->depth = DefaultDepth( splash->display, splash->screen )((&((_XPrivDisplay)(splash->display))->screens[splash ->screen])->root_depth); |
437 | splash->color_map = DefaultColormap( splash->display, splash->screen )((&((_XPrivDisplay)(splash->display))->screens[splash ->screen])->cmap); |
438 | splash->visual = DefaultVisual( splash->display, splash->screen )((&((_XPrivDisplay)(splash->display))->screens[splash ->screen])->root_visual); |
439 | |
440 | splash->display_width = DisplayWidth( splash->display, splash->screen )((&((_XPrivDisplay)(splash->display))->screens[splash ->screen])->width); |
441 | splash->display_height = DisplayHeight( splash->display, splash->screen )((&((_XPrivDisplay)(splash->display))->screens[splash ->screen])->height); |
442 | splash->display_x_pos = 0; |
443 | splash->display_y_pos = 0; |
444 | |
445 | #ifdef USE_XINERAMA1 |
446 | p_screens = XineramaQueryScreens( splash->display, &n_xinerama_screens ); |
447 | if( p_screens ) |
448 | { |
449 | for( i=0; i < n_xinerama_screens; i++ ) |
450 | { |
451 | if ( p_screens[i].screen_number == splash->screen ) |
452 | { |
453 | splash->display_width = p_screens[i].width; |
454 | splash->display_height = p_screens[i].height; |
455 | splash->display_x_pos = p_screens[i].x_org; |
456 | splash->display_y_pos = p_screens[i].y_org; |
457 | break; |
458 | } |
459 | } |
460 | XFree( p_screens ); |
461 | } |
462 | #endif |
463 | return 1; |
464 | } |
465 | |
466 | /** |
467 | * Create the window for the splash screen |
468 | * |
469 | * @return Success: 1; Failure: 0 |
470 | */ |
471 | static int splash_create_window(struct splash* splash) |
472 | { |
473 | Window root_win; |
474 | XGCValues values; |
475 | const char* name = "LibreOffice"; |
476 | const char* icon = "icon"; // FIXME |
477 | XSizeHints size_hints; |
478 | |
479 | root_win = RootWindow( splash->display, splash->screen )((&((_XPrivDisplay)(splash->display))->screens[splash ->screen])->root); |
480 | |
481 | splash->win = XCreateSimpleWindow( splash->display, root_win, |
482 | (splash->display_x_pos + (splash->display_width - splash->width)/2), |
483 | (splash->display_y_pos + (splash->display_height - splash->height)/2), |
484 | splash->width, splash->height, 0, |
485 | BlackPixel( splash->display, splash->screen )((&((_XPrivDisplay)(splash->display))->screens[splash ->screen])->black_pixel), BlackPixel( splash->display, splash->screen )((&((_XPrivDisplay)(splash->display))->screens[splash ->screen])->black_pixel) ); |
486 | |
487 | XSetWindowColormap( splash->display, splash->win, splash->color_map ); |
488 | |
489 | // setup colors |
490 | #define FILL_COLOR( xcol,col ) xcol.red = 256*col.r; xcol.green = 256*col.g; xcol.blue = 256*col.b; |
491 | FILL_COLOR( splash->barcolor, splash->barcol ); |
492 | FILL_COLOR( splash->framecolor, splash->framecol ); |
493 | #undef FILL_COLOR |
494 | |
495 | XAllocColor( splash->display, splash->color_map, &(splash->barcolor) ); |
496 | XAllocColor( splash->display, splash->color_map, &(splash->framecolor) ); |
497 | |
498 | // not resizable, no decorations, etc. |
499 | splash->gc = XCreateGC( splash->display, splash->win, 0/*value_mask*/, &values ); |
500 | |
501 | size_hints.flags = PPosition(1L << 2) | PSize(1L << 3) | PMinSize(1L << 4) | PMaxSize(1L << 5); |
502 | size_hints.x = splash->display_x_pos; |
503 | size_hints.y = splash->display_y_pos; |
504 | size_hints.width = splash->width; |
505 | size_hints.height = splash->height; |
506 | size_hints.min_width = splash->width; |
507 | size_hints.max_width = splash->width; |
508 | size_hints.min_height = splash->height; |
509 | size_hints.max_height = splash->height; |
510 | |
511 | XSetStandardProperties( splash->display, splash->win, name, icon, None0L, |
512 | NULL((void*)0), 0, &size_hints ); |
513 | |
514 | // the actual work |
515 | suppress_decorations(splash); |
516 | create_pixmap(splash); |
517 | |
518 | // show it |
519 | XSelectInput( splash->display, splash->win, 0 ); |
520 | XMapWindow( splash->display, splash->win ); |
521 | |
522 | return 1; |
523 | } |
524 | |
525 | // Re-draw & process the events |
526 | // Just throwing them away - we do not need anything more... |
527 | static void process_events(struct splash* splash) |
528 | { |
529 | XEvent xev; |
530 | int num_events; |
531 | |
532 | XFlush( splash->display ); |
533 | num_events = XPending( splash->display ); |
534 | while ( num_events > 0 ) |
535 | { |
536 | num_events--; |
537 | XNextEvent( splash->display, &xev ); |
538 | } |
539 | } |
540 | |
541 | |
542 | static rtl_String* ustr_to_str( rtl_uString* pStr ) |
543 | { |
544 | rtl_String *pOut = NULL((void*)0); |
545 | |
546 | rtl_uString2String( &pOut, rtl_uString_getStr( pStr ), |
547 | rtl_uString_getLength( pStr ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS(((sal_uInt32)0x0006) | ((sal_uInt32)0x0060) | ((sal_uInt32)0x0100 ) | ((sal_uInt32)0x0400)) ); |
548 | |
549 | return pOut; |
550 | } |
551 | |
552 | static sal_Bool isHiDPI(struct splash* splash) |
553 | { |
554 | const char* pValStr; |
555 | double nDPI; |
556 | |
557 | /* |
558 | * GNOME currently enables HiDPI support when the screen resolution is at least 192 dpi |
559 | * and the screen height (in device pixels) is at least 1200. |
560 | */ |
561 | |
562 | if (splash->display_height < 1200) |
563 | return sal_False((sal_Bool)0); |
564 | |
565 | pValStr = XGetDefault(splash->display, "Xft", "dpi"); |
566 | /* if it's too old to have this, assume it's not hidpi */ |
567 | if (!pValStr) |
568 | return sal_False((sal_Bool)0); |
569 | |
570 | nDPI = strtod(pValStr, NULL((void*)0)); |
571 | if (nDPI < 192) |
572 | return sal_False((sal_Bool)0); |
573 | |
574 | return sal_True((sal_Bool)1); |
575 | } |
576 | |
577 | #define IMG_SUFFIX".png" ".png" |
578 | |
579 | static void splash_load_image( struct splash* splash, rtl_uString* pUAppPath ) |
580 | { |
581 | /* FIXME-BCP47: if we wanted to support language tags here that would get |
582 | * complicated, this is C-source not C++ so LanguageTag can't be used. For |
583 | * now the splash screen will have to get along with language-territory. */ |
584 | |
585 | char *pBuffer, *pSuffix, *pLocale; |
586 | int nLocSize; |
587 | rtl_Locale *pLoc = NULL((void*)0); |
588 | rtl_String *pLang, *pCountry, *pAppPath; |
589 | |
590 | osl_getProcessLocale (&pLoc); |
591 | pLang = ustr_to_str (pLoc->Language); |
592 | pCountry = ustr_to_str (pLoc->Country); |
593 | |
594 | nLocSize = strlen (pLang->buffer) + strlen (pCountry->buffer) + 3; |
595 | pLocale = malloc (nLocSize); |
596 | pLocale[0] = '-'; |
597 | strcpy (pLocale + 1, pLang->buffer); |
598 | strcat (pLocale, "_"); |
599 | strcat (pLocale, pCountry->buffer); |
600 | |
601 | rtl_string_release( pCountry ); |
602 | rtl_string_release( pLang ); |
603 | |
604 | pAppPath = ustr_to_str (pUAppPath); |
605 | pBuffer = malloc (pAppPath->length + nLocSize + 256); |
606 | strcpy (pBuffer, pAppPath->buffer); |
607 | pSuffix = pBuffer + pAppPath->length; |
608 | rtl_string_release( pAppPath ); |
609 | |
610 | strcpy (pSuffix, "intro"); |
611 | strcat (pSuffix, pLocale); |
612 | strcat (pSuffix, IMG_SUFFIX".png"); |
613 | if ( splash_load_bmp( splash, pBuffer ) ) |
614 | goto cleanup; /* success */ |
615 | |
616 | /* load high resolution splash image */ |
617 | splash->bHasHiDpiImage = sal_False((sal_Bool)0); |
618 | if (isHiDPI(splash)) |
619 | { |
620 | strcpy (pSuffix, "intro-highres" IMG_SUFFIX".png"); |
621 | if ( splash_load_bmp( splash, pBuffer ) ) |
622 | { |
623 | splash->bHasHiDpiImage = sal_True((sal_Bool)1); |
624 | goto cleanup; /* success */ |
625 | } |
626 | } |
627 | /* load standard resolution splash image */ |
628 | strcpy (pSuffix, "intro" IMG_SUFFIX".png"); |
629 | if ( splash_load_bmp( splash, pBuffer ) ) |
630 | goto cleanup; /* success */ |
631 | |
632 | fprintf (stderrstderr, "Failed to find intro image\n"); |
633 | |
634 | cleanup: |
635 | free (pLocale); |
636 | free (pBuffer); |
637 | } |
638 | |
639 | /* Load the colors and size of the splash. */ |
640 | static void splash_load_defaults( struct splash* splash, rtl_uString* pAppPath, sal_Bool* bNoDefaults ) |
641 | { |
642 | rtl_uString *pSettings = NULL((void*)0), *pTmp = NULL((void*)0); |
643 | rtlBootstrapHandle handle; |
644 | int logo[1] = { -1 }, |
645 | bar[3] = { -1, -1, -1 }, |
646 | frame[3] = { -1, -1, -1 }, |
647 | pos[2] = { -1, -1 }, |
648 | size[2] = { -1, -1 }; |
649 | |
650 | /* construct the sofficerc file location */ |
651 | rtl_uString_newFromAscii( &pSettings, "file://" ); |
652 | rtl_uString_newConcat( &pSettings, pSettings, pAppPath ); |
653 | rtl_uString_newConcat( &pSettings, pSettings, pTmp ); |
654 | rtl_uString_newFromAscii( &pTmp, SAL_CONFIGFILE( "soffice" )"soffice" "rc" ); |
655 | rtl_uString_newConcat( &pSettings, pSettings, pTmp ); |
656 | |
657 | /* use it as the bootstrap file */ |
658 | handle = rtl_bootstrap_args_open( pSettings ); |
659 | |
660 | /* get the values */ |
661 | get_bootstrap_value( logo, 1, handle, "Logo" ); |
662 | get_bootstrap_value( bar, 3, handle, "ProgressBarColor" ); |
663 | get_bootstrap_value( frame, 3, handle, "ProgressFrameColor" ); |
664 | if (isHiDPI(splash) && splash->bHasHiDpiImage) |
665 | { |
666 | get_bootstrap_value( pos, 2, handle, "ProgressPositionHigh" ); |
667 | get_bootstrap_value( size, 2, handle, "ProgressSizeHigh" ); |
668 | } |
669 | else |
670 | { |
671 | get_bootstrap_value( pos, 2, handle, "ProgressPosition" ); |
672 | get_bootstrap_value( size, 2, handle, "ProgressSize" ); |
673 | } |
674 | |
675 | if ( logo[0] == 0 ) |
676 | { |
677 | *bNoDefaults = sal_True((sal_Bool)1); |
678 | } |
679 | |
680 | splash_setup( splash, bar, frame, pos[0], pos[1], size[0], size[1] ); |
681 | |
682 | /* cleanup */ |
683 | rtl_bootstrap_args_close( handle ); |
684 | rtl_uString_release( pSettings ); |
685 | rtl_uString_release( pTmp ); |
686 | } |
687 | |
688 | |
689 | // Draw the progress |
690 | void splash_draw_progress( struct splash* splash, int progress ) |
691 | { |
692 | int length = 0; |
693 | |
694 | if (!splash) |
695 | { |
696 | return; |
697 | } |
698 | // sanity |
699 | if ( progress < 0 ) |
700 | { |
701 | progress = 0; |
702 | } |
703 | if ( progress > 100 ) |
704 | { |
705 | progress = 100; |
706 | } |
707 | // draw progress... |
708 | length = ( progress * splash->barwidth / 100 ) - ( 2 * splash->barspace ); |
709 | if ( length < 0 ) |
710 | { |
711 | length = 0; |
712 | } |
713 | // border |
714 | XSetForeground( splash->display, splash->gc, splash->framecolor.pixel ); |
715 | XDrawRectangle( splash->display, splash->win, splash->gc, splash->tlx, splash->tly, |
716 | splash->barwidth, splash->barheight ); |
717 | |
718 | // progress bar |
719 | XSetForeground( splash->display, splash->gc, splash->barcolor.pixel ); |
720 | XFillRectangle( splash->display, splash->win, splash->gc, |
721 | splash->tlx + splash->barspace, splash->tly + splash->barspace, |
722 | length + 1, splash->barheight - 2 * splash->barspace + 1 ); |
723 | |
724 | // pending events |
725 | process_events(splash); |
726 | } |
727 | |
728 | void splash_destroy(struct splash* splash) |
729 | { |
730 | if(!splash) |
731 | return; |
732 | |
733 | if(splash->display) |
734 | { |
735 | if(splash->gc) |
736 | { |
737 | XFreeGC(splash->display, splash->gc); |
738 | splash->gc = NULL((void*)0); |
739 | } |
740 | |
741 | XCloseDisplay( splash->display ); |
742 | splash->display = NULL((void*)0); |
743 | png_destroy_read_struct( &(splash->png_ptr), &(splash->info_ptr), NULL((void*)0) ); |
744 | } |
745 | free(splash); |
746 | } |
747 | |
748 | struct splash* splash_create(rtl_uString* pAppPath, int argc, char** argv) |
749 | { |
750 | struct splash* splash; |
751 | sal_Bool bNoDefaults = sal_False((sal_Bool)0); |
752 | |
753 | splash = calloc(1, sizeof(struct splash)); |
754 | if (splash && !splash_init_display(splash, argc, argv)) |
755 | { |
756 | splash_destroy(splash); |
757 | splash = NULL((void*)0); |
758 | } |
759 | |
760 | if (!splash) |
761 | return NULL((void*)0); |
762 | |
763 | splash->width = WINDOW_WIDTH440; |
764 | splash->height = WINDOW_HEIGHT299; |
765 | |
766 | splash->tlx = 212; |
767 | splash->tly = 216; |
768 | splash->barwidth = 263; |
769 | splash->barheight = 8; |
770 | splash->barspace = PROGRESS_BARSPACE2; |
771 | splash->barcol.b = 18; |
772 | splash->barcol.g = 202; |
773 | splash->barcol.r = 157; |
774 | splash->framecol.b = 0xD3; |
775 | splash->framecol.g = 0xD3; |
776 | splash->framecol.r = 0xD3; |
777 | |
778 | splash_load_image( splash, pAppPath ); |
779 | splash_load_defaults( splash, pAppPath, &bNoDefaults ); |
780 | |
781 | if (!bNoDefaults && splash_create_window(splash)) |
782 | { |
783 | splash_draw_progress( splash, 0 ); |
784 | return splash; |
785 | } |
786 | |
787 | splash_destroy(splash); |
788 | return NULL((void*)0); |
789 | } |
790 | |
791 | #else /* not ENABLE_QUICKSTART_LIBPNG */ |
792 | |
793 | struct splash |
794 | { |
795 | }; |
796 | |
797 | /* Stubs that will never be called in this case */ |
798 | void splash_draw_progress( struct splash* splash, int progress ) |
799 | { |
800 | (void)splash; (void)progress; |
801 | } |
802 | |
803 | void splash_destroy(struct splash* splash) |
804 | { |
805 | (void)splash; |
806 | } |
807 | |
808 | struct splash* splash_create(rtl_uString* pAppPath, int argc, char** argv) |
809 | { |
810 | (void)pAppPath; (void)argc; (void)argv; |
811 | return NULL((void*)0); |
812 | } |
813 | |
814 | |
815 | #endif // ENABLE_QUICKSTART_LIBPNG |
816 | |
817 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |