2003-04-20 13:27:16 +00:00
// Transparent.cc for FbTk - Fluxbox Toolkit
// Copyright (c) 2003 Henrik Kinnunen (fluxgen(at)users.sourceforge.net)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
2004-06-07 11:46:05 +00:00
// $Id: Transparent.cc,v 1.6 2004/06/07 11:46:05 rathnor Exp $
2003-04-20 13:27:16 +00:00
# include "Transparent.hh"
# include "App.hh"
2004-06-07 11:46:05 +00:00
# include "I18n.hh"
2003-04-20 13:27:16 +00:00
2003-04-20 14:47:35 +00:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif // HAVE_CONFIG_H
# ifdef HAVE_XRENDER
2003-04-20 13:27:16 +00:00
# include <X11/extensions/Xrender.h>
2003-04-20 14:47:35 +00:00
# endif // HAVE_XRENDER
2003-04-20 13:27:16 +00:00
# include <iostream>
2004-06-07 11:46:05 +00:00
# include <stdio.h>
2003-04-20 13:27:16 +00:00
using namespace std ;
namespace {
2003-04-20 14:47:35 +00:00
# ifdef HAVE_XRENDER
2003-04-20 13:27:16 +00:00
Picture createAlphaPic ( Window drawable , unsigned char alpha ) {
Display * disp = FbTk : : App : : instance ( ) - > display ( ) ;
2004-06-07 11:46:05 +00:00
_FB_USES_NLS ;
2003-04-20 13:27:16 +00:00
// try to find a specific render format
XRenderPictFormat pic_format ;
pic_format . type = PictTypeDirect ;
pic_format . depth = 8 ; // alpha with bit depth 8
pic_format . direct . alphaMask = 0xff ;
XRenderPictFormat * format = XRenderFindFormat ( disp , PictFormatType |
PictFormatDepth | PictFormatAlphaMask ,
& pic_format , 0 ) ;
if ( format = = 0 ) {
2004-06-07 11:46:05 +00:00
cerr < < " FbTk::Transparent: " < < _FBTKTEXT ( Error , NoRenderFormat , " Warning: Failed to find valid format for alpha. " , " transparency requires a pict format, can't get one... " ) < < endl ;
2003-04-20 13:27:16 +00:00
return 0 ;
}
// create one pixel pixmap with depth 8 for alpha
Pixmap alpha_pm = XCreatePixmap ( disp , drawable ,
1 , 1 , 8 ) ;
if ( alpha_pm = = 0 ) {
2004-06-07 11:46:05 +00:00
cerr < < " FbTk::Transparent: " < < _FBTKTEXT ( Error , NoRenderPixmap , " Warning: Failed to create alpha pixmap. " , " XCreatePixmap files for our transparency pixmap " ) < < endl ;
2003-04-20 13:27:16 +00:00
return 0 ;
}
// create picture with alpha_pm as repeated background
XRenderPictureAttributes attr ;
attr . repeat = True ; // small bitmap repeated
Picture alpha_pic = XRenderCreatePicture ( disp , alpha_pm ,
format , CPRepeat , & attr ) ;
if ( alpha_pic = = 0 ) {
XFreePixmap ( disp , alpha_pm ) ;
2004-06-07 11:46:05 +00:00
cerr < < " FbTk::Transparent: " < < _FBTKTEXT ( Error , NoRenderPicture , " Warning: Failed to create alpha picture. " , " XRenderCreatePicture failed " ) < < endl ;
2003-04-20 13:27:16 +00:00
return 0 ;
}
// finaly set alpha and fill with it
XRenderColor color ;
// calculate alpha percent and then scale it to short
color . red = 0xFF ;
color . blue = 0xFF ;
color . green = 0xFF ;
color . alpha = ( ( unsigned short ) ( 255 * alpha ) < < 8 ) ;
2003-05-13 20:50:56 +00:00
if ( alpha = = 0 )
color . alpha = 0xFF00 ;
2003-04-20 13:27:16 +00:00
XRenderFillRectangle ( disp , PictOpSrc , alpha_pic , & color ,
0 , 0 , 1 , 1 ) ;
XFreePixmap ( disp , alpha_pm ) ;
return alpha_pic ;
}
2003-04-20 14:47:35 +00:00
# endif // HAVE_XRENDER
2003-04-20 13:27:16 +00:00
} ;
namespace FbTk {
2003-05-07 09:31:29 +00:00
bool Transparent : : s_init = false ;
bool Transparent : : s_render = false ;
2003-04-20 13:27:16 +00:00
Transparent : : Transparent ( Drawable src , Drawable dest , unsigned char alpha , int screen_num ) :
m_alpha_pic ( 0 ) , m_src_pic ( 0 ) , m_dest_pic ( 0 ) ,
m_source ( src ) , m_dest ( dest ) , m_alpha ( alpha ) {
2003-05-07 09:31:29 +00:00
Display * disp = FbTk : : App : : instance ( ) - > display ( ) ;
// check for RENDER support
if ( ! s_init ) {
int major_opcode , first_event , first_error ;
if ( XQueryExtension ( disp , " RENDER " ,
& major_opcode ,
& first_event , & first_error ) = = False ) {
s_render = false ;
} else { // we got RENDER support
s_render = true ;
}
s_init = true ;
}
2003-04-20 14:47:35 +00:00
# ifdef HAVE_XRENDER
2003-05-07 09:31:29 +00:00
if ( ! s_render )
return ;
2003-04-20 13:27:16 +00:00
allocAlpha ( m_alpha ) ;
XRenderPictFormat * format =
XRenderFindVisualFormat ( disp ,
DefaultVisual ( disp , screen_num ) ) ;
if ( src ! = 0 & & format ! = 0 ) {
m_src_pic = XRenderCreatePicture ( disp , src , format ,
0 , 0 ) ;
}
if ( dest ! = 0 & & format ! = 0 ) {
m_dest_pic = XRenderCreatePicture ( disp , dest , format ,
0 , 0 ) ;
}
2003-04-20 14:47:35 +00:00
# endif // HAVE_XRENDER
2003-04-20 13:27:16 +00:00
}
Transparent : : ~ Transparent ( ) {
2003-04-20 14:47:35 +00:00
# ifdef HAVE_XRENDER
2003-05-07 09:31:29 +00:00
if ( m_alpha_pic ! = 0 & & s_render )
2003-04-20 13:27:16 +00:00
freeAlpha ( ) ;
Display * disp = FbTk : : App : : instance ( ) - > display ( ) ;
2003-05-07 09:31:29 +00:00
if ( m_dest_pic ! = 0 & & s_render )
2003-04-20 13:27:16 +00:00
XRenderFreePicture ( disp , m_dest_pic ) ;
2003-05-07 09:31:29 +00:00
if ( m_src_pic ! = 0 & & s_render )
2003-04-20 13:27:16 +00:00
XRenderFreePicture ( disp , m_src_pic ) ;
2003-04-20 14:47:35 +00:00
# endif // HAVE_XRENDER
2003-04-20 13:27:16 +00:00
}
void Transparent : : setAlpha ( unsigned char alpha ) {
2003-05-07 09:31:29 +00:00
if ( m_source = = 0 | | ! s_render )
2003-04-20 13:27:16 +00:00
return ;
freeAlpha ( ) ;
allocAlpha ( alpha ) ;
}
void Transparent : : setDest ( Drawable dest , int screen_num ) {
2003-04-20 14:47:35 +00:00
# ifdef HAVE_XRENDER
2003-05-07 09:31:29 +00:00
if ( m_dest = = dest | | ! s_render )
2003-04-20 13:27:16 +00:00
return ;
Display * disp = FbTk : : App : : instance ( ) - > display ( ) ;
if ( m_dest_pic ! = 0 ) {
XRenderFreePicture ( disp , m_dest_pic ) ;
m_dest_pic = 0 ;
}
// create new dest pic if we have a valid dest drawable
if ( dest ! = 0 ) {
XRenderPictFormat * format =
XRenderFindVisualFormat ( disp ,
DefaultVisual ( disp , screen_num ) ) ;
2004-06-07 11:46:05 +00:00
if ( format = = 0 ) {
_FB_USES_NLS ;
cerr < < " FbTk::Transparent: " ;
fprintf ( stderr , _FBTKTEXT ( Error , NoRenderVisualFormat , " Failed to find format for screen(%d) " , " XRenderFindVisualFormat failed... include %d for screen number " ) , screen_num ) ;
cerr < < endl ;
}
2003-04-20 13:27:16 +00:00
m_dest_pic = XRenderCreatePicture ( disp , dest , format , 0 , 0 ) ;
}
m_dest = dest ;
2003-04-20 14:47:35 +00:00
# endif // HAVE_XRENDER
2003-04-20 13:27:16 +00:00
}
void Transparent : : setSource ( Drawable source , int screen_num ) {
2003-04-20 14:47:35 +00:00
# ifdef HAVE_XRENDER
2003-05-07 09:31:29 +00:00
if ( m_source = = source | | ! s_render )
2003-04-20 13:27:16 +00:00
return ;
2003-04-26 12:44:24 +00:00
// save old alpha value so we can recreate new later
// with the same value
unsigned char old_alpha = m_alpha ;
2003-04-20 13:27:16 +00:00
if ( m_alpha_pic ! = 0 )
freeAlpha ( ) ;
Display * disp = FbTk : : App : : instance ( ) - > display ( ) ;
if ( m_src_pic ! = 0 ) {
XRenderFreePicture ( disp , m_src_pic ) ;
m_src_pic = 0 ;
}
m_source = source ;
// create new source pic if we have a valid source drawable
if ( m_source ! = 0 ) {
XRenderPictFormat * format =
XRenderFindVisualFormat ( disp ,
DefaultVisual ( disp , screen_num ) ) ;
2004-06-07 11:46:05 +00:00
if ( format = = 0 ) {
_FB_USES_NLS ;
cerr < < " FbTk::Transparent: " ;
fprintf ( stderr , _FBTKTEXT ( Error , NoRenderVisualFormat , " Failed to find format for screen(%d) " , " XRenderFindVisualFormat failed... include %d for screen number " ) , screen_num ) ;
cerr < < endl ;
}
2003-04-20 13:27:16 +00:00
m_src_pic = XRenderCreatePicture ( disp , m_source , format ,
0 , 0 ) ;
}
2003-04-26 12:44:24 +00:00
// recreate new alpha
allocAlpha ( old_alpha ) ;
2003-04-20 14:47:35 +00:00
# endif // HAVE_XRENDER
2003-04-20 13:27:16 +00:00
}
void Transparent : : render ( int src_x , int src_y ,
int dest_x , int dest_y ,
unsigned int width , unsigned int height ) const {
2003-04-20 14:47:35 +00:00
# ifdef HAVE_XRENDER
2003-04-20 13:27:16 +00:00
if ( m_src_pic = = 0 | | m_dest_pic = = 0 | |
2003-05-07 09:31:29 +00:00
m_alpha_pic = = 0 | | ! s_render )
2003-04-20 13:27:16 +00:00
return ;
// render src+alpha to dest picture
XRenderComposite ( FbTk : : App : : instance ( ) - > display ( ) ,
PictOpOver ,
m_src_pic ,
m_alpha_pic ,
m_dest_pic ,
src_x , src_y ,
0 , 0 ,
dest_x , dest_y ,
width , height ) ;
2003-04-20 14:47:35 +00:00
# endif // HAVE_XRENDER
2003-04-20 13:27:16 +00:00
}
void Transparent : : allocAlpha ( unsigned char alpha ) {
2003-04-20 14:47:35 +00:00
# ifdef HAVE_XRENDER
2003-05-07 09:31:29 +00:00
if ( m_source = = 0 | | ! s_render )
2003-04-20 13:27:16 +00:00
return ;
if ( m_alpha_pic ! = 0 )
freeAlpha ( ) ;
m_alpha_pic = createAlphaPic ( m_source , alpha ) ;
m_alpha = alpha ;
2003-04-20 14:47:35 +00:00
# endif // HAVE_XRENDER
2003-04-20 13:27:16 +00:00
}
void Transparent : : freeAlpha ( ) {
2003-04-20 14:47:35 +00:00
# ifdef HAVE_XRENDER
2003-05-07 09:31:29 +00:00
if ( s_render & & m_alpha_pic ! = 0 )
XRenderFreePicture ( FbTk : : App : : instance ( ) - > display ( ) , m_alpha_pic ) ;
2003-04-20 14:47:35 +00:00
# endif // HAVE_XRENDER
2003-04-20 13:27:16 +00:00
m_alpha_pic = 0 ;
m_alpha = 255 ;
}
} ; // end namespace FbTk