Update ooo320-m1
[ooovba.git] / desktop / unx / source / splashx.c
blobc792cc0fc35e5b1bed971b95fb8d4a8261f4f52f
1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile$
7 * $Revision: 9695 $
9 * last change: $Author: jholesovsky $ $Date: 2007-07-03 16:36:09 +0200 (Út, 03 čec 2007) $
11 * The Contents of this file are made available subject to
12 * the terms of GNU Lesser General Public License Version 2.1.
15 * GNU Lesser General Public License Version 2.1
16 * =============================================
17 * Copyright 2005 by Sun Microsystems, Inc.
18 * 901 San Antonio Road, Palo Alto, CA 94303, USA
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License version 2.1, as published by the Free Software Foundation.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32 * MA 02111-1307 USA
34 ************************************************************************/
36 #include <X11/Xlib.h>
37 #include <X11/Xatom.h>
38 #include <X11/Xutil.h>
40 #include "osl/endian.h"
41 #include <fcntl.h>
42 #include <stdint.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
48 #include "splashx.h"
50 typedef struct {
51 unsigned char b, g, r;
52 } color_t;
54 #define WINDOW_WIDTH 440
55 #define WINDOW_HEIGHT 299
57 #define PROGRESS_XOFFSET 12
58 #define PROGRESS_YOFFSET 18
59 #define PROGRESS_BARSPACE 2
61 static Display *display = NULL;
62 static int screen;
63 static int depth;
64 static Visual *visual = NULL;
66 static int width = WINDOW_WIDTH;
67 static int height = WINDOW_HEIGHT;
68 static int alias = 0;
70 static Colormap color_map;
71 static Window win;
72 static GC gc;
74 // Progress bar values
75 // taken from desktop/source/splash/splash.cxx
76 static int tlx = 212;
77 static int tly = 216;
78 static int barwidth = 263;
79 static int barheight = 8;
80 static int barspace = PROGRESS_BARSPACE;
81 static color_t barcol = { 18, 202, 157 };
82 static color_t framecol = { 0xD3, 0xD3, 0xD3 };
84 static XColor barcolor;
85 static XColor framecolor;
87 static char *bitmap = NULL;
89 #define BMP_HEADER_LEN 14
90 #define WIN_INFO_LEN 40
92 #define UINT8( x ) ( (unsigned int)( ( (uint8_t *)( x ) )[0] ) )
94 #define UINT16( x ) ( ( (unsigned int)( ( (uint8_t *)( x ) )[0] ) ) + \
95 ( ( (unsigned int)( ( (uint8_t *)( x ) )[1] ) ) << 8 ) )
97 #define UINT32( x ) ( ( (unsigned int)( ( (uint8_t *)( x ) )[0] ) ) + \
98 ( ( (unsigned int)( ( (uint8_t *)( x ) )[1] ) ) << 8 ) + \
99 ( ( (unsigned int)( ( (uint8_t *)( x ) )[2] ) ) << 16 ) + \
100 ( ( (unsigned int)( ( (uint8_t *)( x ) )[3] ) ) << 24 ) )
102 #define MAX( x, y ) ( ( (x) > (y) )? (x): (y) )
104 #define LOAD_FAILURE( msg ) \
106 fprintf( stderr, "%s: " msg, filename ); \
107 close( fd ); \
108 return 0; \
111 // Load the specified Windows 24bit BMP to 'bitmap'
112 // Return: 1 - success, 0 - failure
113 int splash_load_bmp( char *filename )
115 int fd = open( filename, O_RDONLY );
116 if ( fd < 0 )
117 return 0;
119 char file_header[ BMP_HEADER_LEN ];
121 if ( read( fd, file_header, BMP_HEADER_LEN ) != BMP_HEADER_LEN || file_header[0] != 'B' || file_header[1] != 'M' )
122 LOAD_FAILURE( "Not a bitmap.\n" );
124 //int file_size = UINT32( file_header + 2 );
126 char info_header[ WIN_INFO_LEN ];
127 if ( read( fd, info_header, 4 ) != 4 )
128 LOAD_FAILURE( "Unable to read the header.\n" );
130 int header_size = UINT32( info_header );
131 if ( header_size != WIN_INFO_LEN )
132 LOAD_FAILURE( "Not a Windows bitmap.\n" );
134 if ( read( fd, info_header + 4, WIN_INFO_LEN - 4 ) != WIN_INFO_LEN - 4 )
135 LOAD_FAILURE( "The header ended too early.\n" );
137 width = UINT32( info_header + 4 );
138 height = UINT32( info_header + 8 );
139 alias = width % 4;
141 int bits = UINT16( info_header + 14 );
142 int compression = UINT16( info_header + 16 );
144 if ( bits != 24 )
145 LOAD_FAILURE( "Just 24 bpp bitmaps are supported.\n" );
147 if ( compression != 0 )
148 LOAD_FAILURE( "Just uncompressed bitmaps are supported.\n" );
150 ssize_t bitmap_size = width * height * 3 + alias * height;
151 bitmap = malloc( bitmap_size );
152 if ( bitmap == NULL )
153 LOAD_FAILURE( "Cannot allocate memory for the data.\n" );
155 if ( read( fd, bitmap, bitmap_size ) != bitmap_size )
156 LOAD_FAILURE( "Cannot read the bitmap data.\n" );
158 close( fd );
159 return 1;
162 static void setup_color( int val[3], color_t *col )
164 if ( val[0] < 0 || val[1] < 0 || val[2] < 0 )
165 return;
167 #define CONVERT_COLOR( from,to ) if ( from < 0 ) to = 0; else if ( from > 255 ) to = 255; else to = from;
168 CONVERT_COLOR( val[0], col->r );
169 CONVERT_COLOR( val[1], col->g );
170 CONVERT_COLOR( val[2], col->b );
171 #undef CONVERT_COLOR
174 // setup
175 void splash_setup( int barc[3], int framec[3], int posx, int posy, int w, int h )
177 if ( width <= 500 )
179 barwidth = width - ( 2 * PROGRESS_XOFFSET );
180 barheight = 6;
181 tlx = PROGRESS_XOFFSET;
182 tly = height - PROGRESS_YOFFSET;
184 barcol.r = 0;
185 barcol.g = 0;
186 barcol.b = 128;
189 if ( posx >= 0 )
190 tlx = posx;
191 if ( posy >= 0 )
192 tly = posy;
193 if ( w >= 0 )
194 barwidth = w;
195 if ( h >= 0 )
196 barheight = h;
198 setup_color( barc, &barcol );
199 setup_color( framec, &framecol );
202 // Universal shift: bits >= 0 - left, otherwise right
203 #define SHIFT( x, bits ) ( ( (bits) >= 0 )? ( (x) << (bits) ): ( (x) >> -(bits) ) )
205 // Position of the highest bit (more or less integer log2)
206 inline int HIGHEST_BIT( unsigned long x )
208 int i = 0;
209 for ( ; x; ++i )
210 x >>= 1;
212 return i;
215 // Number of bits set to 1
216 inline int BITS( unsigned long x )
218 int i = 0;
219 for ( ; x; x >>= 1 )
220 if ( x & 1UL )
221 ++i;
223 return i;
226 // Set 'bitmap' as the background of our 'win' window
227 static void create_pixmap()
229 if ( !bitmap )
230 return;
232 Pixmap pixmap = XCreatePixmap( display, win, width, height, depth );
234 unsigned long value_mask = 0;
235 XGCValues values;
236 GC pixmap_gc = XCreateGC( display, pixmap, value_mask, &values );
238 if ( visual->class == TrueColor )
240 unsigned long red_mask = visual->red_mask;
241 unsigned long green_mask = visual->green_mask;
242 unsigned long blue_mask = visual->blue_mask;
244 unsigned long red_delta_mask = ( 1UL << ( 8 - BITS( red_mask ) ) ) - 1;
245 unsigned long green_delta_mask = ( 1UL << ( 8 - BITS( green_mask ) ) ) - 1;
246 unsigned long blue_delta_mask = ( 1UL << ( 8 - BITS( blue_mask ) ) ) - 1;
248 int red_shift = HIGHEST_BIT( red_mask ) - 8;
249 int green_shift = HIGHEST_BIT( green_mask ) - 8;
250 int blue_shift = HIGHEST_BIT( blue_mask ) - 8;
252 XImage *image = XCreateImage( display, visual, depth, ZPixmap,
253 0, NULL, width, height, 32, 0 );
255 int bytes_per_line = image->bytes_per_line;
256 int bpp = image->bits_per_pixel;
257 int byte_order = image->byte_order;
258 int machine_byte_order;
259 #if defined( _LITTLE_ENDIAN )
260 machine_byte_order = LSBFirst;
261 #elif defined( _BIG_ENDIAN )
262 machine_byte_order = MSBFirst;
263 #else
265 fprintf( stderr, "Unsupported machine endianity.\n" );
266 XFreeGC( display, pixmap_gc );
267 XFreePixmap( display, pixmap );
268 XDestroyImage( image );
269 return;
271 #endif
273 char *data = malloc( height * bytes_per_line );
274 image->data = data;
276 // The following dithers & converts the color_t color to one
277 // acceptable for the visual
278 #define COPY_IN_OUT( pix_size, code ) \
280 out += pix_size * width * ( height - 1 ); \
281 int x, y; \
282 for ( y = 0; y < height; ++y ) \
284 unsigned long red_delta = 0, green_delta = 0, blue_delta = 0; \
285 color_t *in = (color_t *)( bitmap + y * ( width * 3 + alias ) ); \
286 for ( x = 0; x < width; ++x, ++in ) \
288 unsigned long red = in->r + red_delta; \
289 unsigned long green = in->g + green_delta; \
290 unsigned long blue = in->b + blue_delta; \
291 red_delta = red & red_delta_mask; \
292 green_delta = green & green_delta_mask; \
293 blue_delta = blue & blue_delta_mask; \
294 if ( red > 255 ) \
295 red = 255; \
296 if ( green > 255 ) \
297 green = 255; \
298 if ( blue > 255 ) \
299 blue = 255; \
300 unsigned long pixel = \
301 ( SHIFT( red, red_shift ) & red_mask ) | \
302 ( SHIFT( green, green_shift ) & green_mask ) | \
303 ( SHIFT( blue, blue_shift ) & blue_mask ); \
304 code \
306 out -= 2 * pix_size * width; \
310 char *out = data;
312 if ( bpp == 32 )
314 if ( machine_byte_order == byte_order )
315 COPY_IN_OUT( 4, *( (uint32_t *)out ) = (uint32_t)pixel; out += 4; )
316 else
317 COPY_IN_OUT( 4, uint32_t tmp = pixel;
318 *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 3 );
319 *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) + 2 );
320 *( (uint8_t *)out + 2 ) = *( (uint8_t *)(&tmp) + 1 );
321 *( (uint8_t *)out + 3 ) = *( (uint8_t *)(&tmp) );
322 out += 4; )
324 else if ( bpp == 24 )
326 if ( machine_byte_order == byte_order && byte_order == LSBFirst )
327 COPY_IN_OUT( 3, *( (color_t *)out ) = *( (color_t *)( &pixel ) ); out += 3; )
328 if ( machine_byte_order == byte_order && byte_order == MSBFirst )
329 COPY_IN_OUT( 3, uint32_t tmp = pixel;
330 *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 1 );
331 *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) + 2 );
332 *( (uint8_t *)out + 2 ) = *( (uint8_t *)(&tmp) + 3 );
333 out += 3; )
334 else
335 COPY_IN_OUT( 3, uint32_t tmp = pixel;
336 *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 3 );
337 *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) + 2 );
338 *( (uint8_t *)out + 2 ) = *( (uint8_t *)(&tmp) + 1 );
339 out += 3; )
341 else if ( bpp == 16 )
343 if ( machine_byte_order == byte_order )
344 COPY_IN_OUT( 2, *( (uint16_t *)out ) = (uint16_t)pixel; out += 2; )
345 else
346 COPY_IN_OUT( 2, uint16_t tmp = pixel;
347 *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 1 );
348 *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) );
349 out += 2; );
351 else if ( bpp == 8 )
353 COPY_IN_OUT( 1, *( (uint8_t *)out ) = (uint8_t)pixel; ++out; )
355 else
357 fprintf( stderr, "Unsupported depth: %d bits per pixel.\n", bpp );
358 XFreeGC( display, pixmap_gc );
359 XFreePixmap( display, pixmap );
360 XDestroyImage( image );
361 return;
364 #undef COPY_IN_OUT
366 XPutImage( display, pixmap, pixmap_gc, image, 0, 0, 0, 0, width, height );
367 XDestroyImage( image );
369 else //if ( depth == 1 || visual->class == DirectColor )
371 // FIXME Something like the following, but faster ;-) - XDrawPoint is not
372 // a good idea...
373 int x, y;
374 for ( y = 0; y < height; ++y )
376 color_t *color = (color_t *)( bitmap + y * ( width * 3 + alias ) );
378 int delta = 0;
379 for ( x = 0; x < width; ++x, ++color )
381 int rnd = (int)( ( (long)( random() - RAND_MAX/2 ) * 32000 )/RAND_MAX );
382 int luminance = delta + rnd + 299 * (int)color->r + 587 * (int)color->g + 114 * (int)color->b;
384 if ( luminance < 128000 )
386 XSetForeground( display, pixmap_gc, BlackPixel( display, screen ) );
387 delta = luminance;
389 else
391 XSetForeground( display, pixmap_gc, WhitePixel( display, screen ) );
392 delta = luminance - 255000;
395 XDrawPoint( display, pixmap, pixmap_gc, x, y );
400 XSetWindowBackgroundPixmap( display, win, pixmap );
402 XFreeGC( display, pixmap_gc );
403 XFreePixmap( display, pixmap );
406 // The old method of hiding the window decorations
407 static void suppress_decorations_motif()
409 struct {
410 unsigned long flags, functions, decorations;
411 long input_mode;
412 unsigned long status;
413 } mwmhints;
415 Atom a = XInternAtom( display, "_MOTIF_WM_HINTS", False );
417 mwmhints.flags = 15; // functions, decorations, input_mode, status
418 mwmhints.functions = 2; // ?
419 mwmhints.decorations = 0;
420 mwmhints.input_mode = 0;
422 XChangeProperty( display, win, a, a, 32,
423 PropModeReplace, (unsigned char*)&mwmhints, 5 );
426 // This is a splash, set it as such.
427 // If it fails, just hide the decorations...
428 static void suppress_decorations()
430 Atom atom_type = XInternAtom( display, "_NET_WM_WINDOW_TYPE", True );
431 Atom atom_splash = XInternAtom( display, "_NET_WM_WINDOW_TYPE_SPLASH", True );
433 if ( atom_type != None && atom_splash != None )
434 XChangeProperty( display, win, atom_type, XA_ATOM, 32,
435 PropModeReplace, (unsigned char*)&atom_splash, 1 );
436 //else
437 suppress_decorations_motif(); // FIXME: Unconditional until Metacity/compiz's SPLASH handling is fixed
440 // Create the window
441 // Return: 1 - success, 0 - failure
442 int splash_create_window( int argc, char** argv )
444 char *display_name = NULL;
445 int i;
446 for ( i = 0; i < argc; i++ )
448 if ( !strcmp( argv[i], "-display" ) || !strcmp( argv[i], "--display" ) )
449 display_name = ( i + 1 < argc )? argv[i+1]: NULL;
452 if ( !display_name )
453 display_name = getenv( "DISPLAY" );
455 // init display
456 display = XOpenDisplay( display_name );
457 if ( !display )
459 fprintf( stderr, "Failed to open display\n" );
460 return 0;
463 // create the window
464 screen = DefaultScreen( display );
465 depth = DefaultDepth( display, screen );
466 color_map = DefaultColormap( display, screen );
467 visual = DefaultVisual( display, screen );
469 Window root_win = RootWindow( display, screen );
470 int display_width = DisplayWidth( display, screen );
471 int display_height = DisplayHeight( display, screen );
473 win = XCreateSimpleWindow( display, root_win,
474 ( display_width - width ) / 2, ( display_height - height ) / 2,
475 width, height, 0,
476 BlackPixel( display, screen ), BlackPixel( display, screen ) );
478 XSetWindowColormap( display, win, color_map );
480 // setup colors
481 #define FILL_COLOR( xcol,col ) xcol.red = 256*col.r; xcol.green = 256*col.g; xcol.blue = 256*col.b;
482 FILL_COLOR( barcolor, barcol );
483 FILL_COLOR( framecolor, framecol );
484 #undef FILL_COLOR
486 XAllocColor( display, color_map, &barcolor );
487 XAllocColor( display, color_map, &framecolor );
489 // not resizable, no decorations, etc.
490 unsigned long value_mask = 0;
491 XGCValues values;
492 gc = XCreateGC( display, win, value_mask, &values );
494 XSizeHints size_hints;
495 size_hints.flags = PPosition | PSize | PMinSize | PMaxSize;
496 size_hints.min_width = width;
497 size_hints.max_width = width;
498 size_hints.min_height = height;
499 size_hints.max_height = height;
501 char *name = "OpenOffice.org";
502 char *icon = "icon"; // FIXME
504 XSetStandardProperties( display, win, name, icon, None,
505 0, 0, &size_hints );
507 // the actual work
508 suppress_decorations();
509 create_pixmap();
511 // show it
512 XSelectInput( display, win, 0 );
513 XMapWindow( display, win );
515 return 1;
518 // Re-draw & process the events
519 // Just throwing them away - we do not need anything more...
520 static void process_events()
522 XEvent xev;
523 int num_events;
525 XFlush( display );
526 num_events = XPending( display );
527 while ( num_events > 0 )
529 num_events--;
530 XNextEvent( display, &xev );
531 //process_event(xev);
535 // Draw the progress
536 void splash_draw_progress( int progress )
538 // sanity
539 if ( progress < 0 )
540 progress = 0;
541 if ( progress > 100 )
542 progress = 100;
544 // draw progress...
545 int length = ( progress * barwidth / 100 ) - ( 2 * barspace );
546 if ( length < 0 )
547 length = 0;
549 // border
550 XSetForeground( display, gc, framecolor.pixel );
551 XDrawRectangle( display, win, gc,
552 tlx, tly,
553 barwidth, barheight );
555 // progress bar
556 XSetForeground( display, gc, barcolor.pixel );
557 XFillRectangle( display, win, gc,
558 tlx + barspace, tly + barspace,
559 length + 1, barheight - 2*barspace + 1 );
561 // pending events
562 process_events();
565 // Close the window & cleanup
566 void splash_close_window()
568 XCloseDisplay( display );
570 free( bitmap );
571 bitmap = NULL;