added support for applying translucency on the titlebar or the content (not really: anything but the titlebar) only

svn path=/trunk/kdebase/kwin/; revision=387795
This commit is contained in:
Thomas Lübking 2005-02-09 18:31:35 +00:00
parent d7e31d3499
commit cd5ac45b77
8 changed files with 230 additions and 26 deletions

View file

@ -79,6 +79,9 @@ Atoms::Atoms()
atoms[n] = &net_wm_window_shapable;
names[n++] = (char*) "_KDE_WM_WINDOW_SHAPABLE";
atoms[n] = &net_wm_window_titleheight;
names[n++] = (char*) "_KDE_WM_WINDOW_TITLEHEIGHT";
Atom fake;
atoms[n] = &fake;
names[n++] = (char *) "_DT_SM_WINDOW_INFO";

View file

@ -41,6 +41,7 @@ class Atoms
Atom net_wm_window_shadow;
Atom net_wm_window_shade;
Atom net_wm_window_shapable;
Atom net_wm_window_titleheight;
Atom xdnd_aware;
Atom xdnd_position;
};

View file

@ -266,6 +266,7 @@ void Client::updateDecoration( bool check_workspace_pos, bool force )
XReparentWindow( qt_xdisplay(), decoration->widget()->winId(), frameId(), 0, 0 );
decoration->widget()->lower();
decoration->borders( border_left, border_right, border_top, border_bottom );
setXTitleHeightProperty(border_top);
int save_workarea_diff_x = workarea_diff_x;
int save_workarea_diff_y = workarea_diff_y;
move( calculateGravitation( false ));
@ -322,6 +323,8 @@ void Client::checkBorderSizes()
move( calculateGravitation( true ));
border_left = new_left;
border_right = new_right;
if (border_top != new_top)
setXTitleHeightProperty(new_top);
border_top = new_top;
border_bottom = new_bottom;
move( calculateGravitation( false ));
@ -2012,6 +2015,12 @@ bool Client::touches(const Client* c)
return FALSE;
}
void Client::setXTitleHeightProperty(int titleHeight)
{
long data = titleHeight;
XChangeProperty(qt_xdisplay(), frameId(), atoms->net_wm_window_titleheight, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &data, 1L);
}
#ifndef NDEBUG
kdbgstream& operator<<( kdbgstream& stream, const Client* cl )
{

View file

@ -391,6 +391,7 @@ class Client : public QObject, public KDecorationDefines
void ungrabButton( int mod );
void resetMaximize();
void resizeDecoration( const QSize& s );
void setXTitleHeightProperty(int titleHeight);
void pingWindow();
void killProcess( bool ask, Time timestamp = CurrentTime );

View file

@ -1197,6 +1197,18 @@ KTranslucencyConfig::KTranslucencyConfig (bool _standAlone, KConfig *_config, QW
QWidget *tGroup = new QWidget(tabW);
QVBoxLayout *vLay = new QVBoxLayout (tGroup,KDialog::marginHint(), KDialog::spacingHint());
vLay->addSpacing(11); // to get the proper gb top offset
QHBoxLayout *hLay = new QHBoxLayout(vLay);
QLabel *label = new QLabel(i18n("Apply translucency on"),tGroup);
hLay->addWidget(label);
transMode = new QComboBox(tGroup);
transMode->insertItem ("The whole window");
transMode->insertItem ("The titlebar only");
transMode->insertItem ("The content only");
hLay->addWidget(transMode);
vLay->addSpacing(11);
QGridLayout *gLay = new QGridLayout(vLay,4,2,KDialog::spacingHint());
gLay->setColStretch(1,1);
@ -1228,6 +1240,8 @@ KTranslucencyConfig::KTranslucencyConfig (bool _standAlone, KConfig *_config, QW
dockWindowOpacity->setSuffix("%");
gLay->addWidget(dockWindowOpacity,3,1);
vLay->addSpacing(11);
keepAboveAsActive = new QCheckBox(i18n("Treat 'keep above' windows as active ones"),tGroup);
vLay->addWidget(keepAboveAsActive);
@ -1244,6 +1258,8 @@ KTranslucencyConfig::KTranslucencyConfig (bool _standAlone, KConfig *_config, QW
useShadows = new QCheckBox(i18n("Use shadows"),sGroup);
vLay2->addWidget(useShadows);
vLay2->addSpacing(11);
QGridLayout *gLay2 = new QGridLayout(vLay2,6,2);
gLay2->setColStretch(1,1);
@ -1287,6 +1303,7 @@ KTranslucencyConfig::KTranslucencyConfig (bool _standAlone, KConfig *_config, QW
shadowColor = new KColorButton(Qt::black,sGroup);
gLay2->addWidget(shadowColor,5,1);
gLay2->setColStretch(1,1);
vLay2->addSpacing(11);
removeShadowsOnMove = new QCheckBox(i18n("Remove shadows on move"),sGroup);
vLay2->addWidget(removeShadowsOnMove);
removeShadowsOnResize = new QCheckBox(i18n("Remove shadows on resize"),sGroup);
@ -1325,6 +1342,7 @@ KTranslucencyConfig::KTranslucencyConfig (bool _standAlone, KConfig *_config, QW
connect(dockWindowTransparency, SIGNAL(toggled(bool)), dockWindowOpacity, SLOT(setEnabled(bool)));
connect(useTranslucency, SIGNAL(toggled(bool)), SLOT(changed()));
connect(transMode, SIGNAL(activated(int)), SLOT(changed()));
connect(activeWindowTransparency, SIGNAL(toggled(bool)), SLOT(changed()));
connect(inactiveWindowTransparency, SIGNAL(toggled(bool)), SLOT(changed()));
connect(movingWindowTransparency, SIGNAL(toggled(bool)), SLOT(changed()));
@ -1365,6 +1383,7 @@ KTranslucencyConfig::KTranslucencyConfig (bool _standAlone, KConfig *_config, QW
// handle kompmgr restarts if necessary
connect(useTranslucency, SIGNAL(toggled(bool)), SLOT(resetKompmgr()));
connect(transMode, SIGNAL(activated(int)), SLOT(resetKompmgr()));
connect(disableARGB, SIGNAL(toggled(bool)), SLOT(resetKompmgr()));
connect(useShadows, SIGNAL(toggled(bool)), SLOT(resetKompmgr()));
connect(inactiveWindowShadowSize, SIGNAL(valueChanged(int)), SLOT(resetKompmgr()));
@ -1401,7 +1420,7 @@ void KTranslucencyConfig::load( void )
keepAboveAsActive->setChecked(config->readBoolEntry("TreatKeepAboveAsActive",true));
activeWindowOpacity->setValue(config->readNumEntry("ActiveWindowOpacity",100));
inactiveWindowOpacity->setValue(config->readNumEntry("InactiveWindowOpacity",50));
inactiveWindowOpacity->setValue(config->readNumEntry("InactiveWindowOpacity",75));
movingWindowOpacity->setValue(config->readNumEntry("MovingWindowOpacity",25));
dockWindowOpacity->setValue(config->readNumEntry("DockOpacity",80));
@ -1418,6 +1437,9 @@ void KTranslucencyConfig::load( void )
KConfig conf_(QDir::homeDirPath() + "/.xcompmgrrc");
conf_.setGroup("xcompmgr");
QString modeString = conf_.readEntry("TransMode","All");
transMode->setCurrentItem(!modeString.compare("Content")?2:!modeString.compare("Title")?1:0);
disableARGB->setChecked(conf_.readBoolEntry("DisableARGB",FALSE));
useShadows->setChecked(conf_.readEntry("Compmode","CompClientShadows").compare("CompClientShadows") == 0);
@ -1440,8 +1462,8 @@ void KTranslucencyConfig::load( void )
fadeInWindows->setChecked(conf_.readBoolEntry("FadeWindows",TRUE));
fadeOnOpacityChange->setChecked(conf_.readBoolEntry("FadeTrans",FALSE));
fadeInSpeed->setValue((int)(conf_.readDoubleNumEntry("FadeInStep",0.028)*1000.0));
fadeOutSpeed->setValue((int)(conf_.readDoubleNumEntry("FadeOutStep",0.03)*1000.0));
fadeInSpeed->setValue((int)(conf_.readDoubleNumEntry("FadeInStep",0.020)*1000.0));
fadeOutSpeed->setValue((int)(conf_.readDoubleNumEntry("FadeOutStep",0.070)*1000.0));
emit KCModule::changed(false);
}
@ -1482,6 +1504,7 @@ void KTranslucencyConfig::save( void )
conf_->writeEntry("DisableARGB",disableARGB->isChecked());
conf_->writeEntry("ShadowOffsetY",-1*shadowTopOffset->value());
conf_->writeEntry("ShadowOffsetX",-1*shadowLeftOffset->value());
conf_->writeEntry("TransMode",transMode->currentItem()==0?"All":transMode->currentItem()==1?"Title":"Content");
int r, g, b;
@ -1512,6 +1535,7 @@ void KTranslucencyConfig::defaults()
if (!kompmgrAvailable_)
return;
useTranslucency->setChecked(false);
transMode->setCurrentItem(0);
activeWindowTransparency->setChecked(false);
inactiveWindowTransparency->setChecked(true);
movingWindowTransparency->setChecked(false);
@ -1520,7 +1544,7 @@ void KTranslucencyConfig::defaults()
disableARGB->setChecked(false);
activeWindowOpacity->setValue(100);
inactiveWindowOpacity->setValue(50);
inactiveWindowOpacity->setValue(75);
movingWindowOpacity->setValue(25);
dockWindowOpacity->setValue(80);
@ -1540,8 +1564,8 @@ void KTranslucencyConfig::defaults()
shadowColor->setColor(Qt::black);
fadeInWindows->setChecked(TRUE);
fadeOnOpacityChange->setChecked(FALSE);
fadeInSpeed->setValue(28);
fadeOutSpeed->setValue(30);
fadeInSpeed->setValue(70);
fadeOutSpeed->setValue(20);
emit KCModule::changed(true);
}

View file

@ -253,6 +253,7 @@ private:
QCheckBox *removeShadowsOnResize;
QCheckBox *removeShadowsOnMove;
QGroupBox *sGroup;
QComboBox *transMode;
// QPushButton *xcompmgrButton;
KIntNumInput *activeWindowOpacity;
KIntNumInput *inactiveWindowOpacity;

View file

@ -80,6 +80,8 @@ typedef struct _win {
Picture alphaPict;
Picture shadowPict;
XserverRegion borderSize;
XserverRegion titleSize;
XserverRegion contentSize;
XserverRegion extents;
unsigned int preShadeOpacity;
Picture shadow;
@ -92,7 +94,7 @@ typedef struct _win {
Atom windowType;
unsigned long damage_sequence; /* sequence when damage was created */
Bool shapable; /* this will allow window managers to exclude windows if just the deco is shaped*/
/*Bool fadesBlocked;*/
int titleHeight;
/* for drawing translucent windows */
XserverRegion borderClip;
@ -148,6 +150,7 @@ Atom opacityAtom;
Atom shadowAtom;
Atom shadeAtom;
Atom shapableAtom;
Atom titleHeightAtom;
Atom winTypeAtom;
Atom winDesktopAtom;
Atom winDockAtom;
@ -163,6 +166,7 @@ Atom winNormalAtom;
#define SHADOW_PROP "_KDE_WM_WINDOW_SHADOW"
#define SHADE_PROP "_KDE_WM_WINDOW_SHADE"
#define SHAPABLE_PROP "_KDE_WM_WINDOW_SHAPABLE"
#define TITLEHEIGHT_PROP "_KDE_WM_WINDOW_TITLEHEIGHT"
#define TRANSLUCENT 0xe0000000
#define OPAQUE 0xffffffff
@ -188,6 +192,12 @@ typedef enum _compMode {
CompClientShadows, /* use window extents for shadow, blurred */
} CompMode;
typedef enum _transMode {
Title, /*only the titlebar is drawn translucent*/
Content, /*only the content is drawn translucent*/
All /*all window is drawn translucent*/
} TransMode;
static void
determine_mode(Display *dpy, win *w);
@ -198,6 +208,7 @@ static XserverRegion
win_extents (Display *dpy, win *w);
CompMode compMode = CompSimple;
TransMode transMode = All;
int shadowRadius = 12;
int shadowOffsetX = 0;
@ -946,6 +957,56 @@ border_size (Display *dpy, win *w)
return border;
}
static XserverRegion
title_size (Display *dpy, win *w)
{
XserverRegion title;
XRectangle r; /*titlebounding rect*/
/*
* if window doesn't exist anymore, this will generate an error
* as well as not generate a region. Perhaps a better XFixes
* architecture would be to have a request that copies instead
* of creates, that way you'd just end up with an empty region
* instead of an invalid XID.
*/
r.x = w->a.x - w->a.border_width;
r.y = w->a.y - w->a.border_width;
r.width = w->a.width + w->a.border_width * 2;
r.height = w->titleHeight + w->a.border_width;
set_ignore (dpy, NextRequest (dpy));
title = XFixesCreateRegion (dpy, &r, 1);
if (!w->borderSize)
w->borderSize = border_size (dpy, w);
set_ignore (dpy, NextRequest (dpy));
XFixesIntersectRegion(dpy, title, w->borderSize, title);
return title;
}
static XserverRegion
content_size (Display *dpy, win *w)
{
XserverRegion content;
XRectangle r; /*contentbounding rect*/
/*
* if window doesn't exist anymore, this will generate an error
* as well as not generate a region. Perhaps a better XFixes
* architecture would be to have a request that copies instead
* of creates, that way you'd just end up with an empty region
* instead of an invalid XID.
*/
r.x = w->a.x - w->a.border_width;
r.y = w->a.y - w->a.border_width + w->titleHeight;
r.width = w->a.width + w->a.border_width * 2;
r.height = w->a.height + w->a.border_width - w->titleHeight;
set_ignore (dpy, NextRequest (dpy));
content = XFixesCreateRegion (dpy, &r, 1);
if (!w->borderSize)
w->borderSize = border_size (dpy, w);
set_ignore (dpy, NextRequest (dpy));
XFixesIntersectRegion(dpy, content, w->borderSize, content);
return content;
}
static void
paint_all (Display *dpy, XserverRegion region)
{
@ -1027,6 +1088,18 @@ paint_all (Display *dpy, XserverRegion region)
XFixesDestroyRegion (dpy, w->borderSize);
w->borderSize = None;
}
if (w->titleSize)
{
set_ignore (dpy, NextRequest (dpy));
XFixesDestroyRegion (dpy, w->titleSize);
w->titleSize = None;
}
if (w->contentSize)
{
set_ignore (dpy, NextRequest (dpy));
XFixesDestroyRegion (dpy, w->contentSize);
w->contentSize = None;
}
if (w->extents)
{
XFixesDestroyRegion (dpy, w->extents);
@ -1042,7 +1115,7 @@ paint_all (Display *dpy, XserverRegion region)
w->borderSize = border_size (dpy, w);
if (!w->extents)
w->extents = win_extents (dpy, w);
if (w->mode == WINDOW_SOLID)
if ((w->mode == WINDOW_SOLID) || ((w->mode == WINDOW_TRANS) && (transMode < All) && w->titleHeight))
{
int x, y, wid, hei;
#if HAS_NAME_WINDOW_PIXMAP
@ -1058,11 +1131,40 @@ paint_all (Display *dpy, XserverRegion region)
#endif
XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, region);
set_ignore (dpy, NextRequest (dpy));
/*XFixesSubtractRegion (dpy, region, region, w->borderSize);
set_ignore (dpy, NextRequest (dpy));*/
if (w->mode == WINDOW_SOLID)
{
XFixesSubtractRegion (dpy, region, region, w->borderSize);
set_ignore (dpy, NextRequest (dpy));
XRenderComposite (dpy, PictOpSrc, w->picture, None, rootBuffer,
0, 0, 0, 0,
x, y, wid, hei);
0, 0, 0, 0, x, y, wid, hei);
}
else
switch (transMode) {
case Title:
{
if (!w->contentSize)
w->contentSize = content_size (dpy, w);
XFixesSubtractRegion (dpy, region, region, w->contentSize);
set_ignore (dpy, NextRequest (dpy));
/*solid part*/
XRenderComposite (dpy, PictOpSrc, w->picture, None, rootBuffer,
0, w->titleHeight, 0, 0, x, y+w->titleHeight, wid, hei - w->titleHeight);
break;
}
case Content:
{
if (!w->titleSize)
w->titleSize = title_size (dpy, w);
XFixesSubtractRegion (dpy, region, region, w->titleSize);
set_ignore (dpy, NextRequest (dpy));
/*solid part*/
XRenderComposite (dpy, PictOpSrc, w->picture, None, rootBuffer,
0, 0, 0, 0, x, y, wid, w->titleHeight);
break;
}
}
}
if (!w->borderClip)
{
@ -1136,9 +1238,25 @@ paint_all (Display *dpy, XserverRegion region)
hei = w->a.height;
#endif
set_ignore (dpy, NextRequest (dpy));
if (!w->titleHeight)
XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer,
0, 0, 0, 0,
x, y, wid, hei);
0, 0, 0, 0, x, y, wid, hei);
else
switch (transMode) {
case All:
XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer,
0, 0, 0, 0, x, y, wid, hei);
break;
/*trans part*/
case Title:
XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer,
0, 0, 0, 0, x, y, wid, w->titleHeight);
break;
case Content:
XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer,
0, w->titleHeight, 0, 0, x, y+w->titleHeight, wid, hei - w->titleHeight);
break;
}
}
else if (w->mode == WINDOW_ARGB)
{
@ -1425,6 +1543,27 @@ get_shapable_prop(Display *dpy, win *w)
return True; /*in general, the window should be shapable*/
}
static unsigned int
get_titleHeight_prop(Display *dpy, win *w)
{
Atom actual;
int format;
unsigned long n, left;
unsigned char *data = NULL;
int result = XGetWindowProperty(dpy, w->id, titleHeightAtom, 0L, 1L, False,
XA_CARDINAL, &actual, &format,
&n, &left, &data);
if (result == Success && data != NULL)
{
unsigned int i;
memcpy (&i, data, sizeof (unsigned int));
XFree( (void *) data);
return i;
}
return 0; /*no titlebar*/
}
/* Get the opacity property from the window in a percent format
not found: default
otherwise: the value
@ -1608,6 +1747,7 @@ add_win (Display *dpy, Window id, Window prev)
new->shadow_height = 0;
new->opacity = OPAQUE;
new->shadowSize = 100;
new->titleHeight = 0;
new->borderClip = None;
new->prev_trans = 0;
@ -1618,6 +1758,7 @@ add_win (Display *dpy, Window id, Window prev)
new->opacity = get_opacity_prop (dpy, new, OPAQUE);
new->shadowSize = get_shadow_prop (dpy, new);
new->shapable = get_shapable_prop(dpy, new);
new->titleHeight = get_titleHeight_prop(dpy, new);
new->windowType = determine_wintype (dpy, new->id);
determine_mode (dpy, new);
@ -2022,6 +2163,7 @@ typedef enum _option{
FadeInStep,
FadeDelta,
DisableARGB,
TransMode_,
NUMBEROFOPTIONS
} Option;
@ -2043,6 +2185,7 @@ options[NUMBEROFOPTIONS] = {
"FadeInStep", /*13*/
"FadeDelta", /*14*/
"DisableARGB", /*15*/
"TransMode", /*16*/
/*put your thingy in here...*/
};
@ -2106,6 +2249,17 @@ setValue(Option option, char *value ){
compMode = CompSimple; /*default*/
}
break;
case TransMode_:
if( strcasecmp(value, "Title") == 0 ){
transMode = Title;
}
else if( strcasecmp(value, "Content") == 0 ){
transMode = Content;
}
else{
transMode = All; /*default*/
}
break;
case Display_:
display = strdup(value);
break;
@ -2363,6 +2517,7 @@ main (int argc, char **argv)
opacityAtom = XInternAtom (dpy, OPACITY_PROP, False);
shadeAtom = XInternAtom (dpy, SHADE_PROP, False);
shapableAtom = XInternAtom (dpy, SHAPABLE_PROP, False);
titleHeightAtom = XInternAtom (dpy, TITLEHEIGHT_PROP, False);
winTypeAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE", False);
winDesktopAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
winDockAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
@ -2545,6 +2700,18 @@ main (int argc, char **argv)
else
printf("arrrg, window not found\n");
}
else if (ev.xproperty.atom == titleHeightAtom)
{
printf("titleheight changed\n");
win * w = find_win(dpy, ev.xproperty.window);
if (w)
{
printf("titleheight window found\n");
w->titleHeight = get_titleHeight_prop(dpy, w);
}
else
printf("arrrg, window not found\n");
}
/* check if Trans or Shadow property was changed */
else if (ev.xproperty.atom == opacityAtom || ev.xproperty.atom == shadowAtom)
{
@ -2614,13 +2781,11 @@ main (int argc, char **argv)
/*this is hardly efficient, but a current workaraound
shaping support isn't that good so far (e.g. we lack shaped shadows)
IDEA: use XRender to scale/shift a copy of the window and then blurr it*/
/*w->fadesBlocked = True;*/
if (w->picture)
{
clipChanged = True;
repair_win (dpy, w);
}
/*w->fadesBlocked = False;*/
}
}
break;

