diff --git a/clients/CMakeLists.txt b/clients/CMakeLists.txt index bcc34ba248..c3eeba72f8 100644 --- a/clients/CMakeLists.txt +++ b/clients/CMakeLists.txt @@ -6,6 +6,7 @@ add_subdirectory( keramik ) add_subdirectory( laptop ) add_subdirectory( modernsystem ) add_subdirectory( oxygen ) +add_subdirectory( ozone ) add_subdirectory( quartz ) add_subdirectory( redmond ) add_subdirectory( web ) diff --git a/clients/ozone/CMakeLists.txt b/clients/ozone/CMakeLists.txt new file mode 100644 index 0000000000..5ffa46301a --- /dev/null +++ b/clients/ozone/CMakeLists.txt @@ -0,0 +1,22 @@ +add_definitions (-DQT3_SUPPORT -DQT3_SUPPORT_WARNINGS) + +########### next target ############### + +set(kwin_ozone_SRCS + lib/helper.cpp + oxygenclient.cpp + oxygenbutton.cpp + oxygen.cpp + ) + +kde4_add_plugin(kwin3_ozone ${kwin_ozone_SRCS}) + + +target_link_libraries(kwin3_ozone ${KDE4_KDEUI_LIBS} ${X11_Xrender_LIB} kdecorations) + +install(TARGETS kwin3_ozone DESTINATION ${PLUGIN_INSTALL_DIR} ) + +########### install files ############### + +install( FILES ozoneclient.desktop DESTINATION ${DATA_INSTALL_DIR}/kwin/ ) + diff --git a/clients/ozone/README b/clients/ozone/README new file mode 100644 index 0000000000..849ad66793 --- /dev/null +++ b/clients/ozone/README @@ -0,0 +1,9 @@ +This decoration is a fork of the Oxygen decoration, for reasons stated +in bug #152030 (comment #70 and others), namely Oxygen developers not +willing to accept widely-requested patches because of not fitting +the Oxygen vision and instead preferring a fork that's not branded +as Oxygen. + +Everything is put into extra namespace called Ozone to make syncing easier. +All visible strings have Oxygen changed to Ozone. +Other things are not renamed to minimize conflicts as much as possible. diff --git a/clients/ozone/oxygen.cpp b/clients/ozone/oxygen.cpp new file mode 100644 index 0000000000..3245b5989e --- /dev/null +++ b/clients/ozone/oxygen.cpp @@ -0,0 +1,148 @@ +////////////////////////////////////////////////////////////////////////////// +// oxygenbutton.h +// ------------------- +// Ozone window decoration for KDE. +// ------------------- +// Copyright (c) 2006, 2007 Riccardo Iaconelli +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +////////////////////////////////////////////////////////////////////////////// + +#include "oxygenclient.h" +#include "oxygen.h" +#include + +extern "C" +{ +KDE_EXPORT KDecorationFactory* create_factory() +{ + return new Ozone::Oxygen::OxygenFactory(); +} +} +namespace Ozone +{ +namespace Oxygen +{ + + +////////////////////////////////////////////////////////////////////////////// +// OxygenFactory Class // +////////////////////////////////////////////////////////////////////////////// + +bool OxygenFactory::initialized_ = false; +Qt::Alignment OxygenFactory::titlealign_ = Qt::AlignLeft; + +////////////////////////////////////////////////////////////////////////////// +// OxygenFactory() +// ---------------- +// Constructor + +OxygenFactory::OxygenFactory() +{ + readConfig(); + initialized_ = true; +} + +////////////////////////////////////////////////////////////////////////////// +// ~OxygenFactory() +// ----------------- +// Destructor + +OxygenFactory::~OxygenFactory() { initialized_ = false; } + +////////////////////////////////////////////////////////////////////////////// +// createDecoration() +// ----------------- +// Create the decoration + +KDecoration* OxygenFactory::createDecoration(KDecorationBridge* b) +{ + return (new OxygenClient(b, this))->decoration(); +} + +////////////////////////////////////////////////////////////////////////////// +// reset() +// ------- +// Reset the handler. Returns true if decorations need to be remade, false if +// only a repaint is necessary + +bool OxygenFactory::reset(unsigned long changed) +{ + // read in the configuration + initialized_ = false; + bool confchange = readConfig(); + initialized_ = true; + + if (confchange || + (changed & (SettingDecoration | SettingButtons | SettingBorder))) { + return true; + } else { + resetDecorations(changed); + return false; + } +} + +////////////////////////////////////////////////////////////////////////////// +// readConfig() +// ------------ +// Read in the configuration file + +bool OxygenFactory::readConfig() +{ + // create a config object + KConfig config("oxygenrc"); + KConfigGroup group = config.group("Windeco"); + + // grab settings + Qt::Alignment oldalign = titlealign_; + QString value = group.readEntry("TitleAlignment", "AlignLeft"); + if (value == "AlignLeft") titlealign_ = Qt::AlignLeft; + else if (value == "AlignHCenter") titlealign_ = Qt::AlignHCenter; + else if (value == "AlignRight") titlealign_ = Qt::AlignRight; + + if (oldalign == titlealign_) + return false; + else + return true; +} + +bool OxygenFactory::supports( Ability ability ) const +{ + switch( ability ) { + // announce + case AbilityAnnounceButtons: + case AbilityAnnounceColors: + // buttons + case AbilityButtonMenu: + case AbilityButtonHelp: + case AbilityButtonMinimize: + case AbilityButtonMaximize: + case AbilityButtonClose: + case AbilityButtonAboveOthers: + case AbilityButtonBelowOthers: + case AbilityButtonSpacer: + return true; + // no colors supported at this time + default: + return false; + }; +} + +} //namespace Oxygen +} //namespace Ozone diff --git a/clients/ozone/oxygen.h b/clients/ozone/oxygen.h new file mode 100644 index 0000000000..7bb99fc812 --- /dev/null +++ b/clients/ozone/oxygen.h @@ -0,0 +1,86 @@ +////////////////////////////////////////////////////////////////////////////// +// oxygenbutton.h +// ------------------- +// Ozone window decoration for KDE. +// ------------------- +// Copyright (c) 2006, 2007 Riccardo Iaconelli +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +////////////////////////////////////////////////////////////////////////////// +#ifndef OXYGEN_H +#define OXYGEN_H + +#include +#include + +namespace Ozone +{ +namespace Oxygen +{ +// OxygenFactory ///////////////////////////////////////////////////////////// + +static const int OXYGEN_BUTTONSIZE = 22; +#define TFRAMESIZE 3 +#define BFRAMESIZE 5 +#define LFRAMESIZE 5 +#define RFRAMESIZE 5 + +enum ButtonType { + ButtonHelp=0, + ButtonMax, + ButtonMin, + ButtonClose, + ButtonMenu, + ButtonSticky, + ButtonAbove, + ButtonBelow, + ButtonTypeCount +}; +Q_DECLARE_FLAGS(ButtonTypes, ButtonType) + +class OxygenFactory: public KDecorationFactory +{ +public: + OxygenFactory(); + virtual ~OxygenFactory(); + virtual KDecoration *createDecoration(KDecorationBridge *b); + virtual bool reset(unsigned long changed); + virtual bool supports( Ability ability ) const; + + static bool initialized(); + static Qt::Alignment titleAlign(); + +private: + bool readConfig(); + +private: + static bool initialized_; + static Qt::Alignment titlealign_; +}; + +inline bool OxygenFactory::initialized() + { return initialized_; } + +inline Qt::Alignment OxygenFactory::titleAlign() + { return titlealign_; } + +} //namespace Oxygen +} //namespace Ozone + +#endif diff --git a/clients/ozone/oxygenbutton.cpp b/clients/ozone/oxygenbutton.cpp new file mode 100644 index 0000000000..7079bf0abd --- /dev/null +++ b/clients/ozone/oxygenbutton.cpp @@ -0,0 +1,276 @@ +////////////////////////////////////////////////////////////////////////////// +// oxygenbutton.cpp +// ------------------- +// Ozone window decoration for KDE. Buttons. +// ------------------- +// Copyright (c) 2006, 2007 Riccardo Iaconelli +// Copyright (c) 2006, 2007 Casper Boemann +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "oxygenclient.h" +#include "oxygenbutton.h" +#include "oxygen.h" + +namespace Ozone +{ +namespace Oxygen +{ +// class OxygenClient; +/* +extern int BUTTONSIZE; +extern int DECOSIZE;*/ + +// static const int DECOSIZE = 8; +////////////////////////////////////////////////////////////////////////////// +// OxygenButton Class // +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// OxygenButton() +// --------------- +// Constructor + +OxygenButton::OxygenButton(OxygenClient &parent, + const QString& tip, ButtonType type) + : KCommonDecorationButton((::ButtonType)type, &parent) + , client_(parent) + , helper_(parent.helper_) + , type_(type) + , lastmouse_(0) + , colorCacheInvalid_(true) +{ + setAutoFillBackground(false); + setAttribute(Qt::WA_OpaquePaintEvent, false); + setFixedSize(OXYGEN_BUTTONSIZE, OXYGEN_BUTTONSIZE); + setCursor(Qt::ArrowCursor); + setToolTip(tip); +} + +OxygenButton::~OxygenButton() +{ +} + +//declare function from oxygenclient.cpp +QColor reduceContrast(const QColor &c0, const QColor &c1, double t); + + +QColor OxygenButton::buttonDetailColor(const QPalette &palette) +{ + if (client_.isActive()) + return palette.color(QPalette::Active, QPalette::ButtonText); + else { + if (colorCacheInvalid_) { + QColor ab = palette.color(QPalette::Active, QPalette::Button); + QColor af = palette.color(QPalette::Active, QPalette::ButtonText); + QColor nb = palette.color(QPalette::Inactive, QPalette::Button); + QColor nf = palette.color(QPalette::Inactive, QPalette::ButtonText); + + colorCacheInvalid_ = false; + cachedButtonDetailColor_ = reduceContrast(nb, nf, qMax(qreal(2.5), KColorUtils::contrastRatio(ab, KColorUtils::mix(ab, af, 0.4)))); + } + return cachedButtonDetailColor_; + } +} + +////////////////////////////////////////////////////////////////////////////// +// sizeHint() +// ---------- +// Return size hint + +QSize OxygenButton::sizeHint() const +{ + return QSize(OXYGEN_BUTTONSIZE, OXYGEN_BUTTONSIZE); +} + +////////////////////////////////////////////////////////////////////////////// +// enterEvent() +// ------------ +// Mouse has entered the button + +void OxygenButton::enterEvent(QEvent *e) +{ + KCommonDecorationButton::enterEvent(e); + if (status_ != Oxygen::Pressed) { + status_ = Oxygen::Hovered; + } + update(); +} + +////////////////////////////////////////////////////////////////////////////// +// leaveEvent() +// ------------ +// Mouse has left the button + +void OxygenButton::leaveEvent(QEvent *e) +{ + KCommonDecorationButton::leaveEvent(e); + // if we wanted to do mouseovers, we would keep track of it here + status_ = Oxygen::Normal; + update(); +} + +////////////////////////////////////////////////////////////////////////////// +// pressSlot() +// ------------ +// Mouse has pressed the button + +void OxygenButton::pressSlot() +{ + status_ = Oxygen::Pressed; + update(); +} +////////////////////////////////////////////////////////////////////////////// +// drawButton() +// ------------ +// Draw the button + +void OxygenButton::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + QPalette pal = palette(); // de-const-ify + + if (type_ == ButtonMenu) { + // we paint the mini icon (which is 16 pixels high) + int dx = (width() - 16) / 2; + int dy = (height() - 16) / 2; + painter.drawPixmap(dx, dy, client_.icon().pixmap(16)); + return; + } + + // Set palette to the right group. + // TODO - fix KWin to do this for us :-). + if (client_.isActive()) + pal.setCurrentColorGroup(QPalette::Active); + else + pal.setCurrentColorGroup(QPalette::Inactive); + + if(client_.maximizeMode() == OxygenClient::MaximizeRestore) + painter.translate(0,-1); + + QColor bg = helper_.backgroundTopColor(pal.window()); + + QLinearGradient lg = helper_.decoGradient(QRect(4,4,13,13), buttonDetailColor(pal)); + + if(status_ == Oxygen::Hovered) { + if(type_ == ButtonClose) { + QColor color = KColorScheme(pal.currentColorGroup()).foreground(KColorScheme::NegativeText).color(); + lg = helper_.decoGradient(QRect(4,4,13,13), color); + painter.drawPixmap(0, 0, helper_.windecoButtonFocused(pal.button(), color,7)); + } + else{ + QColor color = KColorScheme(pal.currentColorGroup()).decoration(KColorScheme::HoverColor).color(); + painter.drawPixmap(0, 0, helper_.windecoButtonFocused(pal.button(), color, 7)); + } + } + else + painter.drawPixmap(0, 0, helper_.windecoButton(pal.button())); + + painter.setRenderHints(QPainter::Antialiasing); + painter.setBrush(Qt::NoBrush); + painter.setPen(QPen(lg, 2.2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + switch(type_) + { + case ButtonSticky: + painter.drawPoint(QPointF(10.5,10.5)); + break; + case ButtonHelp: + painter.translate(1.5, 1.5); + painter.drawArc(7,5,4,4,135*16, -180*16); + painter.drawArc(9,8,4,4,135*16,45*16); + painter.drawPoint(9,12); + break; + case ButtonMin: + painter.drawLine(QPointF( 7.5, 9.5), QPointF(10.5,12.5)); + painter.drawLine(QPointF(10.5,12.5), QPointF(13.5, 9.5)); + break; + case ButtonMax: + switch(client_.maximizeMode()) + { + case OxygenClient::MaximizeRestore: + case OxygenClient::MaximizeVertical: + case OxygenClient::MaximizeHorizontal: + painter.drawLine(QPointF( 7.5,11.5), QPointF(10.5, 8.5)); + painter.drawLine(QPointF(10.5, 8.5), QPointF(13.5,11.5)); + break; + case OxygenClient::MaximizeFull: + { + painter.translate(1.5, 1.5); + //painter.setBrush(lg); + QPoint points[4] = {QPoint(9, 6), QPoint(12, 9), QPoint(9, 12), QPoint(6, 9)}; + //QPoint points[4] = {QPoint(9, 5), QPoint(13, 9), QPoint(9, 13), QPoint(5, 9)}; + painter.drawPolygon(points, 4); + break; + } + } + break; + case ButtonClose: + painter.drawLine(QPointF( 7.5,7.5), QPointF(13.5,13.5)); + painter.drawLine(QPointF(13.5,7.5), QPointF( 7.5,13.5)); + break; + case ButtonAbove: + if(isChecked()) { + QPen newPen = painter.pen(); + newPen.setColor(KColorScheme(pal.currentColorGroup()).decoration(KColorScheme::HoverColor).color()); + painter.setPen(newPen); + } + + painter.drawLine(QPointF( 7.5,14), QPointF(10.5,11)); + painter.drawLine(QPointF(10.5,11), QPointF(13.5,14)); + painter.drawLine(QPointF( 7.5,10), QPointF(10.5, 7)); + painter.drawLine(QPointF(10.5, 7), QPointF(13.5,10)); + break; + case ButtonBelow: + if(isChecked()) { + QPen newPen = painter.pen(); + newPen.setColor(KColorScheme(pal.currentColorGroup()).decoration(KColorScheme::HoverColor).color()); + painter.setPen(newPen); + } + + painter.drawLine(QPointF( 7.5,11), QPointF(10.5,14)); + painter.drawLine(QPointF(10.5,14), QPointF(13.5,11)); + painter.drawLine(QPointF( 7.5, 7), QPointF(10.5,10)); + painter.drawLine(QPointF(10.5,10), QPointF(13.5, 7)); + break; + default: + break; + } +} + + + + + + + + +} //namespace Oxygen +} //namespace Ozone diff --git a/clients/ozone/oxygenbutton.h b/clients/ozone/oxygenbutton.h new file mode 100644 index 0000000000..518daf792d --- /dev/null +++ b/clients/ozone/oxygenbutton.h @@ -0,0 +1,82 @@ +////////////////////////////////////////////////////////////////////////////// +// oxygenbutton.h +// ------------------- +// Ozone window decoration for KDE. Buttons. +// ------------------- +// Copyright (c) 2006, 2007 Riccardo Iaconelli +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +////////////////////////////////////////////////////////////////////////////// +// class QAbstractButton; +#ifndef OXYGENBUTTON_H +#define OXYGENBUTTON_H + +#include + +#include "oxygen.h" +#include "oxygenclient.h" + +namespace Ozone +{ +namespace Oxygen +{ +class OxygenClient; + +enum ButtonStatus { + Normal, + Hovered, + Pressed }; + +Q_DECLARE_FLAGS(ButtonState, ButtonStatus) + +class OxygenButton : public KCommonDecorationButton +{ +public: + explicit OxygenButton(OxygenClient &parent, + const QString &tip=NULL, + ButtonType type=ButtonHelp); + ~OxygenButton(); + + QSize sizeHint() const; + const int lastMousePress(){return lastmouse_;} + void reset(long unsigned int){repaint();} + +private: + void enterEvent(QEvent *e); + void leaveEvent(QEvent *e); + void paintEvent(QPaintEvent *e); + QColor buttonDetailColor(const QPalette &palette); + +private Q_SLOTS: + void pressSlot(); + +private: + OxygenClient &client_; + OxygenHelper &helper_; + ButtonType type_; + ButtonState status_; + int lastmouse_; + bool colorCacheInvalid_; + QColor cachedButtonDetailColor_; +}; + +} //namespace Oxygen +} //namespace Ozone + +#endif diff --git a/clients/ozone/oxygenclient.cpp b/clients/ozone/oxygenclient.cpp new file mode 100644 index 0000000000..1e8c99756d --- /dev/null +++ b/clients/ozone/oxygenclient.cpp @@ -0,0 +1,405 @@ +////////////////////////////////////////////////////////////////////////////// +// oxygenclient.cpp +// ------------------- +// Ozone window decoration for KDE +// ------------------- +// Copyright (c) 2006, 2007 Casper Boemann +// Copyright (c) 2006, 2007 Riccardo Iaconelli +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +////////////////////////////////////////////////////////////////////////////// +// #ifndef OXYGENCLIENT_H +// #define OXYGENCLIENT_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +//Added by qt3to4: +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "math.h" + +#include "oxygenclient.h" +#include "oxygenclient.moc" +#include "oxygenbutton.h" +#include "oxygen.h" + +namespace Ozone +{ +namespace Oxygen +{ + +K_GLOBAL_STATIC_WITH_ARGS(OxygenHelper, globalHelper, ("OxygenDeco")) + +void renderDot(QPainter *p, const QPointF &point, qreal diameter) +{ + p->drawEllipse(QRectF(point.x()-diameter/2, point.y()-diameter/2, diameter, diameter)); +} + + +OxygenClient::OxygenClient(KDecorationBridge *b, KDecorationFactory *f) + : KCommonDecoration(b, f) + , colorCacheInvalid_(true) + , helper_(*globalHelper) +{ +} + +OxygenClient::~OxygenClient() +{ +} +QString OxygenClient::visibleName() const +{ + return i18n("Ozone"); +} + +void OxygenClient::init() +{ + KCommonDecoration::init(); + + widget()->setAutoFillBackground(false); + widget()->setAttribute(Qt::WA_OpaquePaintEvent); +} + +bool OxygenClient::decorationBehaviour(DecorationBehaviour behaviour) const +{ + switch (behaviour) { + case DB_MenuClose: + return true;//Handler()->menuClose(); + + case DB_WindowMask: + return false; + + default: + return KCommonDecoration::decorationBehaviour(behaviour); + } +} + +int OxygenClient::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *btn) const +{ + bool maximized = maximizeMode()==MaximizeFull && !options()->moveResizeMaximizedWindows(); + + switch (lm) { + case LM_BorderLeft: + case LM_BorderRight: + case LM_BorderBottom: + { + if (respectWindowState && maximized) { + return 0; + } else { + return BFRAMESIZE; + } + } + + case LM_TitleEdgeTop: + { + if (respectWindowState && maximized) { + return 0; + } else { + return TFRAMESIZE; + } + } + + case LM_TitleEdgeBottom: + { + return 0; + } + + case LM_TitleEdgeLeft: + case LM_TitleEdgeRight: + { + if (respectWindowState && maximized) { + return 0; + } else { + return 6; + } + } + + case LM_TitleBorderLeft: + case LM_TitleBorderRight: + return 5; + + case LM_ButtonWidth: + case LM_ButtonHeight: + case LM_TitleHeight: + { + if (respectWindowState && isToolWindow()) { + return OXYGEN_BUTTONSIZE; + } else { + return OXYGEN_BUTTONSIZE; + } + } + + case LM_ButtonSpacing: + return 1; + + case LM_ButtonMarginTop: + return 0; + + default: + return KCommonDecoration::layoutMetric(lm, respectWindowState, btn); + } +} + + +KCommonDecorationButton *OxygenClient::createButton(::ButtonType type) +{ + switch (type) { + case MenuButton: + return new OxygenButton(*this, i18n("Menu"), ButtonMenu); + + case HelpButton: + return new OxygenButton(*this, i18n("Help"), ButtonHelp); + + case MinButton: + return new OxygenButton(*this, i18n("Minimize"), ButtonMin); + + case MaxButton: + return new OxygenButton(*this, i18n("Maximize"), ButtonMax); + + case CloseButton: + return new OxygenButton(*this, i18n("Close"), ButtonClose); + + case AboveButton: + return new OxygenButton(*this, i18n("Keep above others"), ButtonAbove); + + case BelowButton: + return new OxygenButton(*this, i18n("Keep below others"), ButtonBelow); + +/* + case OnAllDesktopsButton: + return new OxygenButton(*this, i18n("All Desktops"), ButtonSticky); +*/ + default: + return 0; + } +} + + +// c0 - background +// c1 - foreground +// t - target contrast ratio +QColor reduceContrast(const QColor &c0, const QColor &c1, double t) +{ + double s = KColorUtils::contrastRatio(c0, c1); + if (s < t) + return c1; + + double l = 0.0, h = 1.0; + double x = s, a; + QColor r = c1; + for (int maxiter = 16; maxiter; --maxiter) { + a = 0.5 * (l + h); + r = KColorUtils::mix(c0, c1, a); + x = KColorUtils::contrastRatio(c0, r); + if (fabs(x - t) < 0.01) + break; + if (x > t) + h = a; + else + l = a; + } + return r; +} + + +QColor OxygenClient::titlebarTextColor(const QPalette &palette) +{ + if (isActive()) + return palette.color(QPalette::Active, QPalette::WindowText); + else { + if(colorCacheInvalid_) { + QColor ab = palette.color(QPalette::Active, QPalette::Window); + QColor af = palette.color(QPalette::Active, QPalette::WindowText); + QColor nb = palette.color(QPalette::Inactive, QPalette::Window); + QColor nf = palette.color(QPalette::Inactive, QPalette::WindowText); + + colorCacheInvalid_ = false; + cachedTitlebarTextColor_ = reduceContrast(nb, nf, qMax(qreal(2.5), KColorUtils::contrastRatio(ab, KColorUtils::mix(ab, af, 0.4)))); + } + return cachedTitlebarTextColor_; + } +} + + +void OxygenClient::paintEvent(QPaintEvent *e) +{ + Q_UNUSED(e) + if (!OxygenFactory::initialized()) return; + + QPalette palette = widget()->palette(); + QPainter painter(widget()); + + // Set palette to the right group. + // TODO - fix KWin to do this for us :-). + if (isActive()) + palette.setCurrentColorGroup(QPalette::Active); + else + palette.setCurrentColorGroup(QPalette::Inactive); + + int x,y,w,h; + QRect frame = widget()->frameGeometry(); + QColor color = palette.window().color(); + + const int titleHeight = layoutMetric(LM_TitleHeight); + const int titleTop = layoutMetric(LM_TitleEdgeTop) + frame.top(); + const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft); + const int marginLeft = layoutMetric(LM_TitleBorderLeft); + const int marginRight = layoutMetric(LM_TitleBorderRight); + + const int titleLeft = frame.left() + titleEdgeLeft + buttonsLeftWidth() + marginLeft; + const int titleWidth = frame.width() - + titleEdgeLeft - layoutMetric(LM_TitleEdgeRight) - + buttonsLeftWidth() - buttonsRightWidth() - + marginLeft - marginRight; + + + int splitY = qMin(300, 3*frame.height()/4); + + QPixmap tile = helper_.verticalGradient(color, splitY); + painter.drawTiledPixmap(QRect(0, 0, frame.width(), titleHeight + TFRAMESIZE), tile); + + painter.drawTiledPixmap(QRect(0, 0, LFRAMESIZE, splitY), tile); + painter.fillRect(0, splitY, LFRAMESIZE, frame.height() - splitY, helper_.backgroundBottomColor(color)); + + painter.drawTiledPixmap(QRect(frame.width()-RFRAMESIZE, 0, + RFRAMESIZE, splitY), tile, + QPoint(frame.width()-RFRAMESIZE, 0)); + painter.fillRect(frame.width()-RFRAMESIZE, splitY, RFRAMESIZE, frame.height() - splitY, helper_.backgroundBottomColor(color)); + + painter.fillRect(0, frame.height() - BFRAMESIZE, frame.width(), BFRAMESIZE, helper_.backgroundBottomColor(color)); + + int radialW = qMin(600, frame.width() - LFRAMESIZE - RFRAMESIZE); + tile = helper_.radialGradient(color, radialW); + // In the style we assume the top frame to have a height of 32 this we need offset here with the + // actual value + int frameTopFixer = titleTop+titleHeight - 32; + QRect radialRect = QRect((frame.width() - radialW) / 2, frameTopFixer, radialW, 64); + painter.drawPixmap(radialRect, tile); + + // draw title text + painter.setFont(options()->font(isActive(), false)); + painter.setPen(titlebarTextColor(palette)); + painter.drawText(titleLeft, titleTop-1, titleWidth, titleHeight, // -1 is to go into top resizearea + OxygenFactory::titleAlign() | Qt::AlignVCenter, caption()); + + painter.setRenderHint(QPainter::Antialiasing); + + // Draw dividing line + frame = widget()->rect(); + frame.adjust(1,1,-1,-1); + frame.getRect(&x, &y, &w, &h); + + QColor light = helper_.calcLightColor(color); + QColor dark = helper_.calcDarkColor(color); + dark.setAlpha(120); + + if(!isActive()) { + light.setAlpha(120); + dark.setAlpha(50); + } + + QLinearGradient lg(x,0,x+w,0); + lg.setColorAt(0.5, dark); + dark.setAlpha(0); + lg.setColorAt(0.0, dark); + lg.setColorAt(1.0, dark); + painter.setPen(QPen(lg,1)); + + painter.drawLine(QPointF(x, titleTop+titleHeight-1.5), + QPointF(x+w, titleTop+titleHeight-1.5)); + + lg = QLinearGradient(x,0,x+w,0); + lg.setColorAt(0.5, light); + light.setAlpha(0); + lg.setColorAt(0.0, light); + lg.setColorAt(1.0, light); + painter.setPen(QPen(lg,1)); + + painter.drawLine(QPointF(x, titleTop+titleHeight-0.5), + QPointF(x+w, titleTop+titleHeight-0.5)); + + // Draw shadows of the frame + bool maximized = maximizeMode()==MaximizeFull && !options()->moveResizeMaximizedWindows(); + + if(maximized) + return; + + helper_.drawFloatFrame(&painter, widget()->rect(), color); + + if(!isResizable()) + return; + + // Draw the 3-dots resize handles + qreal cenY = frame.height() / 2 + x + 0.5; + qreal posX = frame.width() + y - 2.5; + painter.setPen(Qt::NoPen); + painter.setBrush(QColor(0, 0, 0, 66)); + renderDot(&painter, QPointF(posX, cenY - 3), 1.8); + renderDot(&painter, QPointF(posX, cenY), 1.8); + renderDot(&painter, QPointF(posX, cenY + 3), 1.8); + + painter.translate(x + frame.width()-9, y + frame.height()-9); + renderDot(&painter, QPointF(2.5, 6.5), 1.8); + renderDot(&painter, QPointF(5.5, 5.5), 1.8); + renderDot(&painter, QPointF(6.5, 2.5), 1.8); +} + +void OxygenClient::updateWindowShape() +{ + bool maximized = maximizeMode()==MaximizeFull && !options()->moveResizeMaximizedWindows(); + int w=widget()->width(); + int h=widget()->height(); + + if(maximized) { + QRegion mask(0,0,w,h); + setMask(mask); + return; + } + + QRegion mask(4, 0, w-8, h); + mask += QRegion(0, 4, w, h-8); + mask += QRegion(2, 1, w-4, h-2); + mask += QRegion(1, 2, w-2, h-4); + + setMask(mask); +} + +} //namespace Oxygen +} //namespace Ozone + +//#include "oxygenclient.moc" + +// #endif diff --git a/clients/ozone/oxygenclient.h b/clients/ozone/oxygenclient.h new file mode 100644 index 0000000000..232e6a8cf3 --- /dev/null +++ b/clients/ozone/oxygenclient.h @@ -0,0 +1,71 @@ +////////////////////////////////////////////////////////////////////////////// +// oxygenclient.h +// ------------------- +// Ozone window decoration for KDE +// ------------------- +// Copyright (c) 2003, 2004 David Johnson +// Copyright (c) 2006, 2007 Riccardo Iaconelli +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +////////////////////////////////////////////////////////////////////////////// + +#ifndef OXYGENCLIENT_H +#define OXYGENCLIENT_H + + +#include + +#include "lib/helper.h" + +class QPoint; + +namespace Ozone +{ +namespace Oxygen { + +class OxygenClient : public KCommonDecoration +{ + Q_OBJECT +public: + OxygenClient(KDecorationBridge *b, KDecorationFactory *f); + virtual ~OxygenClient(); + + virtual QString visibleName() const; + virtual KCommonDecorationButton *createButton(::ButtonType type); + virtual bool decorationBehaviour(DecorationBehaviour behaviour) const; + virtual int layoutMetric(LayoutMetric lm, bool respectWindowState = true, const KCommonDecorationButton * = 0) const; + virtual void updateWindowShape(); + virtual void init(); + +private: + void paintEvent(QPaintEvent *e); + QColor titlebarTextColor(const QPalette &palette); + bool colorCacheInvalid_; + QColor cachedTitlebarTextColor_; + +protected: + friend class OxygenButton; + OxygenHelper &helper_; +}; + + +} // namespace Oxygen +} // namespace Ozone + +#endif // EXAMPLECLIENT_H diff --git a/clients/ozone/ozoneclient.desktop b/clients/ozone/ozoneclient.desktop new file mode 100644 index 0000000000..cba8c3cca2 --- /dev/null +++ b/clients/ozone/ozoneclient.desktop @@ -0,0 +1,4 @@ +# KDE Desktop Entry +[Desktop Entry] +Name=Ozone +X-KDE-Library=kwin3_ozone diff --git a/clients/ozone/snippet.cpp b/clients/ozone/snippet.cpp new file mode 100644 index 0000000000..ea752c526f --- /dev/null +++ b/clients/ozone/snippet.cpp @@ -0,0 +1,72 @@ +////////////////////////////////////////////////////////////////////////////// +// oxygenbutton.h +// ------------------- +// Ozone window decoration for KDE. Buttons. +// ------------------- +// Copyright (c) 2006, 2007 Riccardo Iaconelli +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +////////////////////////////////////////////////////////////////////////////// + +class OxygenWidget : public QWidget +{ +protected: + virtual void paintEvent ( QPaintEvent * event ); +}; + +void OxygenWidget::paintEvent ( QPaintEvent * ) +{ + QPainter painter(this); + + QRadialGradient grad1(QPointF(5.0, 5.0),5.0); + grad1.setColorAt(0.9, QColor(0,0,0,100)); + grad1.setColorAt(1.0, QColor(0,0,0,0)); + QRadialGradient grad2(QPointF(5.0, 5.0),5.0); + grad2.setColorAt(0.0, QColor(235,235,235)); + grad2.setColorAt(1.0, QColor(220,220,220)); + QRadialGradient grad3(QPointF(5.0, 3.75), 3.5,QPointF(5.0, 2.5)); + grad3.setColorAt(0, QColor(255,255,255,50)); + grad3.setColorAt(1, QColor(255,255,255,0)); + QRadialGradient grad4(QPointF(5.0, 3.3), 3.5, QPointF(5.0, 2.1)); + grad4.setColorAt(0, QColor(255,255,255,50)); + grad4.setColorAt(1, QColor(255,255,255,0)); + QBrush brush1(grad1); + QBrush brush2(grad2); + QBrush brush3(grad3); + QBrush brush4(grad4); + + painter.scale(1.6, 1.6); + painter.setRenderHint(QPainter::Antialiasing,true); + + QPainterPath path1; + path1.addEllipse(0.0, 0.0, 10.0, 10.0); + painter.fillPath(path1, brush1); + + QPainterPath path2; + path2.addEllipse(0.5, 0.5, 9.0, 9.0); + painter.fillPath(path2, brush2); + + QPainterPath path3; + path3.addEllipse(1.5, 0.5, 7.0, 6.0); + painter.fillPath(path3, brush3); + + QPainterPath path4; + path4.addEllipse(1.5, 0.5, 7.0, 6.0); + painter.fillPath(path4, brush4); +} diff --git a/kcmkwin/kwindecoration/kwindecoration.cpp b/kcmkwin/kwindecoration/kwindecoration.cpp index 35e7d16c13..ebe79bfc92 100644 --- a/kcmkwin/kwindecoration/kwindecoration.cpp +++ b/kcmkwin/kwindecoration/kwindecoration.cpp @@ -450,7 +450,7 @@ void KWinDecorationModule::readConfig( const KConfigGroup & conf ) oldLibraryName = currentLibraryName; currentLibraryName = conf.readEntry("PluginLib", - ((QPixmap::defaultDepth() > 8) ? "kwin3_oxygen" : "kwin3_plastik")); + ((QPixmap::defaultDepth() > 8) ? "kwin3_ozone" : "kwin3_plastik")); QString decoName = decorationName( currentLibraryName ); // If we are using the "default" kde client, use the "default" entry. diff --git a/plugins.cpp b/plugins.cpp index 995f77122e..0a1f695e5f 100644 --- a/plugins.cpp +++ b/plugins.cpp @@ -33,7 +33,7 @@ PluginMgr::PluginMgr() : KDecorationPlugins( KGlobal::config()) { defaultPlugin = (QPixmap::defaultDepth() > 8) ? - "kwin3_oxygen" : "kwin3_plastik"; + "kwin3_ozone" : "kwin3_plastik"; loadPlugin( "" ); // load the plugin specified in cfg file }