diff options
Diffstat (limited to 'twin/clients/keramik')
34 files changed, 2712 insertions, 0 deletions
diff --git a/twin/clients/keramik/CMakeLists.txt b/twin/clients/keramik/CMakeLists.txt new file mode 100644 index 000000000..67e739d48 --- /dev/null +++ b/twin/clients/keramik/CMakeLists.txt @@ -0,0 +1,65 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( config ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/twin/lib + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES keramik.desktop DESTINATION ${DATA_INSTALL_DIR}/twin ) + + +##### twin3_keramik (module) #################### + +set_source_files_properties( keramik.cpp + PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/tiles.h ) + +tde_add_kpart( twin3_keramik AUTOMOC + SOURCES keramik.cpp + LINK tdecorations-shared tdeui-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) + + +##### tiles.h (header) ########################## + +set( pics + pics/caption-large-left.png pics/caption-small-right.png + pics/titlebar-center.png pics/titlebutton-square.png + pics/border-left.png pics/caption-large-right.png + pics/grabbar-center.png pics/titlebar-left.png + pics/border-right.png pics/caption-small-center.png + pics/grabbar-left.png pics/titlebar-right.png + pics/caption-large-center.png pics/caption-small-left.png + pics/grabbar-right.png pics/titlebutton-round.png + pics/bottom-left.png pics/bottom-right.png pics/bottom-center.png + pics/titlebutton-square-large.png pics/titlebutton-square-huge.png + pics/titlebutton-round-large.png pics/titlebutton-round-huge.png ) + +add_custom_command( OUTPUT tiles.h + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/embedtool ${pics} + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/embedtool ${pics} ) + +tde_add_executable( embedtool + SOURCES embedtool.cpp + LINK ${TQT_LIBRARIES} +) diff --git a/twin/clients/keramik/Makefile.am b/twin/clients/keramik/Makefile.am new file mode 100644 index 000000000..4c7c6e10c --- /dev/null +++ b/twin/clients/keramik/Makefile.am @@ -0,0 +1,44 @@ +INCLUDES = -I$(srcdir)/../../lib $(all_includes) + +SUBDIRS = . config + +noinst_PROGRAMS = embedtool + +noinst_HEADERS = tiles.h + +embedtool_SOURCES = embedtool.cpp +embedtool_LDADD = $(LIB_QT) +embedtool_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_KIO) -lktexteditor + +kde_module_LTLIBRARIES = twin3_keramik.la + +twin3_keramik_la_SOURCES = keramik.cpp +twin3_keramik_la_COMPILE_FIRST = tiles.h +twin3_keramik_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +twin3_keramik_la_LIBADD = $(LIB_TDEUI) ../../lib/libtdecorations.la +#twin3_keramik_la_LDFLAGS = $(all_libraries) -avoid-version -module $(KDE_RPATH) $(KDE_MT_LDFLAGS) + +METASOURCES = AUTO +noinst_headers = keramik.h tiles.h + +lnkdir = $(kde_datadir)/twin +lnk_DATA = keramik.desktop + +EXTRA_DIST = $(lnk_DATA) + +tiles.h: pics/caption-large-left.png pics/caption-small-right.png pics/titlebar-center.png \ + pics/titlebutton-square.png pics/border-left.png pics/caption-large-right.png \ + pics/grabbar-center.png pics/titlebar-left.png pics/border-right.png \ + pics/caption-small-center.png pics/grabbar-left.png pics/titlebar-right.png \ + pics/caption-large-center.png pics/caption-small-left.png pics/grabbar-right.png \ + pics/titlebutton-round.png pics/bottom-left.png pics/bottom-right.png \ + pics/bottom-center.png \ + pics/titlebutton-square-large.png pics/titlebutton-square-huge.png \ + pics/titlebutton-round-large.png pics/titlebutton-round-huge.png + +tiles.h: embedtool + pics=`ls $(srcdir)/pics/*.png 2>/dev/null` ;\ + ./embedtool $$pics + +keramik.lo: tiles.h + diff --git a/twin/clients/keramik/config/CMakeLists.txt b/twin/clients/keramik/config/CMakeLists.txt new file mode 100644 index 000000000..7b5bdb339 --- /dev/null +++ b/twin/clients/keramik/config/CMakeLists.txt @@ -0,0 +1,29 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### twin_keramik_config (module) ############## + +tde_add_kpart( twin_keramik_config AUTOMOC + SOURCES config.cpp keramikconfig.ui + LINK tdeui-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/twin/clients/keramik/config/Makefile.am b/twin/clients/keramik/config/Makefile.am new file mode 100644 index 000000000..19ee4f27d --- /dev/null +++ b/twin/clients/keramik/config/Makefile.am @@ -0,0 +1,13 @@ +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = twin_keramik_config.la + +twin_keramik_config_la_SOURCES = config.cpp keramikconfig.ui +twin_keramik_config_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +twin_keramik_config_la_LIBADD = $(LIB_TDEUI) + +METASOURCES = AUTO +noinst_HEADERS = config.h keramikconfig.h + +lnkdir = $(kde_datadir)/twin + diff --git a/twin/clients/keramik/config/config.cpp b/twin/clients/keramik/config/config.cpp new file mode 100644 index 000000000..1852eadd8 --- /dev/null +++ b/twin/clients/keramik/config/config.cpp @@ -0,0 +1,110 @@ +/* + * + * Keramik KWin client configuration module + * + * Copyright (C) 2002 Fredrik Hglund <fredrik@kde.org> + * + * Based on the Quartz configuration module, + * Copyright (c) 2001 Karol Szwed <gallium@kde.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the license, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <kglobal.h> +#include <klocale.h> + +#include <tqcheckbox.h> + +#include "config.h" +#include "config.moc" + +extern "C" +{ + KDE_EXPORT TQObject* allocate_config( KConfig* conf, TQWidget* parent ) + { + return ( new KeramikConfig( conf, parent ) ); + } +} + + +/* NOTE: + * 'conf' is a pointer to the twindecoration modules open twin config, + * and is by default set to the "Style" group. + * + * 'parent' is the parent of the TQObject, which is a VBox inside the + * Configure tab in twindecoration + */ + +KeramikConfig::KeramikConfig( KConfig* conf, TQWidget* parent ) + : TQObject( parent ) +{ + KGlobal::locale()->insertCatalogue("twin_clients"); + c = new KConfig( "twinkeramikrc" ); + + ui = new KeramikConfigUI( parent ); + connect( ui->showAppIcons, TQT_SIGNAL(clicked()), TQT_SIGNAL(changed()) ); + connect( ui->smallCaptions, TQT_SIGNAL(clicked()), TQT_SIGNAL(changed()) ); + connect( ui->largeGrabBars, TQT_SIGNAL(clicked()), TQT_SIGNAL(changed()) ); + connect( ui->useShadowedText, TQT_SIGNAL(clicked()), TQT_SIGNAL(changed()) ); + + load( conf ); + ui->show(); +} + + +KeramikConfig::~KeramikConfig() +{ + delete ui; + delete c; +} + + +// Loads the configurable options from the twinrc config file +// It is passed the open config from twindecoration to improve efficiency +void KeramikConfig::load( KConfig* ) +{ + c->setGroup("General"); + ui->showAppIcons->setChecked( c->readBoolEntry("ShowAppIcons", true) ); + ui->smallCaptions->setChecked( c->readBoolEntry("SmallCaptionBubbles", false) ); + ui->largeGrabBars->setChecked( c->readBoolEntry("LargeGrabBars", true) ); + ui->useShadowedText->setChecked( c->readBoolEntry("UseShadowedText", true) ); +} + + +// Saves the configurable options to the twinrc config file +void KeramikConfig::save( KConfig* ) +{ + c->setGroup( "General" ); + c->writeEntry( "ShowAppIcons", ui->showAppIcons->isChecked() ); + c->writeEntry( "SmallCaptionBubbles", ui->smallCaptions->isChecked() ); + c->writeEntry( "LargeGrabBars", ui->largeGrabBars->isChecked() ); + c->writeEntry( "UseShadowedText", ui->useShadowedText->isChecked() ); + c->sync(); +} + + +// Sets UI widget defaults which must correspond to style defaults +void KeramikConfig::defaults() +{ + ui->showAppIcons->setChecked( true ); + ui->smallCaptions->setChecked( false ); + ui->largeGrabBars->setChecked( true ); + ui->useShadowedText->setChecked( true ); + + emit changed(); +} + +// vim: set noet ts=4 sw=4: diff --git a/twin/clients/keramik/config/config.h b/twin/clients/keramik/config/config.h new file mode 100644 index 000000000..42d6f007a --- /dev/null +++ b/twin/clients/keramik/config/config.h @@ -0,0 +1,58 @@ +/* + * Keramik KWin client configuration module + * + * Copyright (C) 2002 Fredrik Hglund <fredrik@kde.org> + * + * Based on the Quartz configuration module, + * Copyright (c) 2001 Karol Szwed <gallium@kde.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the license, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __KWIN_KERAMIK_CONFIG_H +#define __KWIN_KERAMIK_CONFIG_H + +#include <kconfig.h> + +#include "keramikconfig.h" + +class KeramikConfig: public TQObject +{ + Q_OBJECT + TQ_OBJECT + + public: + KeramikConfig( KConfig* conf, TQWidget* parent ); + ~KeramikConfig(); + + // These public signals/slots work similar to KCM modules + signals: + void changed(); + + public slots: + void load( KConfig* conf ); + void save( KConfig* conf ); + void defaults(); + + private: + KeramikConfigUI *ui; + KConfig *c; +}; + + +#endif + +// vim: set noet ts=4 sw=4: diff --git a/twin/clients/keramik/config/keramikconfig.ui b/twin/clients/keramik/config/keramikconfig.ui new file mode 100644 index 000000000..dda8d5b5f --- /dev/null +++ b/twin/clients/keramik/config/keramikconfig.ui @@ -0,0 +1,76 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KeramikConfigUI</class> +<widget class="TQWidget"> + <property name="name"> + <cstring>KeramikConfigUI</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>295</width> + <height>104</height> + </rect> + </property> + <property name="caption"> + <string>Keramik</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="TQCheckBox"> + <property name="name"> + <cstring>showAppIcons</cstring> + </property> + <property name="text"> + <string>Display the window &icon in the caption bubble</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Check this option if you want the window icon to be displayed in the caption bubble next to the titlebar text.</string> + </property> + </widget> + <widget class="TQCheckBox"> + <property name="name"> + <cstring>smallCaptions</cstring> + </property> + <property name="text"> + <string>Draw &small caption bubbles on active windows</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Check this option if you want the caption bubble to have the same size on active windows that it has on inactive ones. This option is useful for laptops or low resolution displays where you want maximize the amount of space available to the window contents.</string> + </property> + </widget> + <widget class="TQCheckBox"> + <property name="name"> + <cstring>largeGrabBars</cstring> + </property> + <property name="text"> + <string>Draw g&rab bars below windows</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Check this option if you want a grab bar to be drawn below windows. When this option is not selected only a thin border will be drawn in its place.</string> + </property> + </widget> + <widget class="TQCheckBox"> + <property name="name"> + <cstring>useShadowedText</cstring> + </property> + <property name="text"> + <string>Use shadowed &text</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Check this option if you want the titlebar text to have a 3D look with a shadow behind it.</string> + </property> + </widget> + </vbox> +</widget> +<includes> + <include location="global" impldecl="in implementation">kdialog.h</include> +</includes> +<layoutdefaults spacing="6" margin="11"/> +<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/> +</UI> diff --git a/twin/clients/keramik/embedtool.cpp b/twin/clients/keramik/embedtool.cpp new file mode 100644 index 000000000..d1cbd78fd --- /dev/null +++ b/twin/clients/keramik/embedtool.cpp @@ -0,0 +1,230 @@ +/* + * Keramik KWin embed tool (version 1.0) + * + * Copyright (C) 2002 Fredrik H�glund <fredrik@kde.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the license, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <tqimage.h> +#include <tqtextstream.h> +#include <tqregexp.h> +#include <tqfile.h> +#include <tqfileinfo.h> +#include <tqdatetime.h> + +#include <iostream> + +static int primes[] = { + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, + 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, + 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, + 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, + 179, 181, 191, 193, 197, 199, 211, 223, 227, 229 +}; + +struct EmbedImage { + TQString string; + int width; + int height; + bool alpha; + TQString name; +}; + +class KeramikEmbedder { +public: + KeramikEmbedder(); + ~KeramikEmbedder(); + + void embed( const char * ); + void writeIndex(); + +private: + TQFile *file; + TQPtrList<EmbedImage> *index; + TQTextStream stream; +}; + +KeramikEmbedder::KeramikEmbedder() +{ + TQDateTime date( TQDateTime::tqcurrentDateTime() ); + TQString datestring( date.toString() ); + + file = new TQFile( "tiles.h" ); + file->open( IO_WriteOnly | IO_Truncate ); + + stream.setDevice( TQT_TQIODEVICE(file) ); + + stream << "/*\n"; + stream << " * Generated by embedtool 1.0 on " << datestring << endl; + stream << " */\n\n"; + + stream << "#ifndef __TILES_H\n"; + stream << "#define __TILES_H\n\n"; + stream << "#include <tqimage.h>\n"; + stream << "#include <tqdict.h>\n\n"; + stream << "namespace Keramik {\n\n"; + + index = new TQPtrList<EmbedImage>; + index->setAutoDelete( true ); +} + +KeramikEmbedder::~KeramikEmbedder() +{ + stream << "} // namespace Keramik\n\n"; + stream << "#endif // __TILES_H\n\n"; + stream << "// vim: set noet ts=4 sw=4:\n"; + + file->close(); + delete file; + delete index; +} + +void KeramikEmbedder::embed( const char *name ) +{ + TQFileInfo fileinfo( name ); + TQString basename( fileinfo.baseName() ); + TQString codename( basename ); + TQImage image( name ); + + codename = codename.replace( TQRegExp("[^a-zA-Z0-9]"), "_" ); + + stream << "\tstatic const QRgb " << codename << "_data[] = {" << endl << "\t\t"; + stream.setf( TQTextStream::hex | TQTextStream::right ); + stream.fill( '0' ); + + int pixels = image.width() * image.height(); + TQ_UINT32 *data = reinterpret_cast<TQ_UINT32*>( image.bits() ); + bool hasAlpha = false; + + + for ( int i = 0, j = 0; i < pixels; i++ ) { + if ( tqAlpha( *data ) && tqAlpha( *data ) != 0xff ) + hasAlpha = true; + + stream << "0x" << qSetW(8) << *(data++); + + if ( i != pixels-1 ) { + stream << ','; + + if ( j++ > 4 ) { + j = 0; + stream << endl << "\t\t"; + } else + stream << ' '; + } + } + + stream.reset(); + + stream << endl << "\t}; // " << codename << "_data" << endl << endl; + + EmbedImage *imginfo = new EmbedImage; + imginfo->width = image.width(); + imginfo->height = image.height(); + imginfo->alpha = hasAlpha; + imginfo->name = codename; + imginfo->string = basename; + index->append( imginfo ); +} + +void KeramikEmbedder::writeIndex() +{ + stream << "\tstruct EmbedImage {\n"; + stream << "\t\tconst char *name;\n"; + stream << "\t\tint width;\n"; + stream << "\t\tint height;\n"; + stream << "\t\tbool alpha;\n"; + stream << "\t\tconst QRgb *data;\n"; + stream << "\t};\n\n"; + + uint i = 0; + stream << "\tstatic const EmbedImage image_db[] = {\n"; + for ( EmbedImage *image = index->first(); image; image = index->next() ) + { + stream << "\t\t{ \"" << image->string << "\", " + << image->width << ", " << image->height << + ", " << (image->alpha ? "true" : "false") + << ", " << image->name << "_data }"; + if ( i++ < index->count() - 1 ) + stream << ','; + stream << endl; + } + stream << "\t};\n\n"; + + uint prime = 0; + + for ( i = 0; i < 50; i++ ) + if ( (prime = primes[i]) >= index->count() ) + break; + + stream << "\tclass KeramikImageDb {\n"; + stream << "\tprivate:\n"; + stream << "\t\tstatic KeramikImageDb *m_inst;\n"; + stream << "\t\tTQDict<TQImage> *db;\n\n"; + stream << "\t\tKeramikImageDb() {\n"; + stream << "\t\t\tdb = new TQDict<TQImage>( " << prime << " );\n"; + stream << "\t\t\tdb->setAutoDelete( true );\n\n"; + stream << "\t\t\tfor ( int i = 0; i < " << index->count() << "; i++ ) {\n"; + stream << "\t\t\t\tTQImage *img = new TQImage( (uchar*)image_db[i].data,\n"; + stream << "\t\t\t\t\t\timage_db[i].width, image_db[i].height,\n"; + stream << "\t\t\t\t\t\t32, NULL, 0, TQImage::LittleEndian );\n\n"; + stream << "\t\t\t\tif ( image_db[i].alpha )\n"; + stream << "\t\t\t\t\timg->setAlphaBuffer( true );\n\n"; + stream << "\t\t\t\tdb->insert( image_db[i].name, img );\n"; + stream << "\t\t\t}\n"; + stream << "\t\t}\n\n"; + stream << "\t\t~KeramikImageDb() {\n"; + stream << "\t\t\tdelete db;\n"; + stream << "\t\t}\n\n"; + stream << "\tpublic:\n"; + stream << "\t\tstatic KeramikImageDb* instance() {\n"; + stream << "\t\t\tif ( ! m_inst ) m_inst = new KeramikImageDb;\n"; + stream << "\t\t\treturn m_inst;\n"; + stream << "\t\t}\n\n"; + stream << "\t\tstatic void release() {\n"; + stream << "\t\t\tif ( m_inst ) delete m_inst;\n"; + stream << "\t\t\tm_inst = NULL;\n"; + stream << "\t\t}\n\n"; + stream << "\t\tTQImage *image( const TQString &name ) const {\n"; + stream << "\t\t\treturn db->find( name );\n"; + stream << "\t\t}\n\n"; + stream << "\t}; // class KeramikImageDb\n\n"; + stream << "\tKeramikImageDb *KeramikImageDb::m_inst = NULL;\n\n"; +} + +int main( int argv, char **argc ) +{ + if ( argv < 2 ) { + std::cout << "Insufficient arguments" << std::endl; + return 1; + } + + KeramikEmbedder embedder; + + for ( int i = 1; i < argv; i++ ) + { + std::cout << argc[i] << std::endl; + embedder.embed( argc[i] ); + } + + embedder.writeIndex(); + + return 0; +} + +// vim: set noet ts=4 sw=4: + diff --git a/twin/clients/keramik/keramik.cpp b/twin/clients/keramik/keramik.cpp new file mode 100644 index 000000000..e514e3a20 --- /dev/null +++ b/twin/clients/keramik/keramik.cpp @@ -0,0 +1,1854 @@ +/* + * + * Keramik KWin client (version 0.8) + * + * Copyright (C) 2002 Fredrik H�lund <fredrik@kde.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the license, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <kconfig.h> +#include <klocale.h> +#include <kiconeffect.h> + +#include <tqpainter.h> +#include <tqlayout.h> +#include <tqbitmap.h> +#include <tqstyle.h> +#include <tqtooltip.h> +#include <tqwidget.h> +#include <tqlabel.h> + +#include <X11/Xlib.h> +#include <X11/Xatom.h> + +#include "keramik.h" +#include "keramik.moc" + + + +// ------------------------------------------------------------------------------------------- + +static void flip( TQPixmap *&pix ) +{ + TQPixmap *tmp = new TQPixmap( pix->xForm( TQWMatrix(-1,0,0,1,pix->width(),0) ) ); + delete pix; + pix = tmp; +} + +static void flip( TQBitmap *&pix ) +{ + TQBitmap *tmp = new TQBitmap( pix->xForm( TQWMatrix(-1,0,0,1,pix->width(),0) ) ); + delete pix; + pix = tmp; +} + +namespace Keramik +{ + + const int buttonMargin = 9; // Margin between the window edge and the buttons + const int buttonSpacing = 4; // Spacing between the titlebar buttons + const int iconSpacing = 5; // Spacing between the icon and the text label + + // Default button layout + const char default_left[] = "M"; + const char default_right[] = "HIAX"; + + // Titlebar button bitmaps + const unsigned char menu_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0xf0, 0x07, 0x00, + 0xe0, 0x03, 0x00, 0xc0, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + const unsigned char on_all_desktops_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0xf0, 0x0f, 0x00, + 0xf0, 0x0f, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + const unsigned char not_on_all_desktops_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, + 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + const unsigned char help_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, + 0xf0, 0x07, 0x00, 0x30, 0x06, 0x00, 0x00, 0x07, 0x00, 0x80, 0x03, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + const unsigned char minimize_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + const unsigned char maximize_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x01, 0x00, 0xc0, 0x03, 0x00, 0xe0, 0x07, 0x00, 0xf0, 0x0f, 0x00, + 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + const unsigned char restore_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, + 0xf0, 0x0f, 0x00, 0xe0, 0x07, 0x00, 0xc0, 0x03, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + const unsigned char close_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x0c, 0x00, 0x70, 0x0e, 0x00, 0xe0, 0x07, 0x00, 0xc0, 0x03, 0x00, + 0xc0, 0x03, 0x00, 0xe0, 0x07, 0x00, 0x70, 0x0e, 0x00, 0x30, 0x0c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + const unsigned char above_on_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, + 0x80, 0x01, 0x00, 0xe0, 0x07, 0x00, 0xc0, 0x03, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; + + const unsigned char above_off_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0xc0, 0x03, 0x00, + 0xe0, 0x07, 0x00, 0x80, 0x01, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; + + const unsigned char below_on_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0xc0, 0x03, 0x00, + 0xe0, 0x07, 0x00, 0x80, 0x01, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; + + const unsigned char below_off_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, + 0x80, 0x01, 0x00, 0xe0, 0x07, 0x00, 0xc0, 0x03, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; + + const unsigned char shade_on_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, + 0x10, 0x08, 0x00, 0x10, 0x08, 0x00, 0x10, 0x08, 0x00, 0x10, 0x08, 0x00, + 0x10, 0x08, 0x00, 0x10, 0x08, 0x00, 0x10, 0x08, 0x00, 0xf0, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; + + const unsigned char shade_off_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; + + KeramikHandler *clientHandler = NULL; + bool keramik_initialized = false; + + + +// ------------------------------------------------------------------------------------------- + + + +KeramikHandler::KeramikHandler() +{ + for ( int i = 0; i < NumTiles; i++ ) { + activeTiles[i] = NULL; + inactiveTiles[i] = NULL; + } + + settings_cache = NULL; + + imageDb = KeramikImageDb::instance(); + + // Create the button deco bitmaps + buttonDecos[ Menu ] = new TQBitmap( 17, 17, menu_bits, true ); + buttonDecos[ OnAllDesktops ] = new TQBitmap( 17, 17, on_all_desktops_bits, true ); + buttonDecos[ NotOnAllDesktops ] = new TQBitmap( 17, 17, not_on_all_desktops_bits, true ); + buttonDecos[ Help ] = new TQBitmap( 17, 17, help_bits, true ); + buttonDecos[ Minimize ] = new TQBitmap( 17, 17, minimize_bits, true ); + buttonDecos[ Maximize ] = new TQBitmap( 17, 17, maximize_bits, true ); + buttonDecos[ Restore ] = new TQBitmap( 17, 17, restore_bits, true ); + buttonDecos[ Close ] = new TQBitmap( 17, 17, close_bits, true ); + buttonDecos[ AboveOn ] = new TQBitmap( 17, 17, above_on_bits, true ); + buttonDecos[ AboveOff ] = new TQBitmap( 17, 17, above_off_bits, true ); + buttonDecos[ BelowOn ] = new TQBitmap( 17, 17, below_on_bits, true ); + buttonDecos[ BelowOff ] = new TQBitmap( 17, 17, below_off_bits, true ); + buttonDecos[ ShadeOn ] = new TQBitmap( 17, 17, shade_on_bits, true ); + buttonDecos[ ShadeOff ] = new TQBitmap( 17, 17, shade_off_bits, true ); + + // Selfmask the bitmaps + for ( int i = 0; i < NumButtonDecos; i++ ) + buttonDecos[i]->setMask( *buttonDecos[i] ); + + // Flip the bitmaps horizontally in right-to-left mode + if ( TQApplication::reverseLayout() ) { + for ( int i = 0; i < Help; ++i ) + ::flip( buttonDecos[i] ); + + for ( int i = Help + 1; i < NumButtonDecos; ++i ) + ::flip( buttonDecos[i] ); + } + + readConfig(); + createPixmaps(); + + keramik_initialized = true; +} + + +KeramikHandler::~KeramikHandler() +{ + keramik_initialized = false; + destroyPixmaps(); + + for ( int i = 0; i < NumButtonDecos; i++ ) + delete buttonDecos[i]; + + delete settings_cache; + + KeramikImageDb::release(); + imageDb = NULL; + clientHandler = NULL; +} + + +void KeramikHandler::createPixmaps() +{ + int heightOffset; + int widthOffset; + switch(options()->preferredBorderSize(this)) { + case BorderLarge: + widthOffset = 4; + heightOffset = 0; + break; + case BorderVeryLarge: + widthOffset = 8; + heightOffset = 0; + break; + case BorderHuge: + widthOffset = 14; + heightOffset = 0; + break; + case BorderVeryHuge: + widthOffset = 23; + heightOffset = 10; + break; + case BorderOversized: + widthOffset = 36; + heightOffset = 25; + break; + case BorderTiny: + case BorderNormal: + default: + widthOffset = 0; + heightOffset = 0; + } + int fontHeight = TQFontMetrics(options()->font(true)).height(); + if (fontHeight > heightOffset + 20) + heightOffset = fontHeight - 20; + + TQString size = (heightOffset < 8) ? "" : (heightOffset < 20) ? "-large" : "-huge"; + + TQColor titleColor, captionColor, buttonColor; + TQImage *titleCenter = NULL, *captionLeft = NULL, + *captionRight = NULL, *captionCenter = NULL; + + + // Active tiles + // ------------------------------------------------------------------------- + captionColor = KDecoration::options()->color( ColorTitleBar, true ); + titleColor = KDecoration::options()->color( ColorTitleBlend, true ); + + // Load the titlebar corners. + activeTiles[ TitleLeft ] = loadPixmap( "titlebar-left", titleColor ); + activeTiles[ TitleRight ] = loadPixmap( "titlebar-right", titleColor ); + + // Load the titlebar center tile image (this will be used as + // the background for the caption bubble tiles). + titleCenter = loadImage( "titlebar-center", titleColor ); + + // Load the small version of the caption bubble corner & center images. + captionLeft = loadImage( "caption-small-left", captionColor ); + captionRight = loadImage( "caption-small-right", captionColor ); + captionCenter = loadImage( "caption-small-center", captionColor ); + + // Create the caption bubble tiles (by blending the images onto the titlebar) + activeTiles[ CaptionSmallLeft ] = composite( captionLeft, titleCenter ); + activeTiles[ CaptionSmallRight ] = composite( captionRight, titleCenter ); + activeTiles[ CaptionSmallCenter ] = composite( captionCenter, titleCenter ); + + delete captionLeft; + delete captionRight; + delete captionCenter; + + // Now do the same with the large version + captionLeft = loadImage( "caption-large-left", captionColor ); + captionRight = loadImage( "caption-large-right", captionColor ); + captionCenter = loadImage( "caption-large-center", captionColor ); + + activeTiles[ CaptionLargeLeft ] = composite( captionLeft, titleCenter ); + activeTiles[ CaptionLargeRight ] = composite( captionRight, titleCenter ); + activeTiles[ CaptionLargeCenter ] = composite( captionCenter, titleCenter ); + + delete captionLeft; + delete captionRight; + delete captionCenter; + + // Create the titlebar center tile + activeTiles[ TitleCenter ] = new TQPixmap( *titleCenter ); + + delete titleCenter; + + // Load the left & right border pixmaps + activeTiles[ BorderLeft ] = loadPixmap( "border-left", titleColor ); + activeTiles[ BorderRight ] = loadPixmap( "border-right", titleColor ); + + // Load the bottom grabbar pixmaps + if ( largeGrabBars ) { + activeTiles[ GrabBarLeft ] = loadPixmap( "grabbar-left", titleColor ); + activeTiles[ GrabBarRight ] = loadPixmap( "grabbar-right", titleColor ); + activeTiles[ GrabBarCenter ] = loadPixmap( "grabbar-center", titleColor ); + } else { + activeTiles[ GrabBarLeft ] = loadPixmap( "bottom-left", titleColor ); + activeTiles[ GrabBarRight ] = loadPixmap( "bottom-right", titleColor ); + activeTiles[ GrabBarCenter ] = loadPixmap( "bottom-center", titleColor ); + } + + // Inactive tiles + // ------------------------------------------------------------------------- + captionColor = KDecoration::options()->color( ColorTitleBar, false ); + titleColor = KDecoration::options()->color( ColorTitleBlend, false ); + + inactiveTiles[ TitleLeft ] = loadPixmap( "titlebar-left", titleColor ); + inactiveTiles[ TitleRight ] = loadPixmap( "titlebar-right", titleColor ); + + titleCenter = loadImage( "titlebar-center", titleColor ); + + captionLeft = loadImage( "caption-small-left", captionColor ); + captionRight = loadImage( "caption-small-right", captionColor ); + captionCenter = loadImage( "caption-small-center", captionColor ); + + inactiveTiles[ CaptionSmallLeft ] = composite( captionLeft, titleCenter ); + inactiveTiles[ CaptionSmallRight ] = composite( captionRight, titleCenter ); + inactiveTiles[ CaptionSmallCenter ] = composite( captionCenter, titleCenter ); + + delete captionLeft; + delete captionRight; + delete captionCenter; + + inactiveTiles[ TitleCenter ] = new TQPixmap( *titleCenter ); + + delete titleCenter; + + inactiveTiles[ BorderLeft ] = loadPixmap( "border-left", titleColor ); + inactiveTiles[ BorderRight ] = loadPixmap( "border-right", titleColor ); + + if ( largeGrabBars ) { + inactiveTiles[ GrabBarLeft ] = loadPixmap( "grabbar-left", titleColor ); + inactiveTiles[ GrabBarRight ] = loadPixmap( "grabbar-right", titleColor ); + inactiveTiles[ GrabBarCenter ] = loadPixmap( "grabbar-center", titleColor ); + } else { + inactiveTiles[ GrabBarLeft ] = loadPixmap( "bottom-left", titleColor ); + inactiveTiles[ GrabBarRight ] = loadPixmap( "bottom-right", titleColor ); + inactiveTiles[ GrabBarCenter ] = loadPixmap( "bottom-center", titleColor ); + } + + // Buttons + // ------------------------------------------------------------------------- + buttonColor = TQColor(); //KDecoration::options()->color( ButtonBg, true ); + + titleButtonRound = loadPixmap( "titlebutton-round"+size, buttonColor ); + titleButtonSquare = loadPixmap( "titlebutton-square"+size, buttonColor ); + + + // Prepare the tiles for use + // ------------------------------------------------------------------------- + if ( TQApplication::reverseLayout() ) { + + // Fix lighting + flip( activeTiles[CaptionSmallLeft], activeTiles[CaptionSmallRight] ); + flip( inactiveTiles[CaptionSmallLeft], inactiveTiles[CaptionSmallRight] ); + + flip( activeTiles[CaptionLargeLeft], activeTiles[CaptionLargeRight] ); + + flip( activeTiles[TitleLeft], activeTiles[TitleRight] ); + flip( inactiveTiles[TitleLeft], inactiveTiles[TitleRight] ); + + flip( activeTiles[BorderLeft], activeTiles[BorderRight] ); + flip( inactiveTiles[BorderLeft], inactiveTiles[BorderRight] ); + + flip( activeTiles[GrabBarLeft], activeTiles[GrabBarRight] ); + flip( inactiveTiles[GrabBarLeft], inactiveTiles[GrabBarRight] ); + + ::flip( titleButtonRound ); + ::flip( titleButtonSquare ); + } + + // Pretile the center & border tiles for optimal performance + pretile( activeTiles[ CaptionSmallCenter ], 64, Qt::Horizontal ); + pretile( activeTiles[ CaptionLargeCenter ], 64, Qt::Horizontal ); + pretile( activeTiles[ TitleCenter ], 64, Qt::Horizontal ); + pretile( activeTiles[ GrabBarCenter ], 128, Qt::Horizontal ); + pretile( activeTiles[ BorderLeft ], 128, Qt::Vertical ); + pretile( activeTiles[ BorderRight ], 128, Qt::Vertical ); + + pretile( inactiveTiles[ CaptionSmallCenter ], 64, Qt::Horizontal ); + pretile( inactiveTiles[ TitleCenter ], 64, Qt::Horizontal ); + pretile( inactiveTiles[ GrabBarCenter ], 128, Qt::Horizontal ); + pretile( inactiveTiles[ BorderLeft ], 128, Qt::Vertical ); + pretile( inactiveTiles[ BorderRight ], 128, Qt::Vertical ); + + if (heightOffset > 0) { + addHeight (heightOffset, activeTiles[TitleLeft]); + addHeight (heightOffset, activeTiles[TitleCenter]); + addHeight (heightOffset, activeTiles[TitleRight]); + addHeight (heightOffset, activeTiles[CaptionSmallLeft]); + addHeight (heightOffset, activeTiles[CaptionSmallCenter]); + addHeight (heightOffset, activeTiles[CaptionSmallRight]); + addHeight (heightOffset, activeTiles[CaptionLargeLeft]); + addHeight (heightOffset, activeTiles[CaptionLargeCenter]); + addHeight (heightOffset, activeTiles[CaptionLargeRight]); + + addHeight (heightOffset, inactiveTiles[TitleLeft]); + addHeight (heightOffset, inactiveTiles[TitleCenter]); + addHeight (heightOffset, inactiveTiles[TitleRight]); + addHeight (heightOffset, inactiveTiles[CaptionSmallLeft]); + addHeight (heightOffset, inactiveTiles[CaptionSmallCenter]); + addHeight (heightOffset, inactiveTiles[CaptionSmallRight]); + } + + if (widthOffset > 0) { + addWidth (widthOffset, activeTiles[BorderLeft], true, activeTiles[GrabBarCenter]); + addWidth (widthOffset, activeTiles[BorderRight], false, activeTiles[GrabBarCenter]); + addWidth (widthOffset, inactiveTiles[BorderLeft], true, inactiveTiles[GrabBarCenter]); + addWidth (widthOffset, inactiveTiles[BorderRight], false, inactiveTiles[GrabBarCenter]); + + if (largeGrabBars) + widthOffset = widthOffset*3/2; + + addHeight (widthOffset, activeTiles[GrabBarLeft]); + addHeight (widthOffset, activeTiles[GrabBarCenter]); + addHeight (widthOffset, activeTiles[GrabBarRight]); + addHeight (widthOffset, inactiveTiles[GrabBarLeft]); + addHeight (widthOffset, inactiveTiles[GrabBarCenter]); + addHeight (widthOffset, inactiveTiles[GrabBarRight]); + } +} + + + +void KeramikHandler::destroyPixmaps() +{ + for ( int i = 0; i < NumTiles; i++ ) { + delete activeTiles[i]; + delete inactiveTiles[i]; + activeTiles[i] = NULL; + inactiveTiles[i] = NULL; + } + + delete titleButtonRound; + delete titleButtonSquare; +} + + +void KeramikHandler::addWidth (int width, TQPixmap *&pix, bool left, TQPixmap *bottomPix) { + int w = pix->width()+width; + int h = pix->height(); + + TQPixmap *tmp = new TQPixmap (w, h); + tmp->fill (); + TQPainter p; + p.begin (tmp); + + for (int i = 0; i < h; i++) + p.drawPixmap (0, i, *bottomPix, i%2, 0, w,1); + + if (left) + p.drawPixmap(0, 0, *pix); + else + p.drawPixmap(width, 0, *pix); + + p.end(); + + delete pix; + pix = tmp; +} + + +void KeramikHandler::addHeight (int height, TQPixmap *&pix) { + int w = pix->width(); + int h = pix->height()+height; + + TQPixmap *tmp = new TQPixmap (w, h); + TQPainter p; + p.begin (tmp); + if (pix->height() > 10) { + p.drawPixmap(0, 0, *pix, 0, 0, w, 11); + for (int i = 0; i < height; i+=2) + p.drawPixmap(0, 11+i, *pix, 0, 11, w, 2); + p.drawPixmap(0, 11+height, *pix, 0, 11, w, -1); + } + else { + int lines = h-3; + int factor = pix->height()-3; + for (int i = 0; i < lines; i++) + p.drawPixmap(0, i, *pix, 0, i*factor/lines, w, 1); + p.drawPixmap(0, lines, *pix, 0, factor, w, 3); + } + p.end(); + + delete pix; + pix = tmp; +} + + +void KeramikHandler::flip( TQPixmap *&pix1, TQPixmap *&pix2 ) +{ + // Flip the pixmaps horizontally + TQPixmap *tmp = new TQPixmap( pix1->xForm( TQWMatrix(-1,0,0,1,pix1->width(),0) ) ); + + delete pix1; + pix1 = new TQPixmap( pix2->xForm( TQWMatrix(-1,0,0,1,pix2->width(),0) ) ); + + delete pix2; + pix2 = tmp; +} + + +void KeramikHandler::pretile( TQPixmap *&pix, int size, Qt::Orientation dir ) +{ + TQPixmap *newpix; + TQPainter p; + + if ( dir == Qt::Horizontal ) + newpix = new TQPixmap( size, pix->height() ); + else + newpix = new TQPixmap( pix->width(), size ); + + p.begin( newpix ); + p.drawTiledPixmap( newpix->rect(), *pix ) ; + p.end(); + + delete pix; + pix = newpix; +} + + +void KeramikHandler::readConfig() +{ + KConfig *c = new KConfig( "twinkeramikrc" ); + + c->setGroup( "General" ); + showIcons = c->readBoolEntry( "ShowAppIcons", true ); + shadowedText = c->readBoolEntry( "UseShadowedText", true ); + smallCaptionBubbles = c->readBoolEntry( "SmallCaptionBubbles", false ); + largeGrabBars = c->readBoolEntry( "LargeGrabBars", true ); + + if ( ! settings_cache ) { + settings_cache = new SettingsCache; + settings_cache->largeGrabBars = largeGrabBars; + settings_cache->smallCaptionBubbles = smallCaptionBubbles; + } + + delete c; +} + + +TQPixmap *KeramikHandler::composite( TQImage *over, TQImage *under ) +{ + TQImage dest( over->width(), over->height(), 32 ); + int width = over->width(), height = over->height(); + + // Clear the destination image + TQ_UINT32 *data = reinterpret_cast<TQ_UINT32*>( dest.bits() ); + for (int i = 0; i < width * height; i++) + *(data++) = 0; + + // Copy the under image (bottom aligned) to the destination image + for (int y1 = height - under->height(), y2 = 0; y1 < height; y1++, y2++ ) + { + register TQ_UINT32 *dst = reinterpret_cast<TQ_UINT32*>( dest.scanLine(y1) ); + register TQ_UINT32 *src = reinterpret_cast<TQ_UINT32*>( under->scanLine(y2) ); + + for ( int x = 0; x < width; x++ ) + *(dst++) = *(src++); + } + + // Blend the over image onto the destination + register TQ_UINT32 *dst = reinterpret_cast<TQ_UINT32*>( dest.bits() ); + register TQ_UINT32 *src = reinterpret_cast<TQ_UINT32*>( over->bits() ); + for ( int i = 0; i < width * height; i++ ) + { + int r1 = tqRed( *dst ), g1 = tqGreen( *dst ), b1 = tqBlue( *dst ); + int r2 = tqRed( *src ), g2 = tqGreen( *src ), b2 = tqBlue( *src ); + int a = tqAlpha( *src ); + + if ( a == 0xff ) + *dst = *src; + + else if ( a != 0x00 ) + *dst = tqRgba( TQ_UINT8( r1 + (((r2 - r1) * a) >> 8) ), + TQ_UINT8( g1 + (((g2 - g1) * a) >> 8) ), + TQ_UINT8( b1 + (((b2 - b1) * a) >> 8) ), + 0xff ); + + else if ( tqAlpha(*dst) == 0x00 ) + *dst = 0; + + src++; dst++; + } + + // Create the final pixmap and return it + return new TQPixmap( dest ); +} + + +TQImage *KeramikHandler::loadImage( const TQString &name, const TQColor &col ) +{ + if ( col.isValid() ) { + TQImage *img = new TQImage( imageDb->image(name)->copy() ); + KIconEffect::colorize( *img, col, 1.0 ); + return img; + } else + return new TQImage( imageDb->image(name)->copy() ); +} + + +TQPixmap *KeramikHandler::loadPixmap( const TQString &name, const TQColor &col ) +{ + TQImage *img = loadImage( name, col ); + TQPixmap *pix = new TQPixmap( *img ); + delete img; + + return pix; +} + + +bool KeramikHandler::reset( unsigned long changed ) +{ + keramik_initialized = false; + + bool needHardReset = false; + bool pixmapsInvalid = false; + + // Re-read the config file + readConfig(); + + if ( changed & SettingBorder ) + { + pixmapsInvalid = true; + needHardReset = true; + } + if ( changed & SettingFont ) + { + pixmapsInvalid = true; + needHardReset = true; + } + // Check if the color scheme has changed + if ( changed & SettingColors ) + { + pixmapsInvalid = true; + } + // Check if button positions have changed + + if ( changed & SettingButtons ) { + needHardReset = true; + } + + // Check if tooltips options have changed + if ( changed & SettingTooltips ) { + needHardReset = true; + } + + if ( (settings_cache->largeGrabBars != largeGrabBars) ) { + pixmapsInvalid = true; + needHardReset = true; + } + + if ( (settings_cache->smallCaptionBubbles != smallCaptionBubbles) ) { + needHardReset = true; + } + + // Update our config cache + settings_cache->largeGrabBars = largeGrabBars; + settings_cache->smallCaptionBubbles = smallCaptionBubbles; + + // Do we need to recreate the pixmaps? + if ( pixmapsInvalid ) { + destroyPixmaps(); + createPixmaps(); + } + + keramik_initialized = true; + + // Do we need to "hit the wooden hammer" ? + if ( !needHardReset ) + resetDecorations( changed ); + return needHardReset; +} + + +bool KeramikHandler::supports( Ability ability ) +{ + switch( ability ) + { + case AbilityAnnounceButtons: + case AbilityButtonMenu: + case AbilityButtonOnAllDesktops: + case AbilityButtonSpacer: + case AbilityButtonHelp: + case AbilityButtonMinimize: + case AbilityButtonMaximize: + case AbilityButtonClose: + case AbilityButtonAboveOthers: + case AbilityButtonBelowOthers: + case AbilityButtonShade: + return true; + default: + return false; + }; +} + + +const TQPixmap *KeramikHandler::tile( TilePixmap tilePix, bool active ) const +{ + return ( active ? activeTiles[ tilePix ] : inactiveTiles[ tilePix ] ); +} + +KDecoration* KeramikHandler::createDecoration( KDecorationBridge* bridge ) +{ + return new KeramikClient( bridge, this ); +} + +TQValueList< KeramikHandler::BorderSize > KeramikHandler::borderSizes() const +{ // the list must be sorted + return TQValueList< BorderSize >() << BorderNormal << BorderLarge << + BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized; +} + + +// ------------------------------------------------------------------------------------------- + + + +KeramikButton::KeramikButton( KeramikClient* c, const char *name, Button btn, const TQString &tip, const int realizeBtns ) + : TQButton( c->widget(), name ), + client( c ), button( btn ), hover( false ), lastbutton( Qt::NoButton ) +{ + realizeButtons = realizeBtns; + + TQToolTip::add( this, tip ); // FRAME + setBackgroundMode( NoBackground ); + setCursor( tqarrowCursor ); + int size = clientHandler->roundButton()->height(); + setFixedSize( size, size ); + + setToggleButton( (button == OnAllDesktopsButton) ); +} + + +KeramikButton::~KeramikButton() +{ + // Empty. +} + + +void KeramikButton::enterEvent( TQEvent *e ) +{ + TQButton::enterEvent( e ); + + hover = true; + tqrepaint( false ); +} + + +void KeramikButton::leaveEvent( TQEvent *e ) +{ + TQButton::leaveEvent( e ); + + hover = false; + tqrepaint( false ); +} + + +void KeramikButton::mousePressEvent( TQMouseEvent *e ) +{ + lastbutton = e->button(); + TQMouseEvent me( e->type(), e->pos(), e->globalPos(), (e->button()&realizeButtons)?Qt::LeftButton:Qt::NoButton, e->state() ); + TQButton::mousePressEvent( &me ); +} + + +void KeramikButton::mouseReleaseEvent( TQMouseEvent *e ) +{ + lastbutton = e->button(); + TQMouseEvent me( e->type(), e->pos(), e->globalPos(), (e->button()&realizeButtons)?Qt::LeftButton:Qt::NoButton, e->state() ); + TQButton::mouseReleaseEvent( &me ); +} + + +void KeramikButton::drawButton( TQPainter *p ) +{ + const TQPixmap *pix; + const TQBitmap *deco; + int size = clientHandler->roundButton()->height(); + + // Get the bevel from the client handler + if ( button == MenuButton || button == OnAllDesktopsButton || button == HelpButton ) + pix = clientHandler->roundButton(); + else + pix = clientHandler->squareButton(); + + // Draw the button background + const TQPixmap *background = clientHandler->tile( TitleCenter, client->isActive() ); + p->drawPixmap( 0, 0, *background, + 0, (background->height()-size+1)/2, size, size ); + + if ( isDown() ) { + // Pressed + p->drawPixmap( TQPoint(), *pix, TQStyle::tqvisualRect( TQRect(2*size, 0, size, size), pix->rect() ) ); + p->translate( TQApplication::reverseLayout() ? -1 : 1, 1 ); + } else if ( hover ) + // Mouse over + p->drawPixmap( TQPoint(), *pix, TQStyle::tqvisualRect( TQRect(size, 0, size, size), pix->rect() ) ); + else + // Normal + p->drawPixmap( TQPoint(), *pix, TQStyle::tqvisualRect( TQRect(0, 0, size, size), pix->rect() ) ); + + + // Draw the button deco on the bevel + switch ( button ) { + case MenuButton: + deco = clientHandler->buttonDeco( Menu ); + break; + + case OnAllDesktopsButton: + deco = clientHandler->buttonDeco( client->isOnAllDesktops() ? NotOnAllDesktops : OnAllDesktops ); + break; + + case HelpButton: + deco = clientHandler->buttonDeco( Help ); + // The '?' won't be flipped around in the ctor, so we need to + // shift it to the right to compensate for the button shadow + // being on the left side of the button in RTL mode. + if ( TQApplication::reverseLayout() ) + p->translate( 2, 0 ); + break; + + case MinButton: + deco = clientHandler->buttonDeco( Minimize ); + break; + + case MaxButton: + deco = clientHandler->buttonDeco( client->maximizeMode() == KeramikClient::MaximizeFull ? Restore : Maximize ); + break; + + case CloseButton: + deco = clientHandler->buttonDeco( Close ); + break; + + case AboveButton: + deco = clientHandler->buttonDeco( client->keepAbove() ? AboveOn : AboveOff ); + break; + + case BelowButton: + deco = clientHandler->buttonDeco( client->keepBelow() ? BelowOn : BelowOff ); + break; + + case ShadeButton: + deco = clientHandler->buttonDeco( client->isSetShade() ? ShadeOn : ShadeOff ); + break; + + default: + deco = NULL; + } + + p->setPen( Qt::black ); // ### hardcoded color + p->drawPixmap( (size-17)/2, (size-17)/2, *deco ); +} + + + +// ------------------------------------------------------------------------------------------ + + + +KeramikClient::KeramikClient( KDecorationBridge* bridge, KDecorationFactory* factory ) + : KDecoration( bridge, factory ), + activeIcon( NULL ), inactiveIcon( NULL ), captionBufferDirty( true ), maskDirty( true ) +{ +} + +void KeramikClient::init() +{ + connect( this, TQT_SIGNAL( keepAboveChanged( bool )), TQT_SLOT( keepAboveChange( bool ))); + connect( this, TQT_SIGNAL( keepBelowChanged( bool )), TQT_SLOT( keepBelowChange( bool ))); + + createMainWidget( (WFlags)(WStaticContents | WResizeNoErase | WRepaintNoErase) ); + widget()->installEventFilter( this ); + + // Minimize flicker + widget()->setBackgroundMode( NoBackground ); + + for ( int i=0; i < NumButtons; i++ ) + button[i] = NULL; + + createLayout(); +} + +void KeramikClient::createLayout() +{ + + TQVBoxLayout *mainLayout = new TQVBoxLayout( widget() ); + TQBoxLayout *titleLayout = new TQBoxLayout( 0, TQBoxLayout::LeftToRight, 0, 0, 0 ); + TQHBoxLayout *windowLayout = new TQHBoxLayout(); + + largeTitlebar = ( !maximizedVertical() && clientHandler->largeCaptionBubbles() ); + largeCaption = ( isActive() && largeTitlebar ); + + int grabBarHeight = clientHandler->grabBarHeight(); + int topSpacing = ( largeTitlebar ? 4 : 1 ); + int leftBorderWidth = clientHandler->tile( BorderLeft, true )->width(); + int rightBorderWidth = clientHandler->tile( BorderRight, true )->width(); + topSpacer = new TQSpacerItem( 10, topSpacing, + TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + + mainLayout->addItem( topSpacer ); + + mainLayout->addLayout( titleLayout ); // Titlebar + mainLayout->addLayout( windowLayout, 1 ); // Left border + window + right border + mainLayout->addSpacing( grabBarHeight ); // Bottom grab bar + + titleLayout->setSpacing( buttonSpacing ); + + titleLayout->addSpacing( buttonMargin ); // Left button margin + addButtons( titleLayout, options()->customButtonPositions() ? + options()->titleButtonsLeft() : TQString(default_left) ); + + titlebar = new TQSpacerItem( 10, clientHandler->titleBarHeight(largeTitlebar) + - topSpacing, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + titleLayout->addItem( titlebar ); + + titleLayout->addSpacing( buttonSpacing ); + addButtons( titleLayout, options()->customButtonPositions() ? + options()->titleButtonsRight() : TQString(default_right) ); + titleLayout->addSpacing( buttonMargin - 1 ); // Right button margin + + windowLayout->addSpacing( leftBorderWidth ); // Left border + if( isPreview()) + windowLayout->addWidget( new TQLabel( i18n( "<center><b>Keramik preview</b></center>" ), widget())); + else + windowLayout->addItem( new TQSpacerItem( 0, 0 )); //no widget in the middle + windowLayout->addSpacing( rightBorderWidth ); // Right border +} + + +KeramikClient::~KeramikClient() +{ + delete activeIcon; + delete inactiveIcon; + + activeIcon = inactiveIcon = NULL; +} + + +void KeramikClient::reset( unsigned long ) +{ + if ( clientHandler->largeCaptionBubbles() && !largeTitlebar ) + { + // We're switching from small caption bubbles to large + if ( !maximizedVertical() ) { + topSpacer->changeSize( 10, 4, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + largeTitlebar = true; + largeCaption = isActive(); + + widget()->layout()->activate(); + + // Compensate for the titlebar size change + + // TODO This is wrong, this may break size increments (see bug #53784). + // FRAME + widget()->setGeometry( widget()->x(), widget()->y() - 3, width(), height() + 3 ); + } + } + else if ( !clientHandler->largeCaptionBubbles() && largeTitlebar ) + { + // We're switching from large caption bubbles to small + topSpacer->changeSize( 10, 1, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + largeTitlebar = largeCaption = false; + + widget()->layout()->activate(); + + // Compensate for the titlebar size change + // FRAME + widget()->setGeometry( widget()->x(), widget()->y() + 3, width(), height() - 3 ); + } + + calculateCaptionRect(); + + captionBufferDirty = maskDirty = true; + + // Only tqrepaint the window if it's visible + // (i.e. not minimized and on the current desktop) + if ( widget()->isVisible() ) { + widget()->tqrepaint( false ); + + for ( int i = 0; i < NumButtons; i++ ) + if ( button[i] ) button[i]->tqrepaint( false ); + } +} + +bool KeramikClient::isModalSystemNotification() +{ + unsigned char *data = 0; + Atom actual; + int format, result; + unsigned long n, left; + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(qt_xdisplay(), "_KDE_WM_MODAL_SYS_NOTIFICATION", False); + result = XGetWindowProperty(qt_xdisplay(), windowId(), kde_wm_system_modal_notification, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, /*(unsigned char **)*/ &data); + if (result == Success && data != None && format == 32 ) + { + return TRUE; + } + return FALSE; +} + +void KeramikClient::addButtons( TQBoxLayout *layout, const TQString &s ) +{ + for ( uint i=0; i < s.length(); i++ ) + { + switch ( s[i].latin1() ) + { + // Menu button + case 'M' : + if (!isModalSystemNotification()) { + if ( !button[MenuButton] ) { + button[MenuButton] = new KeramikButton( this, "menu", MenuButton, i18n("Menu"), Qt::LeftButton|Qt::RightButton ); + connect( button[MenuButton], TQT_SIGNAL( pressed() ), TQT_SLOT( menuButtonPressed() ) ); + layout->addWidget( button[MenuButton] ); + } + } + break; + + // OnAllDesktops button + case 'S' : + if (!isModalSystemNotification()) { + if ( !button[OnAllDesktopsButton] ) { + button[OnAllDesktopsButton] = new KeramikButton( this, "on_all_desktops", + OnAllDesktopsButton, isOnAllDesktops()?i18n("Not on all desktops"):i18n("On all desktops") ); + if(isOnAllDesktops()) + button[OnAllDesktopsButton]->toggle(); + connect( button[OnAllDesktopsButton], TQT_SIGNAL( clicked() ), TQT_SLOT( toggleOnAllDesktops() ) ); + layout->addWidget( button[OnAllDesktopsButton] ); + } + } + break; + + // Help button + case 'H' : + if ( !button[HelpButton] && providesContextHelp() ) { + button[HelpButton] = new KeramikButton( this, "help", HelpButton, i18n("Help") ); + connect( button[HelpButton], TQT_SIGNAL( clicked() ), TQT_SLOT( showContextHelp() ) ); + layout->addWidget( button[HelpButton] ); + } + break; + + // Minimize button + case 'I' : + if ( !button[MinButton] && isMinimizable() ) { + button[MinButton] = new KeramikButton( this, "minimize", MinButton, i18n("Minimize") ); + connect( button[MinButton], TQT_SIGNAL( clicked() ), TQT_SLOT( minimize() ) ); + layout->addWidget( button[MinButton] ); + } + break; + + // Maximize button + case 'A' : + if ( !button[MaxButton] && isMaximizable() ) { + button[MaxButton] = new KeramikButton( this, "maximize", MaxButton, i18n("Maximize"), Qt::LeftButton|Qt::MidButton|Qt::RightButton ); + connect( button[MaxButton], TQT_SIGNAL( clicked() ), TQT_SLOT( slotMaximize() ) ); + layout->addWidget( button[MaxButton] ); + } + break; + + // Close button + case 'X' : + if ( !button[CloseButton] && isCloseable() ) { + button[CloseButton] = new KeramikButton( this, "close", CloseButton, i18n("Close") ); + connect( button[CloseButton], TQT_SIGNAL( clicked() ), TQT_SLOT( closeWindow() ) ); + layout->addWidget( button[CloseButton] ); + } + break; + + // Above button + case 'F' : + if ( !button[AboveButton]) { + button[AboveButton] = new KeramikButton( this, "above", AboveButton, i18n("Keep Above Others") ); + connect( button[AboveButton], TQT_SIGNAL( clicked() ), TQT_SLOT( slotAbove() ) ); + layout->addWidget( button[AboveButton] ); + } + break; + + // Below button + case 'B' : + if ( !button[BelowButton]) { + button[BelowButton] = new KeramikButton( this, "below", BelowButton, i18n("Keep Below Others") ); + connect( button[BelowButton], TQT_SIGNAL( clicked() ), TQT_SLOT( slotBelow() ) ); + layout->addWidget( button[BelowButton] ); + } + break; + + // Shade button + case 'L' : + if ( !button[ShadeButton] && isShadeable() ) { + button[ShadeButton] = new KeramikButton( this, "shade", ShadeButton, + isSetShade() ? i18n("Unshade") : i18n( "Shade" )); + connect( button[ShadeButton], TQT_SIGNAL( clicked() ), TQT_SLOT( slotShade() ) ); + layout->addWidget( button[ShadeButton] ); + } + break; + + // Additional spacing + case '_' : + layout->addSpacing( buttonSpacing ); + break; + } + } +} + + +void KeramikClient::updateMask() +{ + if ( !keramik_initialized ) + return; + + // To maximize performance this code uses precalculated bounding rects + // to set the window mask. This saves us from having to allocate a 1bpp + // pixmap, paint the mask on it and then have the X server iterate + // over the pixels to compute the bounding rects from it. + + TQRegion r; + register int w, y = 0; + int nrects; + + if ( TQApplication::reverseLayout() ) { + + // If the caption bubble is visible and extends above the titlebar + if ( largeCaption && captionRect.width() >= 25 ) { + register int x = captionRect.left(); + w = captionRect.width(); + r += TQRegion( x + 11, y++, w - 19, 1 ); + r += TQRegion( x + 9, y++, w - 15, 1 ); + r += TQRegion( x + 7, y++, w - 12, 1 ); + } else { + nrects = 8; + + // Do we have a large titlebar with a retracted caption bubble? + // (i.e. the style is set to use large caption bubbles, we're + // not maximized and not active) + if ( largeTitlebar ) + y = 3; + } + + w = width(); // FRAME + + // The rounded titlebar corners + r += TQRegion( 9, y++, w - 17, 1 ); + r += TQRegion( 7, y++, w - 13, 1 ); + r += TQRegion( 5, y++, w - 9, 1 ); + r += TQRegion( 4, y++, w - 7, 1 ); + r += TQRegion( 3, y++, w - 5, 1 ); + r += TQRegion( 2, y++, w - 4, 1 ); + r += TQRegion( 1, y++, w - 2, 2 ); + } else { + + // If the caption bubble is visible and extends above the titlebar + if ( largeCaption && captionRect.width() >= 25 ) { + nrects = 11; + register int x = captionRect.left(); + w = captionRect.width(); + r += TQRegion( x + 8, y++, w - 19, 1 ); + r += TQRegion( x + 6, y++, w - 15, 1 ); + r += TQRegion( x + 5, y++, w - 12, 1 ); + } else { + nrects = 8; + + // Do we have a large titlebar with a retracted caption bubble? + // (i.e. the style is set to use large caption bubbles, we're + // not maximized and not active) + if ( largeTitlebar ) + y = 3; + } + + w = width(); // FRAME + + // The rounded titlebar corners + r += TQRegion( 8, y++, w - 17, 1 ); + r += TQRegion( 6, y++, w - 13, 1 ); + r += TQRegion( 4, y++, w - 9, 1 ); + r += TQRegion( 3, y++, w - 7, 1 ); + r += TQRegion( 2, y++, w - 5, 1 ); + r += TQRegion( 2, y++, w - 4, 1 ); + r += TQRegion( 1, y++, w - 2, 2 ); + } + + y++; + + // The part of the window below the titlebar + r += TQRegion( 0, y, w, height() - y ); + + setMask( r, YXBanded ); + + maskDirty = false; +} + + +void KeramikClient::updateCaptionBuffer() +{ + if ( !keramik_initialized ) + return; + + bool active = isActive(); + TQPixmap *icon = NULL; + + if ( captionBuffer.size() != captionRect.size() ) + captionBuffer.resize( captionRect.size() ); + + if ( captionBuffer.isNull() ) + return; + + TQPainter p( &captionBuffer ); + + // Draw the caption bubble + if ( active && largeCaption ) { + p.drawPixmap( 0, 0, *clientHandler->tile( CaptionLargeLeft, true ) ); + p.drawTiledPixmap( 15, 0, captionRect.width() - 30, captionRect.height(), + *clientHandler->tile( CaptionLargeCenter, true ) ); + p.drawPixmap( captionRect.width() - 15, 0, *clientHandler->tile( CaptionLargeRight, true ) ); + } else { + p.drawPixmap( 0, 0, *clientHandler->tile( CaptionSmallLeft, active ) ); + p.drawTiledPixmap( 15, 0, captionRect.width() - 30, captionRect.height(), + *clientHandler->tile( CaptionSmallCenter, active ) ); + p.drawPixmap( captionRect.width() - 15, 0, *clientHandler->tile( CaptionSmallRight, active ) ); + } + + if ( clientHandler->showAppIcons() ) + { + if ( active ) { + if ( ! activeIcon ) + activeIcon = new TQPixmap( this->icon().pixmap( TQIconSet::Small, TQIconSet::Normal )); // FRAME + icon = activeIcon; + } else { + if ( ! inactiveIcon ) { + TQImage img = this->icon().pixmap( TQIconSet::Small, TQIconSet::Normal ).convertToImage(); + KIconEffect::semiTransparent( img ); + inactiveIcon = new TQPixmap( img ); + } + icon = inactiveIcon; + } + } + + p.setFont( options()->font( active ) ); + int tw = p.fontMetrics().width( caption() ) + + ( clientHandler->showAppIcons() ? 16 + iconSpacing : 0 ); + + int xpos = QMAX( (captionRect.width() - tw) / 3, 8 ); + TQRect tr = TQStyle::tqvisualRect( TQRect(xpos, 1, captionRect.width() - xpos - 10, + captionRect.height() - 4), captionBuffer.rect() ); + + //p.setPen( Qt::red ); // debug + //p.drawRect( tr ); // debug + + // Application icon + if ( clientHandler->showAppIcons() ) + { + TQRect iconRect = TQStyle::tqvisualRect( TQRect(tr.x(), + 1 + (captionRect.height() - 4 - 16) / 2, 16, 16), tr ); + TQRect r( icon->rect() ); + r.moveCenter( iconRect.center() ); + + if ( tr.width() > 16 ) { + p.drawPixmap( r, *icon ); + } else { + TQRect sr( 0, 0, icon->width(), icon->height() ); + + if ( TQApplication::reverseLayout() ) + sr.addCoords( icon->width() - tr.width(), 0, 0, 0 ); + else + sr.addCoords( 0, 0, -( icon->width() - tr.width() ), 0 ); + + p.drawPixmap( r.x() + sr.x(), r.y() + sr.y(), *icon, + sr.x(), sr.y(), sr.width(), sr.height() ); + } + + //p.drawRect( r ); // debug + + if ( TQApplication::reverseLayout() ) + tr.addCoords( 0, 0, -(16 + iconSpacing), 0 ); + else + tr.addCoords( (16 + iconSpacing), 0, 0, 0 ); + } + + // Draw the titlebar text + int flags = AlignVCenter | SingleLine; + flags |= ( TQApplication::reverseLayout() ? AlignRight : AlignLeft ); + + if ( clientHandler->useShadowedText() ) + { + p.translate( TQApplication::reverseLayout() ? -1 : 1, 1 ); + //p.setPen( options()->color(ColorTitleBar, active).dark() ); + if (tqGray(options()->color(ColorFont, active).rgb()) < 100) + p.setPen( TQColor(200,200,200) ); + else + p.setPen( black ); + p.drawText( tr, flags, caption() ); + p.translate( TQApplication::reverseLayout() ? 1 : -1, -1 ); + } + + p.setPen( options()->color( ColorFont, active ) ); + p.drawText( tr, flags, caption() ); + + captionBufferDirty = false; +} + + +void KeramikClient::calculateCaptionRect() +{ + TQFontMetrics fm( options()->font(isActive()) ); + int cw = fm.width( caption() ) + 95; + int titleBaseY = ( largeTitlebar ? 3 : 0 ); + + if ( clientHandler->showAppIcons() ) + cw += 16 + 4; // icon width + space + + cw = QMIN( cw, titlebar->geometry().width() ); + captionRect = TQStyle::tqvisualRect( TQRect(titlebar->geometry().x(), (largeCaption ? 0 : titleBaseY), + cw, clientHandler->titleBarHeight(largeCaption) ), + titlebar->geometry() ); +} + + +void KeramikClient::captionChange() +{ + TQRect r( captionRect ); + calculateCaptionRect(); + + if ( r.size() != captionRect.size() ) + maskDirty = true; + + captionBufferDirty = true; + + widget()->tqrepaint( r | captionRect, false ); +} + + +void KeramikClient::iconChange() +{ + if ( clientHandler->showAppIcons() ) { + + // Force updateCaptionBuffer() to recreate the cached icons + delete activeIcon; + + delete inactiveIcon; + + activeIcon = inactiveIcon = NULL; + + captionBufferDirty = true; + widget()->tqrepaint( captionRect, false ); + } +} + + +void KeramikClient::activeChange() +{ + bool active = isActive(); + // Note: It's assumed that the same font will always be used for both active + // and inactive windows, since the fonts kcm hasn't supported setting + // different fonts for different window states for some time. + if ( largeTitlebar ) { + largeCaption = ( active && !maximizedVertical() ); + calculateCaptionRect(); + maskDirty = true; + } + + captionBufferDirty = true; + + widget()->tqrepaint( false ); + + for ( int i=0; i < NumButtons; i++ ) + if ( button[i] ) button[i]->tqrepaint( false ); +} + + +void KeramikClient::maximizeChange() +{ + if ( clientHandler->largeCaptionBubbles() ) + { + if ( maximizeMode() & MaximizeVertical ) { + // We've been maximized - shrink the titlebar by 3 pixels + topSpacer->changeSize( 10, 1, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + largeCaption = largeTitlebar = false; + + calculateCaptionRect(); + captionBufferDirty = maskDirty = true; + + widget()->layout()->activate(); + widget()->tqrepaint( false ); + } else if (( maximizeMode() & MaximizeVertical ) == 0 && !largeTitlebar ) { + // We've been restored - enlarge the titlebar by 3 pixels + topSpacer->changeSize( 10, 4, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); + largeCaption = largeTitlebar = true; + + calculateCaptionRect(); + captionBufferDirty = maskDirty = true; + + widget()->layout()->activate(); + widget()->tqrepaint( false ); + } + } + + if ( button[ MaxButton ] ) { + TQToolTip::remove( button[ MaxButton ] ); + TQToolTip::add( button[ MaxButton ], maximizeMode() == MaximizeFull ? i18n("Restore") : i18n("Maximize") ); + button[ MaxButton ]->tqrepaint(); + } +} + + +void KeramikClient::desktopChange() +{ + if ( button[ OnAllDesktopsButton ] ) + { + button[ OnAllDesktopsButton ]->tqrepaint( true ); + TQToolTip::remove( button[ OnAllDesktopsButton ] ); + TQToolTip::add( button[ OnAllDesktopsButton ], isOnAllDesktops() ? i18n("Not on all desktops") : i18n("On all desktops") ); + } +} + + +void KeramikClient::shadeChange() +{ + if ( button[ ShadeButton ] ) + { + button[ ShadeButton ]->tqrepaint( true ); + TQToolTip::remove( button[ ShadeButton ] ); + TQToolTip::add( button[ ShadeButton ], isSetShade() ? i18n("Unshade") : i18n("Shade") ); + } +} + + +void KeramikClient::keepAboveChange( bool ) +{ + if ( button[ AboveButton ] ) + button[ AboveButton ]->tqrepaint( true ); +} + + +void KeramikClient::keepBelowChange( bool ) +{ + if ( button[ BelowButton ] ) + button[ BelowButton ]->tqrepaint( true ); +} + + +void KeramikClient::menuButtonPressed() +{ + TQPoint menuTop ( button[MenuButton]->rect().topLeft() ); + TQPoint menuBottom ( button[MenuButton]->rect().bottomRight() ); + menuTop += TQPoint(-6, -3); + menuBottom += TQPoint(6, 3); + KDecorationFactory* f = factory(); + showWindowMenu( TQRect( button[MenuButton]->mapToGlobal( menuTop ), + button[MenuButton]->mapToGlobal( menuBottom )) ); + if( !f->exists( this )) // 'this' was destroyed + return; + button[MenuButton]->setDown(false); +} + + +void KeramikClient::slotMaximize() +{ + maximize( button[ MaxButton ]->lastButton() ); +} + + +void KeramikClient::slotAbove() +{ + setKeepAbove( !keepAbove()); + button[ AboveButton ]->tqrepaint( true ); +} + + +void KeramikClient::slotBelow() +{ + setKeepBelow( !keepBelow()); + button[ BelowButton ]->tqrepaint( true ); +} + + +void KeramikClient::slotShade() +{ + setShade( !isSetShade()); + button[ ShadeButton ]->tqrepaint( true ); +} + + +void KeramikClient::paintEvent( TQPaintEvent *e ) +{ + if ( !keramik_initialized ) + return; + + TQPainter p( widget()); + TQRect updateRect( e->rect() ); + bool active = isActive(); + + int titleBaseY = ( largeTitlebar ? 3 : 0 ); + int titleBarHeight = clientHandler->titleBarHeight( largeTitlebar ); + int grabBarHeight = clientHandler->grabBarHeight(); + int leftBorderWidth = clientHandler->tile( BorderLeft, active )->width(); + int rightBorderWidth = clientHandler->tile( BorderRight, active )->width(); + + if ( maskDirty ) + updateMask(); + + // Titlebar + // ----------------------------------------------------------------------- + if ( updateRect.y() < titleBarHeight ) + { + int titleBarBaseHeight = titleBarHeight - titleBaseY; + + if ( captionBufferDirty ) + updateCaptionBuffer(); + + // Top left corner + if ( updateRect.x() < 15 ) + p.drawPixmap( 0, titleBaseY, + *clientHandler->tile( TitleLeft, active ) ); + + // Space between the top left corner and the caption bubble + if ( updateRect.x() < captionRect.left() && updateRect.right() >= 15 ) { + int x1 = QMAX( 15, updateRect.x() ); + int x2 = QMIN( captionRect.left(), updateRect.right() ); + + p.drawTiledPixmap( x1, titleBaseY, x2 - x1 + 1, titleBarBaseHeight, + *clientHandler->tile( TitleCenter, active ) ); + } + + // Caption bubble + if ( updateRect.x() <= captionRect.right() && updateRect.right() > 15 ) { + if ( captionRect.width() >= 25 ) + p.drawPixmap( captionRect.left(), active ? 0 : titleBaseY, captionBuffer ); + else + p.drawTiledPixmap( captionRect.x(), titleBaseY, captionRect.width(), + titleBarBaseHeight, *clientHandler->tile( TitleCenter, active ) ); + } + + // Space between the caption bubble and the top right corner + if ( updateRect.right() > captionRect.right() && updateRect.x() < width() - 15 ) { // FRAME + int x1 = QMAX( captionRect.right() + 1, updateRect.x() ); + int x2 = QMIN( width() - 15, updateRect.right() ); + + p.drawTiledPixmap( x1, titleBaseY, x2 - x1 + 1, titleBarBaseHeight, + *clientHandler->tile( TitleCenter, active ) ); + } + + // Top right corner + if ( updateRect.right() >= width() - 15 ) + p.drawPixmap( width() - 15, titleBaseY, + *clientHandler->tile( TitleRight, active ) ); + } + + // Borders + // ----------------------------------------------------------------------- + if ( updateRect.bottom() >= titleBarHeight && + updateRect.top() < height() - grabBarHeight ) + { + int top = QMAX( titleBarHeight, updateRect.top() ); + int bottom = QMIN( updateRect.bottom(), height() - grabBarHeight ); + + // Left border + if ( updateRect.x() < leftBorderWidth ) + p.drawTiledPixmap( 0, top, leftBorderWidth, bottom - top + 1, + *clientHandler->tile( BorderLeft, active ) ); + + // Right border + if ( e->rect().right() > width() - rightBorderWidth - 1 ) + p.drawTiledPixmap( width() - rightBorderWidth, top, rightBorderWidth, + bottom - top + 1, *clientHandler->tile( BorderRight, active ) ); + } + + // Bottom grab bar + // ----------------------------------------------------------------------- + if ( updateRect.bottom() >= height() - grabBarHeight ) { + // Bottom left corner + if ( updateRect.x() < 9 ) + p.drawPixmap( 0, height() - grabBarHeight, + *clientHandler->tile( GrabBarLeft, active ) ); + + // Space between the left corner and the right corner + if ( updateRect.x() < width() - 9 ) { + int x1 = QMAX( 9, updateRect.x() ); + int x2 = QMIN( width() - 9, updateRect.right() ); + + p.drawTiledPixmap( x1, height() - grabBarHeight, x2 - x1 + 1, + grabBarHeight, *clientHandler->tile( GrabBarCenter, active ) ); + } + + // Bottom right corner + if ( updateRect.right() > width() - 9 ) + p.drawPixmap( width() - 9, height() - grabBarHeight, + *clientHandler->tile( GrabBarRight, active ) ); + } + + // Extra drawline for the 1 pixel empty space TQLayout leaves when a window is shaded. + p.setPen( options()->color( ColorTitleBlend, active ) ); + p.drawLine( leftBorderWidth, height() - grabBarHeight - 1, + width() - rightBorderWidth - 1, height() - grabBarHeight - 1 ); +} + + +void KeramikClient::resizeEvent( TQResizeEvent *e ) +{ +// FRAME Client::resizeEvent( e ); + + TQRect r( captionRect ); + calculateCaptionRect(); + + if ( r.size() != captionRect.size() ) + captionBufferDirty = true; + + maskDirty = true; + + if ( widget()->isVisible() ) + { + widget()->update( widget()->rect() ); + int dx = 0; + int dy = 0; + + if ( e->oldSize().width() != width() ) + dx = 32 + QABS( e->oldSize().width() - width() ); + + if ( e->oldSize().height() != height() ) + dy = 8 + QABS( e->oldSize().height() - height() ); + + if ( dy ) + widget()->update( 0, height() - dy + 1, width(), dy ); + + if ( dx ) + { + widget()->update( width() - dx + 1, 0, dx, height() ); + widget()->update( TQRect( TQPoint(4,4), titlebar->geometry().bottomLeft() - TQPoint(1,0) ) ); + widget()->update( TQRect( titlebar->geometry().topRight(), TQPoint( width() - 4, + titlebar->geometry().bottom() ) ) ); + // Titlebar needs no paint event + TQApplication::postEvent( this, new TQPaintEvent( titlebar->geometry(), FALSE ) ); + } + } +} + + +void KeramikClient::mouseDoubleClickEvent( TQMouseEvent *e ) +{ + if ( e->button() == Qt::LeftButton + && TQRect( 0, 0, width(), clientHandler->titleBarHeight( largeTitlebar ) ).contains( e->pos() ) ) + titlebarDblClickOperation(); +} + +void KeramikClient::wheelEvent( TQWheelEvent *e ) +{ + if (isSetShade() + || TQRect( 0, 0, width(), clientHandler->titleBarHeight( largeTitlebar ) ).contains( e->pos() ) ) + titlebarMouseWheelOperation( e->delta()); +} + +KeramikClient::Position KeramikClient::mousePosition( const TQPoint &p ) const +{ + int titleBaseY = (largeTitlebar ? 3 : 0); + + int leftBorder = clientHandler->tile( BorderLeft, true )->width(); + int rightBorder = width() - clientHandler->tile( BorderRight, true )->width() - 1; + int bottomBorder = height() - clientHandler->grabBarHeight() - 1; + int bottomCornerSize = 3*clientHandler->tile( BorderRight, true )->width()/2 + 24; + + // Test if the mouse is over the titlebar area + if ( p.y() < titleBaseY + 11 ) { + // Test for the top left corner + if ( p.x() < leftBorder + 11 ) { + if ( (p.y() < titleBaseY + 3 && p.x() < leftBorder + 11) || + (p.y() < titleBaseY + 6 && p.x() < leftBorder + 6) || + (p.y() < titleBaseY + 11 && p.x() < leftBorder + 3) ) + return PositionTopLeft; + } + + // Test for the top right corner + if ( p.x() > rightBorder - 11 ) { + if ( (p.y() < titleBaseY + 3 && p.x() > rightBorder - 11) || + (p.y() < titleBaseY + 6 && p.x() > rightBorder - 6) || + (p.y() < titleBaseY + 11 && p.x() > rightBorder - 3) ) + return PositionTopRight; + } + + // Test for the top border + if ( p.y() <= 3 || (p.y() <= titleBaseY+3 && + (p.x() < captionRect.left() || p.x() > captionRect.right()) ) ) + return PositionTop; + + // The cursor must be over the center of the titlebar. + return PositionCenter; + } + + // Test the sides + else if ( p.y() < bottomBorder ) { + // Test for the left side + if ( p.x() < leftBorder ) { + if ( p.y() < height() - bottomCornerSize ) + return PositionLeft; + else + return PositionBottomLeft; + } + + // Test for the right side + else if ( p.x() > rightBorder ) { + if ( p.y() < height() - bottomCornerSize ) + return PositionRight; + else + return PositionBottomRight; + } + + // The cursor must be over the center of the window + return PositionCenter; + } + + // Test the grab bar / bottom border + else { + // Test for the bottom left corner + if ( p.x() < bottomCornerSize ) + return PositionBottomLeft; + + // Test for the bottom right corner + else if ( p.x() > width() - bottomCornerSize - 1 ) + return PositionBottomRight; + + // The cursor must be over the bottom border + return PositionBottom; + } + + // We should never get here + return PositionCenter; +} + + +void KeramikClient::resize( const TQSize& s ) +{ + widget()->resize( s ); +} + + +void KeramikClient::borders( int& left, int& right, int& top, int& bottom ) const +{ + int titleBarHeight = clientHandler->titleBarHeight( clientHandler->largeCaptionBubbles() ); + int grabBarHeight = clientHandler->grabBarHeight(); + int leftBorderWidth = clientHandler->tile( BorderLeft, isActive() )->width(); + int rightBorderWidth = clientHandler->tile( BorderRight, isActive() )->width(); + + left = leftBorderWidth; + right = rightBorderWidth; + top = titleBarHeight; + bottom = grabBarHeight; + + if ( ( maximizeMode() & MaximizeHorizontal ) && !options()->moveResizeMaximizedWindows()) + left = right = 0; + if( maximizeMode() & MaximizeVertical) + { + top = clientHandler->titleBarHeight( false ); + if( !options()->moveResizeMaximizedWindows()) + bottom = 0; + } +} + + +TQSize KeramikClient::tqminimumSize() const +{ + return widget()->tqminimumSize(); +} + + +bool KeramikClient::eventFilter( TQObject* o, TQEvent* e ) +{ + if ( TQT_BASE_OBJECT(o) != TQT_BASE_OBJECT(widget()) ) + return false; + + switch ( e->type() ) + { + case TQEvent::Resize: + resizeEvent( TQT_TQRESIZEEVENT( e ) ); + return true; + + case TQEvent::Paint: + paintEvent( TQT_TQPAINTEVENT( e ) ); + return true; + + case TQEvent::MouseButtonDblClick: + mouseDoubleClickEvent( TQT_TQMOUSEEVENT( e ) ); + return true; + + case TQEvent::MouseButtonPress: + processMousePressEvent( TQT_TQMOUSEEVENT( e ) ); + return true; + + case TQEvent::Wheel: + wheelEvent( TQT_TQWHEELEVENT( e )); + return true; + + default: + return false; + } +} + +} // namespace Keramik + + + +// ------------------------------------------------------------------------------------------- + + + +extern "C" +{ + KDE_EXPORT KDecorationFactory *create_factory() + { + Keramik::clientHandler = new Keramik::KeramikHandler(); + return Keramik::clientHandler; + } +} + + + +// vim: set noet ts=4 sw=4: diff --git a/twin/clients/keramik/keramik.desktop b/twin/clients/keramik/keramik.desktop new file mode 100644 index 000000000..7ef21f47d --- /dev/null +++ b/twin/clients/keramik/keramik.desktop @@ -0,0 +1,31 @@ +[Desktop Entry] +Name=Keramik +Name[ar]=قرميدي +Name[be]=Кераміка +Name[bn]=কেরামিক +Name[cs]=Keramika +Name[eo]=Ceramiko +Name[fa]=کرامیک +Name[fy]=Keramyk +Name[hi]=के-रामिक +Name[it]=Ceramica +Name[lo]=ເຄຣາມິກ - K +Name[lv]=Keramika +Name[mk]=Керамик +Name[mn]=Ваар +Name[nb]=Keramikk +Name[ne]=केरामिक +Name[nn]=Keramikk +Name[pa]=ਕੀਰਾਮਿਕ +Name[se]=Bálseduodji +Name[sr]=Керамика +Name[sr@Latn]=Keramika +Name[ta]=கெராமிக் +Name[te]=కెరామిక్ +Name[th]=เครามิก +Name[uk]=Керамік +Name[uz]=Keramika +Name[uz@cyrillic]=Керамика +Name[vi]=Gốm +X-KDE-Library=twin3_keramik + diff --git a/twin/clients/keramik/keramik.h b/twin/clients/keramik/keramik.h new file mode 100644 index 000000000..8e4a98518 --- /dev/null +++ b/twin/clients/keramik/keramik.h @@ -0,0 +1,202 @@ +/* + * + * Keramik KWin client (version 0.8) + * + * Copyright (C) 2002 Fredrik H�glund <fredrik@kde.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the license, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __KERAMIK_H +#define __KERAMIK_H + +#include <tqbutton.h> +#include <kdecoration.h> +#include <kdecorationfactory.h> + +#include "tiles.h" + +class TQSpacerItem; + +namespace Keramik { + + enum TilePixmap { TitleLeft=0, TitleCenter, TitleRight, + CaptionSmallLeft, CaptionSmallCenter, CaptionSmallRight, + CaptionLargeLeft, CaptionLargeCenter, CaptionLargeRight, + GrabBarLeft, GrabBarCenter, GrabBarRight, + BorderLeft, BorderRight, NumTiles }; + + enum Button { MenuButton=0, OnAllDesktopsButton, HelpButton, MinButton, + MaxButton, CloseButton, AboveButton, BelowButton, ShadeButton, + NumButtons }; + + enum ButtonDeco { Menu=0, OnAllDesktops, NotOnAllDesktops, Help, Minimize, Maximize, + Restore, Close, AboveOn, AboveOff, BelowOn, BelowOff, ShadeOn, ShadeOff, + NumButtonDecos }; + + struct SettingsCache + { + bool largeGrabBars:1; + bool smallCaptionBubbles:1; + }; + + class KeramikHandler : public KDecorationFactory + { + public: + KeramikHandler(); + ~KeramikHandler(); + + virtual TQValueList< BorderSize > borderSizes() const; + virtual bool reset( unsigned long changed ); + virtual KDecoration* createDecoration( KDecorationBridge* ); + virtual bool supports( Ability ability ); + + bool showAppIcons() const { return showIcons; } + bool useShadowedText() const { return shadowedText; } + bool largeCaptionBubbles() const { return !smallCaptionBubbles; } + + int titleBarHeight( bool large ) const { + return ( large ? activeTiles[CaptionLargeCenter]->height() + : activeTiles[CaptionSmallCenter]->height() ); + } + + int grabBarHeight() const + { return activeTiles[GrabBarCenter]->height(); } + + const TQPixmap *roundButton() const { return titleButtonRound; } + const TQPixmap *squareButton() const { return titleButtonSquare; } + const TQBitmap *buttonDeco( ButtonDeco deco ) const + { return buttonDecos[ deco ]; } + + inline const TQPixmap *tile( TilePixmap tilePix, bool active ) const; + + private: + void readConfig(); + void createPixmaps(); + void destroyPixmaps(); + + void addWidth (int width, TQPixmap *&pix, bool left, TQPixmap *bottomPix); + void addHeight (int height, TQPixmap *&pix); + void flip( TQPixmap *&, TQPixmap *& ); + void pretile( TQPixmap *&, int, Qt::Orientation ); + TQPixmap *composite( TQImage *, TQImage * ); + TQImage *loadImage( const TQString &, const TQColor & ); + TQPixmap *loadPixmap( const TQString &, const TQColor & ); + + bool showIcons:1, shadowedText:1, + smallCaptionBubbles:1, largeGrabBars:1; + SettingsCache *settings_cache; + KeramikImageDb *imageDb; + + TQPixmap *activeTiles[ NumTiles ]; + TQPixmap *inactiveTiles[ NumTiles ]; + TQBitmap *buttonDecos[ NumButtonDecos ]; + + TQPixmap *titleButtonRound, *titleButtonSquare; + + }; // class KeramikHandler + + class KeramikClient; + class KeramikButton : public TQButton + { + public: + KeramikButton( KeramikClient *, const char *, Button, const TQString &, const int realizeBtns = Qt::LeftButton ); + ~KeramikButton(); + + ButtonState lastButton() const { return lastbutton; } + + private: + void enterEvent( TQEvent * ); + void leaveEvent( TQEvent * ); + void mousePressEvent( TQMouseEvent * ); + void mouseReleaseEvent( TQMouseEvent * ); + void drawButton( TQPainter * ); + + private: + KeramikClient *client; + Button button; + bool hover; + ButtonState lastbutton; + int realizeButtons; + }; // class KeramikButton + + + class KeramikClient : public KDecoration + { + Q_OBJECT + + public: + + KeramikClient( KDecorationBridge* bridge, KDecorationFactory* factory ); + ~KeramikClient(); + virtual void init(); + virtual void reset( unsigned long changed ); + virtual Position mousePosition( const TQPoint& p ) const; + virtual void borders( int& left, int& right, int& top, int& bottom ) const; + virtual void resize( const TQSize& s ); + virtual TQSize tqminimumSize() const; + virtual bool eventFilter( TQObject* o, TQEvent* e ); + virtual void activeChange(); + virtual void captionChange(); + virtual void maximizeChange(); + virtual void desktopChange(); + virtual void shadeChange(); + + private: + void createLayout(); + void addButtons( TQBoxLayout*, const TQString & ); + void updateMask(); // FRAME + void updateCaptionBuffer(); + void iconChange(); + void resizeEvent( TQResizeEvent *); // FRAME + void paintEvent( TQPaintEvent *); // FRAME + void mouseDoubleClickEvent( TQMouseEvent * ); // FRAME + void wheelEvent( TQWheelEvent *); //FRAME + int width() const { return widget()->width(); } + int height() const { return widget()->height(); } + + void calculateCaptionRect(); + + inline bool maximizedVertical() const { + return ( maximizeMode() & MaximizeVertical ); + } + bool isModalSystemNotification(); + + private slots: + void menuButtonPressed(); + void slotMaximize(); + void slotAbove(); + void slotBelow(); + void slotShade(); + void keepAboveChange( bool ); + void keepBelowChange( bool ); + + private: + TQSpacerItem *topSpacer, *titlebar; + KeramikButton *button[ NumButtons ]; + TQRect captionRect; + TQPixmap captionBuffer; + TQPixmap *activeIcon, *inactiveIcon; + bool captionBufferDirty:1, maskDirty:1; + bool largeCaption:1, largeTitlebar:1; + }; // class KeramikClient + +} // namespace Keramik + +#endif // ___KERAMIK_H + +// vim: set noet ts=4 sw=4: diff --git a/twin/clients/keramik/pics/border-left.png b/twin/clients/keramik/pics/border-left.png Binary files differnew file mode 100644 index 000000000..298a0aa9a --- /dev/null +++ b/twin/clients/keramik/pics/border-left.png diff --git a/twin/clients/keramik/pics/border-right.png b/twin/clients/keramik/pics/border-right.png Binary files differnew file mode 100644 index 000000000..1ca876b0d --- /dev/null +++ b/twin/clients/keramik/pics/border-right.png diff --git a/twin/clients/keramik/pics/bottom-center.png b/twin/clients/keramik/pics/bottom-center.png Binary files differnew file mode 100644 index 000000000..d6d002534 --- /dev/null +++ b/twin/clients/keramik/pics/bottom-center.png diff --git a/twin/clients/keramik/pics/bottom-left.png b/twin/clients/keramik/pics/bottom-left.png Binary files differnew file mode 100644 index 000000000..16a2ab982 --- /dev/null +++ b/twin/clients/keramik/pics/bottom-left.png diff --git a/twin/clients/keramik/pics/bottom-right.png b/twin/clients/keramik/pics/bottom-right.png Binary files differnew file mode 100644 index 000000000..2d4045432 --- /dev/null +++ b/twin/clients/keramik/pics/bottom-right.png diff --git a/twin/clients/keramik/pics/caption-large-center.png b/twin/clients/keramik/pics/caption-large-center.png Binary files differnew file mode 100644 index 000000000..786276b55 --- /dev/null +++ b/twin/clients/keramik/pics/caption-large-center.png diff --git a/twin/clients/keramik/pics/caption-large-left.png b/twin/clients/keramik/pics/caption-large-left.png Binary files differnew file mode 100644 index 000000000..7d96bdcea --- /dev/null +++ b/twin/clients/keramik/pics/caption-large-left.png diff --git a/twin/clients/keramik/pics/caption-large-right.png b/twin/clients/keramik/pics/caption-large-right.png Binary files differnew file mode 100644 index 000000000..3055d13a7 --- /dev/null +++ b/twin/clients/keramik/pics/caption-large-right.png diff --git a/twin/clients/keramik/pics/caption-small-center.png b/twin/clients/keramik/pics/caption-small-center.png Binary files differnew file mode 100644 index 000000000..78636dfd1 --- /dev/null +++ b/twin/clients/keramik/pics/caption-small-center.png diff --git a/twin/clients/keramik/pics/caption-small-left.png b/twin/clients/keramik/pics/caption-small-left.png Binary files differnew file mode 100644 index 000000000..cb7e69d73 --- /dev/null +++ b/twin/clients/keramik/pics/caption-small-left.png diff --git a/twin/clients/keramik/pics/caption-small-right.png b/twin/clients/keramik/pics/caption-small-right.png Binary files differnew file mode 100644 index 000000000..9fc74640e --- /dev/null +++ b/twin/clients/keramik/pics/caption-small-right.png diff --git a/twin/clients/keramik/pics/grabbar-center.png b/twin/clients/keramik/pics/grabbar-center.png Binary files differnew file mode 100644 index 000000000..b623b5df2 --- /dev/null +++ b/twin/clients/keramik/pics/grabbar-center.png diff --git a/twin/clients/keramik/pics/grabbar-left.png b/twin/clients/keramik/pics/grabbar-left.png Binary files differnew file mode 100644 index 000000000..653f5ccfb --- /dev/null +++ b/twin/clients/keramik/pics/grabbar-left.png diff --git a/twin/clients/keramik/pics/grabbar-right.png b/twin/clients/keramik/pics/grabbar-right.png Binary files differnew file mode 100644 index 000000000..248d55410 --- /dev/null +++ b/twin/clients/keramik/pics/grabbar-right.png diff --git a/twin/clients/keramik/pics/titlebar-center.png b/twin/clients/keramik/pics/titlebar-center.png Binary files differnew file mode 100644 index 000000000..bac31dc55 --- /dev/null +++ b/twin/clients/keramik/pics/titlebar-center.png diff --git a/twin/clients/keramik/pics/titlebar-left.png b/twin/clients/keramik/pics/titlebar-left.png Binary files differnew file mode 100644 index 000000000..bc8ee5ca3 --- /dev/null +++ b/twin/clients/keramik/pics/titlebar-left.png diff --git a/twin/clients/keramik/pics/titlebar-right.png b/twin/clients/keramik/pics/titlebar-right.png Binary files differnew file mode 100644 index 000000000..d34a465f5 --- /dev/null +++ b/twin/clients/keramik/pics/titlebar-right.png diff --git a/twin/clients/keramik/pics/titlebutton-round-huge.png b/twin/clients/keramik/pics/titlebutton-round-huge.png Binary files differnew file mode 100644 index 000000000..c5ca19342 --- /dev/null +++ b/twin/clients/keramik/pics/titlebutton-round-huge.png diff --git a/twin/clients/keramik/pics/titlebutton-round-large.png b/twin/clients/keramik/pics/titlebutton-round-large.png Binary files differnew file mode 100644 index 000000000..9c3267bf9 --- /dev/null +++ b/twin/clients/keramik/pics/titlebutton-round-large.png diff --git a/twin/clients/keramik/pics/titlebutton-round.png b/twin/clients/keramik/pics/titlebutton-round.png Binary files differnew file mode 100644 index 000000000..dd2369af3 --- /dev/null +++ b/twin/clients/keramik/pics/titlebutton-round.png diff --git a/twin/clients/keramik/pics/titlebutton-square-huge.png b/twin/clients/keramik/pics/titlebutton-square-huge.png Binary files differnew file mode 100644 index 000000000..a908a9f27 --- /dev/null +++ b/twin/clients/keramik/pics/titlebutton-square-huge.png diff --git a/twin/clients/keramik/pics/titlebutton-square-large.png b/twin/clients/keramik/pics/titlebutton-square-large.png Binary files differnew file mode 100644 index 000000000..6e3ada47b --- /dev/null +++ b/twin/clients/keramik/pics/titlebutton-square-large.png diff --git a/twin/clients/keramik/pics/titlebutton-square.png b/twin/clients/keramik/pics/titlebutton-square.png Binary files differnew file mode 100644 index 000000000..871cf751a --- /dev/null +++ b/twin/clients/keramik/pics/titlebutton-square.png |