From 8ad47028f6e81770ba8d4f37f9a495bd05c517ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Sat, 15 Jan 2005 17:07:48 +0000 Subject: [PATCH] Added composite (translucency/shadows) support svn path=/trunk/kdebase/kwin/; revision=378790 --- KWinInterface.h | 6 + Makefile.am | 6 +- activation.cpp | 11 +- atoms.cpp | 9 + atoms.h | 3 + client.cpp | 263 +++++++++++++ client.h | 35 +- events.cpp | 32 +- geometry.cpp | 8 + kcmkwin/kwinoptions/Makefile.am | 2 +- kcmkwin/kwinoptions/main.cpp | 18 +- kcmkwin/kwinoptions/main.h | 2 + kcmkwin/kwinoptions/windows.cpp | 393 +++++++++++++++++++ kcmkwin/kwinoptions/windows.h | 52 ++- kcmkwin/kwinrules/ruleswidget.cpp | 27 +- kcmkwin/kwinrules/ruleswidget.h | 2 + kcmkwin/kwinrules/ruleswidgetbase.ui | 557 ++++++++++++++++----------- main.cpp | 5 +- main.h | 1 + manage.cpp | 2 + options.cpp | 22 ++ options.h | 18 + rules.cpp | 64 +++ rules.h | 8 + useractions.cpp | 58 ++- workspace.cpp | 172 ++++++++- workspace.h | 30 ++ 27 files changed, 1574 insertions(+), 232 deletions(-) diff --git a/KWinInterface.h b/KWinInterface.h index 41b7ce0f09..10b04c0186 100644 --- a/KWinInterface.h +++ b/KWinInterface.h @@ -22,6 +22,12 @@ class KWinInterface : virtual public DCOPObject virtual void nextDesktop() = 0; virtual void previousDesktop() = 0; virtual void circulateDesktopApplications() = 0; + // kompmgr stuff + virtual void startKompmgr() = 0; + virtual void stopKompmgr() = 0; + virtual void setOpacity(unsigned long winId, unsigned int opacityPercent) = 0; + virtual void setShadowSize(unsigned long winId, unsigned int shadowSizePercent) = 0; + virtual void setUnshadowed(unsigned long winId) = 0; k_dcop_signals: diff --git a/Makefile.am b/Makefile.am index e54f3033b5..c652c81e9e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,10 @@ INCLUDES = -I$(srcdir)/lib $(all_includes) -SUBDIRS = lib . killer kcmkwin pics clients oldheaders data +if include_kompmgr +KOMPMGR=kompmgr +endif + +SUBDIRS = lib . killer kcmkwin pics clients oldheaders data $(KOMPMGR) bin_PROGRAMS = lib_LTLIBRARIES = diff --git a/activation.cpp b/activation.cpp index 1ece2b8fff..2330bdd933 100644 --- a/activation.cpp +++ b/activation.cpp @@ -221,8 +221,8 @@ void Workspace::setActiveClient( Client* c, allowed_t ) ++set_active_client_recursion; if( active_client != NULL ) { // note that this may call setActiveClient( NULL ), therefore the recursion counter - active_client->setActive( false ); - } + active_client->setActive( false, !c || !c->isModal() ); + } active_client = c; Q_ASSERT( c == NULL || c->isActive()); if( active_client != NULL ) @@ -771,13 +771,16 @@ Time Client::userTime() const its own. */ -void Client::setActive( bool act) +void Client::setActive( bool act, bool updateOpacity_) { if ( active == act ) return; active = act; workspace()->setActiveClient( act ? this : NULL, Allowed ); - + + if (updateOpacity_) updateOpacity(); + updateShadowSize(); + if ( active ) Notify::raise( Notify::Activate ); diff --git a/atoms.cpp b/atoms.cpp index 05d29cdde4..3bbf2a2bfa 100644 --- a/atoms.cpp +++ b/atoms.cpp @@ -66,7 +66,16 @@ Atoms::Atoms() atoms[n] = &net_wm_take_activity; names[n++] = (char*) "_NET_WM_TAKE_ACTIVITY"; + + atoms[n] = &net_wm_window_opacity; + names[n++] = (char*) "_KDE_WM_WINDOW_OPACITY"; + atoms[n] = &net_wm_window_shadow; + names[n++] = (char*) "_KDE_WM_WINDOW_SHADOW"; + + atoms[n] = &net_wm_window_shade; + names[n++] = (char*) "_KDE_WM_WINDOW_SHADE"; + Atom fake; atoms[n] = &fake; names[n++] = (char *) "_DT_SM_WINDOW_INFO"; diff --git a/atoms.h b/atoms.h index f315ae93f0..cd5bb0caad 100644 --- a/atoms.h +++ b/atoms.h @@ -37,6 +37,9 @@ class Atoms Atom kde_net_wm_user_creation_time; Atom kde_system_tray_embedding; Atom net_wm_take_activity; + Atom net_wm_window_opacity; + Atom net_wm_window_shadow; + Atom net_wm_window_shade; Atom xdnd_aware; Atom xdnd_position; }; diff --git a/client.cpp b/client.cpp index 61c265d196..61e329fe19 100644 --- a/client.cpp +++ b/client.cpp @@ -143,6 +143,9 @@ Client::Client( Workspace *ws ) frame_geometry = QRect( 0, 0, 100, 100 ); // so that decorations don't start with size being (0,0) client_size = QSize( 100, 100 ); + custom_opacity = false; + rule_opacity_active = 0;; //translucency rules + rule_opacity_inactive = 0; //dito. // SELI initialize xsizehints?? } @@ -174,6 +177,7 @@ void Client::deleteClient( Client* c, allowed_t ) void Client::releaseWindow( bool on_shutdown ) { StackingUpdatesBlocker blocker( workspace()); + if (!custom_opacity) setOpacity(FALSE); if (moveResizeMode) leaveMoveResize(); finishWindowRules(); @@ -728,6 +732,10 @@ void Client::setShade( ShadeMode mode ) // TODO all this unmapping, resizing etc. feels too much duplicated from elsewhere if ( isShade()) { // shade_mode == ShadeNormal + // we're about to shade, texx xcompmgr to prepare + uint _shade = 1; + XChangeProperty(qt_xdisplay(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &_shade, 1L); + // shade int h = height(); shade_geometry_change = true; QSize s( sizeForClientSize( QSize( clientSize().width(), 0), SizemodeShaded ) ); @@ -735,6 +743,8 @@ void Client::setShade( ShadeMode mode ) XUnmapWindow( qt_xdisplay(), wrapper ); XUnmapWindow( qt_xdisplay(), client ); XSelectInput( qt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask ); + //as we hid the unmap event, xcompmgr didn't recognize the client wid has vanished, so we'll extra inform it + //done xcompmgr workaround // FRAME repaint( FALSE ); // bool wasStaticContents = testWFlags( WStaticContents ); // setWFlags( WStaticContents ); @@ -757,6 +767,9 @@ void Client::setShade( ShadeMode mode ) else workspace()->focusToNull(); } + // tell xcompmgr shade's done + _shade = 2; + XChangeProperty(qt_xdisplay(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &_shade, 1L); } else { @@ -784,6 +797,7 @@ void Client::setShade( ShadeMode mode ) setActive( TRUE ); XMapWindow( qt_xdisplay(), wrapperId()); XMapWindow( qt_xdisplay(), window()); + XDeleteProperty (qt_xdisplay(), client, atoms->net_wm_window_shade); if ( isActive() ) workspace()->requestFocus( this ); } @@ -1733,6 +1747,255 @@ void Client::cancelAutoRaise() autoRaiseTimer = 0; } +void Client::setOpacity(bool translucent, uint opacity) + { + if (isDesktop()) + return; // xcompmgr does not like non solid desktops and the user could set it accidently by mouse scrolling +// qWarning("setting opacity for %d",qt_xdisplay()); + //rule out activated translulcency with 100% opacity + if (!translucent || opacity == 0xFFFFFFFF) + { + opacity_ = 0xFFFFFFFF; + XDeleteProperty (qt_xdisplay(), frameId(), atoms->net_wm_window_opacity); + XDeleteProperty (qt_xdisplay(), window(), atoms->net_wm_window_opacity); // ??? frameId() is necessary for visible changes, window() is the winId() that would be set by apps - we set both to be sure the app knows what's currently displayd + } + else{ + if(opacity == opacity_) + return; + opacity_ = opacity; + XChangeProperty(qt_xdisplay(), frameId(), atoms->net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &opacity, 1L); + XChangeProperty(qt_xdisplay(), window(), atoms->net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &opacity, 1L); + } + } + +void Client::setShadowSize(uint shadowSize) + { + // ignoring all individual settings - if we control a window, we control it's shadow + // TODO somehow handle individual settings for docks (besides custom sizes) + XChangeProperty(qt_xdisplay(), frameId(), atoms->net_wm_window_shadow, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &shadowSize, 1L); + } + +void Client::updateOpacity() +// extra syncscreen flag allows to avoid double syncs when active state changes (as it will usually change for two windows) + { + if (!(isNormalWindow() || isDialog() || isUtility() )|| custom_opacity) + return; + if (isActive()) + { + if( ruleOpacityActive() ) + setOpacity(rule_opacity_active < 0xFFFFFFFF, rule_opacity_active); + else + setOpacity(options->translucentActiveWindows, options->activeWindowOpacity); + if (isBMP()) + // beep-media-player, only undecorated windows (gtk2 xmms, xmms doesn't work with compmgr at all - s.e.p. :P ) + { + ClientList tmpGroupMembers = group()->members(); + ClientList activeGroupMembers; + activeGroupMembers.append(this); + tmpGroupMembers.remove(this); + ClientList::Iterator it = tmpGroupMembers.begin(); + while (it != tmpGroupMembers.end()) + // search for next attached and not activated client and repeat if found + { + if ((*it) != this && (*it)->isBMP()) + // potential "to activate" client found + { +// qWarning("client found"); + if ((*it)->touches(this)) // first test, if the new client touches the just activated one + { +// qWarning("found client touches me"); + if( ruleOpacityActive() ) + (*it)->setOpacity(rule_opacity_active < 0xFFFFFFFF, rule_opacity_active); + else + (*it)->setOpacity(options->translucentActiveWindows, options->activeWindowOpacity); +// qWarning("activated, search restarted (1)"); + (*it)->setShadowSize(options->activeWindowShadowSize); + activeGroupMembers.append(*it); + tmpGroupMembers.remove(it); + it = tmpGroupMembers.begin(); // restart, search next client + continue; + } + else + { // pot. client does not touch c, so we have to search if it touches some other activated client + bool found = false; + for( ClientList::ConstIterator it2 = activeGroupMembers.begin(); it2 != activeGroupMembers.end(); it2++ ) + { + if ((*it2) != this && (*it2) != (*it) && (*it)->touches(*it2)) + { +// qWarning("found client touches other active client"); + if( ruleOpacityActive() ) + (*it)->setOpacity(rule_opacity_active < 0xFFFFFFFF, rule_opacity_active); + else + (*it)->setOpacity(options->translucentActiveWindows, options->activeWindowOpacity); + (*it)->setShadowSize(options->activeWindowShadowSize); + activeGroupMembers.append(*it); + tmpGroupMembers.remove(it); + it = tmpGroupMembers.begin(); // reset potential client search + found = true; +// qWarning("activated, search restarted (2)"); + break; // skip this loop + } + } + if (found) continue; + } + } + it++; + } + } + else if (isNormalWindow()) + // activate dependend minor windows as well + { + for( ClientList::ConstIterator it = group()->members().begin(); it != group()->members().end(); it++ ) + if ((*it)->isDialog() || (*it)->isUtility()) + if( (*it)->ruleOpacityActive() ) + (*it)->setOpacity((*it)->ruleOpacityActive() < 0xFFFFFFFF, (*it)->ruleOpacityActive()); + else + (*it)->setOpacity(options->translucentActiveWindows, options->activeWindowOpacity); + } + } + else + { + if( ruleOpacityInactive() ) + setOpacity(rule_opacity_inactive < 0xFFFFFFFF, rule_opacity_inactive); + else + setOpacity(options->translucentInactiveWindows && !(keepAbove() && options->keepAboveAsActive), + options->inactiveWindowOpacity); + // deactivate dependend minor windows as well + if (isBMP()) + // beep-media-player, only undecorated windows (gtk2 xmms, xmms doesn't work with compmgr at all - s.e.p. :P ) + { + ClientList tmpGroupMembers = group()->members(); + ClientList inactiveGroupMembers; + inactiveGroupMembers.append(this); + tmpGroupMembers.remove(this); + ClientList::Iterator it = tmpGroupMembers.begin(); + while ( it != tmpGroupMembers.end() ) + // search for next attached and not activated client and repeat if found + { + if ((*it) != this && (*it)->isBMP()) + // potential "to activate" client found + { +// qWarning("client found"); + if ((*it)->touches(this)) // first test, if the new client touches the just activated one + { +// qWarning("found client touches me"); + if( (*it)->ruleOpacityInactive() ) + (*it)->setOpacity((*it)->ruleOpacityInactive() < 0xFFFFFFFF, (*it)->ruleOpacityInactive()); + else + (*it)->setOpacity(options->translucentInactiveWindows && !((*it)->keepAbove() && options->keepAboveAsActive), options->inactiveWindowOpacity); + (*it)->setShadowSize(options->inactiveWindowShadowSize); +// qWarning("deactivated, search restarted (1)"); + inactiveGroupMembers.append(*it); + tmpGroupMembers.remove(it); + it = tmpGroupMembers.begin(); // restart, search next client + continue; + } + else // pot. client does not touch c, so we have to search if it touches some other activated client + { + bool found = false; + for( ClientList::ConstIterator it2 = inactiveGroupMembers.begin(); it2 != inactiveGroupMembers.end(); it2++ ) + { + if ((*it2) != this && (*it2) != (*it) && (*it)->touches(*it2)) + { +// qWarning("found client touches other inactive client"); + if( (*it)->ruleOpacityInactive() ) + (*it)->setOpacity((*it)->ruleOpacityInactive() < 0xFFFFFFFF, (*it)->ruleOpacityInactive()); + else + (*it)->setOpacity(options->translucentInactiveWindows && !((*it)->keepAbove() && options->keepAboveAsActive), options->inactiveWindowOpacity); + (*it)->setShadowSize(options->inactiveWindowShadowSize); +// qWarning("deactivated, search restarted (2)"); + inactiveGroupMembers.append(*it); + tmpGroupMembers.remove(it); + it = tmpGroupMembers.begin(); // reset potential client search + found = true; + break; // skip this loop + } + } + if (found) continue; + } + } + it++; + } + } + else if (isNormalWindow()) + { + for( ClientList::ConstIterator it = group()->members().begin(); it != group()->members().end(); it++ ) + if ((*it)->isUtility()) //don't deactivate dialogs... + if( (*it)->ruleOpacityInactive() ) + (*it)->setOpacity((*it)->ruleOpacityInactive() < 0xFFFFFFFF, (*it)->ruleOpacityInactive()); + else + (*it)->setOpacity(options->translucentInactiveWindows && !((*it)->keepAbove() && options->keepAboveAsActive), options->inactiveWindowOpacity); + } + } + } + +void Client::updateShadowSize() +// extra syncscreen flag allows to avoid double syncs when active state changes (as it will usually change for two windows) + { + if (!(isNormalWindow() || isDialog() || isUtility() )) + return; + if (isActive()) + setShadowSize(options->activeWindowShadowSize); + else + setShadowSize(options->inactiveWindowShadowSize); + } + +uint Client::ruleOpacityInactive() + { + return rule_opacity_inactive;// != 0 ; + } + +uint Client::ruleOpacityActive() + { + return rule_opacity_active;// != 0; + } + +bool Client::getWindowOpacity() //query translucency settings from X, returns true if window opacity is set + { + unsigned char *data = 0; + Atom actual; + int format, result; + unsigned long n, left; + result = XGetWindowProperty(qt_xdisplay(), window(), atoms->net_wm_window_opacity, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, /*(unsigned char **)*/ &data); + if (result == Success && data != None) + { + memcpy (&opacity_, data, sizeof (unsigned int)); + custom_opacity = true; +// setOpacity(opacity_ < 0xFFFFFFFF, opacity_); + return TRUE; + } + return FALSE; + } + +void Client::setCustomOpacityFlag(bool custom) + { + custom_opacity = custom; + } + +uint Client::opacity() + { + return opacity_; + } + +int Client::opacityPercentage() + { + return ((int)100*((double)opacity_/0xffffffff)); + } + +bool Client::touches(const Client* c) +// checks if this client borders c, needed to test beep media player window state + { + if (y() == c->y() + c->height()) // this bottom to c + return TRUE; + if (y() + height() == c->y()) // this top to c + return TRUE; + if (x() == c->x() + c->width()) // this right to c + return TRUE; + if (x() + width() == c->x()) // this left to c + return TRUE; + return FALSE; + } + #ifndef NDEBUG kdbgstream& operator<<( kdbgstream& stream, const Client* cl ) { diff --git a/client.h b/client.h index 8cc077da07..2d15ff558e 100644 --- a/client.h +++ b/client.h @@ -105,7 +105,7 @@ class Client : public QObject, public KDecorationDefines QPixmap miniIcon() const; bool isActive() const; - void setActive( bool ); + void setActive( bool, bool updateOpacity = true ); int desktop() const; void setDesktop( int ); @@ -277,6 +277,21 @@ class Client : public QObject, public KDecorationDefines void cancelAutoRaise(); void destroyClient(); void checkActiveModal(); + void setOpacity(bool translucent, uint opacity = 0); + void setShadowSize(uint shadowSize); + void updateOpacity(); + void updateShadowSize(); + bool hasCustomOpacity(){return custom_opacity;} + void setCustomOpacityFlag(bool custom = true); + bool getWindowOpacity(); + int opacityPercentage(); + void checkAndSetInitialRuledOpacity(); + uint ruleOpacityInactive(); + uint ruleOpacityActive(); + unsigned int opacity(); + bool isBMP(); + void setBMP(bool b); + bool touches(const Client* c); private slots: void autoRaise(); @@ -505,6 +520,14 @@ class Client : public QObject, public KDecorationDefines friend struct ResetupRulesProcedure; void show() { assert( false ); } // SELI remove after Client is no longer QWidget void hide() { assert( false ); } + uint opacity_; + uint savedOpacity_; + bool custom_opacity; + uint rule_opacity_active; //translucency rules + uint rule_opacity_inactive; //dto. + //int shadeOriginalHeight; + bool isBMP_; + }; // NET WM Protocol handler class @@ -856,7 +879,17 @@ inline void Client::setShortcut( const KShortcut& cut ) _shortcut = cut; workspace()->clientShortcutUpdated( this ); } + +inline bool Client::isBMP() + { + return isBMP_; + } +inline void Client::setBMP(bool b) + { + isBMP_ = b; + } + #ifdef NDEBUG inline kndbgstream& operator<<( kndbgstream& stream, const Client* ) { return stream; } diff --git a/events.cpp b/events.cpp index 7c20fa3946..0397c08170 100644 --- a/events.cpp +++ b/events.cpp @@ -567,7 +567,7 @@ bool Client::windowEvent( XEvent* e ) workspace()->setWasUserInteraction(); buttonPressEvent( e->xbutton.window, e->xbutton.button, e->xbutton.state, e->xbutton.x, e->xbutton.y, e->xbutton.x_root, e->xbutton.y_root ); - break;; + break; case KeyRelease: // don't update user time on releases // e.g. if the user presses Alt+F2, the Alt release @@ -1120,7 +1120,35 @@ bool Client::buttonPressEvent( Window w, int button, int state, int x, int y, in Options::MouseCommand com = Options::MouseNothing; bool was_action = false; bool perform_handled = false; - if ( bModKeyHeld ) + if (keyModX != 0 && (state & keyModX) && (state & ControlMask)) + { + switch (button) + { + case Button5: + if (opacity_ > 0) + { + setOpacity(TRUE, (opacity_ > 0xCCCCCCC) ? opacity_ - 0xCCCCCCC : 0); + custom_opacity = true; + } + XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime ); + return true; + case Button4: + if (opacity_ < 0xFFFFFFFF) + { + if (opacity_ < 0xF3333333){ + setOpacity(TRUE, opacity_ + 0xCCCCCCC); + custom_opacity = true; + } + else{ + setOpacity(FALSE, 0xFFFFFFFF); + custom_opacity = false; + } + } + XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime ); + return true; + } + } + else if ( bModKeyHeld ) { was_action = true; switch (button) diff --git a/geometry.cpp b/geometry.cpp index 64d958e809..47e83e497e 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -2108,6 +2108,11 @@ bool Client::startMoveResize() workspace()->setClientIsMoving(this); initialMoveResizeGeom = moveResizeGeom = geometry(); checkUnrestrictedMoveResize(); + // rule out non opaque windows from useless translucency settings, maybe resizes? + if (/*isMove() && */rules()->checkMoveResizeMode( options->moveMode ) == Options::Opaque){ + savedOpacity_ = opacity_; + setOpacity(options->translucentMovingWindows, options->movingWindowOpacity); + } if ( ( isMove() && rules()->checkMoveResizeMode( options->moveMode ) != Options::Opaque ) || ( isResize() && rules()->checkMoveResizeMode( options->resizeMode ) != Options::Opaque ) ) { @@ -2139,6 +2144,9 @@ void Client::finishMoveResize( bool cancel ) void Client::leaveMoveResize() { + // rule out non opaque windows from useless translucency settings, maybe resizes? + if (/*isMove() && */rules()->checkMoveResizeMode( options->moveMode ) == Options::Opaque) + setOpacity(true, savedOpacity_); clearbound(); if (geometryTip) { diff --git a/kcmkwin/kwinoptions/Makefile.am b/kcmkwin/kwinoptions/Makefile.am index cf0888f269..b6abdf0e75 100644 --- a/kcmkwin/kwinoptions/Makefile.am +++ b/kcmkwin/kwinoptions/Makefile.am @@ -12,7 +12,7 @@ noinst_HEADERS = windows.h mouse.h messages: $(XGETTEXT) *.cpp -o $(podir)/kcmkwm.pot -kwin_kcmkwin_options_data_DATA = kwinactions.desktop kwinadvanced.desktop kwinfocus.desktop kwinmoving.desktop +kwin_kcmkwin_options_data_DATA = kwinactions.desktop kwinadvanced.desktop kwinfocus.desktop kwinmoving.desktop kwintranslucency.desktop kwin_kcmkwin_options_datadir = $(kde_appsdir)/.hidden xdg_apps_DATA = kwinoptions.desktop diff --git a/kcmkwin/kwinoptions/main.cpp b/kcmkwin/kwinoptions/main.cpp index 14be031d5c..884d8c2cd0 100644 --- a/kcmkwin/kwinoptions/main.cpp +++ b/kcmkwin/kwinoptions/main.cpp @@ -67,6 +67,14 @@ extern "C" KConfig *c = new KConfig("kwinrc", false, true); return new KAdvancedConfig(true, c, parent, name); } + + KCModule *create_kwintranslucency(QWidget *parent, const char *name) + { + //CT there's need for decision: kwm or kwin? + KGlobal::locale()->insertCatalogue("kcmkwm"); + KConfig *c = new KConfig("kwinrc", false, true); + return new KTranslucencyConfig(true, c, parent, name); + } KDE_EXPORT KCModule *create_kwinoptions ( QWidget *parent, const char* name) { @@ -104,7 +112,12 @@ KWinOptions::KWinOptions(QWidget *parent, const char *name) mAdvanced->layout()->setMargin( KDialog::marginHint() ); tab->addTab(mAdvanced, i18n("Ad&vanced")); connect(mAdvanced, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); - + + mTranslucency = new KTranslucencyConfig(false, mConfig, this, "KWin Translucency"); + mTranslucency->layout()->setMargin( KDialog::marginHint() ); + tab->addTab(mTranslucency, i18n("&Translucency")); + connect(mTranslucency, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + KAboutData *about = new KAboutData(I18N_NOOP("kcmkwinoptions"), I18N_NOOP("Window Behavior Configuration Module"), 0, 0, KAboutData::License_GPL, @@ -134,6 +147,7 @@ void KWinOptions::load() mActions->load(); mMoving->load(); mAdvanced->load(); + mTranslucency->load(); emit KCModule::changed( false ); } @@ -144,6 +158,7 @@ void KWinOptions::save() mActions->save(); mMoving->save(); mAdvanced->save(); + mTranslucency->save(); emit KCModule::changed( false ); // Send signal to kwin @@ -160,6 +175,7 @@ void KWinOptions::defaults() mActions->defaults(); mMoving->defaults(); mAdvanced->defaults(); + mTranslucency->defaults(); } QString KWinOptions::quickHelp() const diff --git a/kcmkwin/kwinoptions/main.h b/kcmkwin/kwinoptions/main.h index e7e01d5a89..127e4ae66e 100644 --- a/kcmkwin/kwinoptions/main.h +++ b/kcmkwin/kwinoptions/main.h @@ -32,6 +32,7 @@ class KConfig; class KFocusConfig; class KActionsConfig; class KAdvancedConfig; +class KTranslucencyConfig; class KWinOptions : public KCModule { @@ -61,6 +62,7 @@ private: KActionsConfig *mActions; KMovingConfig *mMoving; KAdvancedConfig *mAdvanced; + KTranslucencyConfig *mTranslucency; KConfig *mConfig; }; diff --git a/kcmkwin/kwinoptions/windows.cpp b/kcmkwin/kwinoptions/windows.cpp index 2c5f3d0ba7..ae21e7c653 100644 --- a/kcmkwin/kwinoptions/windows.cpp +++ b/kcmkwin/kwinoptions/windows.cpp @@ -23,6 +23,7 @@ #include +#include #include #include #include @@ -31,14 +32,19 @@ #include #include #include +#include +#include #include +#include #include #include #include #include #include #include +#include +#include #include #include @@ -1156,4 +1162,391 @@ void KMovingConfig::setWindowSnapZone(int pxls) { WndwSnap->setValue(pxls); } +KTranslucencyConfig::~KTranslucencyConfig () +{ + if (standAlone) + delete config; + if (kompmgr) + kompmgr->detach(); +} + +KTranslucencyConfig::KTranslucencyConfig (bool _standAlone, KConfig *_config, QWidget *parent, const char *) + : KCModule(parent, "kcmkwm"), config(_config), standAlone(_standAlone) +{ + kompmgr = 0L; + resetKompmgr_ = FALSE; + QVBoxLayout *lay = new QVBoxLayout (this); + if (!kompmgrAvailable()){ + KActiveLabel *label = new KActiveLabel(i18n("It seems as if alpha channel support is not available!
\n" + "Please make sure, you have these things available:
" + "Also make sure you have the following entries in your X Config
(e.g. /etc/XF86Config):

