]> git.sesse.net Git - vlc/blob - modules/gui/skins2/x11/x11_display.cpp
* x11/x11_display.cpp: the "parent" window now receive structure
[vlc] / modules / gui / skins2 / x11 / x11_display.cpp
1 /*****************************************************************************
2  * x11_display.cpp
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id$
6  *
7  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
8  *          Olivier Teulière <ipkiss@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 #ifdef X11_SKINS
26
27 #include <X11/Xlib.h>
28 #include <X11/Xutil.h>
29 #include <X11/extensions/shape.h>
30
31 #include "x11_display.hpp"
32 #include "../src/logger.hpp"
33
34
35 X11Display::X11Display( intf_thread_t *pIntf ): SkinObject( pIntf ),
36     m_mainWindow( 0 ), m_gc( NULL ), m_colormap( 0 )
37 {
38     // Open a connection to the X Server
39     m_pDisplay = XOpenDisplay( NULL );
40
41     if( m_pDisplay == NULL )
42     {
43         MSG_ERR( "Cannot open display" );
44         return;
45     }
46
47     // Load the XShape extension
48     int event, error;
49     XShapeQueryExtension( m_pDisplay, &event, &error );
50
51     // Get the display parameters
52     int screen = DefaultScreen( m_pDisplay );
53     int depth = DefaultDepth( m_pDisplay, screen );
54     int order = ImageByteOrder( m_pDisplay );
55
56     // Template for looking up the XVisualInfo
57     XVisualInfo xVInfoTemplate;
58     xVInfoTemplate.screen = screen;
59     xVInfoTemplate.depth = depth;
60
61     XVisualInfo *pVInfo = NULL;
62     int vCount = 0;
63
64     switch( depth )
65     {
66         case 8:
67             xVInfoTemplate.c_class = DirectColor;
68             // Get the DirectColor visual
69             pVInfo = XGetVisualInfo( m_pDisplay, VisualScreenMask |
70                                      VisualClassMask, &xVInfoTemplate,
71                                      &vCount );
72             if( pVInfo == NULL )
73             {
74                 msg_Err( getIntf(), "no DirectColor visual available" );
75                 m_pDisplay = NULL;
76                 break;
77             }
78             m_pVisual = pVInfo->visual;
79
80             // Compute the color shifts
81             getShifts( pVInfo->red_mask, m_redLeftShift, m_redRightShift );
82             getShifts( pVInfo->green_mask, m_greenLeftShift,
83                        m_greenRightShift );
84             getShifts( pVInfo->blue_mask, m_blueLeftShift, m_blueRightShift );
85
86             // Create a color map
87             m_colormap = XCreateColormap( m_pDisplay,
88                     DefaultRootWindow( m_pDisplay ),
89                     DefaultVisual( m_pDisplay, screen ), AllocAll );
90
91             // Create the palette
92             XColor pColors[255];
93             for( uint16_t i = 0; i < 255; i++ )
94             {
95                 // kludge: colors are indexed reversely because color 255 seems
96                 // to bereserved for black even if we try to set it to white
97                 pColors[i].pixel = 254-i;
98                 pColors[i].pad   = 0;
99                 pColors[i].flags = DoRed | DoGreen | DoBlue;
100                 pColors[i].red   = (i >> m_redLeftShift) << (m_redRightShift + 8);
101                 pColors[i].green = (i >> m_greenLeftShift) << (m_greenRightShift + 8);
102                 pColors[i].blue  = (i >> m_blueLeftShift) << (m_blueRightShift + 8);
103             }
104             XStoreColors( m_pDisplay, m_colormap, pColors, 255 );
105             makePixelImpl = &X11Display::makePixel8;
106             m_pixelSize = 1;
107             break;
108
109         case 16:
110         case 24:
111         case 32:
112             // Get the TrueColor visual
113             xVInfoTemplate.c_class = TrueColor;
114             pVInfo = XGetVisualInfo( m_pDisplay, VisualScreenMask |
115                                      VisualDepthMask | VisualClassMask,
116                                      &xVInfoTemplate, &vCount );
117             if( pVInfo == NULL )
118             {
119                 msg_Err( getIntf(), "No TrueColor visual for depth %d",
120                          depth );
121                 m_pDisplay = NULL;
122                 break;
123             }
124             m_pVisual = pVInfo->visual;
125
126             // Compute the color shifts
127             getShifts( pVInfo->red_mask, m_redLeftShift, m_redRightShift );
128             getShifts( pVInfo->green_mask, m_greenLeftShift,
129                        m_greenRightShift );
130             getShifts( pVInfo->blue_mask, m_blueLeftShift, m_blueRightShift );
131
132             if( depth == 8 )
133             {
134                 makePixelImpl = &X11Display::makePixel8;
135                 m_pixelSize = 1;
136             }
137
138             if( depth == 16 )
139             {
140                 if( order == MSBFirst )
141                 {
142                     makePixelImpl = &X11Display::makePixel16MSB;
143                 }
144                 else
145                 {
146                     makePixelImpl = &X11Display::makePixel16LSB;
147                 }
148                 m_pixelSize = 2;
149             }
150             else
151             {
152                 if( order == MSBFirst )
153                 {
154                     makePixelImpl = &X11Display::makePixel32MSB;
155                 }
156                 else
157                 {
158                     makePixelImpl = &X11Display::makePixel32LSB;
159                 }
160                 m_pixelSize = 4;
161             }
162             break;
163
164         default:
165             msg_Err( getIntf(), "Unsupported depth: %d bpp\n", depth );
166             m_pDisplay = NULL;
167             break;
168     }
169
170     // Free the visual info
171     if( pVInfo )
172     {
173         XFree( pVInfo );
174     }
175
176     // Create a graphics context that doesn't generate GraphicsExpose events
177     if( m_pDisplay )
178     {
179         XGCValues xgcvalues;
180         xgcvalues.graphics_exposures = False;
181         m_gc = XCreateGC( m_pDisplay, DefaultRootWindow( m_pDisplay ),
182                           GCGraphicsExposures, &xgcvalues );
183     }
184
185     // Create a parent window to have a single task in the task bar
186     XSetWindowAttributes attr;
187     m_mainWindow = XCreateWindow( m_pDisplay, DefaultRootWindow( m_pDisplay),
188                                   0, 0, 1, 1, 0, 0, InputOutput,
189                                   CopyFromParent, 0, &attr );
190
191     // Changing decorations
192     struct {
193         unsigned long flags;
194         unsigned long functions;
195         unsigned long decorations;
196         long input_mode;
197         unsigned long status;
198     } motifWmHints;
199     Atom hints_atom = XInternAtom( m_pDisplay, "_MOTIF_WM_HINTS", False );
200     motifWmHints.flags = 2;    // MWM_HINTS_DECORATIONS;
201     motifWmHints.decorations = 0;
202     XChangeProperty( m_pDisplay, m_mainWindow, hints_atom, hints_atom, 32,
203                      PropModeReplace, (unsigned char *)&motifWmHints,
204                      sizeof( motifWmHints ) / sizeof( long ) );
205
206     // Change the window title
207     XStoreName( m_pDisplay, m_mainWindow, "VLC Media Player" );
208
209     // Receive map notify events
210     XSelectInput( m_pDisplay, m_mainWindow, StructureNotifyMask );
211
212     // Set an empty mask for the window
213     Region mask = XCreateRegion();
214     XShapeCombineRegion( m_pDisplay, m_mainWindow, ShapeBounding, 0, 0, mask,
215                          ShapeSet );
216     // Map the window
217     XMapWindow( m_pDisplay, m_mainWindow);
218 }
219
220
221 X11Display::~X11Display()
222 {
223     if( m_mainWindow )
224     {
225         XDestroyWindow( m_pDisplay, m_mainWindow );
226     }
227     if( m_gc )
228     {
229         XFreeGC( m_pDisplay, m_gc );
230     }
231     if( m_colormap )
232     {
233         XFreeColormap( m_pDisplay, m_colormap );
234     }
235     if( m_pDisplay )
236     {
237         XCloseDisplay( m_pDisplay );
238     }
239 }
240
241
242 void X11Display::getShifts( uint32_t mask, int &rLeftShift,
243                             int &rRightShift ) const
244 {
245     for( rLeftShift = 0; (rLeftShift < 32) && !(mask & 1); rLeftShift++ )
246     {
247         mask >>= 1;
248     }
249     for( rRightShift = 8; (mask & 1) ; rRightShift--)
250     {
251         mask >>= 1;
252     }
253     if( rRightShift < 0 )
254     {
255         rLeftShift -= rRightShift;
256         rRightShift = 0;
257     }
258 }
259
260
261 void X11Display::makePixel8( uint8_t *pPixel, uint8_t r, uint8_t g, uint8_t b,
262                              uint8_t a ) const
263 {
264     // Get the current pixel value
265     uint8_t value = 255 - *pPixel;
266
267     // Compute the new color values
268     uint16_t temp;
269     temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
270     uint8_t red = ( temp * (255 - a) + r * a ) / 255;
271     temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
272     uint8_t green = ( temp * (255 - a) + g * a ) / 255;
273     temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
274     uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
275
276     // Set the new pixel value
277     value =
278         ( ((uint8_t)red >> m_redRightShift) << m_redLeftShift ) |
279         ( ((uint8_t)green >> m_greenRightShift) << m_greenLeftShift ) |
280         ( ((uint8_t)blue >> m_blueRightShift) << m_blueLeftShift );
281
282     *pPixel = 255 - value;
283 }
284
285
286 void X11Display::makePixel16MSB( uint8_t *pPixel, uint8_t r, uint8_t g,
287                                  uint8_t b, uint8_t a ) const
288 {
289     // Get the current pixel value
290     uint16_t value = pPixel[1] | pPixel[0] << 8;
291
292     // Compute the new color values
293     uint16_t temp;
294     temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
295     uint8_t red = ( temp * (255 - a) + r * a ) / 255;
296     temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
297     uint8_t green = ( temp * (255 - a) + g * a ) / 255;
298     temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
299     uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
300
301     // Set the new pixel value
302     value =
303         ( ((uint16_t)red >> m_redRightShift) << m_redLeftShift ) |
304         ( ((uint16_t)green >> m_greenRightShift) << m_greenLeftShift ) |
305         ( ((uint16_t)blue >> m_blueRightShift) << m_blueLeftShift );
306
307     pPixel[1] = value;
308     value >>= 8;
309     pPixel[0] = value;
310 }
311
312
313 void X11Display::makePixel16LSB( uint8_t *pPixel, uint8_t r, uint8_t g,
314                                  uint8_t b, uint8_t a ) const
315 {
316     // Get the current pixel value
317     uint16_t value = pPixel[0] | pPixel[1] << 8;
318
319     // Compute the new color values
320     uint16_t temp;
321     temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
322     uint8_t red = ( temp * (255 - a) + r * a ) / 255;
323     temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
324     uint8_t green = ( temp * (255 - a) + g * a ) / 255;
325     temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
326     uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
327
328     // Set the new pixel value
329     value =
330         ( ((uint16_t)red >> m_redRightShift) << m_redLeftShift ) |
331         ( ((uint16_t)green >> m_greenRightShift) << m_greenLeftShift ) |
332         ( ((uint16_t)blue >> m_blueRightShift) << m_blueLeftShift );
333
334     pPixel[0] = value;
335     value >>= 8;
336     pPixel[1] = value;
337 }
338
339
340 void X11Display::makePixel32MSB( uint8_t *pPixel, uint8_t r, uint8_t g,
341                                  uint8_t b, uint8_t a ) const
342 {
343     // Get the current pixel value
344     uint32_t value = pPixel[3] | pPixel[2] << 8 | pPixel[1] << 16 |
345                           pPixel[0] << 24;
346
347     // Compute the new color values
348     uint16_t temp;
349     temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
350     uint8_t red = ( temp * (255 - a) + r * a ) / 255;
351     temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
352     uint8_t green = ( temp * (255 - a) + g * a ) / 255;
353     temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
354     uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
355
356     // Set the new pixel value
357     value =
358         ( ((uint32_t)red >> m_redRightShift) << m_redLeftShift ) |
359         ( ((uint32_t)green >> m_greenRightShift) << m_greenLeftShift ) |
360         ( ((uint32_t)blue >> m_blueRightShift) << m_blueLeftShift );
361
362     pPixel[3] = value;
363     value >>= 8;
364     pPixel[2] = value;
365     value >>= 8;
366     pPixel[1] = value;
367     value >>= 8;
368     pPixel[0] = value;
369 }
370
371
372 void X11Display::makePixel32LSB( uint8_t *pPixel, uint8_t r, uint8_t g,
373                                  uint8_t b, uint8_t a ) const
374 {
375     // Get the current pixel value
376     uint32_t value = pPixel[0] | pPixel[1] << 8 | pPixel[2] << 16 |
377                           pPixel[3] << 24;
378
379     // Compute the new color values
380     uint16_t temp;
381     temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
382     uint8_t red = ( temp * (255 - a) + r * a ) / 255;
383     temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
384     uint8_t green = ( temp * (255 - a) + g * a ) / 255;
385     temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
386     uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
387
388     // Set the new pixel value
389     value =
390         ( ((uint32_t)red >> m_redRightShift) << m_redLeftShift ) |
391         ( ((uint32_t)green >> m_greenRightShift) << m_greenLeftShift ) |
392         ( ((uint32_t)blue >> m_blueRightShift) << m_blueLeftShift );
393
394     pPixel[0] = value;
395     value >>= 8;
396     pPixel[1] = value;
397     value >>= 8;
398     pPixel[2] = value;
399     value >>= 8;
400     pPixel[3] = value;
401 }
402
403
404 unsigned long X11Display::getPixelValue( uint8_t r, uint8_t g, uint8_t b ) const
405 {
406     unsigned long value;
407     value = ( ((uint32_t)r >> m_redRightShift) << m_redLeftShift ) |
408             ( ((uint32_t)g >> m_greenRightShift) << m_greenLeftShift ) |
409             ( ((uint32_t)b >> m_blueRightShift) << m_blueLeftShift );
410     if( m_pixelSize == 1 )
411     {
412         return 255 - value;
413     }
414     else
415     {
416         return value;
417     }
418 }
419
420
421 #endif