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