diff options
Diffstat (limited to 'kwin/clients/quartz')
-rw-r--r-- | kwin/clients/quartz/Makefile.am | 23 | ||||
-rw-r--r-- | kwin/clients/quartz/config/Makefile.am | 16 | ||||
-rw-r--r-- | kwin/clients/quartz/config/config.cpp | 104 | ||||
-rw-r--r-- | kwin/clients/quartz/config/config.h | 47 | ||||
-rw-r--r-- | kwin/clients/quartz/quartz.cpp | 797 | ||||
-rw-r--r-- | kwin/clients/quartz/quartz.desktop | 39 | ||||
-rw-r--r-- | kwin/clients/quartz/quartz.h | 95 |
7 files changed, 1121 insertions, 0 deletions
diff --git a/kwin/clients/quartz/Makefile.am b/kwin/clients/quartz/Makefile.am new file mode 100644 index 000000000..d66643ba5 --- /dev/null +++ b/kwin/clients/quartz/Makefile.am @@ -0,0 +1,23 @@ + +INCLUDES = -I$(srcdir)/../../lib $(all_includes) + +SUBDIRS = . config + +kde_module_LTLIBRARIES = kwin3_quartz.la + +kwin3_quartz_la_SOURCES = quartz.cpp +kwin3_quartz_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +kwin3_quartz_la_LIBADD = $(LIB_KDEUI) ../../lib/libkdecorations.la + +METASOURCES = AUTO +noinst_HEADERS = quartz.h + +lnkdir = $(kde_datadir)/kwin/ +lnk_DATA = quartz.desktop + +EXTRA_DIST = $(lnk_DATA) + + +###KMAKE-start (don't edit or delete this block) + +###KMAKE-end diff --git a/kwin/clients/quartz/config/Makefile.am b/kwin/clients/quartz/config/Makefile.am new file mode 100644 index 000000000..eb64880ee --- /dev/null +++ b/kwin/clients/quartz/config/Makefile.am @@ -0,0 +1,16 @@ +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = kwin_quartz_config.la + +kwin_quartz_config_la_SOURCES = config.cpp +kwin_quartz_config_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +kwin_quartz_config_la_LIBADD = $(LIB_KDEUI) + +METASOURCES = AUTO +noinst_HEADERS = config.h + +lnkdir = $(kde_datadir)/kwin/ + +###KMAKE-start (don't edit or delete this block) + +###KMAKE-end diff --git a/kwin/clients/quartz/config/config.cpp b/kwin/clients/quartz/config/config.cpp new file mode 100644 index 000000000..8c7070b9d --- /dev/null +++ b/kwin/clients/quartz/config/config.cpp @@ -0,0 +1,104 @@ +/* + * + * This file contains the quartz configuration widget + * + * Copyright (c) 2001 + * Karol Szwed <[email protected]> + * http://gallium.n3.net/ + */ + +#include "config.h" +#include <kglobal.h> +#include <qwhatsthis.h> +#include <klocale.h> + + +extern "C" +{ + KDE_EXPORT QObject* allocate_config( KConfig* conf, QWidget* parent ) + { + return(new QuartzConfig(conf, parent)); + } +} + + +/* NOTE: + * 'conf' is a pointer to the kwindecoration modules open kwin config, + * and is by default set to the "Style" group. + * + * 'parent' is the parent of the QObject, which is a VBox inside the + * Configure tab in kwindecoration + */ + +QuartzConfig::QuartzConfig( KConfig* conf, QWidget* parent ) + : QObject( parent ) +{ + quartzConfig = new KConfig("kwinquartzrc"); + KGlobal::locale()->insertCatalogue("kwin_clients"); + gb = new QVBox( parent ); + cbColorBorder = new QCheckBox( + i18n("Draw window frames using &titlebar colors"), gb ); + QWhatsThis::add( cbColorBorder, + i18n("When selected, the window decoration borders " + "are drawn using the titlebar colors; otherwise, they are " + "drawn using normal border colors instead.") ); + cbExtraSmall = new QCheckBox( i18n("Quartz &extra slim"), gb ); + QWhatsThis::add( cbExtraSmall, + i18n("Quartz window decorations with extra-small title bar.") ); + // Load configuration options + load( conf ); + + // Ensure we track user changes properly + connect( cbColorBorder, SIGNAL(clicked()), this, SLOT(slotSelectionChanged()) ); + connect( cbExtraSmall, SIGNAL(clicked()), this, SLOT(slotSelectionChanged()) ); + + // Make the widgets visible in kwindecoration + gb->show(); +} + + +QuartzConfig::~QuartzConfig() +{ + delete gb; + delete quartzConfig; +} + + +void QuartzConfig::slotSelectionChanged() +{ + emit changed(); +} + + +// Loads the configurable options from the kwinrc config file +// It is passed the open config from kwindecoration to improve efficiency +void QuartzConfig::load( KConfig* /*conf*/ ) +{ + quartzConfig->setGroup("General"); + bool override = quartzConfig->readBoolEntry( "UseTitleBarBorderColors", true ); + cbColorBorder->setChecked( override ); + override = quartzConfig->readBoolEntry( "UseQuartzExtraSlim", false ); + cbExtraSmall->setChecked( override ); +} + + +// Saves the configurable options to the kwinrc config file +void QuartzConfig::save( KConfig* /*conf*/ ) +{ + quartzConfig->setGroup("General"); + quartzConfig->writeEntry( "UseTitleBarBorderColors", cbColorBorder->isChecked() ); + quartzConfig->writeEntry( "UseQuartzExtraSlim", cbExtraSmall->isChecked() ); + // Ensure others trying to read this config get updated + quartzConfig->sync(); +} + + +// Sets UI widget defaults which must correspond to style defaults +void QuartzConfig::defaults() +{ + cbColorBorder->setChecked( true ); + cbExtraSmall->setChecked( false ); +} + +#include "config.moc" +// vim: ts=4 diff --git a/kwin/clients/quartz/config/config.h b/kwin/clients/quartz/config/config.h new file mode 100644 index 000000000..815cc9644 --- /dev/null +++ b/kwin/clients/quartz/config/config.h @@ -0,0 +1,47 @@ +/* + * + * This file contains the quartz configuration widget + * + * Copyright (c) 2001 + * Karol Szwed <[email protected]> + * http://gallium.n3.net/ + */ + +#ifndef __KDE_QUARTZCONFIG_H +#define __KDE_QUARTZCONFIG_H + +#include <qcheckbox.h> +#include <qvbox.h> +#include <kconfig.h> + +class QuartzConfig: public QObject +{ + Q_OBJECT + + public: + QuartzConfig( KConfig* conf, QWidget* parent ); + ~QuartzConfig(); + + // These public signals/slots work similar to KCM modules + signals: + void changed(); + + public slots: + void load( KConfig* conf ); + void save( KConfig* conf ); + void defaults(); + + protected slots: + void slotSelectionChanged(); // Internal use + + private: + KConfig* quartzConfig; + QCheckBox* cbColorBorder; + QCheckBox* cbExtraSmall; + QVBox* gb; +}; + + +#endif + +// vim: ts=4 diff --git a/kwin/clients/quartz/quartz.cpp b/kwin/clients/quartz/quartz.cpp new file mode 100644 index 000000000..857971780 --- /dev/null +++ b/kwin/clients/quartz/quartz.cpp @@ -0,0 +1,797 @@ +/* + * + * Gallium-Quartz KWin client + * + * Copyright (C) 2005 Sandro Giessl <[email protected]> + * Copyright 2001 + * Karol Szwed <[email protected]> + * http://gallium.n3.net/ + * + * Based on the KDE default client. + * + * Includes mini titlebars for ToolWindow Support. + * Button positions are now customizable. + * + */ + +#include <kconfig.h> +#include <kdrawutil.h> +#include <kglobal.h> +#include <klocale.h> +#include <kpixmapeffect.h> +#include <qbitmap.h> +#include <qdrawutil.h> +#include <qimage.h> +#include <qapplication.h> + +#include "quartz.h" + + +namespace Quartz { + +static const unsigned char iconify_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +static const unsigned char close_bits[] = { + 0x00, 0x00, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00, 0x30, 0x00, 0x78, 0x00, + 0xcc, 0x00, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char maximize_bits[] = { + 0xff, 0x01, 0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0xff, 0x01, 0x00, 0x00}; + +static const unsigned char minmax_bits[] = { + 0xfc, 0x00, 0xfc, 0x00, 0x84, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xe1, 0x00, + 0x21, 0x00, 0x21, 0x00, 0x3f, 0x00, 0x00, 0x00}; + +static const unsigned char question_bits[] = { + 0x00, 0x00, 0x3c, 0x00, 0x66, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00}; + +static const unsigned char pindown_white_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x1f, 0xa0, 0x03, + 0xb0, 0x01, 0x30, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pindown_gray_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x80, 0x07, 0xc0, 0x03, 0xe0, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pindown_dgray_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x10, 0x70, 0x20, 0x50, 0x20, + 0x48, 0x30, 0xc8, 0x38, 0x08, 0x1f, 0x08, 0x18, 0x10, 0x1c, 0x10, 0x0e, + 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pinup_white_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x11, + 0x3f, 0x15, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pinup_gray_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x0a, 0xbf, 0x0a, 0x80, 0x15, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pinup_dgray_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x40, 0x31, 0x40, 0x2e, + 0x40, 0x20, 0x40, 0x20, 0x7f, 0x2a, 0x40, 0x3f, 0xc0, 0x31, 0xc0, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char above_on_bits[] = { + 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x30, 0x00, 0xfc, 0x00, 0x78, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char above_off_bits[] = { + 0x30, 0x00, 0x78, 0x00, 0xfc, 0x00, 0x30, 0x00, 0xfe, 0x01, 0xfe, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char below_on_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x00, 0xfc, 0x00, + 0x30, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00}; + +static const unsigned char below_off_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, + 0x30, 0x00, 0xfc, 0x00, 0x78, 0x00, 0x30, 0x00}; + +static const unsigned char shade_on_bits[] = { + 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0xfe, 0x01, 0x00, 0x00}; + +static const unsigned char shade_off_bits[] = { + 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + +/////////////////////////////////////////////////////////////////////////// + +// Titlebar button positions +bool onAllDesktopsButtonOnLeft = true; +bool coloredFrame = true; +bool extraSlim = false; + +KPixmap* titleBlocks = NULL; +KPixmap* ititleBlocks = NULL; +KPixmap* pinDownPix = NULL; +KPixmap* pinUpPix = NULL; +KPixmap* ipinDownPix = NULL; +KPixmap* ipinUpPix = NULL; +static int normalTitleHeight; +static int toolTitleHeight; +static int borderWidth; + +bool quartz_initialized = false; +QuartzHandler* clientHandler; + +/////////////////////////////////////////////////////////////////////////// + + +QuartzHandler::QuartzHandler() +{ + quartz_initialized = false; + readConfig(); + createPixmaps(); + quartz_initialized = true; +} + + +QuartzHandler::~QuartzHandler() +{ + quartz_initialized = false; + freePixmaps(); +} + + +KDecoration* QuartzHandler::createDecoration( KDecorationBridge* bridge ) +{ + return new QuartzClient( bridge, this ); +} + + +bool QuartzHandler::reset(unsigned long changed) +{ + quartz_initialized = false; + freePixmaps(); + readConfig(); + createPixmaps(); + quartz_initialized = true; + + // Do we need to "hit the wooden hammer" ? + bool needHardReset = true; + if (changed & SettingColors) + { + needHardReset = false; + } else if (changed & SettingButtons) { + // handled by KCommonDecoration + needHardReset = false; + } + + if (needHardReset) { + return true; + } else { + resetDecorations(changed); + return false; + } + return true; +} + + +bool QuartzHandler::supports( Ability ability ) +{ + switch( ability ) + { + case AbilityAnnounceButtons: + case AbilityButtonMenu: + case AbilityButtonOnAllDesktops: + case AbilityButtonHelp: + case AbilityButtonMinimize: + case AbilityButtonMaximize: + case AbilityButtonClose: + case AbilityButtonAboveOthers: + case AbilityButtonBelowOthers: + case AbilityButtonShade: + case AbilityButtonSpacer: + return true; + default: + return false; + }; +} + + +void QuartzHandler::readConfig() +{ + KConfig conf("kwinquartzrc"); + conf.setGroup("General"); + coloredFrame = conf.readBoolEntry( "UseTitleBarBorderColors", true ); + extraSlim = conf.readBoolEntry( "UseQuartzExtraSlim", false ); + + // A small hack to make the on all desktops button look nicer + onAllDesktopsButtonOnLeft = KDecoration::options()->titleButtonsLeft().contains( 'S' ); + if ( QApplication::reverseLayout() ) + onAllDesktopsButtonOnLeft = !onAllDesktopsButtonOnLeft; + switch(options()->preferredBorderSize(this)) { + case BorderLarge: + borderWidth = 8; + break; + case BorderVeryLarge: + borderWidth = 12; + break; + case BorderHuge: + borderWidth = 18; + break; + case BorderVeryHuge: + borderWidth = 27; + break; + case BorderOversized: + borderWidth = 40; + break; + case BorderTiny: + case BorderNormal: + default: + borderWidth = extraSlim?2:4; + } + + normalTitleHeight = QFontMetrics(options()->font(true)).height(); + int nTH_limit=extraSlim?14:18; + normalTitleHeight = QFontMetrics(options()->font(true)).height()-(extraSlim?1:0); + if (normalTitleHeight < nTH_limit) normalTitleHeight = nTH_limit; + if (normalTitleHeight < borderWidth) normalTitleHeight = borderWidth; + + toolTitleHeight = QFontMetrics(options()->font(true, true)).height(); + if (toolTitleHeight < 12) toolTitleHeight = 12; + if (toolTitleHeight < borderWidth) toolTitleHeight = borderWidth; +} + + +// This does the colour transition magic. (You say "Oh, is that it?") +// This may be made configurable at a later stage +void QuartzHandler::drawBlocks( KPixmap *pi, KPixmap &p, const QColor &c1, const QColor &c2 ) +{ + QPainter px; + + px.begin( pi ); + + // Draw a background gradient first + KPixmapEffect::gradient(p, c1, c2, KPixmapEffect::HorizontalGradient); + + int factor = (pi->height()-2)/4; + int square = factor - (factor+2)/4; + + int x = pi->width() - 5*factor - square; + int y = (pi->height() - 4*factor)/2; + + px.fillRect( x, y, square, square, c1.light(120) ); + px.fillRect( x, y+factor, square, square, c1 ); + px.fillRect( x, y+2*factor, square, square, c1.light(110) ); + px.fillRect( x, y+3*factor, square, square, c1 ); + + px.fillRect( x+factor, y, square, square, c1.light(110) ); + px.fillRect( x+factor, y+factor, square, square, c2.light(110) ); + px.fillRect( x+factor, y+2*factor, square, square, c1.light(120) ); + px.fillRect( x+factor, y+3*factor, square, square, c2.light(130) ); + + px.fillRect( x+2*factor, y+factor, square, square, c1.light(110) ); + px.fillRect( x+2*factor, y+2*factor, square, square, c2.light(120) ); + px.fillRect( x+2*factor, y+3*factor, square, square, c2.light(150) ); + + px.fillRect( x+3*factor, y, square, square, c1.dark(110) ); + px.fillRect( x+3*factor, y+2*factor, square, square, c2.light(120) ); + px.fillRect( x+3*factor, y+3*factor, square, square, c1.dark(120) ); + + px.fillRect( x+4*factor, y+factor, square, square, c1.light(110) ); + px.fillRect( x+4*factor, y+3*factor, square, square, c1.dark(110) ); + + px.fillRect( x+5*factor, y+2*factor, square, square, c2.light(120)); + px.fillRect( x+5*factor, y+3*factor, square, square, c2.light(110) ); +} + + +// This paints the button pixmaps upon loading the style. +void QuartzHandler::createPixmaps() +{ + // Obtain titlebar blend colours, and create the block stuff on pixmaps. + QColorGroup g2 = options()->colorGroup(ColorTitleBlend, true); + QColor c2 = g2.background(); + g2 = options()->colorGroup(ColorTitleBar, true ); + QColor c = g2.background().light(130); + + titleBlocks = new KPixmap(); + titleBlocks->resize( normalTitleHeight*25/18, normalTitleHeight ); + drawBlocks( titleBlocks, *titleBlocks, c, c2 ); + + g2 = options()->colorGroup(ColorTitleBlend, false); + c2 = g2.background(); + g2 = options()->colorGroup(ColorTitleBar, false ); + c = g2.background().light(130); + + ititleBlocks = new KPixmap(); + ititleBlocks->resize( normalTitleHeight*25/18, normalTitleHeight ); + drawBlocks( ititleBlocks, *ititleBlocks, c, c2 ); + + // Set the on all desktops pin pixmaps; + QColorGroup g; + QPainter p; + + g = options()->colorGroup( onAllDesktopsButtonOnLeft ? ColorTitleBar : ColorTitleBlend, true ); + c = onAllDesktopsButtonOnLeft ? g.background().light(130) : g.background(); + g2 = options()->colorGroup( ColorButtonBg, true ); + + pinUpPix = new KPixmap(); + pinUpPix->resize(16, 16); + p.begin( pinUpPix ); + p.fillRect( 0, 0, 16, 16, c); + kColorBitmaps( &p, g2, 0, 1, 16, 16, true, pinup_white_bits, + pinup_gray_bits, NULL, NULL, pinup_dgray_bits, NULL ); + p.end(); + + pinDownPix = new KPixmap(); + pinDownPix->resize(16, 16); + p.begin( pinDownPix ); + p.fillRect( 0, 0, 16, 16, c); + kColorBitmaps( &p, g2, 0, 1, 16, 16, true, pindown_white_bits, + pindown_gray_bits, NULL, NULL, pindown_dgray_bits, NULL ); + p.end(); + + + // Inactive pins + g = options()->colorGroup( onAllDesktopsButtonOnLeft ? ColorTitleBar : ColorTitleBlend, false ); + c = onAllDesktopsButtonOnLeft ? g.background().light(130) : g.background(); + g2 = options()->colorGroup( ColorButtonBg, false ); + + ipinUpPix = new KPixmap(); + ipinUpPix->resize(16, 16); + p.begin( ipinUpPix ); + p.fillRect( 0, 0, 16, 16, c); + kColorBitmaps( &p, g2, 0, 1, 16, 16, true, pinup_white_bits, + pinup_gray_bits, NULL, NULL, pinup_dgray_bits, NULL ); + p.end(); + + ipinDownPix = new KPixmap(); + ipinDownPix->resize(16, 16); + p.begin( ipinDownPix ); + p.fillRect( 0, 0, 16, 16, c); + kColorBitmaps( &p, g2, 0, 1, 16, 16, true, pindown_white_bits, + pindown_gray_bits, NULL, NULL, pindown_dgray_bits, NULL ); + p.end(); +} + + +void QuartzHandler::freePixmaps() +{ + delete titleBlocks; + delete ititleBlocks; + + // On all desktops pin images + delete pinUpPix; + delete ipinUpPix; + delete pinDownPix; + delete ipinDownPix; +} + + +QValueList< QuartzHandler::BorderSize > QuartzHandler::borderSizes() const +{ // the list must be sorted + return QValueList< BorderSize >() << BorderNormal << BorderLarge << + BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized; +} + + +QuartzButton::QuartzButton(ButtonType type, QuartzClient *parent, const char *name) + : KCommonDecorationButton(type, parent, name) +{ + // Eliminate any possible background flicker + setBackgroundMode( QWidget::NoBackground ); + + deco = 0; +} + + +QuartzButton::~QuartzButton() +{ + delete deco; +} + +void QuartzButton::reset(unsigned long changed) +{ + if (changed&DecorationReset || changed&ManualReset || changed&SizeChange || changed&StateChange) { + switch (type() ) { + case CloseButton: + setBitmap(close_bits); + break; + case HelpButton: + setBitmap(question_bits); + break; + case MinButton: + setBitmap(iconify_bits); + break; + case MaxButton: + setBitmap( isOn() ? minmax_bits : maximize_bits ); + break; + case OnAllDesktopsButton: + setBitmap(0); + break; + case ShadeButton: + setBitmap( isOn() ? shade_on_bits : shade_off_bits ); + break; + case AboveButton: + setBitmap( isOn() ? above_on_bits : above_off_bits ); + break; + case BelowButton: + setBitmap( isOn() ? below_on_bits : below_off_bits ); + break; + default: + setBitmap(0); + break; + } + + this->update(); + } +} + +void QuartzButton::setBitmap(const unsigned char *bitmap) +{ + delete deco; + deco = 0; + + if (bitmap) { + deco = new QBitmap(10, 10, bitmap, true); + deco->setMask( *deco ); + repaint( false ); + } +} + +void QuartzButton::drawButton(QPainter *p) +{ + // Never paint if the pixmaps have not been created + if (!quartz_initialized) + return; + + QColor c; + + if (isLeft() ) + c = KDecoration::options()->color(KDecoration::ColorTitleBar, decoration()->isActive()).light(130); + else + c = KDecoration::options()->color(KDecoration::ColorTitleBlend, decoration()->isActive()); + + // Fill the button background with an appropriate color + p->fillRect(0, 0, width(), height(), c ); + + // If we have a decoration bitmap, then draw that + // otherwise we paint a menu button (with mini icon), or a onAllDesktops button. + if( deco ) + { + int xOff = (width()-10)/2; + int yOff = (height()-10)/2; + p->setPen( Qt::black ); + p->drawPixmap(isDown() ? xOff+2: xOff+1, isDown() ? yOff+2 : yOff+1, *deco); + p->setPen( KDecoration::options()->color(KDecoration::ColorButtonBg, decoration()->isActive()).light(150) ); + p->drawPixmap(isDown() ? xOff+1: xOff, isDown() ? yOff+1 : yOff, *deco); + } else + { + QPixmap btnpix; + int Offset = 0; + + if (type() == OnAllDesktopsButton) + { + if (isDown()) + Offset = 1; + + // Select the right onAllDesktops button to paint + if (decoration()->isActive()) + btnpix = isOn() ? *pinDownPix : *pinUpPix; + else + btnpix = isOn() ? *ipinDownPix : *ipinUpPix; + + } else + btnpix = decoration()->icon().pixmap( QIconSet::Small, QIconSet::Normal); + + // Shrink the miniIcon for tiny titlebars. + if ( height() < 16) + { + QPixmap tmpPix; + + // Smooth scale the image + tmpPix.convertFromImage( btnpix.convertToImage().smoothScale(height(), height())); + p->drawPixmap( 0, 0, tmpPix ); + } else { + Offset += (height() - 16)/2; + p->drawPixmap( Offset, Offset, btnpix ); + } + } +} + +/////////////////////////////////////////////////////////////////////////// + +QuartzClient::QuartzClient(KDecorationBridge* bridge, KDecorationFactory* factory) + : KCommonDecoration (bridge, factory) +{ +} + +QString QuartzClient::visibleName() const +{ + return i18n("Quartz"); +} + +QString QuartzClient::defaultButtonsLeft() const +{ + return "M"; +} + +QString QuartzClient::defaultButtonsRight() const +{ + return "HIAX"; +} + +bool QuartzClient::decorationBehaviour(DecorationBehaviour behaviour) const +{ + switch (behaviour) { + case DB_MenuClose: + return false; + + case DB_WindowMask: + return false; + + case DB_ButtonHide: + return true; + + default: + return KCommonDecoration::decorationBehaviour(behaviour); + } +} + +int QuartzClient::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: + case LM_TitleEdgeLeft: + case LM_TitleEdgeRight: + { + if (respectWindowState && maximized) { + return 0; + } else { + return borderSize; + } + } + + case LM_TitleEdgeTop: + return borderSize-1; + + case LM_TitleEdgeBottom: + return 1; + + case LM_TitleBorderLeft: + case LM_TitleBorderRight: + return 5; + + case LM_TitleHeight: + return titleHeight; + + case LM_ButtonWidth: + case LM_ButtonHeight: + return titleHeight-2; + + case LM_ButtonSpacing: + return 1; + + case LM_ExplicitButtonSpacer: + return 3; + + default: + return KCommonDecoration::layoutMetric(lm, respectWindowState, btn); + } +} + +KCommonDecorationButton *QuartzClient::createButton(ButtonType type) +{ + switch (type) { + case MenuButton: + return new QuartzButton(MenuButton, this, "menu"); + + case OnAllDesktopsButton: + return new QuartzButton(OnAllDesktopsButton, this, "on_all_desktops"); + + case HelpButton: + return new QuartzButton(HelpButton, this, "help"); + + case MinButton: + return new QuartzButton(MinButton, this, "minimize"); + + case MaxButton: + return new QuartzButton(MaxButton, this, "maximize"); + + case CloseButton: + return new QuartzButton(CloseButton, this, "close"); + + case AboveButton: + return new QuartzButton(AboveButton, this, "above"); + + case BelowButton: + return new QuartzButton(BelowButton, this, "below"); + + case ShadeButton: + return new QuartzButton(ShadeButton, this, "shade"); + + default: + return 0; + } +} + + +void QuartzClient::init() +{ + // Finally, toolWindows look small + if ( isToolWindow() ) { + titleHeight = toolTitleHeight; + largeButtons = false; + } + else { + titleHeight = normalTitleHeight; + largeButtons = true; + } + + borderSize = borderWidth; + + KCommonDecoration::init(); +} + +void QuartzClient::reset( unsigned long changed ) +{ + if (changed & SettingColors || changed & SettingFont) + { + // repaint the whole thing + widget()->repaint(false); + } + + KCommonDecoration::reset(changed); +} + + +// Quartz Paint magic goes here. +void QuartzClient::paintEvent( QPaintEvent* ) +{ + // Never paint if the pixmaps have not been created + if (!quartz_initialized) + return; + + const bool maxFull = (maximizeMode()==MaximizeFull) && !options()->moveResizeMaximizedWindows(); + + QColorGroup g; + QPainter p(widget()); + + // Obtain widget bounds. + QRect r(widget()->rect()); + int x = r.x(); + int y = r.y(); + int x2 = r.width() - 1; + int y2 = r.height() - 1; + int w = r.width(); + int h = r.height(); + + // Draw part of the frame that is the title color + + if( coloredFrame ) + g = options()->colorGroup(ColorTitleBar, isActive()); + else + g = options()->colorGroup(ColorFrame, isActive()); + + // Draw outer highlights and lowlights + p.setPen( g.light().light(120) ); + p.drawLine( x, y, x2-1, y ); + p.drawLine( x, y+1, x, y2-1 ); + p.setPen( g.dark().light(120) ); + p.drawLine( x2, y, x2, y2 ); + p.drawLine( x, y2, x2, y2 ); + + // Fill out the border edges + QColor frameColor; + if ( coloredFrame) + frameColor = g.background().light(130); + else + frameColor = g.background(); + if (borderSize > 2) { + p.fillRect(x+1, y+1, w-2, borderSize-2, frameColor); // top + if (!maxFull) { + p.fillRect(x+1, y+h-(borderSize-1), w-2, borderSize-2, frameColor); // bottom + p.fillRect(x+1, y+borderSize-1, borderSize-1, h-2*(borderSize-1), frameColor); // left + p.fillRect(x+w-(borderSize), y+borderSize-1, borderSize-1, h-2*(borderSize-1), frameColor); // right + } + } + + // Draw a frame around the wrapped widget. + p.setPen( g.background() ); + if (maxFull) { + p.drawLine(x+1, y+titleHeight+(borderSize-1), w-2, y+titleHeight+(borderSize-1)); + } else { + p.drawRect( x+(borderSize-1), y+titleHeight+(borderSize-1), w-2*(borderSize-1), h-titleHeight-2*(borderSize-1) ); + } + + // Drawing this extra line removes non-drawn areas when shaded + p.drawLine( x+borderSize, y2-borderSize, x2-borderSize, y2-borderSize); + + // Highlight top corner + p.setPen( g.light().light(160) ); + p.drawPoint( x, y ); + p.setPen( g.light().light(140) ); + p.drawPoint( x+1, y ); + p.drawPoint( x, y+1 ); + + // Draw the title bar. + // =================== + int r_x, r_y, r_x2, r_y2; + widget()->rect().coords(&r_x, &r_y, &r_x2, &r_y2); + const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft); + const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop); + const int titleEdgeRight = layoutMetric(LM_TitleEdgeRight); + const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom); + const int ttlHeight = layoutMetric(LM_TitleHeight); + const int titleEdgeBottomBottom = r_y+titleEdgeTop+ttlHeight+titleEdgeBottom-1; + r = QRect(r_x+titleEdgeLeft+buttonsLeftWidth(), r_y+titleEdgeTop, + r_x2-titleEdgeRight-buttonsRightWidth()-(r_x+titleEdgeLeft+buttonsLeftWidth()), + titleEdgeBottomBottom-(r_y+titleEdgeTop) ); + + // Obtain titlebar blend colours + QColor c1 = options()->color(ColorTitleBar, isActive() ).light(130); + QColor c2 = options()->color(ColorTitleBlend, isActive() ); + + // Create a disposable pixmap buffer for the titlebar + KPixmap* titleBuffer = new KPixmap; + titleBuffer->resize( maxFull?w-2:(w-2*(borderSize-1)), titleHeight ); + + QPainter p2( titleBuffer, this ); + + // subtract titleBlocks pixmap width and some + int rightoffset = r.x()+r.width()-titleBlocks->width()-borderSize; + + p2.fillRect( 0, 0, w, r.height(), c1 ); + p2.fillRect( rightoffset, 0, maxFull?w-rightoffset:w-rightoffset-2*(borderSize-1), r.height(), c2 ); + + // 8 bit displays will be a bit dithered, but they still look ok. + if ( isActive() ) + p2.drawPixmap( rightoffset, 0, *titleBlocks ); + else + p2.drawPixmap( rightoffset, 0, *ititleBlocks ); + + // Draw the title text on the pixmap, and with a smaller font + // for toolwindows than the default. + QFont fnt; + if ( largeButtons ) { + fnt = options()->font(true, false); // font not small + } else { + fnt = options()->font(true, true); // font small + fnt.setWeight( QFont::Normal ); // and disable bold + } + p2.setFont( fnt ); + + p2.setPen( options()->color(ColorFont, isActive() )); + p2.drawText(r.x()+4-borderSize, 0, r.width()-3, r.height(), + AlignLeft | AlignVCenter, caption() ); + p2.end(); + + p.drawPixmap( maxFull?1:borderSize-1, borderSize-1, *titleBuffer ); + + delete titleBuffer; +} + +} + +// Extended KWin plugin interface +///////////////////////////////// +extern "C" +{ + KDE_EXPORT KDecorationFactory *create_factory() + { + Quartz::clientHandler = new Quartz::QuartzHandler(); + return Quartz::clientHandler; + } +} + + + +#include "quartz.moc" +// vim: ts=4 +// kate: space-indent off; tab-width 4; diff --git a/kwin/clients/quartz/quartz.desktop b/kwin/clients/quartz/quartz.desktop new file mode 100644 index 000000000..30a177973 --- /dev/null +++ b/kwin/clients/quartz/quartz.desktop @@ -0,0 +1,39 @@ +[Desktop Entry] +Name=Quartz +Name[az]=Kvarts +Name[be]=Кварц +Name[bn]=কোয়ার্ট্জ +Name[csb]=Kwarc +Name[cy]=Cwarts +Name[eo]=Kvarco +Name[es]=Cuarzo +Name[eu]=Kuartzoa +Name[fa]=کوارتز +Name[ga]=Grianchloch +Name[hi]=क्वार्ट्ज +Name[hr]=Kvarc +Name[ka]=კვარცი +Name[kk]=Кварц +Name[ko]=수정 +Name[lo]=ແບບຄວອທ +Name[lv]=Kvarcs +Name[mk]=Кварц +Name[mt]=Kwartz +Name[ne]=क्वार्ज +Name[pl]=Kwarc +Name[pt_BR]=Quartzo +Name[ro]=Cuarț +Name[ru]=Кварц +Name[rw]=Ibuye +Name[ta]=குவார்ட்ஸ் +Name[te]=క్వార్జ్ +Name[tg]=Квартс +Name[th]=แบบควอทซ์ +Name[tr]=Kuartz +Name[uk]=Кварц +Name[uz]=Chaqmoqtosh +Name[uz@cyrillic]=Чақмоқтош +Name[ven]=Musuku +Name[vi]=Thạch anh +Name[zh_TW]=石英 +X-KDE-Library=kwin3_quartz diff --git a/kwin/clients/quartz/quartz.h b/kwin/clients/quartz/quartz.h new file mode 100644 index 000000000..37f3dff6e --- /dev/null +++ b/kwin/clients/quartz/quartz.h @@ -0,0 +1,95 @@ +/* + * Gallium-Quartz KWin client + * + * Copyright (C) 2005 Sandro Giessl <[email protected]> + * Copyright 2001 + * Karol Szwed <[email protected]> + * http://gallium.n3.net/ + * + * Based on the KDE default client. + * + * Includes mini titlebars for ToolWindow Support. + * Button positions are now customizable. + * + */ + +#ifndef __KDEGALLIUM_QUARTZ_H +#define __KDEGALLIUM_QUARTZ_H + +#include <qbitmap.h> +#include <kpixmap.h> +#include "../../lib/kcommondecoration.h" +#include "../../lib/kdecorationfactory.h" + +class QSpacerItem; +class QBoxLayout; + +namespace Quartz { + +class QuartzClient; + +class QuartzHandler: public QObject, public KDecorationFactory +{ + Q_OBJECT + public: + QuartzHandler(); + ~QuartzHandler(); + + virtual KDecoration* createDecoration( KDecorationBridge* ); + virtual bool reset(unsigned long changed); + virtual bool supports( Ability ability ); + virtual QValueList< BorderSize > borderSizes() const; + + private: + void readConfig(); + void createPixmaps(); + void freePixmaps(); + void drawBlocks(KPixmap* pi, KPixmap &p, const QColor &c1, const QColor &c2); +}; + + +class QuartzButton : public KCommonDecorationButton +{ + public: + QuartzButton(ButtonType type, QuartzClient *parent, const char *name); + ~QuartzButton(); + void setBitmap(const unsigned char *bitmap); + + void reset(unsigned long changed); + + protected: + void drawButton(QPainter *p); + + QBitmap* deco; +}; + + +class QuartzClient : public KCommonDecoration +{ + public: + QuartzClient(KDecorationBridge* bridge, KDecorationFactory* factory); + ~QuartzClient() {;} + + virtual QString visibleName() const; + virtual QString defaultButtonsLeft() const; + virtual QString defaultButtonsRight() const; + virtual bool decorationBehaviour(DecorationBehaviour behaviour) const; + virtual int layoutMetric(LayoutMetric lm, bool respectWindowState = true, const KCommonDecorationButton * = 0) const; + virtual KCommonDecorationButton *createButton(ButtonType type); + + virtual void init(); + + protected: + virtual void reset( unsigned long changed ); + void paintEvent( QPaintEvent* ); + + private: + int titleHeight, borderSize; + bool largeButtons; +}; + +} + +#endif +// vim: ts=4 +// kate: space-indent off; tab-width 4; |