" + "Section \"Extensions\"
" + "Option \"Composite\" \"Enable\"
" + "EndSection


" + "And if you have a GPU that supports hardware accelerated Xrender support:

" + "Option \"RenderAccel\" \"true\"
" + "In Section \"Device\""), this); + lay->addWidget(label); + } + else + { + QTabWidget *tabW = new QTabWidget(this); + QWidget *tGroup = new QWidget(tabW); + QVBoxLayout *vLay = new QVBoxLayout (tGroup,11,6); + vLay->addSpacing(11); // to get the proper gb top offset + QGridLayout *gLay = new QGridLayout(vLay,4,2); + gLay->setColStretch(1,1); + + activeWindowTransparency = new QCheckBox(i18n("Active Windows"),tGroup); + gLay->addWidget(activeWindowTransparency,0,0); + activeWindowOpacity = new KIntNumInput(100, tGroup); + activeWindowOpacity->setRange(0,100); + activeWindowOpacity->setSuffix("%"); + gLay->addWidget(activeWindowOpacity,0,1); + + inactiveWindowTransparency = new QCheckBox(i18n("Inactive Windows"),tGroup); + gLay->addWidget(inactiveWindowTransparency,1,0); + inactiveWindowOpacity = new KIntNumInput(100, tGroup); + inactiveWindowOpacity->setRange(0,100); + inactiveWindowOpacity->setSuffix("%"); + gLay->addWidget(inactiveWindowOpacity,1,1); + + movingWindowTransparency = new QCheckBox(i18n("Moving Windows"),tGroup); + gLay->addWidget(movingWindowTransparency,2,0); + movingWindowOpacity = new KIntNumInput(100, tGroup); + movingWindowOpacity->setRange(0,100); + movingWindowOpacity->setSuffix("%"); + gLay->addWidget(movingWindowOpacity,2,1); + + dockWindowTransparency = new QCheckBox(i18n("Dock Windows"),tGroup); + gLay->addWidget(dockWindowTransparency,3,0); + dockWindowOpacity = new KIntNumInput(100, tGroup); + dockWindowOpacity->setRange(0,100); + dockWindowOpacity->setSuffix("%"); + gLay->addWidget(dockWindowOpacity,3,1); + + keepAboveAsActive = new QCheckBox(i18n("Treat 'Keep Above' Windows as active ones"),tGroup); + vLay->addWidget(keepAboveAsActive); + vLay->addStretch(); + tabW->addTab(tGroup, i18n("Translucency")); + + QWidget *sGroup = new QWidget(tabW); +// sGroup->setCheckable(TRUE); + QVBoxLayout *vLay2 = new QVBoxLayout (sGroup,11,6); + vLay2->addSpacing(11); // to get the proper gb top offset + useShadows = new QCheckBox(i18n("Use Shadows"),sGroup); + vLay2->addWidget(useShadows); + + QGridLayout *gLay2 = new QGridLayout(vLay2,6,2); + gLay2->setColStretch(1,1); + + QLabel *label1 = new QLabel(i18n("Active Window Size"),sGroup); + gLay2->addWidget(label1,0,0); + activeWindowShadowSize = new KIntNumInput(12,sGroup); + activeWindowShadowSize->setRange(0,32); +// activeWindowShadowSize->setSuffix("px"); + gLay2->addWidget(activeWindowShadowSize,0,1); + + QLabel *label2 = new QLabel(i18n("Inactive Window Size"),sGroup); + gLay2->addWidget(label2,1,0); + inactiveWindowShadowSize = new KIntNumInput(6,sGroup); + inactiveWindowShadowSize->setRange(0,32); +// inactiveWindowShadowSize->setSuffix("px"); + gLay2->addWidget(inactiveWindowShadowSize,1,1); + + QLabel *label3 = new QLabel(i18n("Dock Window Size"),sGroup); + gLay2->addWidget(label3,2,0); + dockWindowShadowSize = new KIntNumInput(6,sGroup); + dockWindowShadowSize->setRange(0,32); +// dockWindowShadowSize->setSuffix("px"); + gLay2->addWidget(dockWindowShadowSize,2,1); + + QLabel *label4 = new QLabel(i18n("Vertical Offset"),sGroup); + gLay2->addWidget(label4,3,0); + shadowTopOffset = new KIntNumInput(80,sGroup); + shadowTopOffset->setSuffix("%"); + shadowTopOffset->setRange(-200,200); + gLay2->addWidget(shadowTopOffset,3,1); + + QLabel *label5 = new QLabel(i18n("Horizontal Offset"),sGroup); + gLay2->addWidget(label5,4,0); + shadowLeftOffset = new KIntNumInput(0,sGroup); + shadowLeftOffset->setSuffix("%"); + shadowLeftOffset->setRange(-200,200); + gLay2->addWidget(shadowLeftOffset,4,1); + + QLabel *label6 = new QLabel(i18n("Shadow Color"),sGroup); + gLay2->addWidget(label6,5,0); + shadowColor = new KColorButton(Qt::black,sGroup); + gLay2->addWidget(shadowColor,5,1); + gLay2->setColStretch(1,1); + vLay2->addStretch(); + tabW->addTab(sGroup, i18n("Shadows")); + + QWidget *eGroup = new QWidget(this); + QVBoxLayout *vLay3 = new QVBoxLayout (eGroup,11,6); + + fadeInWindows = new QCheckBox(i18n("Fade-In Windows (including Popups)"),eGroup); + fadeOnOpacityChange = new QCheckBox(i18n("Fade between opacity changes"),eGroup); + fadeInSpeed = new KIntNumInput(100, eGroup); + fadeInSpeed->setRange(1,100); + fadeInSpeed->setLabel("Fade-In Speed"); + fadeOutSpeed = new KIntNumInput(100, eGroup); + fadeOutSpeed->setRange(1,100); + fadeOutSpeed->setLabel("Fade-Out Speed"); + vLay3->addWidget(fadeInWindows); + vLay3->addWidget(fadeOnOpacityChange); + vLay3->addWidget(fadeInSpeed); + vLay3->addWidget(fadeOutSpeed); + vLay3->addStretch(); + + tabW->addTab(eGroup, i18n("Effects")); + + useTranslucency = new QCheckBox(i18n("Use Translucency/Shadows"),this); + lay->addWidget(useTranslucency); + lay->addWidget(tabW); + + connect(useTranslucency, SIGNAL(toggled(bool)), tabW, SLOT(setEnabled(bool))); + + connect(activeWindowTransparency, SIGNAL(toggled(bool)), activeWindowOpacity, SLOT(setEnabled(bool))); + connect(inactiveWindowTransparency, SIGNAL(toggled(bool)), inactiveWindowOpacity, SLOT(setEnabled(bool))); + connect(movingWindowTransparency, SIGNAL(toggled(bool)), movingWindowOpacity, SLOT(setEnabled(bool))); + connect(dockWindowTransparency, SIGNAL(toggled(bool)), dockWindowOpacity, SLOT(setEnabled(bool))); + + connect(useTranslucency, SIGNAL(toggled(bool)), SLOT(changed())); + connect(activeWindowTransparency, SIGNAL(toggled(bool)), SLOT(changed())); + connect(inactiveWindowTransparency, SIGNAL(toggled(bool)), SLOT(changed())); + connect(movingWindowTransparency, SIGNAL(toggled(bool)), SLOT(changed())); + connect(dockWindowTransparency, SIGNAL(toggled(bool)), SLOT(changed())); + connect(keepAboveAsActive, SIGNAL(toggled(bool)), SLOT(changed())); + connect(useShadows, SIGNAL(toggled(bool)), SLOT(changed())); + + connect(activeWindowOpacity, SIGNAL(valueChanged(int)), SLOT(changed())); + connect(inactiveWindowOpacity, SIGNAL(valueChanged(int)), SLOT(changed())); + connect(movingWindowOpacity, SIGNAL(valueChanged(int)), SLOT(changed())); + connect(dockWindowOpacity, SIGNAL(valueChanged(int)), SLOT(changed())); + connect(dockWindowShadowSize, SIGNAL(valueChanged(int)), SLOT(changed())); + connect(activeWindowShadowSize, SIGNAL(valueChanged(int)), SLOT(changed())); + connect(inactiveWindowShadowSize, SIGNAL(valueChanged(int)), SLOT(changed())); + connect(shadowTopOffset, SIGNAL(valueChanged(int)), SLOT(changed())); + connect(shadowLeftOffset, SIGNAL(valueChanged(int)), SLOT(changed())); + connect(shadowColor, SIGNAL(changed(const QColor&)), SLOT(changed())); + connect(fadeInWindows, SIGNAL(toggled(bool)), SLOT(changed())); + connect(fadeOnOpacityChange, SIGNAL(toggled(bool)), SLOT(changed())); + connect(fadeInSpeed, SIGNAL(valueChanged(int)), SLOT(changed())); + connect(fadeOutSpeed, SIGNAL(valueChanged(int)), SLOT(changed())); + + connect(useShadows, SIGNAL(toggled(bool)), dockWindowShadowSize, SLOT(setEnabled(bool))); + connect(useShadows, SIGNAL(toggled(bool)), activeWindowShadowSize, SLOT(setEnabled(bool))); + connect(useShadows, SIGNAL(toggled(bool)), inactiveWindowShadowSize, SLOT(setEnabled(bool))); + connect(useShadows, SIGNAL(toggled(bool)), shadowTopOffset, SLOT(setEnabled(bool))); + connect(useShadows, SIGNAL(toggled(bool)), shadowLeftOffset, SLOT(setEnabled(bool))); + connect(useShadows, SIGNAL(toggled(bool)), shadowColor, SLOT(setEnabled(bool))); + + load(); + + tabW->setEnabled(useTranslucency->isChecked()); + + connect(useTranslucency, SIGNAL(toggled(bool)), this, SLOT(showWarning(bool))); + + // handle kompmgr restarts if necessary + connect(useTranslucency, SIGNAL(toggled(bool)), SLOT(resetKompmgr())); + connect(useShadows, SIGNAL(toggled(bool)), SLOT(resetKompmgr())); + connect(inactiveWindowShadowSize, SIGNAL(valueChanged(int)), SLOT(resetKompmgr())); + connect(shadowTopOffset, SIGNAL(valueChanged(int)), SLOT(resetKompmgr())); + connect(shadowLeftOffset, SIGNAL(valueChanged(int)), SLOT(resetKompmgr())); + connect(shadowColor, SIGNAL(changed(const QColor&)), SLOT(resetKompmgr())); + connect(fadeInWindows, SIGNAL(toggled(bool)), SLOT(resetKompmgr())); + connect(fadeOnOpacityChange, SIGNAL(toggled(bool)), SLOT(resetKompmgr())); + connect(fadeInSpeed, SIGNAL(valueChanged(int)), SLOT(resetKompmgr())); + connect(fadeOutSpeed, SIGNAL(valueChanged(int)), SLOT(resetKompmgr())); + + } +} + +void KTranslucencyConfig::resetKompmgr() +{ + resetKompmgr_ = TRUE; +} +void KTranslucencyConfig::load( void ) +{ + + config->setGroup( "Translucency" ); + + useTranslucency->setChecked(config->readBoolEntry("UseTranslucency",false)); + activeWindowTransparency->setChecked(config->readBoolEntry("TranslucentActiveWindows",false)); + inactiveWindowTransparency->setChecked(config->readBoolEntry("TranslucentInactiveWindows",true)); + movingWindowTransparency->setChecked(config->readBoolEntry("TranslucentMovingWindows",false)); + dockWindowTransparency->setChecked(config->readBoolEntry("TranslucentDocks",true)); + keepAboveAsActive->setChecked(config->readBoolEntry("TreatKeepAboveAsActive",true)); + + activeWindowOpacity->setValue(config->readNumEntry("ActiveWindowOpacity",100)); + inactiveWindowOpacity->setValue(config->readNumEntry("InactiveWindowOpacity",50)); + movingWindowOpacity->setValue(config->readNumEntry("MovingWindowOpacity",25)); + dockWindowOpacity->setValue(config->readNumEntry("DockOpacity",80)); + + int ass, iss, dss; + dss = config->readNumEntry("DockShadowSize", 50); + ass = config->readNumEntry("ActiveWindowShadowSize", 200); + iss = config->readNumEntry("InactiveWindowShadowSize", 100); + + activeWindowOpacity->setEnabled(activeWindowTransparency->isChecked()); + inactiveWindowOpacity->setEnabled(inactiveWindowTransparency->isChecked()); + movingWindowOpacity->setEnabled(movingWindowTransparency->isChecked()); + dockWindowOpacity->setEnabled(dockWindowTransparency->isChecked()); + + KConfig conf_(QDir::homeDirPath() + "/.xcompmgrrc"); + conf_.setGroup("xcompmgr"); + + useShadows->setChecked(conf_.readEntry("Compmode","CompClientShadows").compare("CompClientShadows") == 0); + shadowTopOffset->setValue(-1*(conf_.readNumEntry("ShadowOffsetY",-80))); + shadowLeftOffset->setValue(-1*(conf_.readNumEntry("ShadowOffsetX",0))); + + int ss = conf_.readNumEntry("ShadowRadius",6); + dockWindowShadowSize->setValue((int)(dss*ss/100.0)); + activeWindowShadowSize->setValue((int)(ass*ss/100.0)); + inactiveWindowShadowSize->setValue((int)(iss*ss/100.0)); + + QString hex = conf_.readEntry("ShadowColor","#000000"); + uint r, g, b; + r = g = b = 256; + + if (sscanf(hex.latin1(), "0x%02x%02x%02x", &r, &g, &b)!=3 || r > 255 || g > 255 || b > 255) + shadowColor->setColor(Qt::black); + else + shadowColor->setColor(QColor(r,g,b)); + + 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)); + + emit KCModule::changed(false); +} + +void KTranslucencyConfig::save( void ) +{ + config->setGroup( "Translucency" ); + + config->writeEntry("UseTranslucency",useTranslucency->isChecked()); + config->writeEntry("TranslucentActiveWindows",activeWindowTransparency->isChecked()); + config->writeEntry("TranslucentInactiveWindows",inactiveWindowTransparency->isChecked()); + config->writeEntry("TranslucentMovingWindows",movingWindowTransparency->isChecked()); + config->writeEntry("TranslucentDocks",dockWindowTransparency->isChecked()); + config->writeEntry("TreatKeepAboveAsActive",keepAboveAsActive->isChecked()); + config->writeEntry("ActiveWindowOpacity",activeWindowOpacity->value()); + config->writeEntry("InactiveWindowOpacity",inactiveWindowOpacity->value()); + config->writeEntry("MovingWindowOpacity",movingWindowOpacity->value()); + config->writeEntry("DockOpacity",dockWindowOpacity->value()); + // for simplification: + // xcompmgr supports a general shadow radius and additionally lets external apps set a multiplicator for each window + // (speed reasons, so the shadow matrix hasn't to be recreated for every window) + // we set inactive windows to 100%, the radius to the inactive window value and adjust the multiplicators for docks and active windows + // this way the user can set the three values without caring about the radius/multiplicator stuff + config->writeEntry("DockShadowSize",100.0*dockWindowShadowSize->value()/inactiveWindowShadowSize->value()); + config->writeEntry("ActiveWindowShadowSize",100.0*activeWindowShadowSize->value()/inactiveWindowShadowSize->value()); + config->writeEntry("InctiveWindowShadowSize",100); + config->writeEntry("ResetKompmgr",resetKompmgr_); + + KConfig *conf_ = new KConfig(QDir::homeDirPath() + "/.xcompmgrrc"); + conf_->setGroup("xcompmgr"); + + conf_->writeEntry("Compmode",useShadows->isChecked()?"CompClientShadows":""); + conf_->writeEntry("ShadowOffsetY",-1*shadowTopOffset->value()); + conf_->writeEntry("ShadowOffsetX",-1*shadowLeftOffset->value()); + + + int r, g, b; + shadowColor->color().rgb( &r, &g, &b ); + QString hex; + hex.sprintf("0x%02X%02X%02X", r,g,b); + conf_->writeEntry("ShadowColor",hex); + conf_->writeEntry("ShadowRadius",inactiveWindowShadowSize->value()); + conf_->writeEntry("FadeWindows",fadeInWindows->isChecked()); + conf_->writeEntry("FadeTrans",fadeOnOpacityChange->isChecked()); + conf_->writeEntry("FadeInStep",fadeInSpeed->value()/1000.0); + conf_->writeEntry("FadeOutStep",fadeOutSpeed->value()/1000.0); + + delete conf_; + + if (standAlone) + { + config->sync(); + if ( !kapp->dcopClient()->isAttached() ) + kapp->dcopClient()->attach(); + kapp->dcopClient()->send("kwin*", "", "reconfigure()", ""); + } + emit KCModule::changed(false); +} + +void KTranslucencyConfig::defaults() +{ + useTranslucency->setChecked(false); + activeWindowTransparency->setChecked(false); + inactiveWindowTransparency->setChecked(true); + movingWindowTransparency->setChecked(false); + dockWindowTransparency->setChecked(true); + keepAboveAsActive->setChecked(true); + + activeWindowOpacity->setValue(100); + inactiveWindowOpacity->setValue(50); + movingWindowOpacity->setValue(25); + dockWindowOpacity->setValue(80); + + dockWindowShadowSize->setValue(6); + activeWindowShadowSize->setValue(12); + inactiveWindowShadowSize->setValue(6); + shadowTopOffset->setValue(80); + shadowLeftOffset->setValue(0); + + activeWindowOpacity->setEnabled(false); + inactiveWindowOpacity->setEnabled(true); + movingWindowOpacity->setEnabled(false); + dockWindowOpacity->setEnabled(true); + shadowColor->setColor(Qt::black); + fadeInWindows->setChecked(TRUE); + fadeOnOpacityChange->setChecked(FALSE); + fadeInSpeed->setValue(28); + fadeOutSpeed->setValue(30); + emit KCModule::changed(true); +} + + +bool KTranslucencyConfig::kompmgrAvailable() +{ + bool ret; + KProcess proc; + proc << "kompmgr" << "-v"; + ret = proc.start(KProcess::DontCare, KProcess::AllOutput); + proc.detach(); + return ret; +} + +void KTranslucencyConfig::handleXCompMgrOutput( KProcess *proc, char *buffer, int buflen) +{ + if (QString(buffer).contains("Can't open display",false)) + QMessageBox::critical(0, i18n("xCompMgr failure"), i18n("Failed to open display
There's probably an invalid display entry in your ~/.xcompmgrrc"), QMessageBox::Ok, 0); + else if (QString(buffer).contains("No render extension",false)) + QMessageBox::critical(0, i18n("xCompMgr failure"), i18n("Xrender extension not found
You're either using an outdated or a crippled version of XOrg.
Get XOrg ≥ 6.8 from www.freedesktop.org"), QMessageBox::Ok, 0); + else if (QString(buffer).contains("No composite extension",false)) + QMessageBox::critical(0,i18n("xCompMgr failure"), i18n("Composite extension not found
You must use XOrg ≥ 6.8 to have this work
Additionally you need to add a new section to your X config file:
" + "Section \"Extensions\"
" + "Option \"Composite\" \"Enable\"
" + "EndSection
"), QMessageBox::Ok, 0); + else if (QString(buffer).contains("No damage extension",false)) + QMessageBox::critical(0,i18n("xCompMgr failure"), i18n("Damage extension not found
You must use XOrg ≥ 6.8 to have this work"), QMessageBox::Ok,0); + else if (QString(buffer).contains("No XFixes extension",false)) + QMessageBox::critical(0,i18n("xCompMgr failure"), i18n("XFixes extension not found
You must use XOrg ≥ 6.8 to have this work"), QMessageBox::Ok,0); + else return; + kompmgr->detach(); +} + +void KTranslucencyConfig::showWarning(bool alphaActivated) +{ + if (alphaActivated) + QMessageBox::information(0, i18n("Warning"), i18n("Translucency support is new and may cause problems,
including crashes (sometimes the Translucency Engine, seldom even X)"), QMessageBox::Ok, 0); +} + #include "windows.moc" diff --git a/kcmkwin/kwinoptions/windows.h b/kcmkwin/kwinoptions/windows.h index f043df6e1b..02b4cdca49 100644 --- a/kcmkwin/kwinoptions/windows.h +++ b/kcmkwin/kwinoptions/windows.h @@ -30,12 +30,14 @@ class QRadioButton; class QCheckBox; class QPushButton; class QComboBox; +class QGroupBox; class QLabel; class QSlider; class QButtonGroup; class QSpinBox; class QVButtonGroup; +class KColorButton; class KIntNumInput; #define TRANSPARENT 0 @@ -225,5 +227,53 @@ private: QComboBox* focusStealing; }; -#endif +class KProcess; +class KTranslucencyConfig : public KCModule +{ + Q_OBJECT +public: + KTranslucencyConfig( bool _standAlone, KConfig *config, QWidget *parent=0, const char* name=0 ); + ~KTranslucencyConfig(); + + void load(); + void save(); + void defaults(); + +private: + QCheckBox *useTranslucency; + QCheckBox *activeWindowTransparency; + QCheckBox *inactiveWindowTransparency; + QCheckBox *movingWindowTransparency; + QCheckBox *dockWindowTransparency; + QCheckBox *keepAboveAsActive; + QCheckBox *fadeInWindows; + QCheckBox *fadeOnOpacityChange; + QCheckBox *useShadows; + QGroupBox *sGroup; +// QPushButton *xcompmgrButton; + KIntNumInput *activeWindowOpacity; + KIntNumInput *inactiveWindowOpacity; + KIntNumInput *movingWindowOpacity; + KIntNumInput *dockWindowOpacity; + KIntNumInput *dockWindowShadowSize; + KIntNumInput *activeWindowShadowSize; + KIntNumInput *inactiveWindowShadowSize; + KIntNumInput *shadowTopOffset; + KIntNumInput *shadowLeftOffset; + KIntNumInput *fadeInSpeed; + KIntNumInput *fadeOutSpeed; + KColorButton *shadowColor; + KConfig *config; + bool standAlone; + bool alphaActivated; + bool resetKompmgr_; + bool kompmgrAvailable(); + KProcess *kompmgr; + +private slots: + void resetKompmgr(); + void showWarning(bool alphaActivated); + void handleXCompMgrOutput( KProcess *proc, char *buffer, int buflen); +}; +#endif diff --git a/kcmkwin/kwinrules/ruleswidget.cpp b/kcmkwin/kwinrules/ruleswidget.cpp index b7bc10cc22..39a056ce9f 100644 --- a/kcmkwin/kwinrules/ruleswidget.cpp +++ b/kcmkwin/kwinrules/ruleswidget.cpp @@ -94,6 +94,8 @@ RulesWidget::RulesWidget( QWidget* parent, const char* name ) SETUP( ignoreposition, force ); SETUP( minsize, force ); SETUP( maxsize, force ); + SETUP( opacityactive, force ); + SETUP( opacityinactive, force ); KWinModule module; int i; for( i = 1; @@ -137,6 +139,8 @@ UPDATE_ENABLE_SLOT( type ) UPDATE_ENABLE_SLOT( ignoreposition ) UPDATE_ENABLE_SLOT( minsize ) UPDATE_ENABLE_SLOT( maxsize ) +UPDATE_ENABLE_SLOT( opacityactive ) +UPDATE_ENABLE_SLOT( opacityinactive ) #undef UPDATE_ENABLE_SLOT @@ -200,7 +204,22 @@ static QSize strToSize( const QString& str ) return QSize( reg.cap( 1 ).toInt(), reg.cap( 2 ).toInt()); } - +//used for opacity settings +static QString intToStr( const int& s ) + { + if( s < 1 || s > 100 ) + return QString::null; + return QString::number(s); + } + +static int strToInt( const QString& str ) + { + int tmp = str.toInt(); + if( tmp < 1 || tmp > 100 ) + return 100; + return tmp; + } + int RulesWidget::desktopToCombo( int d ) const { if( d >= 1 && d < desktop->count()) @@ -374,6 +393,8 @@ void RulesWidget::setRules( Rules* rules ) CHECKBOX_FORCE_RULE( ignoreposition, ); LINEEDIT_FORCE_RULE( minsize, sizeToStr ); LINEEDIT_FORCE_RULE( maxsize, sizeToStr ); + LINEEDIT_FORCE_RULE( opacityactive, intToStr ); + LINEEDIT_FORCE_RULE( opacityinactive, intToStr ); } #undef GENERIC_RULE @@ -459,6 +480,8 @@ Rules* RulesWidget::rules() const CHECKBOX_FORCE_RULE( ignoreposition, ); LINEEDIT_FORCE_RULE( minsize, strToSize ); LINEEDIT_FORCE_RULE( maxsize, strToSize ); + LINEEDIT_FORCE_RULE( opacityactive, strToInt ); + LINEEDIT_FORCE_RULE( opacityinactive, strToInt ); return rules; } @@ -571,6 +594,8 @@ void RulesWidget::prefillUnusedValues( const KWin::WindowInfo& info ) //CHECKBOX_PREFILL( ignoreposition, ); LINEEDIT_PREFILL( minsize, sizeToStr, info.frameGeometry().size() ); LINEEDIT_PREFILL( maxsize, sizeToStr, info.frameGeometry().size() ); + LINEEDIT_PREFILL( opacityactive, intToStr, 100 /*get the actual opacity somehow*/); + LINEEDIT_PREFILL( opacityinactive, intToStr, 100 /*get the actual opacity somehow*/); } #undef GENERIC_PREFILL diff --git a/kcmkwin/kwinrules/ruleswidget.h b/kcmkwin/kwinrules/ruleswidget.h index 9d200f9eeb..0afa98a33b 100644 --- a/kcmkwin/kwinrules/ruleswidget.h +++ b/kcmkwin/kwinrules/ruleswidget.h @@ -76,6 +76,8 @@ class RulesWidget void updateEnableignoreposition(); void updateEnableminsize(); void updateEnablemaxsize(); + void updateEnableopacityactive(); + void updateEnableopacityinactive(); // internal void detected( bool ); private: diff --git a/kcmkwin/kwinrules/ruleswidgetbase.ui b/kcmkwin/kwinrules/ruleswidgetbase.ui index 526c7db1a3..8e2f477d19 100644 --- a/kcmkwin/kwinrules/ruleswidgetbase.ui +++ b/kcmkwin/kwinrules/ruleswidgetbase.ui @@ -1149,34 +1149,6 @@ unnamed - - - below - - - false - - - - - - - - spacer33 - - - Vertical - - - Expanding - - - - 20 - 70 - - - enable_above @@ -1233,6 +1205,333 @@ &Closeable + + + spacer33 + + + Vertical + + + Expanding + + + + 20 + 110 + + + + + + enable_opacityinactive + + + I&nactive opacity in % + + + Alt+N + + + + + enable_opacityactive + + + A&ctive opacity in % + + + Alt+C + + + + + + Do Not Affect + + + + + Force + + + + rule_opacityinactive + + + false + + + + + + Do Not Affect + + + + + Force + + + + rule_opacityactive + + + false + + + + + opacityinactive + + + false + + + 0123456789 + + + + + opacityactive + + + false + + + 0123456789 + + + + + spacer25 + + + Horizontal + + + Expanding + + + + 181 + 20 + + + + + + spacer24 + + + Horizontal + + + Expanding + + + + 171 + 20 + + + + + + spacer36_7 + + + Horizontal + + + Expanding + + + + 290 + 20 + + + + + + spacer36_6 + + + Horizontal + + + Expanding + + + + 290 + 20 + + + + + + spacer36_5 + + + Horizontal + + + Expanding + + + + 290 + 20 + + + + + + spacer36_4 + + + Horizontal + + + Expanding + + + + 290 + 20 + + + + + + spacer36_3 + + + Horizontal + + + Expanding + + + + 290 + 20 + + + + + + spacer36_2 + + + Horizontal + + + Expanding + + + + 290 + 20 + + + + + + spacer36 + + + Horizontal + + + Expanding + + + + 290 + 20 + + + + + + above + + + false + + + + + + + + below + + + false + + + + + + + + noborder + + + false + + + + + + + + skiptaskbar + + + false + + + + + + + + skippager + + + false + + + + + + + + acceptfocus + + + false + + + + + + + + closeable + + + false + + + + + @@ -1409,191 +1708,6 @@ false - - - spacer36 - - - Horizontal - - - Expanding - - - - 40 - 20 - - - - - - spacer36_2 - - - Horizontal - - - Expanding - - - - 40 - 20 - - - - - - spacer36_3 - - - Horizontal - - - Expanding - - - - 40 - 20 - - - - - - spacer36_4 - - - Horizontal - - - Expanding - - - - 40 - 20 - - - - - - spacer36_5 - - - Horizontal - - - Expanding - - - - 40 - 20 - - - - - - spacer36_6 - - - Horizontal - - - Expanding - - - - 40 - 20 - - - - - - spacer36_7 - - - Horizontal - - - Expanding - - - - 40 - 20 - - - - - - above - - - false - - - - - - - - noborder - - - false - - - - - - - - skiptaskbar - - - false - - - - - - - - skippager - - - false - - - - - - - - closeable - - - false - - - - - - - - acceptfocus - - - false - - - - - @@ -1614,6 +1728,9 @@ &Focus stealing prevention + + Alt+F + @@ -1918,7 +2035,7 @@ 20 - 250 + 90 @@ -1927,8 +2044,6 @@ - - detect1 @@ -2066,16 +2181,22 @@ + klineedit.h + klineedit.h kcombobox.h kpushbutton.h + klineedit.h kcombobox.h kpushbutton.h kpushbutton.h klistbox.h + klineedit.h kcombobox.h kpushbutton.h + klineedit.h kcombobox.h kpushbutton.h + klineedit.h kcombobox.h kpushbutton.h kcombobox.h @@ -2093,6 +2214,10 @@ kcombobox.h kcombobox.h kcombobox.h + krestrictedline.h + krestrictedline.h + kcombobox.h + kcombobox.h kcombobox.h kcombobox.h kcombobox.h diff --git a/main.cpp b/main.cpp index 6ae42a299a..49f3312687 100644 --- a/main.cpp +++ b/main.cpp @@ -114,13 +114,14 @@ Application::Application( ) options = new Options; atoms = new Atoms; - + // create workspace. (void) new Workspace( isSessionRestored() ); syncX(); // trigger possible errors, there's still a chance to abort initting = FALSE; // startup done, we are up and running now. + dcopClient()->send( "ksplash", "", "upAndRunning(QString)", QString("wm started")); XEvent e; e.xclient.type = ClientMessage; @@ -154,7 +155,7 @@ bool Application::x11EventFilter( XEvent *e ) return TRUE; return KApplication::x11EventFilter( e ); } - + static void sighandler(int) { QApplication::exit(); diff --git a/main.h b/main.h index 5a94e7074f..5ac38a61a0 100644 --- a/main.h +++ b/main.h @@ -30,6 +30,7 @@ class Application : public KApplication bool x11EventFilter( XEvent * ); private slots: void lostSelection(); + private: KWinSelectionOwner owner; }; diff --git a/manage.cpp b/manage.cpp index 68327829a9..aebd0233ef 100644 --- a/manage.cpp +++ b/manage.cpp @@ -139,6 +139,8 @@ bool Client::manage( Window w, bool isMapped ) init_minimize = rules()->checkMinimize( init_minimize, !isMapped ); if( rules()->checkNoBorder( false, !isMapped )) setUserNoBorder( true ); + + checkAndSetInitialRuledOpacity(); // initial desktop placement if ( session ) diff --git a/options.cpp b/options.cpp index d19ef1c56f..1ee3b7ac01 100644 --- a/options.cpp +++ b/options.cpp @@ -168,6 +168,28 @@ unsigned long Options::updateSettings() CmdAll2 = mouseCommand(config->readEntry("CommandAll2","Toggle raise and lower"), false ); CmdAll3 = mouseCommand(config->readEntry("CommandAll3","Resize"), false ); + //translucency settings + config->setGroup( "Translucency"); + useTranslucency = config->readBoolEntry("UseTranslucency", false); + translucentActiveWindows = config->readBoolEntry("TranslucentActiveWindows", false); + activeWindowOpacity = (config->readNumEntry("ActiveWindowOpacity", 100)/100.0)*0xFFFFFFFF; + translucentInactiveWindows = config->readBoolEntry("TranslucentInactiveWindows", false); + inactiveWindowOpacity = (config->readNumEntry("InactiveWindowOpacity", 100)/100.0)*0xFFFFFFFF; + translucentMovingWindows = config->readBoolEntry("TranslucentMovingWindows", false); + movingWindowOpacity = (config->readNumEntry("MovingWindowOpacity", 100)/100.0)*0xFFFFFFFF; + translucentDocks = config->readBoolEntry("TranslucentDocks", false); + dockOpacity = (config->readNumEntry("DockOpacity", 100)/100.0)*0xFFFFFFFF; + keepAboveAsActive = config->readBoolEntry("TreatKeepAboveAsActive", true); + //TODO: remove this variable + useTitleMenuSlider = true; + activeWindowShadowSize = config->readNumEntry("ActiveWindowShadowSize", 100); + inactiveWindowShadowSize = config->readNumEntry("InactiveWindowShadowSize", 100); + dockShadowSize = config->readNumEntry("DockShadowSize", 100); + if (resetKompmgr = config->readBoolEntry("ResetKompmgr", false)) + config->writeEntry("ResetKompmgr",FALSE); + + + // Read button tooltip animation effect from kdeglobals // Since we want to allow users to enable window decoration tooltips // and not kstyle tooltips and vise-versa, we don't read the diff --git a/options.h b/options.h index 869fc82a68..44789de65e 100644 --- a/options.h +++ b/options.h @@ -255,6 +255,23 @@ class Options : public KDecorationOptions // timeout before non-responding application will be killed after attempt to close int killPingTimeout; + + //translucency settings + bool useTranslucency; + bool translucentActiveWindows; + uint activeWindowOpacity; + bool translucentInactiveWindows; + uint inactiveWindowOpacity; + bool translucentMovingWindows; + uint movingWindowOpacity; + bool translucentDocks; + uint dockOpacity; + bool keepAboveAsActive; + bool useTitleMenuSlider; + uint activeWindowShadowSize; + uint inactiveWindowShadowSize; + uint dockShadowSize; + bool resetKompmgr; private: WindowOperation OpTitlebarDblClick; @@ -281,6 +298,7 @@ class Options : public KDecorationOptions bool desktop_topmenu; // List of window classes for which not to use focus stealing prevention QStringList ignoreFocusStealingClasses; + }; extern Options* options; diff --git a/rules.cpp b/rules.cpp index 0051697f98..8326b012da 100644 --- a/rules.cpp +++ b/rules.cpp @@ -39,6 +39,8 @@ Rules::Rules() , sizerule( UnusedSetRule ) , minsizerule( UnusedForceRule ) , maxsizerule( UnusedForceRule ) + , opacityactiverule( UnusedForceRule ) + , opacityinactiverule( UnusedForceRule ) , ignorepositionrule( UnusedForceRule ) , desktoprule( UnusedSetRule ) , typerule( UnusedForceRule ) @@ -131,6 +133,12 @@ void Rules::readFromCfg( KConfig& cfg ) READ_FORCE_RULE( maxsize, Size, ); if( maxsize.isEmpty()) maxsize = QSize( 32767, 32767 ); + READ_FORCE_RULE( opacityactive, Num, ); + if( opacityactive < 0 || opacityactive > 100 ) + opacityactive = 100; + READ_FORCE_RULE( opacityinactive, Num, ); + if( opacityinactive < 0 || opacityinactive > 100 ) + opacityinactive = 100; READ_FORCE_RULE( ignoreposition, Bool, ); READ_SET_RULE( desktop, Num, ); type = readType( cfg, "type" ); @@ -216,6 +224,8 @@ void Rules::write( KConfig& cfg ) const WRITE_SET_RULE( size, ); WRITE_FORCE_RULE( minsize, ); WRITE_FORCE_RULE( maxsize, ); + WRITE_FORCE_RULE( opacityactive, ); + WRITE_FORCE_RULE( opacityinactive, ); WRITE_FORCE_RULE( ignoreposition, ); WRITE_SET_RULE( desktop, ); WRITE_FORCE_RULE( type, ); @@ -248,6 +258,8 @@ bool Rules::isEmpty() const && sizerule == UnusedSetRule && minsizerule == UnusedForceRule && maxsizerule == UnusedForceRule + && opacityactiverule == UnusedForceRule + && opacityinactiverule == UnusedForceRule && ignorepositionrule == UnusedForceRule && desktoprule == UnusedSetRule && typerule == UnusedForceRule @@ -472,6 +484,16 @@ bool Rules::update( Client* c ) updated = updated || noborder != c->isUserNoBorder(); noborder = c->isUserNoBorder(); } + if (opacityactiverule == ( ForceRule )Force) + { + updated = updated || (uint) (opacityactive/100.0*0xffffffff) != c->ruleOpacityActive(); + opacityactive = (uint)(((double)c->ruleOpacityActive())/0xffffffff*100); + } + if (opacityinactiverule == ( ForceRule )Force) + { + updated = updated || (uint) (opacityinactive/100.0*0xffffffff) != c->ruleOpacityInactive(); + opacityinactive = (uint)(((double)c->ruleOpacityInactive())/0xffffffff*100); + } return updated; } @@ -527,6 +549,8 @@ bool Rules::applySize( QSize& s, bool init ) const APPLY_FORCE_RULE( minsize, MinSize, QSize ) APPLY_FORCE_RULE( maxsize, MaxSize, QSize ) +APPLY_FORCE_RULE( opacityactive, OpacityActive, int ) +APPLY_FORCE_RULE( opacityinactive, OpacityInactive, int ) APPLY_FORCE_RULE( ignoreposition, IgnorePosition, bool ) APPLY_RULE( desktop, Desktop, int ) APPLY_FORCE_RULE( type, Type, NET::WindowType ) @@ -671,6 +695,8 @@ CHECK_RULE( Position, QPoint ) CHECK_RULE( Size, QSize ) CHECK_FORCE_RULE( MinSize, QSize ) CHECK_FORCE_RULE( MaxSize, QSize ) +CHECK_FORCE_RULE( OpacityActive, int ) +CHECK_FORCE_RULE( OpacityInactive, int ) CHECK_FORCE_RULE( IgnorePosition, bool ) CHECK_RULE( Desktop, int ) CHECK_FORCE_RULE( Type, NET::WindowType ) @@ -715,6 +741,7 @@ void Client::setupWindowRules( bool ignore_temporary ) // check only after getting the rules, because there may be a rule forcing window type if( isTopMenu()) // TODO cannot have restrictions client_rules = WindowRules(); + checkAndSetInitialRuledOpacity(); if( isManaged()) { // apply force rules // Placement - does need explicit update, just like some others below @@ -763,6 +790,43 @@ void Client::finishWindowRules() updateWindowRules(); client_rules = WindowRules(); } + +void Client::checkAndSetInitialRuledOpacity() +//apply kwin-rules for window-translucency upon hitting apply or starting to manage client + { + int tmp; + + //active translucency + tmp = -1; + tmp = rules()->checkOpacityActive(tmp); + if( tmp != -1 ) //rule did apply and returns valid value + { + rule_opacity_active = (uint)((tmp/100.0)*0xffffffff); + } + else + rule_opacity_active = 0; + + //inactive translucency + tmp = -1; + tmp = rules()->checkOpacityInactive(tmp); + if( tmp != -1 ) //rule did apply and returns valid value + { + rule_opacity_inactive = (uint)((tmp/100.0)*0xffffffff); + } + else + rule_opacity_inactive = 0; + + return; + + if( isDock() ) + //workaround for docks, as they don't have active/inactive settings and don't aut, therefore we take only the active one... + { + uint tmp = rule_opacity_active ? rule_opacity_active : options->dockOpacity; + setOpacity(tmp < 0xFFFFFFFF && (rule_opacity_active || options->translucentDocks), tmp); + } + else + updateOpacity(); + } // Workspace diff --git a/rules.h b/rules.h index 652938747d..c40ef7d23b 100644 --- a/rules.h +++ b/rules.h @@ -47,6 +47,8 @@ class WindowRules QSize checkSize( QSize s, bool init = false ) const; QSize checkMinSize( QSize s ) const; QSize checkMaxSize( QSize s ) const; + int checkOpacityActive(int s) const; + int checkOpacityInactive(int s) const; bool checkIgnorePosition( bool ignore ) const; int checkDesktop( int desktop, bool init = false ) const; NET::WindowType checkType( NET::WindowType type ) const; @@ -91,6 +93,8 @@ class Rules bool applySize( QSize& s, bool init ) const; bool applyMinSize( QSize& s ) const; bool applyMaxSize( QSize& s ) const; + bool applyOpacityActive(int& s) const; + bool applyOpacityInactive(int& s) const; bool applyIgnorePosition( bool& ignore ) const; bool applyDesktop( int& desktop, bool init ) const; bool applyType( NET::WindowType& type ) const; @@ -177,6 +181,10 @@ class Rules ForceRule minsizerule; QSize maxsize; ForceRule maxsizerule; + int opacityactive; + ForceRule opacityactiverule; + int opacityinactive; + ForceRule opacityinactiverule; bool ignoreposition; ForceRule ignorepositionrule; int desktop; diff --git a/useractions.cpp b/useractions.cpp index 94d4641bc9..4b1d21bab7 100644 --- a/useractions.cpp +++ b/useractions.cpp @@ -21,6 +21,10 @@ License. See the file "COPYING" for the exact licensing terms. #include "workspace.h" #include +#include +#include +#include +#include #include #include #include @@ -49,7 +53,7 @@ QPopupMenu* Workspace::clientPopup() popup->setFont(KGlobalSettings::menuFont()); connect( popup, SIGNAL( aboutToShow() ), this, SLOT( clientPopupAboutToShow() ) ); connect( popup, SIGNAL( activated(int) ), this, SLOT( clientPopupActivated(int) ) ); - + advanced_popup = new QPopupMenu( popup ); advanced_popup->setCheckable( TRUE ); advanced_popup->setFont(KGlobalSettings::menuFont()); @@ -67,6 +71,24 @@ QPopupMenu* Workspace::clientPopup() popup->insertItem(i18n("Ad&vanced"), advanced_popup ); desk_popup_index = popup->count(); + + if (options->useTranslucency){ + QPopupMenu *trans_popup = new QPopupMenu( popup ); + QVBox *transBox = new QVBox(trans_popup); + transButton = new QPushButton(transBox, "transButton"); + QToolTip::add(transButton, i18n("Reset opacity to default value")); + transSlider = new QSlider(0, 100, 1, 100, Qt::Vertical, transBox, "transSlider"); + QToolTip::add(transSlider, i18n("Slide this to set the window's opacity")); + connect(transButton, SIGNAL(clicked()), SLOT(resetClientOpacity())); + connect(transButton, SIGNAL(clicked()), trans_popup, SLOT(hide())); + connect(transSlider, SIGNAL(valueChanged(int)), SLOT(setTransButtonText(int))); + connect(transSlider, SIGNAL(sliderMoved(int)), this, SLOT(setPopupClientOpacity(int))); + connect(transSlider, SIGNAL(sliderReleased()), trans_popup, SLOT(hide())); + transSlider->setValue(100-popup_client->opacityPercentage()); + trans_popup->insertItem(transBox); + popup->insertItem(i18n("&Opacity"), trans_popup ); + } + popup->insertItem( SmallIconSet( "move" ), i18n("&Move")+'\t'+keys->shortcut("Window Move").seq(0).toString(), Options::MoveOp ); popup->insertItem( i18n("Re&size")+'\t'+keys->shortcut("Window Resize").seq(0).toString(), Options::ResizeOp ); popup->insertItem( i18n("Mi&nimize")+'\t'+keys->shortcut("Window Minimize").seq(0).toString(), Options::MinimizeOp ); @@ -86,6 +108,35 @@ QPopupMenu* Workspace::clientPopup() } return popup; } + +//sets the transparency of the client to given value(given by slider) +void Workspace::setPopupClientOpacity(int value) + { + popup_client->setCustomOpacityFlag(true); + value = 100 - value; + value<100?popup_client->setOpacity(true, (uint)((value/100.0)*0xffffffff)):popup_client->setOpacity(false,0xffffffff); + } + +void Workspace::setTransButtonText(int value) + { + value = 100 - value; + if(value < 0) + transButton->setText("000 %"); + else if (value >= 100 ) + transButton->setText("100 %"); + else if(value < 10) + transButton->setText("00"+QString::number(value)+" %"); + else if(value < 100) + transButton->setText("0"+QString::number(value)+" %"); + } + +void Workspace::resetClientOpacity() + { + popup_client->setCustomOpacityFlag(false); + popup_client->updateOpacity(); + setTransButtonText(popup_client->opacityPercentage()); + } + /*! The client popup menu will become visible soon. @@ -122,6 +173,11 @@ void Workspace::clientPopupAboutToShow() advanced_popup->setItemEnabled( Options::NoBorderOp, active_popup_client->userCanSetNoBorder() ); popup->setItemEnabled( Options::MinimizeOp, active_popup_client->isMinimizable() ); popup->setItemEnabled( Options::CloseOp, active_popup_client->isCloseable() ); + if (options->useTranslucency) + { + transSlider->setValue(100-popup_client->opacityPercentage()); + setTransButtonText(popup_client->opacityPercentage()); + } } diff --git a/workspace.cpp b/workspace.cpp index 765a3ced0d..b70cecdb7f 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -18,6 +18,7 @@ License. See the file "COPYING" for the exact licensing terms. #include #include #include +#include #include #include #include @@ -52,6 +53,10 @@ extern int screen_number; Workspace *Workspace::_self = 0; +KProcess* kompmgr; + +bool allowKompmgrRestart = TRUE; + // Rikkus: This class is too complex. It needs splitting further. // It's a nightmare to understand, especially with so few comments :( @@ -185,6 +190,15 @@ Workspace::Workspace( bool restore ) #if (QT_VERSION-0 >= 0x030200) // XRANDR support connect( kapp->desktop(), SIGNAL( resized( int )), SLOT( desktopResized())); #endif + + // 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 (options->useTranslucency) + { + kompmgr = new KProcess; + connect(kompmgr, SIGNAL(receivedStderr(KProcess*, char*, int)), SLOT(handleKompmgrOutput(KProcess*, char*, int))); + *kompmgr << "kompmgr"; + startKompmgr(); + } } @@ -192,6 +206,10 @@ void Workspace::init() { checkElectricBorders(); +// not used yet +// topDock = 0L; +// maximizedWindowCounter = 0; + supportWindow = new QWidget; XLowerWindow( qt_xdisplay(), supportWindow->winId()); // see usage in layers.cpp @@ -399,6 +417,8 @@ void Workspace::init() Workspace::~Workspace() { + if (kompmgr) + delete kompmgr; blockStackingUpdates( true ); // TODO grabXServer(); // use stacking_order, so that kwin --replace keeps stacking order @@ -456,6 +476,21 @@ Client* Workspace::createClient( Window w, bool is_mapped ) void Workspace::addClient( Client* c, allowed_t ) { + // waited with trans settings until window figured out if active or not ;) +// qWarning("%s", (const char*)(c->resourceClass())); + c->setBMP(c->resourceName() == "beep-media-player" || c->decorationId() == None); + // first check if the window has it's own opinion of it's translucency ;) + c->getWindowOpacity(); + if (c->isDock()) + { +// if (c->x() == 0 && c->y() == 0 && c->width() > c->height()) topDock = c; + if (!c->hasCustomOpacity()) // this xould be done slightly more efficient, but we want to support the topDock in future + { + c->setShadowSize(options->dockShadowSize); + c->setOpacity(options->translucentDocks, options->dockOpacity); + } + } +//------------------------------------------------ Group* grp = findGroup( c->window()); if( grp != NULL ) grp->gotLeader( c ); @@ -826,6 +861,14 @@ void Workspace::slotReconfigure() loadWindowRules(); forEachClient( ResetupRulesProcedure()); + + if (options->resetKompmgr) // need restart + { + bool tmp = options->useTranslucency; + stopKompmgr(); + if (tmp) + QTimer::singleShot( 200, this, SLOT(startKompmgr()) ); // wait some time to ensure system's ready for restart + } } void Workspace::loadDesktopSettings() @@ -896,7 +939,7 @@ QStringList Workspace::configModules(bool controlCenter) if (controlCenter) args << "kde-kwinoptions.desktop"; else if (kapp->authorizeControlModule("kde-kwinoptions.desktop")) - args << "kwinactions" << "kwinfocus" << "kwinmoving" << "kwinadvanced" << "kwinrules"; + args << "kwinactions" << "kwinfocus" << "kwinmoving" << "kwinadvanced" << "kwinrules" << "kwintranslucency"; return args; } @@ -2270,6 +2313,133 @@ void Workspace::helperDialog( const QString& message, const Client* c ) proc.start( KProcess::DontCare ); } + +// kompmgr stuff + +void Workspace::startKompmgr() +{ + if (!kompmgr || kompmgr->isRunning()) + return; + if (!kompmgr->start(KProcess::OwnGroup, KProcess::Stderr)) + { + options->useTranslucency = FALSE; + if (QMessageBox::warning(0, i18n("Failed to start kompmgr - KWin"), i18n("The Composite Manager could not be started.
Make sure you've got \"kompmgr\" in a $PATH directory"), "OK", "Don't try again") == 1) + { + KConfig *config = KGlobal::config(); + config->setGroup( "Translucency" ); + config->writeEntry("UseTranslucency",FALSE); + } + } + else + { + connect(kompmgr, SIGNAL(processExited(KProcess*)), SLOT(restartKompmgr())); + options->useTranslucency = TRUE; + allowKompmgrRestart = FALSE; + QTimer::singleShot( 60000, this, SLOT(unblockKompmgrRestart()) ); + } + if (popup){ delete popup; popup = 0L; } // to add/remove opacity slider +} + +void Workspace::stopKompmgr() +{ + kompmgr->disconnect(this, SLOT(restartKompmgr())); + options->useTranslucency = FALSE; + if (popup){ delete popup; popup = 0L; } // to add/remove opacity slider + kompmgr->kill(); +} + +void Workspace::unblockKompmgrRestart() +{ + allowKompmgrRestart = TRUE; +} + +void Workspace::restartKompmgr() +// this is for inernal purpose (crashhandling) only, usually you want to use workspace->stopKompmgr(); QTimer::singleShot(200, workspace, SLOT(startKompmgr())); +{ + if (!allowKompmgrRestart) // uh-ohh + { + options->useTranslucency = FALSE; + QMessageBox::information(0, i18n("Composite Manager Failure - KWin"), i18n("The Composite Manager crashed twice within a minute and is therefore disabled for this session"), QMessageBox::Ok, 0); + return; + } + if (!kompmgr) + return; +// this should be useless, i keep it for maybe future need +// if (!kcompmgr) +// { +// kompmgr = new KProcess; +// kompmgr->clearArguments(); +// *kompmgr << "kompmgr"; +// } +// ------------------- + if (!kompmgr->start(KProcess::NotifyOnExit, KProcess::Stderr)) + { + options->useTranslucency = FALSE; + QMessageBox::warning(0, i18n("Failed to start kompmgr - KWin"), i18n("The Composite Manager could not be started.
Make sure you've got \"kompmgr\" in a $PATH directory"), QMessageBox::Ok, 0); + } + else + { + allowKompmgrRestart = FALSE; + QTimer::singleShot( 60000, this, SLOT(unblockKompmgrRestart()) ); + } +} + +void Workspace::handleKompmgrOutput( KProcess *proc, char *buffer, int buflen) +{ + if (QString(buffer).contains("Started",false)); // don't do anything, just pass to the connection release + else if (QString(buffer).contains("Can't open display",false)) + QMessageBox::critical(0, i18n("xCompMgr failure"), i18n("Failed to open display
There's probably an invalid display entry in your ~/.xcompmgrrc"), QMessageBox::Ok, 0); + else if (QString(buffer).contains("No render extension",false)) + QMessageBox::critical(0, i18n("xCompMgr failure"), i18n("Xrender extension not found
You're either using an outdated or a crippled version of XOrg.
Get XOrg ≥ 6.8 from www.freedesktop.org"), QMessageBox::Ok, 0); + else if (QString(buffer).contains("No composite extension",false)) + QMessageBox::critical(0,i18n("xCompMgr failure"), i18n("Composite extension not found
You must use XOrg ≥ 6.8 to have this work
Additionally you need to add a new section to your X config file:
" + "Section \"Extensions\"
" + "Option \"Composite\" \"Enable\"
" + "EndSection
"), QMessageBox::Ok, 0); + else if (QString(buffer).contains("No damage extension",false)) + QMessageBox::critical(0,i18n("xCompMgr failure"), i18n("Damage extension not found
You must use XOrg ≥ 6.8 to have this work"), QMessageBox::Ok,0); + else if (QString(buffer).contains("No XFixes extension",false)) + QMessageBox::critical(0,i18n("xCompMgr failure"), i18n("XFixes extension not found
You must use XOrg ≥ 6.8 to have this work"), QMessageBox::Ok,0); + else return; //skip others + // kompmgr startup failed or succeeded, release connection + kompmgr->closeStderr(); + disconnect(kompmgr, SIGNAL(receivedStderr(KProcess*, char*, int)), this, SLOT(handleKompmgrOutput(KProcess*, char*, int))); +} + + +void Workspace::setOpacity(unsigned long winId, unsigned int opacityPercent) +{ + if (opacityPercent > 100) opacityPercent = 100; + for( ClientList::ConstIterator it = stackingOrder().begin(); it != stackingOrder().end(); it++ ) + if (winId == (*it)->window()) + { + (*it)->setOpacity(opacityPercent < 100, (unsigned int)((opacityPercent/100.0)*0xFFFFFFFF)); + return; + } +} + +void Workspace::setShadowSize(unsigned long winId, unsigned int shadowSizePercent) +{ + //this is open to the user by dcop - to avoid stupid trials, we limit the max shadow size to 400% + if (shadowSizePercent > 400) shadowSizePercent = 400; + for( ClientList::ConstIterator it = stackingOrder().begin(); it != stackingOrder().end(); it++ ) + if (winId == (*it)->window()) + { + (*it)->setShadowSize(shadowSizePercent); + return; + } +} + +void Workspace::setUnshadowed(unsigned long winId) +{ + for( ClientList::ConstIterator it = stackingOrder().begin(); it != stackingOrder().end(); it++ ) + if (winId == (*it)->window()) + { + (*it)->setShadowSize(0); + return; + } +} + } // namespace #include "workspace.moc" diff --git a/workspace.h b/workspace.h index ccc387d6df..4fdfd4b441 100644 --- a/workspace.h +++ b/workspace.h @@ -32,6 +32,9 @@ class KShortcutDialog; class KStartupInfo; class KStartupInfoId; class KStartupInfoData; +class QSlider; +class QPushButton; +class KProcess; namespace KWinInternal { @@ -223,6 +226,11 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine void sendPingToWindow( Window w, Time timestamp ); // called from Client::pingWindow() void sendTakeActivity( Client* c, Time timestamp, long flags ); // called from Client::takeActivity() + + void stopKompmgr(); + void setOpacity(unsigned long winId, unsigned int opacityPercent); + void setShadowSize(unsigned long winId, unsigned int shadowSizePercent); + void setUnshadowed(unsigned long winId); // redundant, equals setShadowSize(inId, 0) // only called from Client::destroyClient() or Client::releaseWindow() void removeClient( Client*, allowed_t ); @@ -258,6 +266,8 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine void cancelDelayFocus(); void requestDelayFocus( Client* ); + + void toggleTopDockShadows(bool on); public slots: void refresh(); @@ -331,6 +341,9 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine void setupWindowShortcutDone( bool ); void updateClientArea(); + + // kompmgr, also dcop + void startKompmgr(); private slots: void desktopPopupAboutToShow(); @@ -346,6 +359,14 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine void gotTemporaryRulesMessage( const QString& ); void cleanupTemporaryRules(); void writeWindowRules(); + // kompmgr + void setPopupClientOpacity(int v); + void resetClientOpacity(); + void setTransButtonText(int value); + void unblockKompmgrRestart(); + void restartKompmgr(); + void handleKompmgrOutput( KProcess *proc, char *buffer, int buflen); + // end protected: bool keyPressMouseEmulation( XKeyEvent& ev ); @@ -571,6 +592,15 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine Window null_focus_window; bool forced_global_mouse_grab; friend class StackingUpdatesBlocker; + + //kompmgr + QSlider *transSlider; + QPushButton *transButton; + // not used yet + /*Client* topDock; + int maximizedWindowCounter; + int topDockShadowSize;*/ + //end }; // helper for Workspace::blockStackingUpdates() being called in pairs (true/false)