View file

@ -175,17 +175,17 @@ unsigned long Options::updateSettings()
translucentActiveWindows = config->readBoolEntry("TranslucentActiveWindows", false);
activeWindowOpacity = uint((config->readNumEntry("ActiveWindowOpacity", 100)/100.0)*0xFFFFFFFF);
translucentInactiveWindows = config->readBoolEntry("TranslucentInactiveWindows", false);
inactiveWindowOpacity = uint((config->readNumEntry("InactiveWindowOpacity", 100)/100.0)*0xFFFFFFFF);
inactiveWindowOpacity = uint((config->readNumEntry("InactiveWindowOpacity", 75)/100.0)*0xFFFFFFFF);
translucentMovingWindows = config->readBoolEntry("TranslucentMovingWindows", false);
movingWindowOpacity = uint((config->readNumEntry("MovingWindowOpacity", 100)/100.0)*0xFFFFFFFF);
movingWindowOpacity = uint((config->readNumEntry("MovingWindowOpacity", 50)/100.0)*0xFFFFFFFF);
translucentDocks = config->readBoolEntry("TranslucentDocks", false);
dockOpacity = uint((config->readNumEntry("DockOpacity", 100)/100.0)*0xFFFFFFFF);
dockOpacity = uint((config->readNumEntry("DockOpacity", 80)/100.0)*0xFFFFFFFF);
keepAboveAsActive = config->readBoolEntry("TreatKeepAboveAsActive", true);
//TODO: remove this variable
useTitleMenuSlider = true;
activeWindowShadowSize = config->readNumEntry("ActiveWindowShadowSize", 100);
activeWindowShadowSize = config->readNumEntry("ActiveWindowShadowSize", 200);
inactiveWindowShadowSize = config->readNumEntry("InactiveWindowShadowSize", 100);
dockShadowSize = config->readNumEntry("DockShadowSize", 100);
dockShadowSize = config->readNumEntry("DockShadowSize", 80);
removeShadowsOnMove = config->readBoolEntry("RemoveShadowsOnMove", true);
removeShadowsOnResize = config->readBoolEntry("RemoveShadowsOnResize", true);
if (resetKompmgr = config->readBoolEntry("ResetKompmgr", false))