1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
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,
34 ************************************************************************/
37 #include <X11/Xatom.h>
38 #include <X11/Xutil.h>
40 #include "osl/endian.h"
51 unsigned char b
, g
, r
;
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
;
64 static Visual
*visual
= NULL
;
66 static int width
= WINDOW_WIDTH
;
67 static int height
= WINDOW_HEIGHT
;
70 static Colormap color_map
;
74 // Progress bar values
75 // taken from desktop/source/splash/splash.cxx
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 ); \
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
);
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 );
141 int bits
= UINT16( info_header
+ 14 );
142 int compression
= UINT16( info_header
+ 16 );
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" );
162 static void setup_color( int val
[3], color_t
*col
)
164 if ( val
[0] < 0 || val
[1] < 0 || val
[2] < 0 )
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
);
175 void splash_setup( int barc
[3], int framec
[3], int posx
, int posy
, int w
, int h
)
179 barwidth
= width
- ( 2 * PROGRESS_XOFFSET
);
181 tlx
= PROGRESS_XOFFSET
;
182 tly
= height
- PROGRESS_YOFFSET
;
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
)
215 // Number of bits set to 1
216 inline int BITS( unsigned long x
)
226 // Set 'bitmap' as the background of our 'win' window
227 static void create_pixmap()
232 Pixmap pixmap
= XCreatePixmap( display
, win
, width
, height
, depth
);
234 unsigned long value_mask
= 0;
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
;
265 fprintf( stderr
, "Unsupported machine endianity.\n" );
266 XFreeGC( display
, pixmap_gc
);
267 XFreePixmap( display
, pixmap
);
268 XDestroyImage( image
);
273 char *data
= malloc( height
* bytes_per_line
);
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 ); \
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; \
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 ); \
306 out -= 2 * pix_size * width; \
314 if ( machine_byte_order
== byte_order
)
315 COPY_IN_OUT( 4, *( (uint32_t *)out
) = (uint32_t)pixel
; out
+= 4; )
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
) );
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 );
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 );
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; )
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
) );
353 COPY_IN_OUT( 1, *( (uint8_t *)out
) = (uint8_t)pixel
; ++out
; )
357 fprintf( stderr
, "Unsupported depth: %d bits per pixel.\n", bpp
);
358 XFreeGC( display
, pixmap_gc
);
359 XFreePixmap( display
, pixmap
);
360 XDestroyImage( image
);
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
374 for ( y
= 0; y
< height
; ++y
)
376 color_t
*color
= (color_t
*)( bitmap
+ y
* ( width
* 3 + alias
) );
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
) );
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()
410 unsigned long flags
, functions
, decorations
;
412 unsigned long status
;
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 );
437 suppress_decorations_motif(); // FIXME: Unconditional until Metacity/compiz's SPLASH handling is fixed
441 // Return: 1 - success, 0 - failure
442 int splash_create_window( int argc
, char** argv
)
444 char *display_name
= NULL
;
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
;
453 display_name
= getenv( "DISPLAY" );
456 display
= XOpenDisplay( display_name
);
459 fprintf( stderr
, "Failed to open display\n" );
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,
476 BlackPixel( display
, screen
), BlackPixel( display
, screen
) );
478 XSetWindowColormap( display
, win
, color_map
);
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
);
486 XAllocColor( display
, color_map
, &barcolor
);
487 XAllocColor( display
, color_map
, &framecolor
);
489 // not resizable, no decorations, etc.
490 unsigned long value_mask
= 0;
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
,
508 suppress_decorations();
512 XSelectInput( display
, win
, 0 );
513 XMapWindow( display
, win
);
518 // Re-draw & process the events
519 // Just throwing them away - we do not need anything more...
520 static void process_events()
526 num_events
= XPending( display
);
527 while ( num_events
> 0 )
530 XNextEvent( display
, &xev
);
531 //process_event(xev);
536 void splash_draw_progress( int progress
)
541 if ( progress
> 100 )
545 int length
= ( progress
* barwidth
/ 100 ) - ( 2 * barspace
);
550 XSetForeground( display
, gc
, framecolor
.pixel
);
551 XDrawRectangle( display
, win
, gc
,
553 barwidth
, barheight
);
556 XSetForeground( display
, gc
, barcolor
.pixel
);
557 XFillRectangle( display
, win
, gc
,
558 tlx
+ barspace
, tly
+ barspace
,
559 length
+ 1, barheight
- 2*barspace
+ 1 );
565 // Close the window & cleanup
566 void splash_close_window()
568 XCloseDisplay( display
);