diff options
author | Michele Calgaro <[email protected]> | 2014-11-27 11:57:26 +0900 |
---|---|---|
committer | Michele Calgaro <[email protected]> | 2014-11-27 11:57:26 +0900 |
commit | df0af3a449600b8617cd8c29ec5263adff7b04e6 (patch) | |
tree | cc9eb953eadc4d6f6882e22d426b2fd80262b328 | |
parent | 48fe5507cdaa620625441c7e1f70eb98b7ca78e5 (diff) | |
parent | 84987892db83c0fcc68bb4f0d2403571a29cbad3 (diff) | |
download | tdebase-df0af3a449600b8617cd8c29ec5263adff7b04e6.tar.gz tdebase-df0af3a449600b8617cd8c29ec5263adff7b04e6.zip |
Merge branch 'master' of http://scm.trinitydesktop.org/scm/git/tdebase
-rw-r--r-- | ksmserver/shutdowndlg.cpp | 20 | ||||
-rwxr-xr-x | migratekde3 | 20 | ||||
-rw-r--r-- | r14-xdg-update | 21 | ||||
-rw-r--r-- | twin/compton-tde/common.h | 31 | ||||
-rw-r--r-- | twin/compton-tde/compton.c | 158 | ||||
-rw-r--r-- | twin/compton-tde/opengl.c | 242 | ||||
-rw-r--r-- | twin/kcmtwin/twinoptions/windows.cpp | 13 | ||||
-rw-r--r-- | twin/kcmtwin/twinoptions/windows.h | 1 | ||||
-rw-r--r-- | twin/workspace.cpp | 82 |
9 files changed, 420 insertions, 168 deletions
diff --git a/ksmserver/shutdowndlg.cpp b/ksmserver/shutdowndlg.cpp index 5c50602cb..6573f8bd2 100644 --- a/ksmserver/shutdowndlg.cpp +++ b/ksmserver/shutdowndlg.cpp @@ -87,6 +87,11 @@ KSMShutdownFeedback::KSMShutdownFeedback() m_grayImage.setAlphaBuffer(false); m_grayImage.fill(0); // Set the alpha buffer to 0 (fully transparent) m_grayImage.setAlphaBuffer(true); + + // Signal that we want a greyscale filter on the transparency + Atom kde_wm_transparent_greyscale_filter; + kde_wm_transparent_greyscale_filter = XInternAtom(tqt_xdisplay(), "_TDE_TRANSPARENCY_FILTER_GREYSCALE_BLEND", False); + XChangeProperty(tqt_xdisplay(), winId(), kde_wm_transparent_greyscale_filter, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); } else { // The hacks below aren't needed any more because Qt3 supports true transparency for the fading logout screen when composition is available @@ -135,10 +140,10 @@ void KSMShutdownFeedback::slotPaintEffect() m_root.resize( width(), height() ); TQImage blendedImage = m_grayImage; TQPainter p; - p.begin( &m_root ); - blendedImage.setAlphaBuffer(false); - p.drawImage( 0, 0, blendedImage ); - p.end(); + p.begin( &m_root ); + blendedImage.setAlphaBuffer(false); + p.drawImage( 0, 0, blendedImage ); + p.end(); setBackgroundPixmap( m_root ); setGeometry( TQApplication::desktop()->geometry() ); @@ -150,7 +155,7 @@ void KSMShutdownFeedback::slotPaintEffect() uchar * end = m_grayImage.bits() + m_grayImage.numBytes(); while ( r != end ) { - *reinterpret_cast<TQRgb*>(r) = tqRgba(0, 0, 0, 128); + *reinterpret_cast<TQRgb*>(r) = tqRgba(0, 0, 0, 255); r += 4; } @@ -220,7 +225,6 @@ void KSMShutdownFeedback::slotPaintEffect() { TQImage img( imgWidth, y2-start_y1, 32 ); memcpy( img.bits(), m_grayImage.scanLine( start_y1 ), ( y2-start_y1 ) * imgWidth * 4 ); - register uchar * rs = m_unfadedImage.scanLine( start_y1 ); register uchar * rd = img.bits(); for( int y = start_y1; y < y2; ++y ) { @@ -228,8 +232,8 @@ void KSMShutdownFeedback::slotPaintEffect() short int opac = static_cast<short int>( 128 - cosf( M_PI*(y-y1)/heightUnit )*128.0f ); for( short int x = 0; x < imgWidth; ++x ) { - *reinterpret_cast<TQRgb*>(rd) = tqRgba(0, 0, 0, ((255.0-opac)/(255.0/127.0))); - rs += 4; rd += 4; + *reinterpret_cast<TQRgb*>(rd) = tqRgba(0, 0, 0, ((255.0-opac))); + rd += 4; } } bitBlt( this, 0, start_y1, &img ); diff --git a/migratekde3 b/migratekde3 index c106dd718..eff7f182e 100755 --- a/migratekde3 +++ b/migratekde3 @@ -130,6 +130,16 @@ else fi unset BIN_DIR +# Trap when the user runs this script while in a Trinity session. +# Most files can be updated "live" but some can't, such as kdeglobals. +if [ "$TDE_FULL_SESSION" != "" ] && [ "$TDE_SESSION_UID" != "" ] && [ "`ps ax | grep \`tail -n1 $HOME/.DCOPserver_\`uname -n\`__0 2>/dev/null\` | grep -v grep`" != "" ]; then + MESSAGE="You are running this script while a Trinity session is active.\nMost files can be updated \"live\" but some cannot, such as kdeglobals.\n\nThis script probably will not complete successfully. :-)" + # Are we in X? Display an X dialog explaining breakage. + printf "%b" "$MESSAGE\n" + Wait_For_Response "Continue?" + Proceed_From_Response +fi + echo echo "This script migrates an existing KDE3 profile directory." echo "The definition of a KDE3 profile directory includes some" @@ -172,16 +182,6 @@ if [ "$TDEHOME_LINK" != "" ]; then fi fi -# Trap when the user runs this script while in a Trinity session. -# Most files can be updated "live" but some can't, such as kdeglobals. -if [ "$TDE_FULL_SESSION" != "" ] || [ "$TDE_SESSION_UID" != "" ] || [ -f $HOME/.DCOPserver_`uname -n`__* ]; then - MESSAGE="You are running this script while a Trinity session is active.\nMost files can be updated \"live\" but some cannot, such as kdeglobals.\n\nThis script might complete successfully and might not. Probably not. :-)" - # Are we in X? Display an X dialog explaining breakage. - printf "%b" "$MESSAGE\n" - Wait_For_Response "Continue?" - Proceed_From_Response -fi - if [ -d "$HOME/.trinity" ] && [ "$BACKUP" = "true" ]; then echo "$HOME/.trinity already exists." 1>&2 echo "User requested a backup copy." diff --git a/r14-xdg-update b/r14-xdg-update index 8bf357fff..0db17af91 100644 --- a/r14-xdg-update +++ b/r14-xdg-update @@ -3,7 +3,7 @@ # A script to perform R14.0.0 XDG compliance updates. SCRIPT_NAME="`basename \`readlink -f $0\``" -SCRIPT_VERSION=201410170 +SCRIPT_VERSION=201411240 # This script should be needed to run only once, but corner cases # and file/directory permissions could cause incomplete updates. @@ -91,7 +91,7 @@ fi unset KDEGLOBALS_KEY_VALUE -WARNING_MESSAGE="Trinity R14 XDG compliance updates will not be performed.\n\nWithout R14 XDG compliance updates, some Trinity apps will fail to\nfunction properly.\n\nFailures include the following:\n\n* Many left-side icon lists will not populate,\n such as the Panel and Konqueror configuration dialogs.\n\n* User-defined keyboard shortcuts fail (khotkeysrc).\n System defined shortcuts remain functional.\n\n* User-defined app preferences fail (profilerc).\n\n* Konqueror navigation/sidebar panel won't open.\n\n* User-defined konqueror service menus, kicker customization,\n* konqueror sidebar, Recent Documents list fail.\n\nPlease exercise appropriate action.\n" +WARNING_MESSAGE="Trinity R14 XDG compliance updates have been interrupted.\n\nWithout R14 XDG compliance updates, some Trinity apps will fail to\nfunction properly.\n\nFailures include the following:\n\n* Many left-side icon lists will not populate,\n such as the Panel and Konqueror configuration dialogs.\n\n* User-defined keyboard shortcuts fail (khotkeysrc).\n System defined shortcuts remain functional.\n\n* User-defined app preferences fail (profilerc).\n\n* Konqueror navigation/sidebar panel won't open.\n\n* User-defined konqueror service menus, kicker customization,\n* konqueror sidebar, Recent Documents list fail.\n\nPlease exercise appropriate action.\n" # As the user should not be logged into a Trinity session when running # this script, or an administrator might run this script remotely, the @@ -175,14 +175,14 @@ if [ "$TDEHOME_LINK" != "" ]; then if [ "$USER_DIR" = "$HOME" ] && [ "$DISPLAY" != "" ]; then echo "[r14-xdg-update] Warning! The profile directory $PROFILE_DIR is a" 1>&2 echo " sym link to $TDEHOME_LINK!" 1>&2 - echo " R14 updates will not be performed because Trinity needs its own" 1>&2 + echo " R14 updates will not continue because Trinity needs its own" 1>&2 echo " separate profile directory." 1>&2 echo " Without R14 updates some Trinity apps will fail to function correctly." 1>&2 fi - MESSAGE="Oops! The profile directory $PROFILE_DIR is a sym link to $TDEHOME_LINK.\n\n${WARNING_MESSAGE}\nPossible remedies:\n\n* Contact your system administrator.\n\n* Break the sym link to force creating a fresh Trinity profile.\n\n* Use the migratekde3 script to migrate a KDE3 profile to Trinity." + MESSAGE="Oops! The profile directory $PROFILE_DIR is a sym link to $TDEHOME_LINK.\n\n${WARNING_MESSAGE}\nPossible remedies:\n\n* Contact your system administrator.\n\n* Manually break the sym link to force creating a fresh Trinity profile.\n\n* Use the ${TDEDIR}/bin/migratekde3 script to migrate a KDE3 profile to Trinity." # Are we in X? Display an X dialog explaining breakage. if [ "$USER_DIR" = "$HOME" ] && [ "$DISPLAY" != "" ]; then - MESSAGE="${MESSAGE}\n\nSelecting the Continue button means retaining the KDE3 profile and\nbreaking the sym link. With the sym link broken, run the migratekde3\nscript before restarting Trinity to migrate a KDE3 profile or\nallow Trinity to create a fresh profile." + MESSAGE="${MESSAGE}\n\nSelecting the Continue button means preserving the KDE3 profile and\nbreaking the sym link. With the sym link broken, the ${TDEDIR}/bin/migratekde3\nscript will run to migrate the KDE3 profile to Trinity." printf "%b" "$MESSAGE" | xmessage -center -file - -buttons Continue,Quit > /dev/null 2>/dev/null EXIT_CODE="$?" unset TDEHOME_LINK @@ -193,7 +193,7 @@ if [ "$TDEHOME_LINK" != "" ]; then exit 1 else # User selected the Continue button: continue this script and start TDE. - Log "The user chose to continue, which will break the sym link." + Log "The user chose to continue to break the sym link." BREAK_SYMLINK="true" fi else @@ -207,20 +207,21 @@ if [ "$TDEHOME_LINK" != "" ]; then if [ "$BREAK_SYMLINK" = "true" ]; then unlink "$USER_DIR/.trinity" 2>/dev/null if [ "`readlink \"$USER_DIR/.trinity\"`" = "" ]; then - MESSAGE="Sym link broken. With the sym link broken, run the migratekde3\nscript before restarting Trinity to migrate a KDE3 profile or\nallow Trinity to create a fresh profile." + MESSAGE="Sym link broken. With the sym link broken, will now attempt\nto migrate the KDE3 profile." Message_Prefix printf "%b" "$MESSAGE" echo + ${TDEDIR}/bin/migratekde3 else MESSAGE="Unable to break the sym link. Check file and directory privileges. Quitting." Message_Prefix echo "$MESSAGE" echo + unset PROFILE_DIR + unset TDEHOME_LINK + exit 1 fi fi - unset PROFILE_DIR - unset TDEHOME_LINK - exit 1 fi unset TDEHOME_LINK diff --git a/twin/compton-tde/common.h b/twin/compton-tde/common.h index 759e64698..9ff5a2148 100644 --- a/twin/compton-tde/common.h +++ b/twin/compton-tde/common.h @@ -490,6 +490,21 @@ typedef struct { } glx_blur_cache_t; typedef struct { + /// Fragment shader for greyscale. + GLuint frag_shader; + /// GLSL program for greyscale. + GLuint prog; + /// Location of uniform "greyscale_weights" in greyscale GLSL program. + GLint unifm_greyscale_weights; + /// Location of uniform "enable_blend" in greyscale GLSL program. + GLint unifm_enable_blend; + /// Location of uniform "tex_scr" in greyscale GLSL program. + GLint unifm_tex_scr; + /// Location of uniform "alpha_scr" in greyscale GLSL program. + GLint unifm_alpha_scr; +} glx_greyscale_t; + +typedef struct { /// Framebuffer used for greyscale conversion. GLuint fbo; /// Textures used for greyscale conversion. @@ -817,6 +832,9 @@ typedef struct { #ifdef CONFIG_VSYNC_OPENGL_GLSL glx_blur_pass_t blur_passes[MAX_BLUR_PASS]; #endif +#ifdef CONFIG_VSYNC_OPENGL_GLSL + glx_greyscale_t greyscale_glsl; +#endif } glx_session_t; #define CGLX_SESSION_INIT { .context = NULL } @@ -1068,6 +1086,8 @@ typedef struct _session_t { Atom atom_win_type_tde_transparent_to_desktop; /// Atom of property <code>_TDE_TRANSPARENCY_FILTER_GREYSCALE</code>. Atom atom_win_type_tde_transparency_filter_greyscale; + /// Atom of property <code>_TDE_TRANSPARENCY_FILTER_GREYSCALE_BLEND</code>. + Atom atom_win_type_tde_transparency_filter_greyscale_blend; /// Array of atoms of all possible window types. Atom atoms_wintypes[NUM_WINTYPES]; /// Linked list of additional atoms to track. @@ -1263,6 +1283,11 @@ typedef struct _win { /// Background state on last paint. bool greyscale_background_last; + /// Whether to set window background to blended greyscale. + bool greyscale_blended_background; + /// Blended greyscale alpha divisor. + int greyscale_blended_background_alpha_divisor; + /// Whether to show black background bool show_black_background; @@ -2202,6 +2227,9 @@ glx_on_root_change(session_t *ps); bool glx_init_blur(session_t *ps); +bool +glx_init_greyscale(session_t *ps); + #ifdef CONFIG_VSYNC_OPENGL_GLSL bool glx_load_prog_main(session_t *ps, @@ -2245,7 +2273,7 @@ glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z, bool glx_greyscale_dst(session_t *ps, int dx, int dy, int width, int height, float z, - XserverRegion reg_tgt, const reg_data_t *pcache_reg, glx_greyscale_cache_t *pbc); + glx_texture_t *ptex, XserverRegion reg_tgt, const reg_data_t *pcache_reg, glx_greyscale_cache_t *pbc); bool glx_render_(session_t *ps, const glx_texture_t *ptex, @@ -2342,7 +2370,6 @@ free_glx_bc(session_t *ps, glx_blur_cache_t *pbc) { static inline void free_glx_gc_resize(session_t *ps, glx_greyscale_cache_t *pbc) { free_texture_r(ps, &pbc->textures[0]); - free_texture_r(ps, &pbc->textures[1]); pbc->width = 0; pbc->height = 0; } diff --git a/twin/compton-tde/compton.c b/twin/compton-tde/compton.c index dea363f60..4a78f7f8a 100644 --- a/twin/compton-tde/compton.c +++ b/twin/compton-tde/compton.c @@ -944,6 +944,9 @@ static Bool determine_window_transparency_filter_greyscale(const session_t *ps, Window w); static Bool +determine_window_transparency_filter_greyscale_blended(const session_t *ps, Window w); + +static Bool determine_window_transparent_to_black(const session_t *ps, Window w); static Bool @@ -1590,6 +1593,7 @@ xr_greyscale_dst(session_t *ps, Picture tgt_buffer, XRenderComposite(ps->dpy, PictOpSrc, ps->black_picture, None, tmp_picture, 0, 0, 0, 0, 0, 0, wid, hei); + XRenderComposite(ps->dpy, PictOpHSLLuminosity, tgt_buffer, None, tmp_picture, x, y, 0, 0, 0, 0, wid, hei); @@ -1723,7 +1727,7 @@ win_greyscale_background(session_t *ps, win *w, Picture tgt_buffer, #ifdef CONFIG_VSYNC_OPENGL_GLSL case BKEND_GLX: glx_greyscale_dst(ps, x, y, wid, hei, ps->psglx->z - 0.5, - reg_paint, pcache_reg, &w->glx_greyscale_cache); + NULL, reg_paint, pcache_reg, &w->glx_greyscale_cache); break; #endif default: @@ -1821,6 +1825,71 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint, Picture pict = w->paint.pict; + if (w->greyscale_blended_background) { + // Set window background to greyscale + switch (ps->o.backend) { + case BKEND_XRENDER: + case BKEND_XR_GLX_HYBRID: + { + // Blend here such that 0 window alpha is fully colored and 100 window alpha is fully greyscale + // PictOpInReverse is used to copy alpha from the source to the destination while preserving destination color + // provided that the source has alpha set to 1 (equivalent of CAIRO_OPERATOR_DEST_IN) + const int x = w->a.x; + const int y = w->a.y; + const int wid = w->widthb; + const int hei = w->heightb; + XserverRegion reg_clip = reg_paint; + Picture tgt_buffer = ps->tgt_buffer.pict; + + // Apply clipping region to save some CPU + if (reg_paint) { + XserverRegion reg = copy_region(ps, reg_paint); + XFixesTranslateRegion(ps->dpy, reg, -x, -y); + XFixesSetPictureClipRegion(ps->dpy, pict, 0, 0, reg); + free_region(ps, ®); + } + + // Create greyscale version of background + Picture greyscale_picture = xr_build_picture(ps, wid, hei, w->pictfmt); + XRenderComposite(ps->dpy, PictOpSrc, tgt_buffer, None, + greyscale_picture, x, y, 0, 0, 0, 0, wid, hei); + win_greyscale_background(ps, w, greyscale_picture, reg_paint, pcache_reg); + + Picture tmp_picture = xr_build_picture(ps, wid, hei, w->pictfmt); + + if (!tmp_picture) { + printf_errf("(): Failed to build intermediate Picture."); + } + else { + if (reg_clip && tmp_picture) + XFixesSetPictureClipRegion(ps->dpy, tmp_picture, reg_clip, 0, 0); + + // Transfer greyscale picture to temporary picture + XRenderComposite(ps->dpy, PictOpSrc, greyscale_picture, None, + tmp_picture, 0, 0, 0, 0, 0, 0, wid, hei); + + // Transfer alpha of window to temporary picture + XRenderComposite(ps->dpy, PictOpInReverse, pict, None, + tmp_picture, 0, 0, 0, 0, 0, 0, wid, hei); + + // Blend greyscale picture over main color buffer + XRenderComposite(ps->dpy, PictOpOver, tmp_picture, None, tgt_buffer, + 0, 0, 0, 0, x, y, wid, hei); + + free_picture(ps, &tmp_picture); + free_picture(ps, &greyscale_picture); + } + } + break; +#ifdef CONFIG_VSYNC_OPENGL + case BKEND_GLX: + glx_greyscale_dst(ps, x, y, wid, hei, ps->psglx->z - 0.5, + w->paint.ptex, reg_paint, pcache_reg, &w->glx_greyscale_cache); + break; +#endif + } + } + // Invert window color, if required if (bkend_use_xrender(ps) && w->invert_color) { Picture newpict = xr_build_picture(ps, wid, hei, w->pictfmt); @@ -1846,7 +1915,12 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint, } } - const double dopacity = get_opacity_percent(w); + double dopacity = get_opacity_percent(w); + + if (w->greyscale_blended_background) { + double scaling_factor = (1.0 / w->greyscale_blended_background_alpha_divisor); + dopacity = dopacity * scaling_factor; + } if (!w->frame_opacity) { win_render(ps, w, 0, 0, wid, hei, dopacity, reg_paint, pcache_reg, pict); @@ -2438,9 +2512,10 @@ map_win(session_t *ps, Window id) { /* This needs to be here since we don't get PropertyNotify when unmapped */ w->opacity = wid_get_opacity_prop(ps, w->id, OPAQUE); - w->greyscale_background = determine_window_transparency_filter_greyscale(ps, id); + w->greyscale_blended_background = determine_window_transparency_filter_greyscale_blended(ps, id); w->show_root_tile = determine_window_transparent_to_desktop(ps, id); w->show_black_background = determine_window_transparent_to_black(ps, id); + win_determine_greyscale_background(ps, w); // Update window mode here to check for ARGB windows win_determine_mode(ps, w); @@ -2632,6 +2707,28 @@ get_window_transparency_filter_greyscale(const session_t *ps, Window w) } static Bool +get_window_transparency_filter_greyscale_blended(const session_t *ps, Window w) +{ + Atom actual; + int format; + unsigned long n, left; + + unsigned char *data; + int result = XGetWindowProperty (ps->dpy, w, ps->atom_win_type_tde_transparency_filter_greyscale_blend, 0L, 1L, False, + XA_ATOM, &actual, &format, + &n, &left, &data); + + if (result == Success && data != None && format == 32 ) + { + Atom a; + a = *(long*)data; + XFree ( (void *) data); + return True; + } + return False; +} + +static Bool get_window_transparent_to_desktop(const session_t *ps, Window w) { Atom actual; @@ -2711,6 +2808,41 @@ determine_window_transparency_filter_greyscale (const session_t *ps, Window w) } static Bool +determine_window_transparency_filter_greyscale_blended (const session_t *ps, Window w) +{ + Window root_return, parent_return; + Window *children = NULL; + unsigned int nchildren, i; + Bool type; + + type = get_window_transparency_filter_greyscale_blended (ps, w); + if (type == True) { + return True; + } + + if (!XQueryTree (ps->dpy, w, &root_return, &parent_return, &children, + &nchildren)) + { + /* XQueryTree failed. */ + if (children) + XFree ((void *)children); + return False; + } + + for (i = 0;i < nchildren;i++) + { + type = determine_window_transparency_filter_greyscale_blended (ps, children[i]); + if (type == True) + return True; + } + + if (children) + XFree ((void *)children); + + return False; +} + +static Bool determine_window_transparent_to_desktop (const session_t *ps, Window w) { Window root_return, parent_return; @@ -3449,6 +3581,8 @@ add_win(session_t *ps, Window id, Window prev) { .blur_background = false, .greyscale_background = false, + .greyscale_blended_background = false, + .greyscale_blended_background_alpha_divisor = 2, .show_black_background = false, .show_root_tile = false, @@ -6696,6 +6830,7 @@ init_atoms(session_t *ps) { ps->atom_win_type_tde_transparent_to_black = get_atom(ps, "_TDE_TRANSPARENT_TO_BLACK"); ps->atom_win_type_tde_transparent_to_desktop = get_atom(ps, "_TDE_TRANSPARENT_TO_DESKTOP"); ps->atom_win_type_tde_transparency_filter_greyscale = get_atom(ps, "_TDE_TRANSPARENCY_FILTER_GREYSCALE"); + ps->atom_win_type_tde_transparency_filter_greyscale_blend = get_atom(ps, "_TDE_TRANSPARENCY_FILTER_GREYSCALE_BLEND"); } #ifdef CONFIG_XRANDR @@ -7136,6 +7271,22 @@ init_filters(session_t *ps) { } } + // Greyscale filter + switch (ps->o.backend) { + case BKEND_XRENDER: + case BKEND_XR_GLX_HYBRID: + { + break; + } +#ifdef CONFIG_VSYNC_OPENGL + case BKEND_GLX: + { + if (!glx_init_greyscale(ps)) + return false; + } +#endif + } + return true; } @@ -7666,6 +7817,7 @@ session_init(session_t *ps_old, int argc, char **argv) { .atom_win_type_tde_transparent_to_black = None, .atom_win_type_tde_transparent_to_desktop = None, .atom_win_type_tde_transparency_filter_greyscale = None, + .atom_win_type_tde_transparency_filter_greyscale_blend = None, .atoms_wintypes = { 0 }, .track_atom_lst = NULL, diff --git a/twin/compton-tde/opengl.c b/twin/compton-tde/opengl.c index de485de74..4cbfeb455 100644 --- a/twin/compton-tde/opengl.c +++ b/twin/compton-tde/opengl.c @@ -531,6 +531,106 @@ glx_init_blur(session_t *ps) { #endif } +// RAJJA FIXME +/** + * Initialize GLX greyscale filter. + */ +bool +glx_init_greyscale(session_t *ps) { +#ifdef CONFIG_VSYNC_OPENGL_GLSL + { + char *lc_numeric_old = mstrcpy(setlocale(LC_NUMERIC, NULL)); + // Enforce LC_NUMERIC locale "C" here to make sure decimal point is sane + setlocale(LC_NUMERIC, "C"); + + // Adapted from http://trac.openscenegraph.org/projects/osg//wiki/Support/Tutorials/ShadersSampleGrayingOut + static const char *FRAG_SHADER_GREYSCALE = + "#version 110\n" + "uniform sampler2D tex_scr;\n" + "uniform sampler2D alpha_scr;\n" + "uniform int enable_blend;\n" + "uniform vec4 greyscale_weights; // [0.3, 0.59, 0.11, 1.0]\n" + "\n" + "void main( void )\n" + "{\n" + " // Fetch the regular RGB texel color from the source texture\n" + " vec4 texel_color = texture2D( tex_scr, gl_TexCoord[0].xy );\n" + "\n" + " //\n" + " // Converting to grayscale:\n" + " //\n" + " // Converting an image to grayscale is done by taking a weighted average of\n" + " // the red, green and blue color components. The standard weights for this\n" + " // type of conversion are (0.30, 0.59, 0.11). Therefore, the gray component\n" + " // or luminance that we need to compute can be defined as a luminance\n" + " // filter like so:\n" + " //\n" + " // luminance = 0.30*R + 0.59*G + 0.11*B\n" + " //\n" + " // If we think of our RGB colors as vectors, we can see that this \n" + " // calculation is actually just a dot product.\n" + " //\n" + "\n" + " vec4 scaledColor = texel_color * greyscale_weights;\n" + " float luminance = scaledColor.r + scaledColor.g + scaledColor.b;\n" + "\n" + " if (enable_blend == 1) {\n" + " // Fetch the regular RGB texel color from the blend texture\n" + " vec4 blend_texel = texture2D( alpha_scr, vec2(gl_TexCoord[0].x, 1.0 - gl_TexCoord[0].y) );\n" + " vec4 grey_pixel = vec4(luminance,luminance,luminance,1);\n" + " gl_FragColor = mix(texel_color, grey_pixel, blend_texel.a);\n" + " }\n" + " else {\n" + " gl_FragColor = vec4(luminance,luminance,luminance,1);\n" + " }\n" + "\n" + "}"; + + glx_greyscale_t *greyscale_glsl = &ps->psglx->greyscale_glsl; + greyscale_glsl->frag_shader = glx_create_shader(GL_FRAGMENT_SHADER, FRAG_SHADER_GREYSCALE); + + if (!greyscale_glsl->frag_shader) { + printf_errf("(): Failed to create fragment shader."); + return false; + } + + // Build program + greyscale_glsl->prog = glx_create_program(&greyscale_glsl->frag_shader, 1); + if (!greyscale_glsl->prog) { + printf_errf("(): Failed to create GLSL program."); + return false; + } + + // Get uniform addresses +#define P_GET_UNIFM_LOC(name, target) { \ + greyscale_glsl->target = glGetUniformLocation(greyscale_glsl->prog, name); \ + if (greyscale_glsl->target < 0) { \ + printf_errf("(): Failed to get location of uniform '" name "'. Might be troublesome."); \ + } \ + } + + P_GET_UNIFM_LOC("greyscale_weights", unifm_greyscale_weights); + P_GET_UNIFM_LOC("enable_blend", unifm_enable_blend); + P_GET_UNIFM_LOC("tex_scr", unifm_tex_scr); + P_GET_UNIFM_LOC("alpha_scr", unifm_alpha_scr); + +#undef P_GET_UNIFM_LOC + + // Restore LC_NUMERIC + setlocale(LC_NUMERIC, lc_numeric_old); + free(lc_numeric_old); + } + + + glx_check_err(ps); + + return true; +#else + printf_errf("(): GLSL support not compiled in. Cannot do greyscale with GLX backend."); + return false; +#endif +} + #ifdef CONFIG_VSYNC_OPENGL_GLSL /** @@ -1387,113 +1487,62 @@ glx_blur_dst_end: bool glx_greyscale_dst(session_t *ps, int dx, int dy, int width, int height, float z, - XserverRegion reg_tgt, const reg_data_t *pcache_reg, glx_greyscale_cache_t *pbc) { + glx_texture_t *ptex, XserverRegion reg_tgt, const reg_data_t *pcache_reg, glx_greyscale_cache_t *gsc) { + + glx_greyscale_t *greyscale_glsl = &ps->psglx->greyscale_glsl; + assert(greyscale_glsl->prog); + bool ret = false; // Calculate copy region size glx_greyscale_cache_t ibc = { .width = 0, .height = 0 }; - if (!pbc) - pbc = &ibc; + if (!gsc) + gsc = &ibc; #ifdef DEBUG_GLX printf_dbgf("(): %d, %d, %d, %d\n", dx, dy, width, height); #endif // Free textures if size inconsistency discovered - if (width != pbc->width || height != pbc->height) - free_glx_gc_resize(ps, pbc); + if (width != gsc->width || height != gsc->height) + free_glx_gc_resize(ps, gsc); - // Generate FBO and textures if needed - if (!pbc->textures[0]) - pbc->textures[0] = glx_gen_texture(ps, GL_TEXTURE_2D, width, height); - GLuint tex_scr1 = pbc->textures[0]; - pbc->width = width; - pbc->height = height; + // Generate textures + if (!gsc->textures[0]) + gsc->textures[0] = glx_gen_texture(ps, GL_TEXTURE_2D, width, height); + GLuint tex_scr1 = gsc->textures[0]; + gsc->width = width; + gsc->height = height; if (!tex_scr1) { printf_errf("(): Failed to allocate texture."); goto glx_greyscale_dst_end; } - // Texture scaling factor - GLfloat texfac_x = 1.0f, texfac_y = 1.0f; - texfac_x /= width; - texfac_y /= height; - - // Greyscale conversion in OpenGL ES taken nearly verbatim from this answer on Stack Overflow: http://stackoverflow.com/a/9690145 - - // Enable texture unit 0 to divide RGB values in our texture by 2 - glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex_scr1); + if (ptex) { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, ptex->texture); + } + glActiveTexture(GL_TEXTURE0); // Read destination pixels into the GL texture glx_copy_region_to_tex(ps, GL_TEXTURE_2D, dx, dy, dx, dy, width, height); - // Finish setting up texture - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glClientActiveTexture(GL_TEXTURE0); - - // GL_MODULATE is Arg0 * Arg1 - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); - - // Configure Arg0 - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); - - // Configure Arg1 - float multipliers[4] = {.5, .5, .5, 0.0}; - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); - glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (GLfloat*)&multipliers); - - // Enable texture unit 1 to increase RGB values by .5 - glActiveTexture(GL_TEXTURE1); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, tex_scr1); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glClientActiveTexture(GL_TEXTURE1); - - // GL_ADD is Arg0 + Arg1 - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD); - - // Configure Arg0 - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); - - // Configure Arg1 - GLfloat additions[4] = {.5, .5, .5, 0.0}; - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); - glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (GLfloat*)&additions); + // Texture scaling factor + GLfloat texfac_x = 1.0f, texfac_y = 1.0f; + texfac_x /= width; + texfac_y /= height; - // Enable texture combiner 2 to get a DOT3_RGB product of your RGB values - glActiveTexture(GL_TEXTURE2); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, tex_scr1); - glClientActiveTexture(GL_TEXTURE2); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - - // GL_DOT3_RGB is 4*((Arg0r - 0.5) * (Arg1r - 0.5) + (Arg0g - 0.5) * (Arg1g - 0.5) + (Arg0b - 0.5) * (Arg1b - 0.5)) - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB); - - // Configure Arg0 - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); - - // Configure Arg1 - // We want this to adjust our DOT3 by R*0.3 + G*0.59 + B*0.11 - // So, our actual adjustment will need to take into consideration - // the fact that OpenGL will subtract .5 from our Arg1 - // and we need to also take into consideration that we have divided - // our RGB values by 2 and we are multiplying the entire - // DOT3 product by 4 - // So, for Red adjustment you will get : - // .65 = (4*(0.3))/2 + 0.5 = (0.3/2) + 0.5 - GLfloat weights[4] = {.65, .795, .555, 1.}; - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); - glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (GLfloat*)&weights); +// glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glUseProgram(greyscale_glsl->prog); + // These coefficients exactly match the non-GL greyscale conversion which uses the XRender PictOpHSLLuminosity operation + glUniform4f(greyscale_glsl->unifm_greyscale_weights, 0.3, 0.59, 0.11, 1.0); + glUniform1i(greyscale_glsl->unifm_enable_blend, ((ptex)?1:0)); + glUniform1i(greyscale_glsl->unifm_tex_scr, 0); + glUniform1i(greyscale_glsl->unifm_alpha_scr, 1); // Render! { @@ -1527,26 +1576,21 @@ glx_greyscale_dst(session_t *ps, int dx, int dy, int width, int height, float z, P_PAINTREG_END(); } - glEnd(); - - // Clean up by disabling your texture combiners or texture units. - glActiveTexture(GL_TEXTURE2); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glDisable(GL_TEXTURE_2D); - - glActiveTexture(GL_TEXTURE1); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glDisable(GL_TEXTURE_2D); - - glActiveTexture(GL_TEXTURE0); - glClientActiveTexture(GL_TEXTURE0); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glUseProgram(0); ret = true; glx_greyscale_dst_end: - if (&ibc == pbc) { - free_glx_gc(ps, pbc); + if (ptex) { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, 0); + } + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + + if (&ibc == gsc) { + free_glx_gc(ps, gsc); } glx_check_err(ps); diff --git a/twin/kcmtwin/twinoptions/windows.cpp b/twin/kcmtwin/twinoptions/windows.cpp index 30d48d15d..3e2757545 100644 --- a/twin/kcmtwin/twinoptions/windows.cpp +++ b/twin/kcmtwin/twinoptions/windows.cpp @@ -1349,9 +1349,12 @@ KTranslucencyConfig::KTranslucencyConfig (bool _standAlone, TDEConfig *_config, vLay->addWidget(useOpenGL); blurBackground = new TQCheckBox(i18n("Blur the background of transparent windows"),tGroup); vLay->addWidget(blurBackground); + greyscaleBackground = new TQCheckBox(i18n("Desaturate the background of transparent windows"),tGroup); + vLay->addWidget(greyscaleBackground); if (TDECompositor != "compton-tde") { useOpenGL->hide(); blurBackground->hide(); + greyscaleBackground->hide(); } vLay->addStretch(); @@ -1490,6 +1493,8 @@ KTranslucencyConfig::KTranslucencyConfig (bool _standAlone, TDEConfig *_config, connect(useOpenGL, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed())); connect(useOpenGL, TQT_SIGNAL(toggled(bool)), blurBackground, TQT_SLOT(setEnabled(bool))); connect(blurBackground, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed())); + connect(useOpenGL, TQT_SIGNAL(toggled(bool)), greyscaleBackground, TQT_SLOT(setEnabled(bool))); + connect(greyscaleBackground, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed())); connect(useShadows, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed())); connect(useShadowsOnMenuWindows, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed())); connect(useShadowsOnToolTipWindows, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed())); @@ -1530,6 +1535,7 @@ KTranslucencyConfig::KTranslucencyConfig (bool _standAlone, TDEConfig *_config, connect(disableARGB, TQT_SIGNAL(toggled(bool)), TQT_SLOT(resetKompmgr())); connect(useOpenGL, TQT_SIGNAL(toggled(bool)), TQT_SLOT(resetKompmgr())); connect(blurBackground, TQT_SIGNAL(toggled(bool)), TQT_SLOT(resetKompmgr())); + connect(greyscaleBackground, TQT_SIGNAL(toggled(bool)), TQT_SLOT(resetKompmgr())); connect(useShadows, TQT_SIGNAL(toggled(bool)), TQT_SLOT(resetKompmgr())); connect(useShadowsOnMenuWindows, TQT_SIGNAL(toggled(bool)), TQT_SLOT(resetKompmgr())); connect(useShadowsOnToolTipWindows, TQT_SIGNAL(toggled(bool)), TQT_SLOT(resetKompmgr())); @@ -1607,6 +1613,8 @@ void KTranslucencyConfig::load( void ) useOpenGL->setChecked(conf_.readBoolEntry("useOpenGL",FALSE)); blurBackground->setChecked(conf_.readBoolEntry("blurBackground",FALSE)); blurBackground->setEnabled(useOpenGL->isChecked()); + greyscaleBackground->setChecked(conf_.readBoolEntry("greyscaleBackground",FALSE)); + greyscaleBackground->setEnabled(useOpenGL->isChecked()); useShadows->setChecked(conf_.readEntry("Compmode","").compare("CompClientShadows") == 0); useShadowsOnMenuWindows->setChecked(conf_.readBoolEntry("ShadowsOnMenuWindows",TRUE)); @@ -1683,6 +1691,7 @@ void KTranslucencyConfig::save( void ) conf_->writeEntry("DisableARGB",disableARGB->isChecked()); conf_->writeEntry("useOpenGL",useOpenGL->isChecked()); conf_->writeEntry("blurBackground",blurBackground->isChecked()); + conf_->writeEntry("greyscaleBackground",greyscaleBackground->isChecked()); conf_->writeEntry("ShadowOffsetY",-1*shadowTopOffset->value()); conf_->writeEntry("ShadowOffsetX",-1*shadowLeftOffset->value()); @@ -1759,13 +1768,15 @@ void KTranslucencyConfig::save( void ) stream << "backend = \"" << (useOpenGL->isChecked()?"glx":"xrender") << "\";\n"; stream << "vsync = \"" << (useOpenGL->isChecked()?"opengl":"none") << "\";\n"; - stream << "blur-background = \"" << ((blurBackground->isChecked() && useOpenGL->isChecked())?"true":"false") << "\";\n"; + stream << "blur-background = " << ((blurBackground->isChecked() && useOpenGL->isChecked())?"true":"false") << ";\n"; stream << "blur-background-fixed = true;\n"; stream << "blur-background-exclude = [\n"; stream << " \"window_type = 'dock'\",\n"; stream << " \"window_type = 'desktop'\"\n"; stream << "];\n"; + stream << "greyscale-background = " << ((greyscaleBackground->isChecked() && useOpenGL->isChecked())?"true":"false") << ";\n"; + // Global settings stream << "no-dock-shadow = true;\n"; stream << "no-dnd-shadow = true;\n"; diff --git a/twin/kcmtwin/twinoptions/windows.h b/twin/kcmtwin/twinoptions/windows.h index facde4136..52596ad1c 100644 --- a/twin/kcmtwin/twinoptions/windows.h +++ b/twin/kcmtwin/twinoptions/windows.h @@ -261,6 +261,7 @@ private: TQCheckBox *disableARGB; TQCheckBox *useOpenGL; TQCheckBox *blurBackground; + TQCheckBox *greyscaleBackground; TQCheckBox *fadeInWindows; TQCheckBox *fadeInMenuWindows; TQCheckBox *fadeInToolTipWindows; diff --git a/twin/workspace.cpp b/twin/workspace.cpp index 77b6bc42b..7c36d24f5 100644 --- a/twin/workspace.cpp +++ b/twin/workspace.cpp @@ -78,6 +78,46 @@ bool supportsCompMgr() return damageExt && compositeExt && xfixesExt; } +pid_t getCompositorPID() { + // Attempt to load the compton-tde pid file + char *filename; + const char *pidfile = "compton-tde.pid"; + char uidstr[sizeof(uid_t)*8+1]; + sprintf(uidstr, "%d", getuid()); + int n = strlen(P_tmpdir)+strlen(uidstr)+strlen(pidfile)+3; + filename = (char*)malloc(n*sizeof(char)+1); + memset(filename,0,n); + strcat(filename, P_tmpdir); + strcat(filename, "/."); + strcat(filename, uidstr); + strcat(filename, "-"); + strcat(filename, pidfile); + + // Now that we did all that by way of introduction...read the file! + FILE *pFile; + char buffer[255]; + pFile = fopen(filename, "r"); + pid_t kompmgrpid = 0; + if (pFile) + { + printf("[twin-workspace] Using '%s' as compton-tde pidfile\n\n", filename); + // obtain file size + fseek (pFile , 0 , SEEK_END); + unsigned long lSize = ftell (pFile); + if (lSize > 254) + lSize = 254; + rewind (pFile); + size_t result = fread (buffer, 1, lSize, pFile); + fclose(pFile); + kompmgrpid = atoi(buffer); + } + + free(filename); + filename = NULL; + + return kompmgrpid; +} + // Rikkus: This class is too complex. It needs splitting further. // It's a nightmare to understand, especially with so few comments :( @@ -227,41 +267,7 @@ Workspace::Workspace( bool restore ) // start kompmgr - i wanted to put this into main.cpp, but that would prevent dcop support, as long as Application was no dcop_object // If compton-tde is already running, send it SIGTERM - // Attempt to load the compton-tde pid file - char *filename; - const char *pidfile = "compton-tde.pid"; - char uidstr[sizeof(uid_t)*8+1]; - sprintf(uidstr, "%d", getuid()); - int n = strlen(P_tmpdir)+strlen(uidstr)+strlen(pidfile)+3; - filename = (char*)malloc(n*sizeof(char)+1); - memset(filename,0,n); - strcat(filename, P_tmpdir); - strcat(filename, "/."); - strcat(filename, uidstr); - strcat(filename, "-"); - strcat(filename, pidfile); - - // Now that we did all that by way of introduction...read the file! - FILE *pFile; - char buffer[255]; - pFile = fopen(filename, "r"); - int kompmgrpid = 0; - if (pFile) - { - printf("[twin-workspace] Using '%s' as compton-tde pidfile\n\n", filename); - // obtain file size - fseek (pFile , 0 , SEEK_END); - unsigned long lSize = ftell (pFile); - if (lSize > 254) - lSize = 254; - rewind (pFile); - size_t result = fread (buffer, 1, lSize, pFile); - fclose(pFile); - kompmgrpid = atoi(buffer); - } - - free(filename); - filename = NULL; + pid_t kompmgrpid = getCompositorPID(); if (options->useTranslucency) { @@ -2817,6 +2823,12 @@ void Workspace::startKompmgr() TQTimer::singleShot( 200, this, TQT_SLOT(startKompmgr()) ); return; } + pid_t kompmgrpid = getCompositorPID(); + if (kill(kompmgrpid, 0) >= 0) + { + // Active PID file detected; do not attempt to restart + return; + } if (!kompmgr || kompmgr->isRunning()) { kompmgrReloadSettings(); return; |