diff options
Diffstat (limited to 'twin/clients')
119 files changed, 15984 insertions, 0 deletions
diff --git a/twin/clients/CMakeLists.txt b/twin/clients/CMakeLists.txt new file mode 100644 index 000000000..c9a8faf85 --- /dev/null +++ b/twin/clients/CMakeLists.txt @@ -0,0 +1,20 @@ +################################################# +# +# (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( plastik ) +add_subdirectory( b2 ) +add_subdirectory( default ) +add_subdirectory( keramik ) +add_subdirectory( laptop ) +add_subdirectory( modernsystem ) +add_subdirectory( quartz ) +add_subdirectory( redmond ) +add_subdirectory( web ) diff --git a/twin/clients/Makefile.am b/twin/clients/Makefile.am new file mode 100644 index 000000000..c62b21019 --- /dev/null +++ b/twin/clients/Makefile.am @@ -0,0 +1,8 @@ +SUBDIRS = plastik b2 default keramik laptop modernsystem quartz redmond web +# need to be ported: kwmtheme (almost done) +# only for testing: test + +messages: rc.cpp + $(EXTRACTRC) `find . -name \*.ui` >> rc.cpp + $(XGETTEXT) `find . -name \*.cpp` -o $(podir)/twin_clients.pot + -rm rc.cpp diff --git a/twin/clients/PORTING b/twin/clients/PORTING new file mode 100644 index 000000000..0c0c1a6ea --- /dev/null +++ b/twin/clients/PORTING @@ -0,0 +1,159 @@ +It's suggested you check sources of some KDE CVS decoration if in doubts or in need of an example. +Also, the API is documented in the .h header files. + +Makefile.am: +- Change twin_ to twin3_ (in LDFLAGS, LIBADD, kde_module_LTLIBRARIES, SOURCES). +- Make sure LDFLAGS contains $(KDE_PLUGIN) and -module . +- Add -ltdecorations to LIBADD. +- Do NOT rename the directory where the .desktop file is installed ( $(kde_datadir)/twin/ ). + +.desktop file: +- Change twin_ to twin3_ in X-TDE-Library. + +Sources: +- There are no twin/something.h includes, and don't use the KWinInternal namespace. +- Use QToolTip instead of KWinToolTip. +- Use QButton instead of KWinButton, QToolButton instead of KWinToolButton and QWidget + instead of KWinWidgetButton. +- For tooltips, use simply QToolTip::add(). +- Change Client* to MyClient* (or whatever is your main client class) in your MyButton. +- Pass parent->widget() to QButton constructor in your MyButton constructor. +- Make your MyClient class inherit from KDecoration instead of Client. +- Make MyClient constructor take KDecorationBridge* and KDecorationFactory* as arguments, + and pass these arguments to KDecoration constructor. +- Except for data members initialization, make the constructor empty, move everything + to void MyClient::init(). +- As the first thing in init(), call createMainWidget(); if your client class took some + flags such as WResizeNoErase, pass them to this function. +- Then, do 'widget()->installEventFilter( this );'. +- Implement MyClient::eventFilter() - as MyClient is now no longer QWidget, you need the event + filter to call all the functions that used to be called directly. Usually, it's something + like: +===== +bool MyClient::eventFilter( QObject* o, QEvent* e ) +{ + if ( o != widget() ) + return false; + + switch ( e->type() ) + { + case QEvent::Resize: + resizeEvent( static_cast< QResizeEvent* >( e ) ); + return true; + + case QEvent::Paint: + paintEvent( static_cast< QPaintEvent* >( e ) ); + return true; + + case QEvent::MouseButtonDblClick: + mouseDoubleClickEvent( static_cast< QMouseEvent* >( e ) ); + return true; + + case QEvent::Wheel: + wheelEvent( static_cast< QWheelEvent* >( e )); + return true; + + case QEvent::MouseButtonPress: + processMousePressEvent( static_cast< QMouseEvent* >( e ) ); + return true; + + case QEvent::Show: + showEvent( static_cast< QShowEvent* >( e ) ); + return true; + + default: + return false; + } +} +===== +- In MyClient, 'this' will have to be often replaced with 'widget()', pay special attention + to cases where this won't cause compile error (e.g. in connect() calls, which take QObject* ). +- Also, many calls may need 'widget()->' prepended. +- Layout is created in init(), so call createLayout() directly there (if it's implemented). +- Remove calls to Client methods (Client::resizeEvent() and so on). +- Replace Options:: with KDecorationOptions:: . +- Replace 'options' with 'options()' in MyClient (which is KDecoration::options()), if often used + outside of MyClient, you may want to create (this assumes your code is in its namespace): +===== +inline const KDecorationOptions* options() { return KDecoration::options(); } +===== +- Options for colors need 'Color' prepended (e.g. 'ColorButtonBg'). +- Replace miniIcon() with getting the right pixmap from icon() (usually + 'icon().pixmap( QIconSet::Small, QIconSet::Normal )' ). +- Replace stickyChange() with desktopChange(), and test isOnAllDesktops(). +- Replace Sticky with OnAllDestops. +- Replace iconify with minimize. +- Change activeChange(bool) to activeChange(), and use isActive() to check the state. + Similar for desktopChange, captionChange(), iconChange(), maximizeChange(). +- Replace 'contextHelp()' with 'showContextHelp()'. +- WindowWrapperShowEvent() is gone, simply use showEvent() filtered by the event filter if needed. +- Change 'animateIconifyOrDeiconify()' to 'animateMinize()', if it's empty, simply remove it. + Make sure it doesn't reenter the event loop (no kapp->processEvents()). +- Buttons should use explicit setCursor() if they don't want cursor set by mousePosition(). + I.e. usually call setCursor( ArrowCursor ) in your MyButton. +- In the part where you insert windowWrapper() into the layout, i.e. something like +===== + layout->addWidget( windowWrapper()); +===== + replace it with something like +===== + if( isPreview()) + layout->addWidget( new QLabel( i18n( "<center><b>MyDecoration</b></center>" ), widget())); + else + layout->addItem( new QSpacerItem( 0, 0 )); +===== +- Implement MyClient::minimumSize(). +- Handling maximization - to change vertical or horizontal maximalization, use e.g. + 'maximize( maximizeMode() ^ MaximizeVertical', to change normal maximalization, i.e. after + left-clicking on the button, use + 'maximize( maximizeMode() == MaximizeFull ? MaximizeRestore : MaximizeFull );' (which also + means that there's also no maximize() slot). + Also, if your decoration button has only two visual states representing the maximalization state, + it's recommended that it shows the maximized state only for MaximizeFull state. +- Make sure the decoration matches the window state after init() is finished, that is, that + the buttons represent correctly the maximalization, on-all-desktops etc. states. As the + simplest solution, you can call maximizeChange(), desktopChange(), etc. at the end + of init(). +- Use 'titlebarDblClickOperation()' for performing the application after doubleclicking + the titlebar. +- Implement borders() returning the width of the top,left,right and bottom border. You may + check values like 'maximizeMode() == MaximizeFull && !options()->moveResizeMaximizedWindows()' + to check whether you can disable some borders completely. + Note that your painting code must of course match these sizes. +- If your code uses XGrabServer() or XUnGrabServer(), replace them with (un)grabXServer(). +- In cases where you call some function from the KDecoration API that can possibly destroy + the decoration (e.g. showWindowMenu() or closeWindow()), make sure to use exists() if some more + code will follow this call. Refer to showWindowMenu() documentation for an example. +- Create class MyFactory inheriting from KDecorationFactory, and move the code that was + in 'extern "C"' to it: From init() to constructor, from deinit() to destructor, from allocate() + or create() to createDecoration(). Pass the KDecorationBridge* argument and 'this' to created + MyClient objects. If createDecoration() needs to know the window type (e.g. it used the tool + argument), use windowType() similarly like in KDecoration, and pass it the KDecorationBridge* + argument. +- Add something like this: +===== +extern "C" +{ + KDecorationFactory *create_factory() + { + return new MyNamespace::MyFactory(); + } +} +===== +- The reset handling has changed: There's no signal resetClients(), and no + slotResetAllClientsDelayed(). If your MyClient has some slotReset(), make it + reset( unsigned long ), where the argument is mask of things that have changed ( SettingXYZ ). + If you have some global function that handles resetting, make it + MyFactory::reset( unsigned long ). Try to minimize the effects of the changed things, + e.g. if only the color setting has changed, doing a repaint is often enough, and there's no need + to recreate the decorations. If you need to recreate the decorations, return true + from MyFactory::reset(), otherwise, you may call resetDecorations() to call reset() in all + MyClient instances. +- Implement resize() to resize the decoration to the given size + (usually 'widget()->resize( s );' is enough). +- Review mousePosition() if it's implemented. Position constants need 'Position' prepended, + e.g. Top -> PositionTop. +- Note that you cannot use "appdata" with TDEStandardDirs, as the decoration will be used + also in other applications than twin. +- Implement all missing pure virtual functions. For mousePosition(), you may call + KDecoration::mousePosition() if it's sufficient. diff --git a/twin/clients/REQUIREMENTS_FOR_CVS b/twin/clients/REQUIREMENTS_FOR_CVS new file mode 100644 index 000000000..0c8c2a6d7 --- /dev/null +++ b/twin/clients/REQUIREMENTS_FOR_CVS @@ -0,0 +1,20 @@ +If you are looking to include a C++ KWin style client in CVS make sure you +follow the following requirements: + +A) You must follow the current color scheme for all decorations. *No* fixed +pixmaps are allowed for the clients. If you wish to draw your decorations +use as few shades as possible, then use kpixmap2bitmap in tdegraphics +to convert them into individual bitmaps. Once this is done you can +draw the bitmaps using a colorgroup with kColorBitmaps. + +If your client is just a set of pixmaps that doesn't follow any of the options +I suggest you make a KWM theme so the user gets those options to +configure the pixmaps and look. Making a plain pixmapped dedicated style +makes no sense since it is less configurable than KWM themes and cannot follow +client plugin options. + +B) You must follow at least the color settings in the Options class. + +Daniel M. Duley +mosfet@kde.org + diff --git a/twin/clients/b2/CMakeLists.txt b/twin/clients/b2/CMakeLists.txt new file mode 100644 index 000000000..c7f4bdb9d --- /dev/null +++ b/twin/clients/b2/CMakeLists.txt @@ -0,0 +1,37 @@ +################################################# +# +# (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 b2.desktop DESTINATION ${DATA_INSTALL_DIR}/twin ) + + +##### twin3_b2 (module) ######################### + +tde_add_kpart( twin3_b2 AUTOMOC + SOURCES b2client.cpp + LINK tdecorations-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/twin/clients/b2/Makefile.am b/twin/clients/b2/Makefile.am new file mode 100644 index 000000000..ccd7f39fa --- /dev/null +++ b/twin/clients/b2/Makefile.am @@ -0,0 +1,23 @@ + +INCLUDES = -I$(srcdir)/../../lib $(all_includes) + +SUBDIRS = . config + +kde_module_LTLIBRARIES = twin3_b2.la + +twin3_b2_la_SOURCES = b2client.cpp +twin3_b2_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +# twin_b2_la_LDFLAGS = $(all_libraries) -avoid-version -module $(KDE_RPATH) $(KDE_MT_LDFLAGS) +twin3_b2_la_LIBADD = ../../lib/libtdecorations.la + +METASOURCES = AUTO +noinst_HEADERS = b2client.h + +lnkdir = $(kde_datadir)/twin/ +lnk_DATA = b2.desktop + +EXTRA_DIST = $(lnk_DATA) + +###KMAKE-start (don't edit or delete this block) + +###KMAKE-end diff --git a/twin/clients/b2/b2.desktop b/twin/clients/b2/b2.desktop new file mode 100644 index 000000000..e95f4f72c --- /dev/null +++ b/twin/clients/b2/b2.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Name=B II +Name[hi]=बी II +Name[lo]= B II +Name[te]=బి II +Name[th]=ชุดตกแต่ง B II +X-TDE-Library=twin3_b2 diff --git a/twin/clients/b2/b2client.cpp b/twin/clients/b2/b2client.cpp new file mode 100644 index 000000000..6a7a8296e --- /dev/null +++ b/twin/clients/b2/b2client.cpp @@ -0,0 +1,1454 @@ +/* + * B-II KWin Client + * + * Changes: + * Customizable button positions by Karol Szwed <gallium@kde.org> + * + * Thin frame in fixed size windows, titlebar gradient support, accessibility + * improvements, customizable menu double click action and button hover + * effects are + * Copyright (c) 2003,2004 Luciano Montanaro <mikelima@cirulla.net> + */ + +#include "b2client.h" +#include <tqapplication.h> +#include <tqlayout.h> +#include <tqdrawutil.h> +#include <kpixmapeffect.h> +#include <kimageeffect.h> +#include <kicontheme.h> +#include <kiconeffect.h> +#include <kdrawutil.h> +#include <tdelocale.h> +#include <tdeconfig.h> +#include <tqbitmap.h> +#include <tqlabel.h> +#include <tqtooltip.h> + +#include <X11/Xlib.h> +#include <X11/Xatom.h> + +namespace B2 { + +#include "bitmaps.h" + +enum { + Norm = 0, + Hover, Down, INorm, IHover, IDown, + NumStates +}; + +enum { + P_CLOSE = 0, + P_MAX, P_NORMALIZE, P_ICONIFY, P_PINUP, P_MENU, P_HELP, P_SHADE, P_RESIZE, + P_NUM_BUTTON_TYPES +}; + +#define NUM_PIXMAPS (P_NUM_BUTTON_TYPES * NumStates) + +static KPixmap *pixmap[NUM_PIXMAPS]; + +// active +#define PIXMAP_A(i) (pixmap[(i) * NumStates + Norm]) +// active, hover +#define PIXMAP_AH(i) (pixmap[(i) * NumStates + Hover]) +// active, down +#define PIXMAP_AD(i) (pixmap[(i) * NumStates + Down]) +// inactive +#define PIXMAP_I(i) (pixmap[(i) * NumStates + INorm]) +// inactive, hover +#define PIXMAP_IH(i) (pixmap[(i) * NumStates + IHover]) +// inactive, down +#define PIXMAP_ID(i) (pixmap[(i) * NumStates + IDown]) + +static KPixmap* titleGradient[2] = {0, 0}; + +static int thickness = 4; // Frame thickness +static int buttonSize = 16; + +enum DblClickOperation { + NoOp = 0, + MinimizeOp, + ShadeOp, + CloseOp +}; + +static DblClickOperation menu_dbl_click_op = NoOp; + +static bool pixmaps_created = false; +static bool colored_frame = false; +static bool do_draw_handle = true; +static bool drawSmallBorders = false; + +// ===================================== + +extern "C" KDE_EXPORT KDecorationFactory* create_factory() +{ + return new B2::B2ClientFactory(); +} + +// ===================================== + +static inline const KDecorationOptions *options() +{ + return KDecoration::options(); +} + +static void redraw_pixmaps(); + +static void read_config(B2ClientFactory *f) +{ + // Force button size to be in a reasonable range. + // If the frame width is large, the button size must be large too. + buttonSize = (TQFontMetrics(options()->font(true)).height() + 1) & 0x3e; + if (buttonSize < 16) buttonSize = 16; + + TDEConfig conf("twinb2rc"); + conf.setGroup("General"); + colored_frame = conf.readBoolEntry("UseTitleBarBorderColors", false); + do_draw_handle = conf.readBoolEntry("DrawGrabHandle", true); + drawSmallBorders = !options()->moveResizeMaximizedWindows(); + + TQString opString = conf.readEntry("MenuButtonDoubleClickOperation", "NoOp"); + if (opString == "Close") { + menu_dbl_click_op = B2::CloseOp; + } else if (opString == "Minimize") { + menu_dbl_click_op = B2::MinimizeOp; + } else if (opString == "Shade") { + menu_dbl_click_op = B2::ShadeOp; + } else { + menu_dbl_click_op = B2::NoOp; + } + + switch (options()->preferredBorderSize(f)) { + case KDecoration::BorderTiny: + thickness = 2; + break; + case KDecoration::BorderLarge: + thickness = 5; + break; + case KDecoration::BorderVeryLarge: + thickness = 8; + break; + case KDecoration::BorderHuge: + thickness = 12; + break; + case KDecoration::BorderVeryHuge: + case KDecoration::BorderOversized: + case KDecoration::BorderNormal: + default: + thickness = 4; + } +} + +static void drawB2Rect(KPixmap *pix, const TQColor &primary, bool down) +{ + TQPainter p(pix); + TQColor hColor = primary.light(150); + TQColor lColor = primary.dark(150); + + if (down) tqSwap(hColor, lColor); + + if (TQPixmap::defaultDepth() > 8) { + KPixmapEffect::gradient(*pix, hColor, lColor, + KPixmapEffect::DiagonalGradient); + } + else + pix->fill(primary); + int x2 = pix->width() - 1; + int y2 = pix->height() - 1; + p.setPen(lColor); + p.drawLine(0, 0, x2, 0); + p.drawLine(0, 0, 0, y2); + p.drawLine(1, x2 - 1, x2 - 1, y2 - 1); + p.drawLine(x2 - 1, 1, x2 - 1, y2 - 1); + p.setPen(hColor); + p.drawRect(1, 1, x2, y2); + +} + +TQPixmap* twin_get_menu_pix_hack() +{ + //return menu_pix; FIXME + return PIXMAP_A(P_MENU); +} + +static void create_pixmaps() +{ + if (pixmaps_created) + return; + pixmaps_created = true; + + int i; + int bsize = buttonSize - 2; + if (bsize < 16) bsize = 16; + + for (i = 0; i < NUM_PIXMAPS; i++) { + pixmap[i] = new KPixmap; + switch (i / NumStates) { + case P_MAX: // will be initialized by copying P_CLOSE + case P_RESIZE: + break; + case P_ICONIFY: + pixmap[i]->resize(10, 10); break; + case P_SHADE: + case P_CLOSE: + pixmap[i]->resize(bsize, bsize); break; + default: + pixmap[i]->resize(16, 16); break; + } + } + + // there seems to be no way to load X bitmaps from data properly, so + // we need to create new ones for each mask :P + TQBitmap pinupMask(16, 16, pinup_mask_bits, true); + PIXMAP_A(P_PINUP)->setMask(pinupMask); + PIXMAP_I(P_PINUP)->setMask(pinupMask); + TQBitmap pindownMask(16, 16, pindown_mask_bits, true); + PIXMAP_AD(P_PINUP)->setMask(pindownMask); + PIXMAP_ID(P_PINUP)->setMask(pindownMask); + + TQBitmap menuMask(16, 16, menu_mask_bits, true); + for (i = 0; i < NumStates; i++) + pixmap[P_MENU * NumStates + i]->setMask(menuMask); + + TQBitmap helpMask(16, 16, help_mask_bits, true); + for (i = 0; i < NumStates; i++) + pixmap[P_HELP * NumStates + i]->setMask(helpMask); + + TQBitmap normalizeMask(16, 16, true); + // draw normalize icon mask + TQPainter mask; + mask.begin(&normalizeMask); + + TQBrush one(Qt::color1); + mask.fillRect(normalizeMask.width() - 12, normalizeMask.height() - 12, + 12, 12, one); + mask.fillRect(0, 0, 10, 10, one); + mask.end(); + + for (i = 0; i < NumStates; i++) + pixmap[P_NORMALIZE * NumStates + i]->setMask(normalizeMask); + + TQBitmap shadeMask(bsize, bsize, true); + mask.begin(&shadeMask); + mask.fillRect(0, 0, bsize, 6, one); + mask.end(); + for (i = 0; i < NumStates; i++) + pixmap[P_SHADE * NumStates + i]->setMask(shadeMask); + + titleGradient[0] = 0; + titleGradient[1] = 0; + + redraw_pixmaps(); +} + +static void delete_pixmaps() +{ + for (int i = 0; i < NUM_PIXMAPS; i++) { + delete pixmap[i]; + pixmap[i] = 0; + } + for (int i = 0; i < 2; i++) { + delete titleGradient[i]; + titleGradient[i] = 0; + } + pixmaps_created = false; +} + +// ===================================== + +B2ClientFactory::B2ClientFactory() +{ + read_config(this); + create_pixmaps(); +} + +B2ClientFactory::~B2ClientFactory() +{ + delete_pixmaps(); +} + +KDecoration *B2ClientFactory::createDecoration(KDecorationBridge *b) +{ + return new B2::B2Client(b, this); +} + +bool B2ClientFactory::reset(unsigned long changed) +{ + bool needsReset = SettingColors ? true : false; + // TODO Do not recreate decorations if it is not needed. Look at + // ModernSystem for how to do that + read_config(this); + if (changed & SettingFont) { + delete_pixmaps(); + create_pixmaps(); + needsReset = true; + } + redraw_pixmaps(); + // For now just return true. + return needsReset; +} + +bool B2ClientFactory::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: + case AbilityButtonResize: + return true; + default: + return false; + }; +} + +TQValueList< B2ClientFactory::BorderSize > B2ClientFactory::borderSizes() const +{ + // the list must be sorted + return TQValueList< BorderSize >() << BorderTiny << BorderNormal << + BorderLarge << BorderVeryLarge << BorderHuge; +} + +// ===================================== + +void B2Client::maxButtonClicked() +{ + maximize(button[BtnMax]->last_button); +} + +void B2Client::shadeButtonClicked() +{ + setShade(!isSetShade()); +} + +void B2Client::resizeButtonPressed() +{ + performWindowOperation(ResizeOp); +} + +B2Client::B2Client(KDecorationBridge *b, KDecorationFactory *f) + : KDecoration(b, f), bar_x_ofs(0), in_unobs(0) +{ +} + +void B2Client::init() +{ + const TQString tips[] = { + i18n("Menu"), + isOnAllDesktops() ? + i18n("Not on all desktops") : i18n("On all desktops"), + i18n("Minimize"), i18n("Maximize"), + i18n("Close"), i18n("Help"), + isSetShade() ? i18n("Unshade") : i18n("Shade"), + i18n("Resize") + }; + + // Check this early, otherwise the preview will be rendered badly. + resizable = isResizable(); + + createMainWidget((WFlags)(WResizeNoErase | WRepaintNoErase)); + widget()->installEventFilter(this); + + widget()->setBackgroundMode(NoBackground); + + // Set button pointers to NULL so we know what has been created + for (int i = 0; i < BtnCount; i++) + button[i] = NULL; + + g = new TQGridLayout(widget(), 3, 3); + // Left and right border width + + leftSpacer = new TQSpacerItem(thickness, 16, + TQSizePolicy::Fixed, TQSizePolicy::Expanding); + rightSpacer = new TQSpacerItem(thickness, 16, + TQSizePolicy::Fixed, TQSizePolicy::Expanding); + + g->addItem(leftSpacer, 1, 0); + g->addItem(rightSpacer, 1, 2); + + // Top border height + topSpacer = new TQSpacerItem(10, buttonSize + 4, + TQSizePolicy::Expanding, TQSizePolicy::Fixed); + g->addItem(topSpacer, 0, 1); + + // Bottom border height. + bottomSpacer = new TQSpacerItem(10, + thickness + (mustDrawHandle() ? 4 : 0), + TQSizePolicy::Expanding, TQSizePolicy::Fixed); + g->addItem(bottomSpacer, 2, 1); + if (isPreview()) { + TQLabel *previewLabel = new TQLabel( + i18n("<b><center>B II preview</center></b>"), + widget()); + g->addWidget(previewLabel, 1, 1); + + } else { + g->addItem(new TQSpacerItem(0, 0), 1, 1); + } + + // titlebar + g->setRowSpacing(0, buttonSize + 4); + + titlebar = new B2Titlebar(this); + titlebar->setMinimumWidth(buttonSize + 4); + titlebar->setFixedHeight(buttonSize + 4); + + TQBoxLayout *titleLayout = new TQBoxLayout(titlebar, + TQBoxLayout::LeftToRight, 0, 1, 0); + titleLayout->addSpacing(3); + + if (options()->customButtonPositions()) { + addButtons(options()->titleButtonsLeft(), tips, titlebar, titleLayout); + titleLayout->addItem(titlebar->captionSpacer); + addButtons(options()->titleButtonsRight(), tips, titlebar, titleLayout); + } else { + addButtons("MSH", tips, titlebar, titleLayout); + titleLayout->addItem(titlebar->captionSpacer); + addButtons("IAX", tips, titlebar, titleLayout); + } + + titleLayout->addSpacing(3); + + TQColor c = options()->colorGroup(KDecoration::ColorTitleBar, isActive()). + color(TQColorGroup::Button); + + for (int i = 0; i < BtnCount; i++) { + if (button[i]) + button[i]->setBg(c); + } + + titlebar->updateGeometry(); + positionButtons(); + titlebar->recalcBuffer(); + titlebar->installEventFilter(this); +} + +bool B2Client::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(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + result = XGetWindowProperty(tqt_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 B2Client::addButtons(const TQString& s, const TQString tips[], + B2Titlebar* tb, TQBoxLayout* titleLayout) +{ + if (s.length() <= 0) + return; + + for (unsigned int i = 0; i < s.length(); i++) { + switch (s[i].latin1()) { + case 'M': // Menu button + if (!isModalSystemNotification()) { + if (!button[BtnMenu]) { + button[BtnMenu] = new B2Button(this, tb, tips[BtnMenu], + Qt::LeftButton | Qt::RightButton); + button[BtnMenu]->setPixmaps(P_MENU); + button[BtnMenu]->setUseMiniIcon(); + connect(button[BtnMenu], TQT_SIGNAL(pressed()), + this, TQT_SLOT(menuButtonPressed())); + titleLayout->addWidget(button[BtnMenu]); + } + } + break; + case 'S': // Sticky button + if (!isModalSystemNotification()) { + if (!button[BtnSticky]) { + button[BtnSticky] = new B2Button(this, tb, tips[BtnSticky]); + button[BtnSticky]->setPixmaps(P_PINUP); + button[BtnSticky]->setToggle(); + button[BtnSticky]->setDown(isOnAllDesktops()); + connect(button[BtnSticky], TQT_SIGNAL(clicked()), + this, TQT_SLOT(toggleOnAllDesktops())); + titleLayout->addWidget(button[BtnSticky]); + } + } + break; + case 'H': // Help button + if (providesContextHelp() && (!button[BtnHelp])) { + button[BtnHelp] = new B2Button(this, tb, tips[BtnHelp]); + button[BtnHelp]->setPixmaps(P_HELP); + connect(button[BtnHelp], TQT_SIGNAL(clicked()), + this, TQT_SLOT(showContextHelp())); + titleLayout->addWidget(button[BtnHelp]); + } + break; + case 'I': // Minimize button + if (isMinimizable() && (!button[BtnIconify])) { + button[BtnIconify] = new B2Button(this, tb,tips[BtnIconify]); + button[BtnIconify]->setPixmaps(P_ICONIFY); + connect(button[BtnIconify], TQT_SIGNAL(clicked()), + this, TQT_SLOT(minimize())); + titleLayout->addWidget(button[BtnIconify]); + } + break; + case 'A': // Maximize button + if (isMaximizable() && (!button[BtnMax])) { + button[BtnMax] = new B2Button(this, tb, tips[BtnMax], + Qt::LeftButton | Qt::MidButton | Qt::RightButton); + button[BtnMax]->setPixmaps(maximizeMode() == MaximizeFull ? + P_NORMALIZE : P_MAX); + connect(button[BtnMax], TQT_SIGNAL(clicked()), + this, TQT_SLOT(maxButtonClicked())); + titleLayout->addWidget(button[BtnMax]); + } + break; + case 'X': // Close button + if (isCloseable() && !button[BtnClose]) { + button[BtnClose] = new B2Button(this, tb, tips[BtnClose]); + button[BtnClose]->setPixmaps(P_CLOSE); + connect(button[BtnClose], TQT_SIGNAL(clicked()), + this, TQT_SLOT(closeWindow())); + titleLayout->addWidget(button[BtnClose]); + } + break; + case 'L': // Shade button + if (isShadeable() && !button[BtnShade]) { + button[BtnShade] = new B2Button(this, tb, tips[BtnShade]); + button[BtnShade]->setPixmaps(P_SHADE); + connect(button[BtnShade], TQT_SIGNAL(clicked()), + this, TQT_SLOT(shadeButtonClicked())); + titleLayout->addWidget(button[BtnShade]); + } + break; + case 'R': // Resize button + if (resizable && !button[BtnResize]) { + button[BtnResize] = new B2Button(this, tb, tips[BtnResize]); + button[BtnResize]->setPixmaps(P_RESIZE); + connect(button[BtnResize], TQT_SIGNAL(pressed()), + this, TQT_SLOT(resizeButtonPressed())); + titleLayout->addWidget(button[BtnResize]); + } + break; + case '_': // Additional spacing + titleLayout->addSpacing(4); + break; + } + } +} + +bool B2Client::mustDrawHandle() const +{ + if (drawSmallBorders && (maximizeMode() & MaximizeVertical)) { + return false; + } else { + return do_draw_handle && resizable; + } +} + +void B2Client::iconChange() +{ + if (button[BtnMenu]) + button[BtnMenu]->repaint(false); +} + +// Gallium: New button show/hide magic for customizable +// button positions. +void B2Client::calcHiddenButtons() +{ + // Hide buttons in this order: + // Shade, Sticky, Help, Resize, Maximize, Minimize, Close, Menu + B2Button* btnArray[] = { + button[BtnShade], button[BtnSticky], button[BtnHelp], button[BtnResize], + button[BtnMax], button[BtnIconify], button[BtnClose], button[BtnMenu] + }; + int minWidth = 120; + int currentWidth = width(); + int count = 0; + int i; + + // Determine how many buttons we need to hide + while (currentWidth < minWidth) { + currentWidth += buttonSize + 1; // Allow for spacer (extra 1pix) + count++; + } + // Bound the number of buttons to hide + if (count > BtnCount) count = BtnCount; + + // Hide the required buttons + for (i = 0; i < count; i++) { + if (btnArray[i] && btnArray[i]->isVisible()) + btnArray[i]->hide(); + } + // Show the rest of the buttons + for (i = count; i < BtnCount; i++) { + if (btnArray[i] && (!btnArray[i]->isVisible())) + btnArray[i]->show(); + } +} + +void B2Client::resizeEvent(TQResizeEvent * /*e*/) +{ + calcHiddenButtons(); + titlebar->layout()->activate(); + positionButtons(); + + /* may be the resize cut off some space occupied by titlebar, which + was moved, so instead of reducing it, we first try to move it */ + titleMoveAbs(bar_x_ofs); + + doShape(); + widget()->repaint(); // the frame is misrendered without this +} + +void B2Client::captionChange() +{ + positionButtons(); + titleMoveAbs(bar_x_ofs); + doShape(); + titlebar->recalcBuffer(); + titlebar->repaint(false); +} + +void B2Client::paintEvent(TQPaintEvent* e) +{ + TQPainter p(widget()); + + KDecoration::ColorType frameColorGroup = colored_frame ? + KDecoration::ColorTitleBar : KDecoration::ColorFrame; + + TQRect t = titlebar->geometry(); + + // Frame height, this is used a lot of times + int fHeight = height() - t.height(); + + // distance from the bottom border - it is different if window is resizable + int bb = mustDrawHandle() ? 4 : 0; + int bDepth = thickness + bb; + + TQColorGroup fillColor = options()->colorGroup(frameColorGroup, isActive()); + TQBrush fillBrush(options()->color(frameColorGroup, isActive())); + + // outer frame rect + p.drawRect(0, t.bottom() - thickness + 1, + width(), fHeight - bb + thickness); + + if (thickness >= 2) { + // inner window rect + p.drawRect(thickness - 1, t.bottom(), + width() - 2 * (thickness - 1), fHeight - bDepth + 2); + + if (thickness >= 3) { + // frame shade panel + qDrawShadePanel(&p, 1, t.bottom() - thickness + 2, + width() - 2, fHeight - 2 - bb + thickness, fillColor, false); + if (thickness == 4) { + p.setPen(fillColor.background()); + p.drawRect(thickness - 2, t.bottom() - 1, + width() - 2 * (thickness - 2), fHeight + 4 - bDepth); + } else if (thickness > 4) { + qDrawShadePanel(&p, thickness - 2, + t.bottom() - 1, width() - 2 * (thickness - 2), + fHeight + 4 - bDepth, fillColor, true); + if (thickness >= 5) { + // draw frame interior + p.fillRect(2, t.bottom() - thickness + 3, + width() - 4, thickness - 4, fillBrush); + p.fillRect(2, height() - bDepth + 2, + width() - 4, thickness - 4, fillBrush); + p.fillRect(2, t.bottom() - 1, + thickness - 4, fHeight - bDepth + 4, fillBrush); + p.fillRect(width() - thickness + 2, t.bottom() - 1, + thickness - 4, fHeight - bDepth + 4, fillBrush); + } + } + } + } + + // bottom handle rect + if (mustDrawHandle()) { + p.setPen(Qt::black); + int hx = width() - 40; + int hw = 40; + + p.drawLine(width() - 1, height() - thickness - 4, + width() - 1, height() - 1); + p.drawLine(hx, height() - 1, width() - 1, height() - 1); + p.drawLine(hx, height() - 4, hx, height() - 1); + + p.fillRect(hx + 1, height() - thickness - 3, + hw - 2, thickness + 2, fillBrush); + + p.setPen(fillColor.dark()); + p.drawLine(width() - 2, height() - thickness - 4, + width() - 2, height() - 2); + p.drawLine(hx + 1, height() - 2, width() - 2, height() - 2); + + p.setPen(fillColor.light()); + p.drawLine(hx + 1, height() - thickness - 2, + hx + 1, height() - 3); + p.drawLine(hx + 1, height() - thickness - 3, + width() - 3, height() - thickness - 3); + } + + /* OK, we got a paint event, which means parts of us are now visible + which were not before. We try the titlebar if it is currently fully + obscured, and if yes, try to unobscure it, in the hope that some + of the parts which we just painted were in the titlebar area. + It can happen, that the titlebar, as it got the FullyObscured event + had no chance of becoming partly visible. The problem is, that + we now might have the space available, but the titlebar gets no + visibilitinotify events until its state changes, so we just try + */ + if (titlebar->isFullyObscured()) { + /* We first see, if our repaint contained the titlebar area */ + TQRegion reg(TQRect(0, 0, width(), buttonSize + 4)); + reg = reg.intersect(e->region()); + if (!reg.isEmpty()) + unobscureTitlebar(); + } +} + +void B2Client::doShape() +{ + TQRect t = titlebar->geometry(); + TQRegion mask(widget()->rect()); + // top to the tilebar right + if (bar_x_ofs) { + // left from bar + mask -= TQRect(0, 0, bar_x_ofs, t.height() - thickness); + // top left point + mask -= TQRect(0, t.height() - thickness, 1, 1); + } + if (t.right() < width() - 1) { + mask -= TQRect(width() - 1, + t.height() - thickness, 1, 1); //top right point + mask -= TQRect(t.right() + 1, 0, + width() - t.right() - 1, t.height() - thickness); + } + // bottom right point + mask -= TQRect(width() - 1, height() - 1, 1, 1); + if (mustDrawHandle()) { + // bottom left point + mask -= TQRect(0, height() - 5, 1, 1); + // handle left point + mask -= TQRect(width() - 40, height() - 1, 1, 1); + // bottom left + mask -= TQRect(0, height() - 4, width() - 40, 4); + } else { + // bottom left point + mask -= TQRect(0, height() - 1, 1, 1); + } + + setMask(mask); +} + +void B2Client::showEvent(TQShowEvent *) +{ + calcHiddenButtons(); + positionButtons(); + doShape(); +} + +KDecoration::Position B2Client::mousePosition(const TQPoint& p) const +{ + const int range = 16; + TQRect t = titlebar->geometry(); + t.setHeight(buttonSize + 4 - thickness); + int ly = t.bottom(); + int lx = t.right(); + int bb = mustDrawHandle() ? 0 : 5; + + if (p.x() > t.right()) { + if (p.y() <= ly + range && p.x() >= width() - range) + return PositionTopRight; + else if (p.y() <= ly + thickness) + return PositionTop; + } else if (p.x() < bar_x_ofs) { + if (p.y() <= ly + range && p.x() <= range) + return PositionTopLeft; + else if (p.y() <= ly + thickness) + return PositionTop; + } else if (p.y() < ly) { + if (p.x() > bar_x_ofs + thickness && + p.x() < lx - thickness && p.y() > thickness) + return KDecoration::mousePosition(p); + if (p.x() > bar_x_ofs + range && p.x() < lx - range) + return PositionTop; + if (p.y() <= range) { + if (p.x() <= bar_x_ofs + range) + return PositionTopLeft; + else return PositionTopRight; + } else { + if (p.x() <= bar_x_ofs + range) + return PositionLeft; + else return PositionRight; + } + } + + if (p.y() >= height() - 8 + bb) { + /* the normal Client:: only wants border of 4 pixels */ + if (p.x() <= range) return PositionBottomLeft; + if (p.x() >= width() - range) return PositionBottomRight; + return PositionBottom; + } + + return KDecoration::mousePosition(p); +} + +void B2Client::titleMoveAbs(int new_ofs) +{ + if (new_ofs < 0) new_ofs = 0; + if (new_ofs + titlebar->width() > width()) { + new_ofs = width() - titlebar->width(); + } + if (bar_x_ofs != new_ofs) { + bar_x_ofs = new_ofs; + positionButtons(); + doShape(); + widget()->repaint(0, 0, width(), buttonSize + 4, false); + titlebar->repaint(false); + } +} + +void B2Client::titleMoveRel(int xdiff) +{ + titleMoveAbs(bar_x_ofs + xdiff); +} + +void B2Client::desktopChange() +{ + bool on = isOnAllDesktops(); + if (B2Button *b = button[BtnSticky]) { + b->setDown(on); + TQToolTip::remove(b); + TQToolTip::add(b, + on ? i18n("Not on all desktops") : i18n("On all desktops")); + } +} + +void B2Client::maximizeChange() +{ + bool m = maximizeMode() == MaximizeFull; + if (button[BtnMax]) { + button[BtnMax]->setPixmaps(m ? P_NORMALIZE : P_MAX); + button[BtnMax]->repaint(); + TQToolTip::remove(button[BtnMax]); + TQToolTip::add(button[BtnMax], + m ? i18n("Restore") : i18n("Maximize")); + } + bottomSpacer->changeSize(10, thickness + (mustDrawHandle() ? 4 : 0), + TQSizePolicy::Expanding, TQSizePolicy::Minimum); + + g->activate(); + doShape(); + widget()->repaint(false); +} + +void B2Client::activeChange() +{ + widget()->repaint(false); + titlebar->repaint(false); + + TQColor c = options()->colorGroup( + KDecoration::ColorTitleBar, isActive()).color(TQColorGroup::Button); + + for (int i = 0; i < BtnCount; i++) + if (button[i]) { + button[i]->setBg(c); + button[i]->repaint(false); + } +} + +void B2Client::shadeChange() +{ + bottomSpacer->changeSize(10, thickness + (mustDrawHandle() ? 4 : 0), + TQSizePolicy::Expanding, TQSizePolicy::Minimum); + g->activate(); + doShape(); + if (B2Button *b = button[BtnShade]) { + TQToolTip::remove(b); + TQToolTip::add(b, isSetShade() ? i18n("Unshade") : i18n("Shade")); + } +} + +TQSize B2Client::minimumSize() const +{ + int left, right, top, bottom; + borders(left, right, top, bottom); + return TQSize(left + right + 2 * buttonSize, top + bottom); +} + +void B2Client::resize(const TQSize& s) +{ + widget()->resize(s); +} + +void B2Client::borders(int &left, int &right, int &top, int &bottom) const +{ + left = right = thickness; + top = buttonSize + 4; + bottom = thickness + (mustDrawHandle() ? 4 : 0); +} + +void B2Client::menuButtonPressed() +{ + static B2Client *lastClient = NULL; + + bool dbl = (lastClient == this && + time.elapsed() <= TQApplication::doubleClickInterval()); + lastClient = this; + time.start(); + if (!dbl) { + KDecorationFactory* f = factory(); + TQRect menuRect = button[BtnMenu]->rect(); + TQPoint menuTop = button[BtnMenu]->mapToGlobal(menuRect.topLeft()); + TQPoint menuBottom = button[BtnMenu]->mapToGlobal(menuRect.bottomRight()); + showWindowMenu(TQRect(menuTop, menuBottom)); + if (!f->exists(this)) // 'this' was destroyed + return; + button[BtnMenu]->setDown(false); + } else { + switch (menu_dbl_click_op) { + case B2::MinimizeOp: + minimize(); + break; + case B2::ShadeOp: + setShade(!isSetShade()); + break; + case B2::CloseOp: + closeWindow(); + break; + case B2::NoOp: + default: + break; + } + } +} + +void B2Client::unobscureTitlebar() +{ + /* we just noticed, that we got obscured by other windows + so we look at all windows above us (stacking_order) merging their + masks, intersecting it with our titlebar area, and see if we can + find a place not covered by any window */ + if (in_unobs) { + return; + } + in_unobs = 1; + TQRegion reg(TQRect(0,0,width(), buttonSize + 4)); + reg = unobscuredRegion(reg); + if (!reg.isEmpty()) { + // there is at least _one_ pixel from our title area, which is not + // obscured, we use the first rect we find + // for a first test, we use boundingRect(), later we may refine + // to rect(), and search for the nearest, or biggest, or smthg. + titleMoveAbs(reg.boundingRect().x()); + } + in_unobs = 0; +} + +static void redraw_pixmaps() +{ + int i; + TQColorGroup aGrp = options()->colorGroup(KDecoration::ColorButtonBg, true); + TQColorGroup iGrp = options()->colorGroup(KDecoration::ColorButtonBg, false); + + // close + drawB2Rect(PIXMAP_A(P_CLOSE), aGrp.button(), false); + drawB2Rect(PIXMAP_AH(P_CLOSE), aGrp.button(), true); + drawB2Rect(PIXMAP_AD(P_CLOSE), aGrp.button(), true); + + drawB2Rect(PIXMAP_I(P_CLOSE), iGrp.button(), false); + drawB2Rect(PIXMAP_IH(P_CLOSE), iGrp.button(), true); + drawB2Rect(PIXMAP_ID(P_CLOSE), iGrp.button(), true); + + // shade + KPixmap thinBox; + thinBox.resize(buttonSize - 2, 6); + for (i = 0; i < NumStates; i++) { + bool is_act = (i < 2); + bool is_down = ((i & 1) == 1); + KPixmap *pix = pixmap[P_SHADE * NumStates + i]; + TQColor color = is_act ? aGrp.button() : iGrp.button(); + drawB2Rect(&thinBox, color, is_down); + pix->fill(Qt::black); + bitBlt(TQT_TQPAINTDEVICE(pix), 0, 0, TQT_TQPAINTDEVICE(&thinBox), + 0, 0, thinBox.width(), thinBox.height(), TQt::CopyROP, true); + } + + // maximize + for (i = 0; i < NumStates; i++) { + *pixmap[P_MAX * NumStates + i] = *pixmap[P_CLOSE * NumStates + i]; + pixmap[P_MAX * NumStates + i]->detach(); + } + + // normalize + iconify + KPixmap smallBox; + smallBox.resize(10, 10); + KPixmap largeBox; + largeBox.resize(12, 12); + + for (i = 0; i < NumStates; i++) { + bool is_act = (i < 3); + bool is_down = (i == Down || i == IDown); + KPixmap *pix = pixmap[P_NORMALIZE * NumStates + i]; + drawB2Rect(&smallBox, is_act ? aGrp.button() : iGrp.button(), is_down); + drawB2Rect(&largeBox, is_act ? aGrp.button() : iGrp.button(), is_down); + pix->fill(options()->color(KDecoration::ColorTitleBar, is_act)); + bitBlt(TQT_TQPAINTDEVICE(pix), pix->width() - 12, pix->width() - 12, TQT_TQPAINTDEVICE(&largeBox), + 0, 0, 12, 12, TQt::CopyROP, true); + bitBlt(TQT_TQPAINTDEVICE(pix), 0, 0, TQT_TQPAINTDEVICE(&smallBox), 0, 0, 10, 10, TQt::CopyROP, true); + + bitBlt(TQT_TQPAINTDEVICE(pixmap[P_ICONIFY * NumStates + i]), 0, 0, + TQT_TQPAINTDEVICE(&smallBox), 0, 0, 10, 10, TQt::CopyROP, true); + } + + // resize + for (i = 0; i < NumStates; i++) { + bool is_act = (i < 3); + bool is_down = (i == Down || i == IDown); + *pixmap[P_RESIZE * NumStates + i] = *pixmap[P_CLOSE * NumStates + i]; + pixmap[P_RESIZE * NumStates + i]->detach(); + drawB2Rect(&smallBox, is_act ? aGrp.button() : iGrp.button(), is_down); + bitBlt(TQT_TQPAINTDEVICE(pixmap[P_RESIZE * NumStates + i]), + 0, 0, TQT_TQPAINTDEVICE(&smallBox), 0, 0, 10, 10, TQt::CopyROP, true); + } + + + TQPainter p; + // x for close + menu + help + for (int j = 0; j < 3; j++) { + int pix; + unsigned const char *light, *dark; + switch (j) { + case 0: + pix = P_CLOSE; light = close_white_bits; dark = close_dgray_bits; + break; + case 1: + pix = P_MENU; light = menu_white_bits; dark = menu_dgray_bits; + break; + default: + pix = P_HELP; light = help_light_bits; dark = help_dark_bits; + break; + } + int off = (pixmap[pix * NumStates]->width() - 16) / 2; + for (i = 0; i < NumStates; i++) { + p.begin(pixmap[pix * NumStates + i]); + kColorBitmaps(&p, (i < 3) ? aGrp : iGrp, off, off, 16, 16, true, + light, NULL, NULL, dark, NULL, NULL); + p.end(); + } + } + + // pin + for (i = 0; i < NumStates; i++) { + bool isDown = (i == Down || i == IDown); + unsigned const char *white = isDown ? pindown_white_bits : pinup_white_bits; + unsigned const char *gray = isDown ? pindown_gray_bits : pinup_gray_bits; + unsigned const char *dgray =isDown ? pindown_dgray_bits : pinup_dgray_bits; + p.begin(pixmap[P_PINUP * NumStates + i]); + kColorBitmaps(&p, (i < 3) ? aGrp : iGrp, 0, 0, 16, 16, true, white, + gray, NULL, dgray, NULL, NULL); + p.end(); + } + + // Apply the hilight effect to the 'Hover' icons + TDEIconEffect ie; + TQPixmap hilighted; + for (i = 0; i < P_NUM_BUTTON_TYPES; i++) { + int offset = i * NumStates; + hilighted = ie.apply(*pixmap[offset + Norm], + TDEIcon::Small, TDEIcon::ActiveState); + *pixmap[offset + Hover] = hilighted; + + hilighted = ie.apply(*pixmap[offset + INorm], + TDEIcon::Small, TDEIcon::ActiveState); + *pixmap[offset + IHover] = hilighted; + } + + + // Create the titlebar gradients + if (TQPixmap::defaultDepth() > 8) { + TQColor titleColor[4] = { + options()->color(KDecoration::ColorTitleBar, true), + options()->color(KDecoration::ColorFrame, true), + + options()->color(KDecoration::ColorTitleBlend, false), + options()->color(KDecoration::ColorTitleBar, false) + }; + + if (colored_frame) { + titleColor[0] = options()->color(KDecoration::ColorTitleBlend, true); + titleColor[1] = options()->color(KDecoration::ColorTitleBar, true); + } + + for (i = 0; i < 2; i++) { + if (titleColor[2 * i] != titleColor[2 * i + 1]) { + if (!titleGradient[i]) { + titleGradient[i] = new KPixmap; + } + titleGradient[i]->resize(64, buttonSize + 3); + KPixmapEffect::gradient(*titleGradient[i], + titleColor[2 * i], titleColor[2 * i + 1], + KPixmapEffect::VerticalGradient); + } else { + delete titleGradient[i]; + titleGradient[i] = 0; + } + } + } +} + +void B2Client::positionButtons() +{ + TQFontMetrics fm(options()->font(isActive())); + TQString cap = caption(); + if (cap.length() < 5) // make sure the titlebar has sufficiently wide + cap = "XXXXX"; // area for dragging the window + int textLen = fm.width(cap); + + TQRect t = titlebar->captionSpacer->geometry(); + int titleWidth = titlebar->width() - t.width() + textLen + 2; + if (titleWidth > width()) titleWidth = width(); + + titlebar->resize(titleWidth, buttonSize + 4); + titlebar->move(bar_x_ofs, 0); +} + +// Transparent bound stuff. + +static TQRect *visible_bound; +static TQPointArray bound_shape; + +bool B2Client::drawbound(const TQRect& geom, bool clear) +{ + if (clear) { + if (!visible_bound) return true; + } + + if (!visible_bound) { + visible_bound = new TQRect(geom); + TQRect t = titlebar->geometry(); + int frameTop = geom.top() + t.bottom(); + int barLeft = geom.left() + bar_x_ofs; + int barRight = barLeft + t.width() - 1; + if (barRight > geom.right()) barRight = geom.right(); + // line width is 5 pixels, so compensate for the 2 outer pixels (#88657) + TQRect g = geom; + g.setLeft( g.left() + 2 ); + g.setTop( g.top() + 2 ); + g.setRight( g.right() - 2 ); + g.setBottom( g.bottom() - 2 ); + frameTop += 2; + barLeft += 2; + barRight -= 2; + + bound_shape.putPoints(0, 8, + g.left(), frameTop, + barLeft, frameTop, + barLeft, g.top(), + barRight, g.top(), + barRight, frameTop, + g.right(), frameTop, + g.right(), g.bottom(), + g.left(), g.bottom()); + } else { + *visible_bound = geom; + } + TQPainter p(workspaceWidget()); + p.setPen(TQPen(Qt::white, 5)); + p.setRasterOp(TQt::XorROP); + p.drawPolygon(bound_shape); + + if (clear) { + delete visible_bound; + visible_bound = 0; + } + return true; +} + +bool B2Client::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: + titlebar->mouseDoubleClickEvent(TQT_TQMOUSEEVENT(e)); + return true; + case TQEvent::Wheel: + titlebar->wheelEvent(TQT_TQWHEELEVENT(e)); + return true; + case TQEvent::MouseButtonPress: + processMousePressEvent(TQT_TQMOUSEEVENT(e)); + return true; + case TQEvent::Show: + showEvent(TQT_TQSHOWEVENT(e)); + return true; + default: + break; + } + return false; +} + +// ===================================== + +B2Button::B2Button(B2Client *_client, TQWidget *parent, + const TQString& tip, const int realizeBtns) + : TQButton(parent, 0), hover(false) +{ + setBackgroundMode(NoBackground); + setCursor(tqarrowCursor); + realizeButtons = realizeBtns; + client = _client; + useMiniIcon = false; + setFixedSize(buttonSize, buttonSize); + TQToolTip::add(this, tip); +} + + +TQSize B2Button::sizeHint() const +{ + return TQSize(buttonSize, buttonSize); +} + +TQSizePolicy B2Button::sizePolicy() const +{ + return(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed)); +} + +void B2Button::drawButton(TQPainter *p) +{ + KPixmap* gradient = titleGradient[client->isActive() ? 0 : 1]; + if (gradient) { + p->drawTiledPixmap(0, 0, buttonSize, buttonSize, *gradient, 0, 2); + } else { + p->fillRect(rect(), bg); + } + if (useMiniIcon) { + TQPixmap miniIcon = client->icon().pixmap(TQIconSet::Small, + client->isActive() ? TQIconSet::Normal : TQIconSet::Disabled); + p->drawPixmap((width() - miniIcon.width()) / 2, + (height() - miniIcon.height()) / 2, miniIcon); + } else { + int type; + if (client->isActive()) { + if (isOn() || isDown()) + type = Down; + else if (hover) + type = Hover; + else + type = Norm; + } else { + if (isOn() || isDown()) + type = IDown; + else if (hover) + type = IHover; + else + type = INorm; + } + p->drawPixmap((width() - icon[type]->width()) / 2, + (height() - icon[type]->height()) / 2, *icon[type]); + } +} + +void B2Button::setPixmaps(int button_id) +{ + button_id *= NumStates; + for (int i = 0; i < NumStates; i++) { + icon[i] = B2::pixmap[button_id + i]; + } + repaint(false); +} + +void B2Button::mousePressEvent(TQMouseEvent * e) +{ + last_button = e->button(); + TQMouseEvent me(e->type(), e->pos(), e->globalPos(), + (e->button() & realizeButtons) ? Qt::LeftButton : Qt::NoButton, + e->state()); + TQButton::mousePressEvent(&me); +} + +void B2Button::mouseReleaseEvent(TQMouseEvent * e) +{ + last_button = e->button(); + TQMouseEvent me(e->type(), e->pos(), e->globalPos(), + (e->button() & realizeButtons) ? Qt::LeftButton : Qt::NoButton, + e->state()); + TQButton::mouseReleaseEvent(&me); +} + +void B2Button::enterEvent(TQEvent *e) +{ + hover = true; + repaint(false); + TQButton::enterEvent(e); +} + +void B2Button::leaveEvent(TQEvent *e) +{ + hover = false; + repaint(false); + TQButton::leaveEvent(e); +} + +// ===================================== + +B2Titlebar::B2Titlebar(B2Client *parent) + : TQWidget(parent->widget(), 0, (WFlags)(WStyle_Customize | WRepaintNoErase)), + client(parent), + set_x11mask(false), isfullyobscured(false), shift_move(false) +{ + setBackgroundMode(NoBackground); + captionSpacer = new TQSpacerItem(buttonSize, buttonSize + 4, + TQSizePolicy::Expanding, TQSizePolicy::Fixed); +} + +bool B2Titlebar::x11Event(XEvent *e) +{ + if (!set_x11mask) { + set_x11mask = true; + XSelectInput(tqt_xdisplay(), winId(), + KeyPressMask | KeyReleaseMask | + ButtonPressMask | ButtonReleaseMask | + KeymapStateMask | + ButtonMotionMask | + EnterWindowMask | LeaveWindowMask | + FocusChangeMask | + ExposureMask | + PropertyChangeMask | + StructureNotifyMask | SubstructureRedirectMask | + VisibilityChangeMask); + } + switch (e->type) { + case VisibilityNotify: + isfullyobscured = false; + if (e->xvisibility.state == VisibilityFullyObscured) { + isfullyobscured = true; + client->unobscureTitlebar(); + } + break; + default: + break; + } + return TQWidget::x11Event(e); +} + +void B2Titlebar::drawTitlebar(TQPainter &p, bool state) +{ + KPixmap* gradient = titleGradient[state ? 0 : 1]; + + TQRect t = rect(); + // black titlebar frame + p.setPen(Qt::black); + p.drawLine(0, 0, 0, t.bottom()); + p.drawLine(0, 0, t.right(), 0); + p.drawLine(t.right(), 0, t.right(), t.bottom()); + + // titlebar fill + const TQColorGroup cg = + options()->colorGroup(KDecoration::ColorTitleBar, state); + TQBrush brush(cg.background()); + if (gradient) brush.setPixmap(*gradient); + qDrawShadeRect(&p, 1, 1, t.right() - 1, t.height() - 1, + cg, false, 1, 0, &brush); + + // and the caption + p.setPen(options()->color(KDecoration::ColorFont, state)); + p.setFont(options()->font(state)); + t = captionSpacer->geometry(); + p.drawText(t, AlignLeft | AlignVCenter, client->caption()); +} + +void B2Titlebar::recalcBuffer() +{ + titleBuffer.resize(width(), height()); + + TQPainter p(&titleBuffer); + drawTitlebar(p, true); + oldTitle = caption(); +} + +void B2Titlebar::resizeEvent(TQResizeEvent *) +{ + recalcBuffer(); + repaint(false); +} + + +void B2Titlebar::paintEvent(TQPaintEvent *) +{ + if(client->isActive()) + bitBlt(TQT_TQPAINTDEVICE(this), 0, 0, TQT_TQPAINTDEVICE(&titleBuffer), 0, 0, titleBuffer.width(), + titleBuffer.height(), TQt::CopyROP, true); + else { + TQPainter p(this); + drawTitlebar(p, false); + } +} + +void B2Titlebar::mouseDoubleClickEvent(TQMouseEvent *e) +{ + if (e->button() == Qt::LeftButton && e->y() < height()) { + client->titlebarDblClickOperation(); + } +} + +void B2Titlebar::wheelEvent(TQWheelEvent *e) +{ + if (client->isSetShade() || TQT_TQRECT_OBJECT(rect()).contains(e->pos())) + client->titlebarMouseWheelOperation( e->delta()); +} + +void B2Titlebar::mousePressEvent(TQMouseEvent * e) +{ + shift_move = e->state() & ShiftButton; + if (shift_move) { + moveOffset = e->globalPos(); + } else { + e->ignore(); + } +} + +void B2Titlebar::mouseReleaseEvent(TQMouseEvent * e) +{ + if (shift_move) shift_move = false; + else e->ignore(); +} + +void B2Titlebar::mouseMoveEvent(TQMouseEvent * e) +{ + if (shift_move) { + int oldx = mapFromGlobal(moveOffset).x(); + int xdiff = e->globalPos().x() - moveOffset.x(); + moveOffset = e->globalPos(); + if (oldx >= 0 && oldx <= rect().right()) { + client->titleMoveRel(xdiff); + } + } else { + e->ignore(); + } +} + +} // namespace B2 + +#include "b2client.moc" + +// vim: sw=4 + diff --git a/twin/clients/b2/b2client.h b/twin/clients/b2/b2client.h new file mode 100644 index 000000000..30220b175 --- /dev/null +++ b/twin/clients/b2/b2client.h @@ -0,0 +1,167 @@ +/* + * B-II KWin Client + * + * Changes: + * Customizable button positions by Karol Szwed <gallium@kde.org> + * Ported to the trinity.2 API by Luciano Montanaro <mikelima@cirulla.net> + */ + +#ifndef __B2CLIENT_H +#define __B2CLIENT_H + +#include <tqvariant.h> +#include <tqdatetime.h> +#include <tqbutton.h> +#include <tqbitmap.h> +#include <kpixmap.h> +#include <kdecoration.h> +#include <kdecorationfactory.h> + +class TQSpacerItem; +class TQBoxLayout; +class TQGridLayout; + +namespace B2 { + +class B2Client; + +class B2Button : public TQButton +{ +public: + B2Button(B2Client *_client=0, TQWidget *parent=0, const TQString& tip=NULL, const int realizeBtns = Qt::LeftButton); + ~B2Button() {}; + + void setBg(const TQColor &c){bg = c;} + void setPixmaps(KPixmap *pix, KPixmap *pixDown, KPixmap *iPix, + KPixmap *iPixDown); + void setPixmaps(int button_id); + void setToggle(){setToggleType(Toggle);} + void setActive(bool on){setOn(on);} + void setUseMiniIcon(){useMiniIcon = true;} + TQSize sizeHint() const; + TQSizePolicy sizePolicy() const; +protected: + virtual void drawButton(TQPainter *p); + void drawButtonLabel(TQPainter *){;} + + void mousePressEvent( TQMouseEvent* e ); + void mouseReleaseEvent( TQMouseEvent* e ); +private: + void enterEvent(TQEvent *e); + void leaveEvent(TQEvent *e); + + bool useMiniIcon; + KPixmap *icon[6]; + TQColor bg; //only use one color (the rest is pixmap) so forget TQPalette ;) + +public: + B2Client* client; + ButtonState last_button; + int realizeButtons; + bool hover; +}; + +class B2Titlebar : public TQWidget +{ + friend class B2Client; +public: + B2Titlebar(B2Client *parent); + ~B2Titlebar(){;} + bool isFullyObscured() const {return isfullyobscured;} + void recalcBuffer(); + TQSpacerItem *captionSpacer; +protected: + void paintEvent( TQPaintEvent* ); + bool x11Event(XEvent *e); + void mouseDoubleClickEvent( TQMouseEvent * ); + void wheelEvent(TQWheelEvent *); + void mousePressEvent( TQMouseEvent * ); + void mouseReleaseEvent( TQMouseEvent * ); + void mouseMoveEvent(TQMouseEvent *); + void resizeEvent(TQResizeEvent *ev); +private: + void drawTitlebar(TQPainter &p, bool state); + + B2Client *client; + TQString oldTitle; + KPixmap titleBuffer; + TQPoint moveOffset; + bool set_x11mask; + bool isfullyobscured; + bool shift_move; +}; + +class B2Client : public KDecoration +{ + Q_OBJECT + friend class B2Titlebar; +public: + B2Client(KDecorationBridge *b, KDecorationFactory *f); + ~B2Client(){;} + void init(); + void unobscureTitlebar(); + void titleMoveAbs(int new_ofs); + void titleMoveRel(int xdiff); + // transparent stuff + virtual bool drawbound(const TQRect& geom, bool clear); +protected: + void resizeEvent( TQResizeEvent* ); + void paintEvent( TQPaintEvent* ); + void showEvent( TQShowEvent* ); + void windowWrapperShowEvent( TQShowEvent* ); + void captionChange(); + void desktopChange(); + void shadeChange(); + void activeChange(); + void maximizeChange(); + void iconChange(); + void doShape(); + Position mousePosition( const TQPoint& p ) const; + void resize(const TQSize&); + void borders(int &, int &, int &, int &) const; + TQSize minimumSize() const; + bool eventFilter(TQObject *, TQEvent *); +private slots: + void menuButtonPressed(); + //void slotReset(); + void maxButtonClicked(); + void shadeButtonClicked(); + void resizeButtonPressed(); +private: + void addButtons(const TQString& s, const TQString tips[], + B2Titlebar* tb, TQBoxLayout* titleLayout); + void positionButtons(); + void calcHiddenButtons(); + bool mustDrawHandle() const; + bool isModalSystemNotification(); + + enum ButtonType{BtnMenu=0, BtnSticky, BtnIconify, BtnMax, BtnClose, + BtnHelp, BtnShade, BtnResize, BtnCount}; + B2Button* button[BtnCount]; + TQGridLayout *g; + // Border spacers + TQSpacerItem *topSpacer; + TQSpacerItem *bottomSpacer; + TQSpacerItem *leftSpacer; + TQSpacerItem *rightSpacer; + B2Titlebar *titlebar; + int bar_x_ofs; + int in_unobs; + TQTime time; + bool resizable; +}; + +class B2ClientFactory : public TQObject, public KDecorationFactory +{ +public: + B2ClientFactory(); + virtual ~B2ClientFactory(); + virtual KDecoration *createDecoration(KDecorationBridge *); + virtual bool reset(unsigned long changed); + virtual bool supports( Ability ability ); + TQValueList< B2ClientFactory::BorderSize > borderSizes() const; +}; + +} + +#endif diff --git a/twin/clients/b2/bitmaps.h b/twin/clients/b2/bitmaps.h new file mode 100644 index 000000000..2f610f4b2 --- /dev/null +++ b/twin/clients/b2/bitmaps.h @@ -0,0 +1,98 @@ +#ifndef __STDCLIENT_BITMAPS_H +#define __STDCLIENT_BITMAPS_H + +/** + * The standard client has the capability to color it's titlebar buttons + * according to the new color scheme. In order to do this it needs a bitmap + * for each shade which it draws into a pixmap with the appropriate color. + * These are all the bitmaps. + */ + +static const unsigned char close_white_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0x04, 0x08, 0x08, 0x04, 0x10, 0x02, + 0x20, 0x01, 0x40, 0x00, 0x40, 0x00, 0x20, 0x01, 0x10, 0x02, 0x08, 0x04, + 0x04, 0x08, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char close_dgray_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x18, 0x30, 0x30, 0x18, 0x60, 0x0c, + 0xc0, 0x06, 0x80, 0x03, 0x80, 0x03, 0xc0, 0x06, 0x60, 0x0c, 0x30, 0x18, + 0x18, 0x30, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char menu_white_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0x3f, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char menu_dgray_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char menu_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0x3f, 0x04, 0x20, 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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 pindown_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x1f, 0xf0, 0x3f, 0xf0, 0x3f, + 0xf8, 0x3f, 0xf8, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf0, 0x1f, 0xf0, 0x0f, + 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 pinup_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0xc0, 0x31, 0xc0, 0x3f, + 0xff, 0x3f, 0xff, 0x3f, 0xff, 0x3f, 0xc0, 0x3f, 0xc0, 0x31, 0xc0, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char help_mask_bits[] = { + 0x00,0x00,0x00,0x00,0xe0,0x03,0xf0,0x07,0x70,0x0e,0x60,0x0e,0x00,0x0f,0x80, + 0x07,0xc0,0x03,0xc0,0x01,0x80,0x01,0xc0,0x00,0xc0,0x01,0x80,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x4c,0x0b,0x08,0x58,0x65,0x09,0x08,0x90,0x00,0x00, + 0x00,0x09,0x04,0x00,0x00,0x72,0x6f,0x6f,0x74,0x00,0x24,0x31,0x24,0x47,0x6b, + 0x65,0x44,0x78,0x63 }; + +static const unsigned char help_dark_bits[] = { + 0x00,0x00,0x00,0x00,0xe0,0x03,0x30,0x06,0x30,0x06,0x00,0x06,0x00,0x03,0x80, + 0x01,0xc0,0x00,0xc0,0x00,0x00,0x00,0xc0,0x00,0xc0,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x65,0x64,0x28,0x29,0x00,0x00,0x00,0x00,0x90,0x00,0x00, + 0x00,0x21,0x00,0x00,0x00,0x34,0xfe,0x12,0x2b,0x00,0x00,0xff,0xff,0x58,0xc0, + 0x01,0x2b,0x45,0xfe }; + +static const unsigned char help_light_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0x40,0x08,0x60,0x08,0x00,0x0c,0x00, + 0x06,0x00,0x03,0x00,0x01,0x80,0x01,0x00,0x00,0x00,0x01,0x80,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x4c,0x0b,0x08,0x58,0x65,0x09,0x08,0x90,0x00,0x00, + 0x00,0x09,0x04,0x00,0x00,0x72,0x6f,0x6f,0x74,0x00,0x24,0x31,0x24,0x47,0x6b, + 0x65,0x44,0x78,0x63 }; + +#endif + diff --git a/twin/clients/b2/config/CMakeLists.txt b/twin/clients/b2/config/CMakeLists.txt new file mode 100644 index 000000000..0785fb176 --- /dev/null +++ b/twin/clients/b2/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_b2_config (module) ################### + +tde_add_kpart( twin_b2_config AUTOMOC + SOURCES config.cpp + LINK tdeui-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/twin/clients/b2/config/Makefile.am b/twin/clients/b2/config/Makefile.am new file mode 100644 index 000000000..4319b5375 --- /dev/null +++ b/twin/clients/b2/config/Makefile.am @@ -0,0 +1,16 @@ +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = twin_b2_config.la + +twin_b2_config_la_SOURCES = config.cpp +twin_b2_config_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +twin_b2_config_la_LIBADD = $(LIB_TDEUI) + +METASOURCES = AUTO +noinst_HEADERS = config.h + +lnkdir = $(kde_datadir)/twin/ + +###KMAKE-start (don't edit or delete this block) + +###KMAKE-end diff --git a/twin/clients/b2/config/config.cpp b/twin/clients/b2/config/config.cpp new file mode 100644 index 000000000..77ca65338 --- /dev/null +++ b/twin/clients/b2/config/config.cpp @@ -0,0 +1,165 @@ +/* + * This file contains the B2 configuration widget + * + * Copyright (c) 2001 + * Karol Szwed <gallium@kde.org> + * http://gallium.n3.net/ + */ + +#include "config.h" +#include <tdeglobal.h> +#include <tqwhatsthis.h> +#include <tqvbox.h> +#include <tdelocale.h> + + +extern "C" +{ + KDE_EXPORT TQObject* allocate_config( TDEConfig* conf, TQWidget* parent ) + { + return(new B2Config(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 + */ + +B2Config::B2Config( TDEConfig* conf, TQWidget* parent ) + : TQObject( parent ) +{ + TDEGlobal::locale()->insertCatalogue("twin_b2_config"); + b2Config = new TDEConfig("twinb2rc"); + gb = new TQVBox(parent); + + cbColorBorder = new TQCheckBox( + i18n("Draw window frames using &titlebar colors"), gb); + TQWhatsThis::add(cbColorBorder, + i18n("When selected, the window borders " + "are drawn using the titlebar colors; otherwise, they are " + "drawn using normal border colors.")); + + // Grab Handle + showGrabHandleCb = new TQCheckBox( + i18n("Draw &resize handle"), gb); + TQWhatsThis::add(showGrabHandleCb, + i18n("When selected, decorations are drawn with a \"grab handle\" " + "in the bottom right corner of the windows; " + "otherwise, no grab handle is drawn.")); + + // Double click menu option support + actionsGB = new TQHGroupBox(i18n("Actions Settings"), gb); + TQLabel *menuDblClickLabel = new TQLabel(actionsGB); + menuDblClickLabel->setText(i18n("Double click on menu button:")); + menuDblClickOp = new TQComboBox(actionsGB); + menuDblClickOp->insertItem(i18n("Do Nothing")); + menuDblClickOp->insertItem(i18n("Minimize Window")); + menuDblClickOp->insertItem(i18n("Shade Window")); + menuDblClickOp->insertItem(i18n("Close Window")); + + TQWhatsThis::add(menuDblClickOp, + i18n("An action can be associated to a double click " + "of the menu button. Leave it to none if in doubt.")); + + // Load configuration options + load(conf); + + // Ensure we track user changes properly + connect(cbColorBorder, TQT_SIGNAL(clicked()), + this, TQT_SLOT(slotSelectionChanged())); + connect(showGrabHandleCb, TQT_SIGNAL(clicked()), + this, TQT_SLOT(slotSelectionChanged())); + connect(menuDblClickOp, TQT_SIGNAL(activated(int)), + this, TQT_SLOT(slotSelectionChanged())); + // Make the widgets visible in twindecoration + gb->show(); +} + + +B2Config::~B2Config() +{ + delete b2Config; + delete gb; +} + + +void B2Config::slotSelectionChanged() +{ + emit changed(); +} + + +// Loads the configurable options from the twinrc config file +// It is passed the open config from twindecoration to improve efficiency +void B2Config::load(TDEConfig * /*conf*/) +{ + b2Config->setGroup("General"); + + bool override = b2Config->readBoolEntry("UseTitleBarBorderColors", false); + cbColorBorder->setChecked(override); + + override = b2Config->readBoolEntry( "DrawGrabHandle", true ); + showGrabHandleCb->setChecked(override); + + TQString returnString = b2Config->readEntry( + "MenuButtonDoubleClickOperation", "NoOp"); + + int op; + if (returnString == "Close") { + op = 3; + } else if (returnString == "Shade") { + op = 2; + } else if (returnString == "Minimize") { + op = 1; + } else { + op = 0; + } + + menuDblClickOp->setCurrentItem(op); + +} + +static TQString opToString(int op) +{ + switch (op) { + case 1: + return "Minimize"; + case 2: + return "Shade"; + case 3: + return "Close"; + case 0: + default: + return "NoOp"; + } +} + + +// Saves the configurable options to the twinrc config file +void B2Config::save(TDEConfig * /*conf*/) +{ + b2Config->setGroup("General"); + b2Config->writeEntry("UseTitleBarBorderColors", cbColorBorder->isChecked()); + b2Config->writeEntry("DrawGrabHandle", showGrabHandleCb->isChecked()); + b2Config->writeEntry("MenuButtonDoubleClickOperation", + opToString(menuDblClickOp->currentItem())); + // Ensure others trying to read this config get updated + b2Config->sync(); +} + + +// Sets UI widget defaults which must correspond to style defaults +void B2Config::defaults() +{ + cbColorBorder->setChecked(false); + showGrabHandleCb->setChecked(true); + menuDblClickOp->setCurrentItem(0); +} + +#include "config.moc" +// vim: ts=4 diff --git a/twin/clients/b2/config/config.h b/twin/clients/b2/config/config.h new file mode 100644 index 000000000..a1ca8ebdd --- /dev/null +++ b/twin/clients/b2/config/config.h @@ -0,0 +1,50 @@ +/* + * This file contains the B2 configuration widget + * + * Copyright (c) 2001 + * Karol Szwed <gallium@kde.org> + * http://gallium.n3.net/ + */ + +#ifndef _KDE_B2CONFIG_H +#define _KDE_B2CONFIG_H + +#include <tqcheckbox.h> +#include <tqgroupbox.h> +#include <tqhgroupbox.h> +#include <tqlabel.h> +#include <tqcombobox.h> +#include <tdeconfig.h> + +class B2Config: public TQObject +{ + Q_OBJECT + + public: + B2Config( TDEConfig* conf, TQWidget* parent ); + ~B2Config(); + + // These public signals/slots work similar to KCM modules + signals: + void changed(); + + public slots: + void load( TDEConfig* conf ); + void save( TDEConfig* conf ); + void defaults(); + + protected slots: + void slotSelectionChanged(); // Internal use + + private: + TDEConfig* b2Config; + TQCheckBox* cbColorBorder; + TQCheckBox* showGrabHandleCb; + TQHGroupBox* actionsGB; + TQComboBox* menuDblClickOp; + TQWidget* gb; +}; + +#endif + +// vim: ts=4 diff --git a/twin/clients/default/CMakeLists.txt b/twin/clients/default/CMakeLists.txt new file mode 100644 index 000000000..142a9b783 --- /dev/null +++ b/twin/clients/default/CMakeLists.txt @@ -0,0 +1,32 @@ +################################################# +# +# (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} +) + + +##### twin3_default (module) #################### + +tde_add_kpart( twin3_default AUTOMOC + SOURCES kdedefault.cpp + LINK tdecorations-shared tdecore-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/twin/clients/default/Makefile.am b/twin/clients/default/Makefile.am new file mode 100644 index 000000000..3e687a2a6 --- /dev/null +++ b/twin/clients/default/Makefile.am @@ -0,0 +1,14 @@ + +INCLUDES = -I$(srcdir)/../../lib $(all_includes) + +SUBDIRS = . config + +kde_module_LTLIBRARIES = twin3_default.la + +twin3_default_la_SOURCES = kdedefault.cpp +twin3_default_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +twin3_default_la_LIBADD = $(LIB_TDECORE) ../../lib/libtdecorations.la + +METASOURCES = AUTO +noinst_HEADERS = kdedefault.h + diff --git a/twin/clients/default/config/CMakeLists.txt b/twin/clients/default/config/CMakeLists.txt new file mode 100644 index 000000000..5814e011f --- /dev/null +++ b/twin/clients/default/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_default_config (module) ############## + +tde_add_kpart( twin_default_config AUTOMOC + SOURCES config.cpp + LINK tdeui-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/twin/clients/default/config/Makefile.am b/twin/clients/default/config/Makefile.am new file mode 100644 index 000000000..3a1df8aa2 --- /dev/null +++ b/twin/clients/default/config/Makefile.am @@ -0,0 +1,16 @@ +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = twin_default_config.la + +twin_default_config_la_SOURCES = config.cpp +twin_default_config_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +twin_default_config_la_LIBADD = $(LIB_TDEUI) + +METASOURCES = AUTO +noinst_HEADERS = config.h + +lnkdir = $(kde_datadir)/twin/ + +###KMAKE-start (don't edit or delete this block) + +###KMAKE-end diff --git a/twin/clients/default/config/config.cpp b/twin/clients/default/config/config.cpp new file mode 100644 index 000000000..f479c0c69 --- /dev/null +++ b/twin/clients/default/config/config.cpp @@ -0,0 +1,131 @@ +/* + * + * KDE2 Default configuration widget + * + * Copyright (c) 2001 + * Karol Szwed <gallium@kde.org> + * http://gallium.n3.net/ + */ + +#include "config.h" +#include <tdeglobal.h> +#include <tqwhatsthis.h> +#include <kdialog.h> +#include <tdelocale.h> +#include <tqpixmap.h> +#include <tqvbox.h> + +extern "C" +{ + KDE_EXPORT TQObject* allocate_config( TDEConfig* conf, TQWidget* parent ) + { + return(new KDEDefaultConfig(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 + +KDEDefaultConfig::KDEDefaultConfig( TDEConfig* conf, TQWidget* parent ) + : TQObject( parent ) +{ + TDEGlobal::locale()->insertCatalogue("twin_clients"); + highcolor = TQPixmap::defaultDepth() > 8; + gb = new TQVBox( parent ); + gb->setSpacing( KDialog::spacingHint() ); + + cbShowStipple = new TQCheckBox( i18n("Draw titlebar &stipple effect"), gb ); + TQWhatsThis::add( cbShowStipple, + i18n("When selected, active titlebars are drawn " + "with a stipple (dotted) effect; otherwise, they are " + "drawn without the stipple.")); + + cbShowGrabBar = new TQCheckBox( i18n("Draw g&rab bar below windows"), gb ); + TQWhatsThis::add( cbShowGrabBar, + i18n("When selected, decorations are drawn with a \"grab bar\" " + "below windows; otherwise, no grab bar is drawn.")); + + // Only show the gradient checkbox for highcolor displays + if (highcolor) + { + cbUseGradients = new TQCheckBox( i18n("Draw &gradients"), gb ); + TQWhatsThis::add( cbUseGradients, + i18n("When selected, decorations are drawn with gradients " + "for high-color displays; otherwise, no gradients are drawn.") ); + } + + // Load configuration options + load( conf ); + + // Ensure we track user changes properly + connect( cbShowStipple, TQT_SIGNAL(clicked()), + this, TQT_SLOT(slotSelectionChanged()) ); + connect( cbShowGrabBar, TQT_SIGNAL(clicked()), + this, TQT_SLOT(slotSelectionChanged()) ); + if (highcolor) + connect( cbUseGradients, TQT_SIGNAL(clicked()), + this, TQT_SLOT(slotSelectionChanged()) ); + + // Make the widgets visible in twindecoration + gb->show(); +} + + +KDEDefaultConfig::~KDEDefaultConfig() +{ + delete gb; +} + + +void KDEDefaultConfig::slotSelectionChanged() +{ + emit changed(); +} + + +// Loads the configurable options from the twinrc config file +// It is passed the open config from twindecoration to improve efficiency +void KDEDefaultConfig::load( TDEConfig* conf ) +{ + conf->setGroup("KDEDefault"); + bool override = conf->readBoolEntry( "ShowTitleBarStipple", true ); + cbShowStipple->setChecked( override ); + + override = conf->readBoolEntry( "ShowGrabBar", true ); + cbShowGrabBar->setChecked( override ); + + if (highcolor) { + override = conf->readBoolEntry( "UseGradients", true ); + cbUseGradients->setChecked( override ); + } +} + + +// Saves the configurable options to the twinrc config file +void KDEDefaultConfig::save( TDEConfig* conf ) +{ + conf->setGroup("KDEDefault"); + conf->writeEntry( "ShowTitleBarStipple", cbShowStipple->isChecked() ); + conf->writeEntry( "ShowGrabBar", cbShowGrabBar->isChecked() ); + + if (highcolor) + conf->writeEntry( "UseGradients", cbUseGradients->isChecked() ); + // No need to conf->sync() - twindecoration will do it for us +} + + +// Sets UI widget defaults which must correspond to style defaults +void KDEDefaultConfig::defaults() +{ + cbShowStipple->setChecked( true ); + cbShowGrabBar->setChecked( true ); + + if (highcolor) + cbUseGradients->setChecked( true ); +} + +#include "config.moc" +// vim: ts=4 diff --git a/twin/clients/default/config/config.h b/twin/clients/default/config/config.h new file mode 100644 index 000000000..a09ac1ab3 --- /dev/null +++ b/twin/clients/default/config/config.h @@ -0,0 +1,49 @@ +/* + * + * KDE2 Default configuration widget + * + * Copyright (c) 2001 + * Karol Szwed <gallium@kde.org> + * http://gallium.n3.net/ + */ + +#ifndef _KDE_DEFAULT_CONFIG_H +#define _KDE_DEFAULT_CONFIG_H + +#include <tqcheckbox.h> +#include <tqgroupbox.h> +#include <tdeconfig.h> +#include <tqhbox.h> +#include <tqlabel.h> +#include <tqvbox.h> + +class KDEDefaultConfig: public TQObject +{ + Q_OBJECT + + public: + KDEDefaultConfig( TDEConfig* conf, TQWidget* parent ); + ~KDEDefaultConfig(); + + // These public signals/slots work similar to KCM modules + signals: + void changed(); + + public slots: + void load( TDEConfig* conf ); + void save( TDEConfig* conf ); + void defaults(); + + protected slots: + void slotSelectionChanged(); // Internal use + + private: + TQCheckBox* cbShowStipple; + TQCheckBox* cbShowGrabBar; + TQCheckBox* cbUseGradients; + TQVBox* gb; + bool highcolor; +}; + +#endif +// vim: ts=4 diff --git a/twin/clients/default/kdedefault.cpp b/twin/clients/default/kdedefault.cpp new file mode 100644 index 000000000..7892c4adc --- /dev/null +++ b/twin/clients/default/kdedefault.cpp @@ -0,0 +1,1069 @@ +/* + * + * KDE2 Default KWin client + * + * Copyright (C) 1999, 2001 Daniel Duley <mosfet@kde.org> + * Matthias Ettrich <ettrich@kde.org> + * Karol Szwed <gallium@kde.org> + * + * Draws mini titlebars for tool windows. + * Many features are now customizable. + */ + +#include "kdedefault.h" + +#include <tdeconfig.h> +#include <tdeglobal.h> +#include <kpixmapeffect.h> +#include <kimageeffect.h> +#include <kdrawutil.h> +#include <tdelocale.h> +#include <tqlayout.h> +#include <tqdrawutil.h> +#include <tqbitmap.h> +#include <tqimage.h> +#include <tqtooltip.h> +#include <tqapplication.h> +#include <tqlabel.h> +#include <kdebug.h> + +namespace Default +{ + +static const unsigned char iconify_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, + 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char close_bits[] = { + 0x00, 0x00, 0x84, 0x00, 0xce, 0x01, 0xfc, 0x00, 0x78, 0x00, 0x78, 0x00, + 0xfc, 0x00, 0xce, 0x01, 0x84, 0x00, 0x00, 0x00}; + +static const unsigned char maximize_bits[] = { + 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, + 0x86, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00}; + +static const unsigned char minmax_bits[] = { + 0x7f, 0x00, 0x7f, 0x00, 0x63, 0x00, 0xfb, 0x03, 0xfb, 0x03, 0x1f, 0x03, + 0x1f, 0x03, 0x18, 0x03, 0xf8, 0x03, 0xf8, 0x03}; + +static const unsigned char question_bits[] = { + 0x00, 0x00, 0x78, 0x00, 0xcc, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x30, 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 }; + +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 pindown_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x1f, 0xf0, 0x3f, 0xf0, 0x3f, + 0xf8, 0x3f, 0xf8, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf0, 0x1f, 0xf0, 0x0f, + 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 pinup_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0xc0, 0x31, 0xc0, 0x3f, + 0xff, 0x3f, 0xff, 0x3f, 0xff, 0x3f, 0xc0, 0x3f, 0xc0, 0x31, 0xc0, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +// =========================================================================== + +static TQPixmap* titlePix; +static KPixmap* titleBuffer; +static KPixmap* aUpperGradient; +static KPixmap* iUpperGradient; + +static KPixmap* pinDownPix; +static KPixmap* pinUpPix; +static KPixmap* ipinDownPix; +static KPixmap* ipinUpPix; + +static KPixmap* rightBtnUpPix[2]; +static KPixmap* rightBtnDownPix[2]; +static KPixmap* irightBtnUpPix[2]; +static KPixmap* irightBtnDownPix[2]; + +static KPixmap* leftBtnUpPix[2]; +static KPixmap* leftBtnDownPix[2]; +static KPixmap* ileftBtnUpPix[2]; +static KPixmap* ileftBtnDownPix[2]; + +static KDEDefaultHandler* clientHandler; +static int toolTitleHeight; +static int normalTitleHeight; +static int borderWidth; +static int grabBorderWidth; +static bool KDEDefault_initialized = false; +static bool useGradients; +static bool showGrabBar; +static bool showTitleBarStipple; + + +// =========================================================================== + +KDEDefaultHandler::KDEDefaultHandler() +{ + clientHandler = this; + readConfig( false ); + createPixmaps(); + KDEDefault_initialized = true; +} + + +KDEDefaultHandler::~KDEDefaultHandler() +{ + KDEDefault_initialized = false; + freePixmaps(); + clientHandler = NULL; +} + +KDecoration* KDEDefaultHandler::createDecoration( KDecorationBridge* b ) +{ + return new KDEDefaultClient( b, this ); +} + +bool KDEDefaultHandler::reset( unsigned long changed ) +{ + KDEDefault_initialized = false; + changed |= readConfig( true ); + if( changed & SettingColors ) + { // pixmaps need to be recreated + freePixmaps(); + createPixmaps(); + } + KDEDefault_initialized = true; + // SettingButtons is handled by KCommonDecoration + bool need_recreate = ( changed & ( SettingDecoration | SettingFont | SettingBorder )) != 0; + if( need_recreate ) // something else than colors changed + return true; + resetDecorations( changed ); + return false; +} + + +unsigned long KDEDefaultHandler::readConfig( bool update ) +{ + unsigned long changed = 0; + TDEConfig* conf = TDEGlobal::config(); + conf->setGroup("KDEDefault"); + + bool new_showGrabBar = conf->readBoolEntry("ShowGrabBar", true); + bool new_showTitleBarStipple = conf->readBoolEntry("ShowTitleBarStipple", true); + bool new_useGradients = conf->readBoolEntry("UseGradients", true); + int new_titleHeight = TQFontMetrics(options()->font(true)).height(); + int new_toolTitleHeight = TQFontMetrics(options()->font(true, true)).height()-2; + + int new_borderWidth; + switch(options()->preferredBorderSize(this)) { + case BorderLarge: + new_borderWidth = 8; + break; + case BorderVeryLarge: + new_borderWidth = 12; + break; + case BorderHuge: + new_borderWidth = 18; + break; + case BorderVeryHuge: + new_borderWidth = 27; + break; + case BorderOversized: + new_borderWidth = 40; + break; + case BorderTiny: + case BorderNormal: + default: + new_borderWidth = 4; + } + + if (new_titleHeight < 16) new_titleHeight = 16; + if (new_titleHeight < new_borderWidth) new_titleHeight = new_borderWidth; + if (new_toolTitleHeight < 12) new_toolTitleHeight = 12; + if (new_toolTitleHeight < new_borderWidth) new_toolTitleHeight = new_borderWidth; + + if( update ) + { + if( new_showGrabBar != showGrabBar + || new_titleHeight != normalTitleHeight + || new_toolTitleHeight != toolTitleHeight + || new_borderWidth != borderWidth ) + changed |= SettingDecoration; // need recreating the decoration + if( new_showTitleBarStipple != showTitleBarStipple + || new_useGradients != useGradients + || new_titleHeight != normalTitleHeight + || new_toolTitleHeight != toolTitleHeight ) + changed |= SettingColors; // just recreate the pixmaps and repaint + } + + showGrabBar = new_showGrabBar; + showTitleBarStipple = new_showTitleBarStipple; + useGradients = new_useGradients; + normalTitleHeight = new_titleHeight; + toolTitleHeight = new_toolTitleHeight; + borderWidth = new_borderWidth; + grabBorderWidth = (borderWidth > 15) ? borderWidth + 15 : 2*borderWidth; + return changed; +} + + +// This paints the button pixmaps upon loading the style. +void KDEDefaultHandler::createPixmaps() +{ + bool highcolor = useGradients && (TQPixmap::defaultDepth() > 8); + + // Make the titlebar stipple optional + if (showTitleBarStipple) + { + TQPainter p; + TQPainter maskPainter; + int i, x, y; + titlePix = new TQPixmap(132, normalTitleHeight+2); + TQBitmap mask(132, normalTitleHeight+2); + mask.fill(Qt::color0); + + p.begin(titlePix); + maskPainter.begin(&mask); + maskPainter.setPen(Qt::color1); + for(i=0, y=2; i < 9; ++i, y+=4) + for(x=1; x <= 132; x+=3) + { + p.setPen(options()->color(ColorTitleBar, true).light(150)); + p.drawPoint(x, y); + maskPainter.drawPoint(x, y); + p.setPen(options()->color(ColorTitleBar, true).dark(150)); + p.drawPoint(x+1, y+1); + maskPainter.drawPoint(x+1, y+1); + } + maskPainter.end(); + p.end(); + titlePix->setMask(mask); + } else + titlePix = NULL; + + TQColor activeTitleColor1(options()->color(ColorTitleBar, true)); + TQColor activeTitleColor2(options()->color(ColorTitleBlend, true)); + + TQColor inactiveTitleColor1(options()->color(ColorTitleBar, false)); + TQColor inactiveTitleColor2(options()->color(ColorTitleBlend, false)); + + // Create titlebar gradient images if required + aUpperGradient = NULL; + iUpperGradient = NULL; + + if(highcolor) + { + // Create the titlebar gradients + if (activeTitleColor1 != activeTitleColor2) + { + aUpperGradient = new KPixmap; + aUpperGradient->resize(128, normalTitleHeight+2); + KPixmapEffect::gradient(*aUpperGradient, + activeTitleColor1, + activeTitleColor2, + KPixmapEffect::VerticalGradient); + } + + if (inactiveTitleColor1 != inactiveTitleColor2) + { + iUpperGradient = new KPixmap; + iUpperGradient->resize(128, normalTitleHeight+2); + + KPixmapEffect::gradient(*iUpperGradient, + inactiveTitleColor1, + inactiveTitleColor2, + KPixmapEffect::VerticalGradient); + } + } + + // Set the sticky pin pixmaps; + TQColorGroup g; + TQPainter p; + + // Active pins + g = options()->colorGroup( ColorButtonBg, true ); + pinUpPix = new KPixmap(); + pinUpPix->resize(16, 16); + p.begin( pinUpPix ); + kColorBitmaps( &p, g, 0, 0, 16, 16, true, pinup_white_bits, + pinup_gray_bits, NULL, NULL, pinup_dgray_bits, NULL ); + p.end(); + pinUpPix->setMask( TQBitmap(16, 16, pinup_mask_bits, true) ); + + pinDownPix = new KPixmap(); + pinDownPix->resize(16, 16); + p.begin( pinDownPix ); + kColorBitmaps( &p, g, 0, 0, 16, 16, true, pindown_white_bits, + pindown_gray_bits, NULL, NULL, pindown_dgray_bits, NULL ); + p.end(); + pinDownPix->setMask( TQBitmap(16, 16, pindown_mask_bits, true) ); + + // Inactive pins + g = options()->colorGroup( ColorButtonBg, false ); + ipinUpPix = new KPixmap(); + ipinUpPix->resize(16, 16); + p.begin( ipinUpPix ); + kColorBitmaps( &p, g, 0, 0, 16, 16, true, pinup_white_bits, + pinup_gray_bits, NULL, NULL, pinup_dgray_bits, NULL ); + p.end(); + ipinUpPix->setMask( TQBitmap(16, 16, pinup_mask_bits, true) ); + + ipinDownPix = new KPixmap(); + ipinDownPix->resize(16, 16); + p.begin( ipinDownPix ); + kColorBitmaps( &p, g, 0, 0, 16, 16, true, pindown_white_bits, + pindown_gray_bits, NULL, NULL, pindown_dgray_bits, NULL ); + p.end(); + ipinDownPix->setMask( TQBitmap(16, 16, pindown_mask_bits, true) ); + + // Create a title buffer for flicker-free painting + titleBuffer = new KPixmap(); + + // Cache all possible button states + leftBtnUpPix[true] = new KPixmap(); + leftBtnUpPix[true]->resize(normalTitleHeight, normalTitleHeight); + leftBtnDownPix[true] = new KPixmap(); + leftBtnDownPix[true]->resize(normalTitleHeight, normalTitleHeight); + ileftBtnUpPix[true] = new KPixmap(); + ileftBtnUpPix[true]->resize(normalTitleHeight, normalTitleHeight); + ileftBtnDownPix[true] = new KPixmap(); + ileftBtnDownPix[true]->resize(normalTitleHeight, normalTitleHeight); + + rightBtnUpPix[true] = new KPixmap(); + rightBtnUpPix[true]->resize(normalTitleHeight, normalTitleHeight); + rightBtnDownPix[true] = new KPixmap(); + rightBtnDownPix[true]->resize(normalTitleHeight, normalTitleHeight); + irightBtnUpPix[true] = new KPixmap(); + irightBtnUpPix[true]->resize(normalTitleHeight, normalTitleHeight); + irightBtnDownPix[true] = new KPixmap(); + irightBtnDownPix[true]->resize(normalTitleHeight, normalTitleHeight); + + leftBtnUpPix[false] = new KPixmap(); + leftBtnUpPix[false]->resize(toolTitleHeight, normalTitleHeight); + leftBtnDownPix[false] = new KPixmap(); + leftBtnDownPix[false]->resize(toolTitleHeight, normalTitleHeight); + ileftBtnUpPix[false] = new KPixmap(); + ileftBtnUpPix[false]->resize(normalTitleHeight, normalTitleHeight); + ileftBtnDownPix[false] = new KPixmap(); + ileftBtnDownPix[false]->resize(normalTitleHeight, normalTitleHeight); + + rightBtnUpPix[false] = new KPixmap(); + rightBtnUpPix[false]->resize(toolTitleHeight, toolTitleHeight); + rightBtnDownPix[false] = new KPixmap(); + rightBtnDownPix[false]->resize(toolTitleHeight, toolTitleHeight); + irightBtnUpPix[false] = new KPixmap(); + irightBtnUpPix[false]->resize(toolTitleHeight, toolTitleHeight); + irightBtnDownPix[false] = new KPixmap(); + irightBtnDownPix[false]->resize(toolTitleHeight, toolTitleHeight); + + // Draw the button state pixmaps + g = options()->colorGroup( ColorTitleBar, true ); + drawButtonBackground( leftBtnUpPix[true], g, false ); + drawButtonBackground( leftBtnDownPix[true], g, true ); + drawButtonBackground( leftBtnUpPix[false], g, false ); + drawButtonBackground( leftBtnDownPix[false], g, true ); + + g = options()->colorGroup( ColorButtonBg, true ); + drawButtonBackground( rightBtnUpPix[true], g, false ); + drawButtonBackground( rightBtnDownPix[true], g, true ); + drawButtonBackground( rightBtnUpPix[false], g, false ); + drawButtonBackground( rightBtnDownPix[false], g, true ); + + g = options()->colorGroup( ColorTitleBar, false ); + drawButtonBackground( ileftBtnUpPix[true], g, false ); + drawButtonBackground( ileftBtnDownPix[true], g, true ); + drawButtonBackground( ileftBtnUpPix[false], g, false ); + drawButtonBackground( ileftBtnDownPix[false], g, true ); + + g = options()->colorGroup( ColorButtonBg, false ); + drawButtonBackground( irightBtnUpPix[true], g, false ); + drawButtonBackground( irightBtnDownPix[true], g, true ); + drawButtonBackground( irightBtnUpPix[false], g, false ); + drawButtonBackground( irightBtnDownPix[false], g, true ); +} + + +void KDEDefaultHandler::freePixmaps() +{ + // Free button pixmaps + if (rightBtnUpPix[true]) + delete rightBtnUpPix[true]; + if(rightBtnDownPix[true]) + delete rightBtnDownPix[true]; + if (irightBtnUpPix[true]) + delete irightBtnUpPix[true]; + if (irightBtnDownPix[true]) + delete irightBtnDownPix[true]; + + if (leftBtnUpPix[true]) + delete leftBtnUpPix[true]; + if(leftBtnDownPix[true]) + delete leftBtnDownPix[true]; + if (ileftBtnUpPix[true]) + delete ileftBtnUpPix[true]; + if (ileftBtnDownPix[true]) + delete ileftBtnDownPix[true]; + + if (rightBtnUpPix[false]) + delete rightBtnUpPix[false]; + if(rightBtnDownPix[false]) + delete rightBtnDownPix[false]; + if (irightBtnUpPix[false]) + delete irightBtnUpPix[false]; + if (irightBtnDownPix[false]) + delete irightBtnDownPix[false]; + + if (leftBtnUpPix[false]) + delete leftBtnUpPix[false]; + if(leftBtnDownPix[false]) + delete leftBtnDownPix[false]; + if (ileftBtnUpPix[false]) + delete ileftBtnUpPix[false]; + if (ileftBtnDownPix[false]) + delete ileftBtnDownPix[false]; + + // Title images + if (titleBuffer) + delete titleBuffer; + if (titlePix) + delete titlePix; + if (aUpperGradient) + delete aUpperGradient; + if (iUpperGradient) + delete iUpperGradient; + + // Sticky pin images + if (pinUpPix) + delete pinUpPix; + if (ipinUpPix) + delete ipinUpPix; + if (pinDownPix) + delete pinDownPix; + if (ipinDownPix) + delete ipinDownPix; +} + + +void KDEDefaultHandler::drawButtonBackground(KPixmap *pix, + const TQColorGroup &g, bool sunken) +{ + TQPainter p; + int w = pix->width(); + int h = pix->height(); + int x2 = w-1; + int y2 = h-1; + + bool highcolor = useGradients && (TQPixmap::defaultDepth() > 8); + TQColor c = g.background(); + + // Fill the background with a gradient if possible + if (highcolor) + KPixmapEffect::gradient(*pix, c.light(130), c.dark(130), + KPixmapEffect::VerticalGradient); + else + pix->fill(c); + + p.begin(pix); + // outer frame + p.setPen(g.mid()); + p.drawLine(0, 0, x2, 0); + p.drawLine(0, 0, 0, y2); + p.setPen(g.light()); + p.drawLine(x2, 0, x2, y2); + p.drawLine(0, x2, y2, x2); + p.setPen(g.dark()); + p.drawRect(1, 1, w-2, h-2); + p.setPen(sunken ? g.mid() : g.light()); + p.drawLine(2, 2, x2-2, 2); + p.drawLine(2, 2, 2, y2-2); + p.setPen(sunken ? g.light() : g.mid()); + p.drawLine(x2-2, 2, x2-2, y2-2); + p.drawLine(2, x2-2, y2-2, x2-2); +} + +TQValueList< KDEDefaultHandler::BorderSize > KDEDefaultHandler::borderSizes() const +{ // the list must be sorted + return TQValueList< BorderSize >() << BorderNormal << BorderLarge << + BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized; +} + +bool KDEDefaultHandler::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; + }; +} + +// =========================================================================== + +KDEDefaultButton::KDEDefaultButton(ButtonType type, KDEDefaultClient *parent, const char *name) + : KCommonDecorationButton(type, parent, name) +{ + setBackgroundMode( TQWidget::NoBackground ); + + isMouseOver = false; + deco = NULL; + large = !decoration()->isToolWindow(); +} + + +KDEDefaultButton::~KDEDefaultButton() +{ + if (deco) + delete deco; +} + + +void KDEDefaultButton::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 KDEDefaultButton::setBitmap(const unsigned char *bitmap) +{ + delete deco; + deco = 0; + + if (bitmap) { + deco = new TQBitmap(10, 10, bitmap, true); + deco->setMask( *deco ); + } +} + + +void KDEDefaultButton::drawButton(TQPainter *p) +{ + if (!KDEDefault_initialized) + return; + + const bool active = decoration()->isActive(); + + if (deco) { + // Fill the button background with an appropriate button image + KPixmap btnbg; + + if (isLeft() ) { + if (isDown()) + btnbg = active ? + *leftBtnDownPix[large] : *ileftBtnDownPix[large]; + else + btnbg = active ? + *leftBtnUpPix[large] : *ileftBtnUpPix[large]; + } else { + if (isDown()) + btnbg = active ? + *rightBtnDownPix[large] : *irightBtnDownPix[large]; + else + btnbg = active ? + *rightBtnUpPix[large] : *irightBtnUpPix[large]; + } + + p->drawPixmap( 0, 0, btnbg ); + + } else if ( isLeft() ) { + + // Fill the button background with an appropriate color/gradient + // This is for sticky and menu buttons + KPixmap* grad = active ? aUpperGradient : iUpperGradient; + if (!grad) { + TQColor c = KDecoration::options()->color(KDecoration::ColorTitleBar, active); + p->fillRect(0, 0, width(), height(), c ); + } else + p->drawPixmap( 0, 0, *grad, 0,1, width(), height() ); + + } else { + // Draw a plain background for menus or sticky buttons on RHS + TQColor c = KDecoration::options()->color(KDecoration::ColorFrame, active); + 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 sticky button. + if( deco ) { + // Select the appropriate button decoration color + bool darkDeco = tqGray( KDecoration::options()->color( + isLeft() ? KDecoration::ColorTitleBar : KDecoration::ColorButtonBg, + active).rgb() ) > 127; + + if (isMouseOver) + p->setPen( darkDeco ? Qt::darkGray : Qt::lightGray ); + else + p->setPen( darkDeco ? Qt::black : Qt::white ); + + int xOff = (width()-10)/2; + int yOff = (height()-10)/2; + p->drawPixmap(isDown() ? xOff+1: xOff, isDown() ? yOff+1 : yOff, *deco); + + } else { + KPixmap btnpix; + + if (type()==OnAllDesktopsButton) { + if (active) + btnpix = isOn() ? *pinDownPix : *pinUpPix; + else + btnpix = isOn() ? *ipinDownPix : *ipinUpPix; + } else + btnpix = decoration()->icon().pixmap( TQIconSet::Small, TQIconSet::Normal ); + + // Intensify the image if required + if (isMouseOver) { + btnpix = KPixmapEffect::intensity(btnpix, 0.8); + } + + // Smooth scale the pixmap for small titlebars + // This is slow, but we assume this isn't done too often + if ( width() < 16 ) { + btnpix.convertFromImage(TQImage(btnpix.convertToImage()).smoothScale(12, 12)); + p->drawPixmap( 0, 0, btnpix ); + } + else + p->drawPixmap( width()/2-8, height()/2-8, btnpix ); + } +} + + +void KDEDefaultButton::enterEvent(TQEvent *e) +{ + isMouseOver=true; + repaint(false); + TQButton::enterEvent(e); +} + + +void KDEDefaultButton::leaveEvent(TQEvent *e) +{ + isMouseOver=false; + repaint(false); + TQButton::leaveEvent(e); +} + + +// =========================================================================== + +KDEDefaultClient::KDEDefaultClient( KDecorationBridge* b, KDecorationFactory* f ) + : KCommonDecoration( b, f )/*, + m_closing(false)*/ +{ +} + +TQString KDEDefaultClient::visibleName() const +{ + return i18n("KDE2"); +} + +TQString KDEDefaultClient::defaultButtonsLeft() const +{ + return "MS"; +} + +TQString KDEDefaultClient::defaultButtonsRight() const +{ + return "HIAX"; +} + +bool KDEDefaultClient::decorationBehaviour(DecorationBehaviour behaviour) const +{ + switch (behaviour) { + case DB_MenuClose: + return true; + case DB_WindowMask: + return true; + case DB_ButtonHide: + return true; + + default: + return KCommonDecoration::decorationBehaviour(behaviour); + } +} + +int KDEDefaultClient::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *btn) const +{ + switch (lm) { + case LM_BorderLeft: + case LM_BorderRight: + return borderWidth; + + case LM_BorderBottom: + return mustDrawHandle() ? grabBorderWidth : borderWidth; + + case LM_TitleEdgeLeft: + case LM_TitleEdgeRight: + return borderWidth; + + case LM_TitleEdgeTop: + return 3; + + case LM_TitleEdgeBottom: + return 1; + + case LM_TitleBorderLeft: + case LM_TitleBorderRight: + return 1; + + case LM_TitleHeight: + return titleHeight; + + case LM_ButtonWidth: + case LM_ButtonHeight: + return titleHeight; + + case LM_ButtonSpacing: + return 0; + + case LM_ExplicitButtonSpacer: + if ( !isToolWindow() ) + return borderWidth/2; + // fall though + default: + return KCommonDecoration::layoutMetric(lm, respectWindowState, btn); + } +} + +KCommonDecorationButton *KDEDefaultClient::createButton(ButtonType type) +{ + switch (type) { + case MenuButton: + return new KDEDefaultButton(MenuButton, this, "menu"); + case OnAllDesktopsButton: + return new KDEDefaultButton(OnAllDesktopsButton, this, "on_all_desktops"); + case HelpButton: + return new KDEDefaultButton(HelpButton, this, "help"); + case MinButton: + return new KDEDefaultButton(MinButton, this, "minimize"); + case MaxButton: + return new KDEDefaultButton(MaxButton, this, "maximize"); + case CloseButton: + return new KDEDefaultButton(CloseButton, this, "close"); + case AboveButton: + return new KDEDefaultButton(AboveButton, this, "above"); + case BelowButton: + return new KDEDefaultButton(BelowButton, this, "below"); + case ShadeButton: + return new KDEDefaultButton(ShadeButton, this, "shade"); + + default: + return 0; + } +} + +void KDEDefaultClient::init() +{ + // Finally, toolWindows look small + if ( isToolWindow() ) { + titleHeight = toolTitleHeight; + } + else { + titleHeight = normalTitleHeight; + } + + KCommonDecoration::init(); +} + +void KDEDefaultClient::reset( unsigned long changed) +{ + widget()->repaint(); + + KCommonDecoration::reset(changed); +} + +bool KDEDefaultClient::mustDrawHandle() const +{ + bool drawSmallBorders = !options()->moveResizeMaximizedWindows(); + if (drawSmallBorders && (maximizeMode() & MaximizeVertical)) { + return false; + } else { + return showGrabBar && isResizable(); + } +} + +void KDEDefaultClient::paintEvent( TQPaintEvent* ) +{ + if (!KDEDefault_initialized) + return; + + TQColorGroup g; + int offset; + + KPixmap* upperGradient = isActive() ? aUpperGradient : iUpperGradient; + + TQPainter p(widget()); + + // Obtain widget bounds. + TQRect 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(); + + // Determine where to place the extended left titlebar + int leftFrameStart = (h > 42) ? y+titleHeight+26: y+titleHeight; + + // Determine where to make the titlebar color transition + r = titleRect(); + int rightOffset = r.x()+r.width()+1; + + // Create a disposable pixmap buffer for the titlebar + // very early before drawing begins so there is no lag + // during painting pixels. + titleBuffer->resize( rightOffset-3, titleHeight+1 ); + + // Draw an outer black frame + p.setPen(Qt::black); + p.drawRect(x,y,w,h); + + // Draw part of the frame that is the titlebar color + g = options()->colorGroup(ColorTitleBar, isActive()); + p.setPen(g.light()); + p.drawLine(x+1, y+1, rightOffset-1, y+1); + p.drawLine(x+1, y+1, x+1, leftFrameStart+borderWidth-4); + + // Draw titlebar colour separator line + p.setPen(g.dark()); + p.drawLine(rightOffset-1, y+1, rightOffset-1, titleHeight+2); + + p.fillRect(x+2, y+titleHeight+3, + borderWidth-4, leftFrameStart+borderWidth-y-titleHeight-8, + options()->color(ColorTitleBar, isActive() )); + + // Finish drawing the titlebar extension + p.setPen(Qt::black); + p.drawLine(x+1, leftFrameStart+borderWidth-4, x+borderWidth-2, leftFrameStart-1); + p.setPen(g.mid()); + p.drawLine(x+borderWidth-2, y+titleHeight+3, x+borderWidth-2, leftFrameStart-2); + + // Fill out the border edges + g = options()->colorGroup(ColorFrame, isActive()); + p.setPen(g.light()); + p.drawLine(rightOffset, y+1, x2-1, y+1); + p.drawLine(x+1, leftFrameStart+borderWidth-3, x+1, y2-1); + p.setPen(g.dark()); + p.drawLine(x2-1, y+1, x2-1, y2-1); + p.drawLine(x+1, y2-1, x2-1, y2-1); + + p.setPen(options()->color(ColorFrame, isActive())); + TQPointArray a; + TQBrush brush( options()->color(ColorFrame, isActive()), Qt::SolidPattern ); + p.setBrush( brush ); // use solid, yellow brush + a.setPoints( 4, x+2, leftFrameStart+borderWidth-4, + x+borderWidth-2, leftFrameStart, + x+borderWidth-2, y2-2, + x+2, y2-2); + p.drawPolygon( a ); + p.fillRect(x2-borderWidth+2, y+titleHeight+3, + borderWidth-3, y2-y-titleHeight-4, + options()->color(ColorFrame, isActive() )); + + // Draw the bottom handle if required + if (mustDrawHandle()) + { + if(w > 50) + { + qDrawShadePanel(&p, x+1, y2-grabBorderWidth+2, 2*borderWidth+12, grabBorderWidth-2, + g, false, 1, &g.brush(TQColorGroup::Mid)); + qDrawShadePanel(&p, x+2*borderWidth+13, y2-grabBorderWidth+2, w-4*borderWidth-26, grabBorderWidth-2, + g, false, 1, isActive() ? + &g.brush(TQColorGroup::Background) : + &g.brush(TQColorGroup::Mid)); + qDrawShadePanel(&p, x2-2*borderWidth-12, y2-grabBorderWidth+2, 2*borderWidth+12, grabBorderWidth-2, + g, false, 1, &g.brush(TQColorGroup::Mid)); + } else + qDrawShadePanel(&p, x+1, y2-grabBorderWidth+2, w-2, grabBorderWidth-2, + g, false, 1, isActive() ? + &g.brush(TQColorGroup::Background) : + &g.brush(TQColorGroup::Mid)); + offset = grabBorderWidth; + } else + { + p.fillRect(x+2, y2-borderWidth+2, w-4, borderWidth-3, + options()->color(ColorFrame, isActive() )); + offset = borderWidth; + } + + // Draw a frame around the wrapped widget. + p.setPen( g.dark() ); + p.drawRect( x+borderWidth-1, y+titleHeight+3, w-2*borderWidth+2, h-titleHeight-offset-2 ); + + // Draw the title bar. + r = titleRect(); + + // Obtain titlebar blend colours + TQColor c1 = options()->color(ColorTitleBar, isActive() ); + TQColor c2 = options()->color(ColorFrame, isActive() ); + + // Fill with frame color behind RHS buttons + p.fillRect( rightOffset, y+2, x2-rightOffset-1, titleHeight+1, c2); + + TQPainter p2( titleBuffer, this ); + + // Draw the titlebar gradient + if (upperGradient) + p2.drawTiledPixmap(0, 0, rightOffset-3, titleHeight+1, *upperGradient); + else + p2.fillRect(0, 0, rightOffset-3, titleHeight+1, c1); + + // Draw the title text on the pixmap, and with a smaller font + // for toolwindows than the default. + TQFont fnt = options()->font(true); + + if ( isToolWindow() ) + fnt.setPointSize( fnt.pointSize()-2 ); // Shrink font by 2pt + + p2.setFont( fnt ); + + // Draw the titlebar stipple if active and available + if (isActive() && titlePix) + { + TQFontMetrics fm(fnt); + int captionWidth = fm.width(caption()); + if (caption().isRightToLeft()) + p2.drawTiledPixmap( r.x(), 0, r.width()-captionWidth-4, + titleHeight+1, *titlePix ); + else + p2.drawTiledPixmap( r.x()+captionWidth+3, 0, r.width()-captionWidth-4, + titleHeight+1, *titlePix ); + } + + p2.setPen( options()->color(ColorFont, isActive()) ); + p2.drawText(r.x(), 1, r.width()-1, r.height(), + (caption().isRightToLeft() ? AlignRight : AlignLeft) | AlignVCenter, + caption() ); + + bitBlt( widget(), 2, 2, titleBuffer ); + + p2.end(); + + // Ensure a shaded window has no unpainted areas + // Is this still needed? +#if 1 + p.setPen(c2); + p.drawLine(x+borderWidth, y+titleHeight+4, x2-borderWidth, y+titleHeight+4); +#endif +} + +TQRegion KDEDefaultClient::cornerShape(WindowCorner corner) +{ + switch (corner) { + case WC_TopLeft: + return TQRect(0, 0, 1, 1); + + case WC_TopRight: + return TQRect(width()-1, 0, 1, 1); + + case WC_BottomLeft: + return TQRect(0, height()-1, 1, 1); + + case WC_BottomRight: + return TQRect(width()-1, height()-1, 1, 1); + + default: + return TQRegion(); + } +} + +} // namespace + +// Extended KWin plugin interface +extern "C" KDE_EXPORT KDecorationFactory* create_factory() +{ + return new Default::KDEDefaultHandler(); +} + +// vim: ts=4 +// kate: space-indent off; tab-width 4; diff --git a/twin/clients/default/kdedefault.h b/twin/clients/default/kdedefault.h new file mode 100644 index 000000000..70b8847fa --- /dev/null +++ b/twin/clients/default/kdedefault.h @@ -0,0 +1,103 @@ +/* + * + * KDE2 Default KWin client + * + * Copyright (C) 1999, 2001 Daniel Duley <mosfet@kde.org> + * Matthias Ettrich <ettrich@kde.org> + * Karol Szwed <gallium@kde.org> + * + * Draws mini titlebars for tool windows. + * Many features are now customizable. + */ + +#ifndef _KDE_DEFAULT_H +#define _KDE_DEFAULT_H + +#include <tqbutton.h> +#include <tqbitmap.h> +#include <tqdatetime.h> +#include <kpixmap.h> +#include <kcommondecoration.h> +#include <kdecorationfactory.h> + +class TQSpacerItem; +class TQBoxLayout; +class TQGridLayout; + +namespace Default { + +class KDEDefaultClient; + +class KDEDefaultHandler: public KDecorationFactory +{ + public: + KDEDefaultHandler(); + ~KDEDefaultHandler(); + KDecoration* createDecoration( KDecorationBridge* b ); + bool reset( unsigned long changed ); + virtual TQValueList< BorderSize > borderSizes() const; + virtual bool supports( Ability ability ); + + private: + unsigned long readConfig( bool update ); + void createPixmaps(); + void freePixmaps(); + void drawButtonBackground(KPixmap *pix, + const TQColorGroup &g, bool sunken); +}; + + +// class KDEDefaultButton : public TQButton, public KDecorationDefines +class KDEDefaultButton : public KCommonDecorationButton +{ + public: + KDEDefaultButton(ButtonType type, KDEDefaultClient *parent, const char *name); + ~KDEDefaultButton(); + + void reset(unsigned long changed); + + void setBitmap(const unsigned char *bitmap); + + protected: + void enterEvent(TQEvent *); + void leaveEvent(TQEvent *); + void drawButton(TQPainter *p); + void drawButtonLabel(TQPainter*) {;} + + TQBitmap* deco; + bool large; + bool isMouseOver; +}; + + +class KDEDefaultClient : public KCommonDecoration +{ + public: + KDEDefaultClient( KDecorationBridge* b, KDecorationFactory* f ); + ~KDEDefaultClient() {;} + + virtual TQString visibleName() const; + virtual TQString defaultButtonsLeft() const; + virtual TQString 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 TQRegion cornerShape(WindowCorner corner); + + void init(); + void reset( unsigned long changed ); + + protected: + void paintEvent( TQPaintEvent* ); + + private: + bool mustDrawHandle() const; + int titleHeight; +}; + +} + +#endif +// vim: ts=4 +// kate: space-indent off; tab-width 4; diff --git a/twin/clients/keramik/CMakeLists.txt b/twin/clients/keramik/CMakeLists.txt new file mode 100644 index 000000000..89f563d3a --- /dev/null +++ b/twin/clients/keramik/CMakeLists.txt @@ -0,0 +1,54 @@ +################################################# +# +# (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) ########################## + +file(GLOB _pics "${CMAKE_CURRENT_SOURCE_DIR}/pics/*.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..17c1c3f9c --- /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_TDEIO) -ltdetexteditor + +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..0f3be48c7 --- /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 <tdeglobal.h> +#include <tdelocale.h> + +#include <tqcheckbox.h> + +#include "config.h" +#include "config.moc" + +extern "C" +{ + KDE_EXPORT TQObject* allocate_config( TDEConfig* 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( TDEConfig* conf, TQWidget* parent ) + : TQObject( parent ) +{ + TDEGlobal::locale()->insertCatalogue("twin_clients"); + c = new TDEConfig( "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( TDEConfig* ) +{ + 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( TDEConfig* ) +{ + 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..886acb0f5 --- /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 <tdeconfig.h> + +#include "keramikconfig.h" + +class KeramikConfig: public TQObject +{ + Q_OBJECT + + + public: + KeramikConfig( TDEConfig* conf, TQWidget* parent ); + ~KeramikConfig(); + + // These public signals/slots work similar to KCM modules + signals: + void changed(); + + public slots: + void load( TDEConfig* conf ); + void save( TDEConfig* conf ); + void defaults(); + + private: + KeramikConfigUI *ui; + TDEConfig *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..a635c4ee2 --- /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::currentDateTime() ); + 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..55eb5787d --- /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 <tdeconfig.h> +#include <tdelocale.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() +{ + TDEConfig *c = new TDEConfig( "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() ); + TDEIconEffect::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; + repaint( false ); +} + + +void KeramikButton::leaveEvent( TQEvent *e ) +{ + TQButton::leaveEvent( e ); + + hover = false; + repaint( 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::visualRect( 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::visualRect( TQRect(size, 0, size, size), pix->rect() ) ); + else + // Normal + p->drawPixmap( TQPoint(), *pix, TQStyle::visualRect( 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 repaint the window if it's visible + // (i.e. not minimized and on the current desktop) + if ( widget()->isVisible() ) { + widget()->repaint( false ); + + for ( int i = 0; i < NumButtons; i++ ) + if ( button[i] ) button[i]->repaint( 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(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + result = XGetWindowProperty(tqt_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(); + TDEIconEffect::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 = TQMAX( (captionRect.width() - tw) / 3, 8 ); + TQRect tr = TQStyle::visualRect( 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::visualRect( 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 = TQMIN( cw, titlebar->geometry().width() ); + captionRect = TQStyle::visualRect( 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()->repaint( 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()->repaint( 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()->repaint( false ); + + for ( int i=0; i < NumButtons; i++ ) + if ( button[i] ) button[i]->repaint( 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()->repaint( 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()->repaint( false ); + } + } + + if ( button[ MaxButton ] ) { + TQToolTip::remove( button[ MaxButton ] ); + TQToolTip::add( button[ MaxButton ], maximizeMode() == MaximizeFull ? i18n("Restore") : i18n("Maximize") ); + button[ MaxButton ]->repaint(); + } +} + + +void KeramikClient::desktopChange() +{ + if ( button[ OnAllDesktopsButton ] ) + { + button[ OnAllDesktopsButton ]->repaint( 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 ]->repaint( true ); + TQToolTip::remove( button[ ShadeButton ] ); + TQToolTip::add( button[ ShadeButton ], isSetShade() ? i18n("Unshade") : i18n("Shade") ); + } +} + + +void KeramikClient::keepAboveChange( bool ) +{ + if ( button[ AboveButton ] ) + button[ AboveButton ]->repaint( true ); +} + + +void KeramikClient::keepBelowChange( bool ) +{ + if ( button[ BelowButton ] ) + button[ BelowButton ]->repaint( 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 ]->repaint( true ); +} + + +void KeramikClient::slotBelow() +{ + setKeepBelow( !keepBelow()); + button[ BelowButton ]->repaint( true ); +} + + +void KeramikClient::slotShade() +{ + setShade( !isSetShade()); + button[ ShadeButton ]->repaint( 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 = TQMAX( 15, updateRect.x() ); + int x2 = TQMIN( 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 = TQMAX( captionRect.right() + 1, updateRect.x() ); + int x2 = TQMIN( 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 = TQMAX( titleBarHeight, updateRect.top() ); + int bottom = TQMIN( 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 = TQMAX( 9, updateRect.x() ); + int x2 = TQMIN( 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::minimumSize() const +{ + return widget()->minimumSize(); +} + + +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..55e7b0d32 --- /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-TDE-Library=twin3_keramik + diff --git a/twin/clients/keramik/keramik.h b/twin/clients/keramik/keramik.h new file mode 100644 index 000000000..59f9960c5 --- /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 minimumSize() 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 diff --git a/twin/clients/kwmtheme/Makefile.am b/twin/clients/kwmtheme/Makefile.am new file mode 100644 index 000000000..e9d3c36b8 --- /dev/null +++ b/twin/clients/kwmtheme/Makefile.am @@ -0,0 +1,15 @@ +SUBDIRS=cli_installer +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = twin3_kwmtheme.la + +twin3_kwmtheme_la_SOURCES = kwmthemeclient.cpp +twin3_kwmtheme_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +twin3_kwmtheme_la_LIBADD = -ltdecorations + +METASOURCES = AUTO +noinst_HEADERS = kwmthemeclient.h + +lnkdir = $(kde_datadir)/twin +lnk_DATA = kwmtheme.desktop + diff --git a/twin/clients/kwmtheme/cli_installer/Makefile.am b/twin/clients/kwmtheme/cli_installer/Makefile.am new file mode 100644 index 000000000..d9ee417ca --- /dev/null +++ b/twin/clients/kwmtheme/cli_installer/Makefile.am @@ -0,0 +1,18 @@ + +# set the include path for X, qt and KDE +INCLUDES= $(all_includes) + +####### This part is very kwmtheme specific +# you can add here more. This one gets installed +bin_PROGRAMS = kwmtheme + +# Which sources should be compiled for kwmtheme. +kwmtheme_SOURCES = main.cpp + +# the library search path. +kwmtheme_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor + +# the libraries to link against. Be aware of the order. First the libraries, +# that depend on the following ones. +kwmtheme_LDADD = $(LIB_TDECORE) + diff --git a/twin/clients/kwmtheme/cli_installer/main.cpp b/twin/clients/kwmtheme/cli_installer/main.cpp new file mode 100644 index 000000000..27af172e1 --- /dev/null +++ b/twin/clients/kwmtheme/cli_installer/main.cpp @@ -0,0 +1,166 @@ +#include <tqfile.h> +#include <tqdir.h> +#include <tdeapplication.h> +#include <ksimpleconfig.h> +#include <tdeglobal.h> +#include <kdebug.h> +#include <kstandarddirs.h> +#include <tdecmdlineargs.h> +#include <tdelocale.h> + +static const char description[] = + I18N_NOOP("Installs a KWM theme"); + +static TDECmdLineOptions options[] = +{ + { "+[file]", I18N_NOOP("Path to a theme config file"), 0 }, + TDECmdLineLastOption +}; + +void copy(const TQString &src, const TQString &dest) +{ + TQFile copyInput(src); + TQFile copyOutput(dest); + if(!copyInput.open(IO_ReadOnly)){ + kdWarning() << "Couldn't open " << src << endl; + return; + } + if(!copyOutput.open(IO_WriteOnly)){ + kdWarning() << "Couldn't open " << dest << endl; + copyInput.close(); + return; + } + while(!copyInput.atEnd()){ + copyOutput.putch(copyInput.getch()); + } + copyInput.close(); + copyOutput.close(); +} + +int main(int argc, char **argv) +{ + TDECmdLineArgs::init(argc, argv, "kwmtheme", description, "0.1"); + TDECmdLineArgs::addCmdLineOptions( options ); + TDEApplication app(argc, argv); + TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); + if(!args->count()){ + kdWarning() << "You need to specify the path to a theme config file!" << endl; + return(1); + } + + TQString srcStr = TQString(TQFile::decodeName(args->arg(0))); + TQFile f(srcStr); + TQString tmpStr; + + if(!f.exists()){ + kdWarning() << "Specified theme config file doesn't exist!" << endl; + return(2); + } + + TQStringList appDirs = TDEGlobal::dirs()->findDirs("data", "twin"); + TQString localDirStr = *(appDirs.end()); + if(localDirStr.isEmpty()){ + localDirStr = TDEGlobal::dirs()->saveLocation("data", "twin"); + } + localDirStr += "/pics/"; + if(!TQFile::exists(localDirStr)) + TQDir().mkdir(localDirStr); + + TQFileInfo fi(f); + KSimpleConfig input(fi.absFilePath()); + srcStr = fi.dirPath(true) + "/"; + TDEConfig *output = TDEGlobal::config(); + input.setGroup("Window Border"); + output->setGroup("General"); + + tmpStr = input.readEntry("shapePixmapTop"); + if(!tmpStr.isEmpty()){ + copy(srcStr+tmpStr, localDirStr+tmpStr); + } + output->writeEntry("wm_top", tmpStr, true, true); + tmpStr = input.readEntry("shapePixmapBottom"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_bottom", tmpStr, true, true); + tmpStr = input.readEntry("shapePixmapLeft"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_left", tmpStr, true, true); + tmpStr = input.readEntry("shapePixmapRight"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_right", tmpStr, true, true); + tmpStr = input.readEntry("shapePixmapTopLeft"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_topleft", tmpStr, true, true); + tmpStr = input.readEntry("shapePixmapTopRight"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_topright", tmpStr, true, true); + tmpStr = input.readEntry("shapePixmapBottomLeft"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_bottomleft", tmpStr, true, true); + tmpStr = input.readEntry("shapePixmapBottomRight"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_bottomright", tmpStr, true, true); + + + input.setGroup("Window Titlebar"); + output->writeEntry("TitleAlignment", input.readEntry("TitleAlignment"), true, true); + output->writeEntry("PixmapUnderTitleText", input.readEntry("PixmapUnderTitleText"), true, true); + output->writeEntry("TitleFrameShaded", input.readEntry("TitleFrameShaded"), true, true); + + tmpStr = input.readEntry("MenuButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("menu", tmpStr, true, true); + tmpStr = input.readEntry("PinUpButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("pinup", tmpStr, true, true); + tmpStr = input.readEntry("PinDownButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("pindown", tmpStr, true, true); + tmpStr = input.readEntry("CloseButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("close", tmpStr, true, true); + tmpStr = input.readEntry("MaximizeButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("maximize", tmpStr, true, true); + tmpStr = input.readEntry("MaximizeDownButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("maximizedown", tmpStr, true, true); + tmpStr = input.readEntry("MinimizeButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("iconify", tmpStr, true, true); + tmpStr = input.readEntry("TitlebarPixmapActive"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("TitlebarPixmapActive", tmpStr, true, true); + tmpStr = input.readEntry("TitlebarPixmapInactive"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("TitlebarPixmapInactive", tmpStr, true, true); + + input.setGroup("Window Button Layout"); + output->setGroup("Buttons"); + output->writeEntry("ButtonA", input.readEntry("ButtonA"), true, true); + output->writeEntry("ButtonB", input.readEntry("ButtonB"), true, true); + output->writeEntry("ButtonC", input.readEntry("ButtonC"), true, true); + output->writeEntry("ButtonD", input.readEntry("ButtonD"), true, true); + output->writeEntry("ButtonE", input.readEntry("ButtonE"), true, true); + output->writeEntry("ButtonF", input.readEntry("ButtonF"), true, true); + + output->sync(); + + return(0); +} + diff --git a/twin/clients/kwmtheme/kwmtheme.desktop b/twin/clients/kwmtheme/kwmtheme.desktop new file mode 100644 index 000000000..201618279 --- /dev/null +++ b/twin/clients/kwmtheme/kwmtheme.desktop @@ -0,0 +1,81 @@ +[Desktop Entry] +Name=KWM Theme +Name[af]=KWM Tema +Name[ar]=سمة KWM +Name[az]=KWM Örtüsü +Name[be]=Тэма KWM +Name[bn]=KWM থীম +Name[br]=Gwiskad KWM +Name[bs]=KWM Tema +Name[ca]=Tema KWM +Name[cs]=Téma KWM +Name[csb]=Témë KWM +Name[cy]=Thema KWM +Name[da]=KWM-tema +Name[de]=KWM-Design +Name[el]=Θέμα KWM +Name[eo]=KWM-etoso +Name[es]=Tema de KWM +Name[et]=KWM teema +Name[eu]=KWM gaia +Name[fa]=چهره KWM +Name[fi]=KWM-teema +Name[fr]=Thème KWM +Name[fy]=KWM-tema +Name[ga]=Téama KWM +Name[gl]=Tema do KWM +Name[hi]=केडबल्यूएम प्रसंग +Name[hr]=KWM tema +Name[hu]=KWM téma +Name[id]=Theme KWM +Name[is]=KWM þema +Name[it]=Tema KWM +Name[ja]=KWM テーマ +Name[ka]=KWM სტილი +Name[kk]=KWM нақышы +Name[km]=ស្បែក KWM +Name[ko]=KWM 테마 +Name[lo]=ແບບຕົວຈັດການຫນ້າຕ່າງ KWM +Name[lt]=KWM tema +Name[lv]=KWM Tēma +Name[mk]=KWM тема +Name[mn]=KWM-Хэлбэр +Name[ms]=Temas KWM +Name[mt]=Tema KWM +Name[nb]=KWM-tema +Name[nds]=KWM-Muster +Name[ne]=KWM विषयवस्तु +Name[nl]=KWM-thema +Name[nn]=KWM-tema +Name[nso]=Molaetsa wa KWM +Name[oc]=Tema KWM +Name[pa]=KWM ਸਰੂਪ +Name[pl]=Motyw KWM +Name[pt]=Tema KWM +Name[pt_BR]=Tema KWM +Name[ro]=Tematică KWM +Name[ru]=Стиль KWM +Name[rw]=Insanganyamatsiko KWM +Name[se]=KWM-fáddá +Name[sk]=Téma KWM +Name[sl]=Tema KWM +Name[sr]=KWM тема +Name[sr@Latn]=KWM tema +Name[ss]=Indzikimba ye KWM +Name[sv]=KWM-tema +Name[ta]=KWM தலைப்பு +Name[tg]=Услуби KWM +Name[th]=ชุดตกแต่งหน้าต่าง KWM +Name[tr]=KWM Teması +Name[tt]=KWM Tışlaw +Name[uk]=Тема KWM +Name[uz]=KWM mavzusi +Name[uz@cyrillic]=KWM мавзуси +Name[ven]=Thero ya KWM +Name[vi]=Sắc thái KWM +Name[wa]=Tinme KWM +Name[xh]=Umxholo we KWM +Name[zh_CN]=KWM 主题 +Name[zh_TW]=KWM 主題 +Name[zu]=Ingqikithi ye-KWM +X-TDE-Library=twin3_kwmtheme diff --git a/twin/clients/kwmtheme/kwmthemeclient.cpp b/twin/clients/kwmtheme/kwmthemeclient.cpp new file mode 100644 index 000000000..73c8feaca --- /dev/null +++ b/twin/clients/kwmtheme/kwmthemeclient.cpp @@ -0,0 +1,936 @@ +#include <tdeconfig.h> +#include "kwmthemeclient.h" +#include <tdeglobal.h> +#include <tqlayout.h> +#include <tqdrawutil.h> +#include <tqpainter.h> +#include <kpixmapeffect.h> +#include <kstandarddirs.h> +#include <kdebug.h> +#include <tdelocale.h> +#include <tqbitmap.h> +#include <tqstyle.h> +#include <tqlabel.h> +#include <tqtooltip.h> + +namespace KWMTheme { + + +/* static TQPixmap stretchPixmap(TQPixmap& src, bool stretchVert){ + TQPixmap dest; + TQBitmap *srcMask, *destMask; + int w, h, w2, h2; + TQPainter p; + + if (src.isNull()) return src; + + w = src.width(); + h = src.height(); + + if (stretchVert){ + w2 = w; + for (h2=h; h2<100; h2=h2<<1) + ; + } + else{ + h2 = h; + for (w2=w; w2<100; w2=w2<<1) + ; + } + if (w2==w && h2==h) return src; + + dest = src; + dest.resize(w2, h2); + + p.begin(&dest); + p.drawTiledPixmap(0, 0, w2, h2, src); + p.end(); + + srcMask = (TQBitmap*)src.mask(); + if (srcMask){ + destMask = (TQBitmap*)dest.mask(); + p.begin(destMask); + p.drawTiledPixmap(0, 0, w2, h2, *srcMask); + p.end(); + } + return dest; +} */ + + +inline const KDecorationOptions* options() { return KDecoration::options(); } + +enum FramePixmap{FrameTop=0, FrameBottom, FrameLeft, FrameRight, FrameTopLeft, + FrameTopRight, FrameBottomLeft, FrameBottomRight}; + +static TQPixmap *framePixmaps[8]; +static TQPixmap *menuPix, *iconifyPix, *closePix, *maxPix, *minmaxPix, + *pinupPix, *pindownPix; +static KPixmap *aTitlePix = 0; +static KPixmap *iTitlePix = 0; +static KPixmapEffect::GradientType grType; +static int maxExtent, titleAlign; +static bool titleGradient = true; +static bool pixmaps_created = false; +static bool titleSunken = false; +static bool titleTransparent; + +static void create_pixmaps() +{ + const char *keys[] = {"wm_top", "wm_bottom", "wm_left", "wm_right", + "wm_topleft", "wm_topright", "wm_bottomleft", "wm_bottomright"}; + + if(pixmaps_created) + return; + pixmaps_created = true; + + TDEConfig *config = TDEGlobal::config(); + config->setGroup("General"); + TQString tmpStr; + + for(int i=0; i < 8; ++i) + { + framePixmaps[i] = new TQPixmap(locate("data", + "twin/pics/"+config->readEntry(keys[i], " "))); + if(framePixmaps[i]->isNull()) + kdWarning() << "Unable to load frame pixmap for " << keys[i] << endl; + } +/* + *framePixmaps[FrameTop] = stretchPixmap(*framePixmaps[FrameTop], false); + *framePixmaps[FrameBottom] = stretchPixmap(*framePixmaps[FrameBottom], false); + *framePixmaps[FrameLeft] = stretchPixmap(*framePixmaps[FrameLeft], true); + *framePixmaps[FrameRight] = stretchPixmap(*framePixmaps[FrameRight], true); +*/ + maxExtent = framePixmaps[FrameTop]->height(); + if(framePixmaps[FrameBottom]->height() > maxExtent) + maxExtent = framePixmaps[FrameBottom]->height(); + if(framePixmaps[FrameLeft]->width() > maxExtent) + maxExtent = framePixmaps[FrameLeft]->width(); + if(framePixmaps[FrameRight]->width() > maxExtent) + maxExtent = framePixmaps[FrameRight]->width(); + + maxExtent++; + + menuPix = new TQPixmap(locate("data", + "twin/pics/"+config->readEntry("menu", " "))); + iconifyPix = new TQPixmap(locate("data", + "twin/pics/"+config->readEntry("iconify", " "))); + maxPix = new TQPixmap(locate("appdata", + "pics/"+config->readEntry("maximize", " "))); + minmaxPix = new TQPixmap(locate("data", + "twin/pics/"+config->readEntry("maximizedown", " "))); + closePix = new TQPixmap(locate("data", + "twin/pics/"+config->readEntry("close", " "))); + pinupPix = new TQPixmap(locate("data", + "twin/pics/"+config->readEntry("pinup", " "))); + pindownPix = new TQPixmap(locate("data", + "twin/pics/"+config->readEntry("pindown", " "))); + if(menuPix->isNull()) + menuPix->load(locate("data", "twin/pics/menu.png")); + if(iconifyPix->isNull()) + iconifyPix->load(locate("data", "twin/pics/iconify.png")); + if(maxPix->isNull()) + maxPix->load(locate("data", "twin/pics/maximize.png")); + if(minmaxPix->isNull()) + minmaxPix->load(locate("data", "twin/pics/maximizedown.png")); + if(closePix->isNull()) + closePix->load(locate("data", "twin/pics/close.png")); + if(pinupPix->isNull()) + pinupPix->load(locate("data", "twin/pics/pinup.png")); + if(pindownPix->isNull()) + pindownPix->load(locate("data", "twin/pics/pindown.png")); + + tmpStr = config->readEntry("TitleAlignment"); + if(tmpStr == "right") + titleAlign = Qt::AlignRight | Qt::AlignVCenter; + else if(tmpStr == "middle") + titleAlign = Qt::AlignCenter; + else + titleAlign = Qt::AlignLeft | Qt::AlignVCenter; + titleSunken = config->readBoolEntry("TitleFrameShaded", true); + // titleSunken = true; // is this fixed? + titleTransparent = config->readBoolEntry("PixmapUnderTitleText", true); + + tmpStr = config->readEntry("TitlebarLook"); + if(tmpStr == "shadedVertical"){ + aTitlePix = new KPixmap; + aTitlePix->resize(32, 20); + KPixmapEffect::gradient(*aTitlePix, + options()->color(KDecorationOptions::ColorTitleBar, true), + options()->color(KDecorationOptions::ColorTitleBlend, true), + KPixmapEffect::VerticalGradient); + iTitlePix = new KPixmap; + iTitlePix->resize(32, 20); + KPixmapEffect::gradient(*iTitlePix, + options()->color(KDecorationOptions::ColorTitleBar, false), + options()->color(KDecorationOptions::ColorTitleBlend, false), + KPixmapEffect::VerticalGradient); + titleGradient = false; // we can just tile this + + } + else if(tmpStr == "shadedHorizontal") + grType = KPixmapEffect::HorizontalGradient; + else if(tmpStr == "shadedDiagonal") + grType = KPixmapEffect::DiagonalGradient; + else if(tmpStr == "shadedCrossDiagonal") + grType = KPixmapEffect::CrossDiagonalGradient; + else if(tmpStr == "shadedPyramid") + grType = KPixmapEffect::PyramidGradient; + else if(tmpStr == "shadedRectangle") + grType = KPixmapEffect::RectangleGradient; + else if(tmpStr == "shadedPipeCross") + grType = KPixmapEffect::PipeCrossGradient; + else if(tmpStr == "shadedElliptic") + grType = KPixmapEffect::EllipticGradient; + else{ + titleGradient = false; + tmpStr = config->readEntry("TitlebarPixmapActive", ""); + if(!tmpStr.isEmpty()){ + aTitlePix = new KPixmap; + aTitlePix->load(locate("data", "twin/pics/" + tmpStr)); + } + else + aTitlePix = NULL; + tmpStr = config->readEntry("TitlebarPixmapInactive", ""); + if(!tmpStr.isEmpty()){ + iTitlePix = new KPixmap; + iTitlePix->load(locate("data", "twin/pics/" + tmpStr)); + } + else + iTitlePix = NULL; + } +} + +static void delete_pixmaps() +{ + for(int i=0; i < 8; ++i) + delete framePixmaps[i]; + + delete menuPix; + delete iconifyPix; + delete closePix; + delete maxPix; + delete minmaxPix; + delete pinupPix; + delete pindownPix; + delete aTitlePix; + aTitlePix = 0; + delete iTitlePix; + iTitlePix = 0; + + titleGradient = true; + pixmaps_created = false; + titleSunken = false; +} + +void MyButton::drawButtonLabel(TQPainter *p) +{ + if(pixmap()){ + // If we have a theme who's button covers the entire width or + // entire height, we shift down/right by 1 pixel so we have + // some visual notification of button presses. i.e. for MGBriezh + int offset = (isDown() && ((pixmap()->width() >= width()) || + (pixmap()->height() >= height()))) ? 1 : 0; + style().drawItem(p, TQRect( offset, offset, width(), height() ), + AlignCenter, colorGroup(), + true, pixmap(), TQString::null); + } +} + +KWMThemeClient::KWMThemeClient( KDecorationBridge* b, KDecorationFactory* f ) + : KDecoration( b, f ) +{ +} + +void KWMThemeClient::init() +{ + createMainWidget( WResizeNoErase | WStaticContents ); + widget()->installEventFilter( this ); + + stickyBtn = maxBtn = mnuBtn = 0; + layout = new TQGridLayout(widget()); + layout->addColSpacing(0, maxExtent); + layout->addColSpacing(2, maxExtent); + + layout->addRowSpacing(0, maxExtent); + + layout->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Fixed, + TQSizePolicy::Expanding)); + + if( isPreview()) + layout->addWidget( new TQLabel( i18n( "<center><b>KWMTheme</b></center>" ), widget()), 2, 1); + else + layout->addItem( new TQSpacerItem( 0, 0 ), 2, 1); + + // Without the next line, shading flickers + layout->addItem( new TQSpacerItem(0, 0, TQSizePolicy::Fixed, TQSizePolicy::Expanding) ); + layout->addRowSpacing(3, maxExtent); + layout->setRowStretch(2, 10); + layout->setColStretch(1, 10); + + TQBoxLayout* hb = new TQBoxLayout(0, TQBoxLayout::LeftToRight, 0, 0, 0); + layout->addLayout( hb, 1, 1 ); + + TDEConfig *config = TDEGlobal::config(); + config->setGroup("Buttons"); + TQString val; + MyButton *btn; + int i; + static const char *defaultButtons[]={"Menu","Sticky","Off","Iconify", + "Maximize","Close"}; + static const char keyOffsets[]={"ABCDEF"}; + for(i=0; i < 6; ++i){ + if(i == 3){ + titlebar = new TQSpacerItem(10, 20, TQSizePolicy::Expanding, + TQSizePolicy::Minimum ); + hb->addItem( titlebar ); + } + TQString key("Button"); + key += TQChar(keyOffsets[i]); + val = config->readEntry(key, defaultButtons[i]); + if(val == "Menu"){ + mnuBtn = new MyButton(widget(), "menu"); + TQToolTip::add( mnuBtn, i18n("Menu")); + iconChange(); + hb->addWidget(mnuBtn); + mnuBtn->setFixedSize(20, 20); + connect(mnuBtn, TQT_SIGNAL(pressed()), this, + TQT_SLOT(menuButtonPressed())); + } + else if(val == "Sticky"){ + stickyBtn = new MyButton(widget(), "sticky"); + TQToolTip::add( stickyBtn, i18n("Sticky")); + if (isOnAllDesktops()) + stickyBtn->setPixmap(*pindownPix); + else + stickyBtn->setPixmap(*pinupPix); + connect(stickyBtn, TQT_SIGNAL( clicked() ), this, TQT_SLOT(toggleOnAllDesktops())); + hb->addWidget(stickyBtn); + stickyBtn->setFixedSize(20, 20); + } + else if((val == "Iconify") && isMinimizable()){ + btn = new MyButton(widget(), "iconify"); + TQToolTip::add( btn, i18n("Minimize")); + btn->setPixmap(*iconifyPix); + connect(btn, TQT_SIGNAL(clicked()), this, TQT_SLOT(minimize())); + hb->addWidget(btn); + btn->setFixedSize(20, 20); + } + else if((val == "Maximize") && isMaximizable()){ + maxBtn = new MyButton(widget(), "max"); + TQToolTip::add( maxBtn, i18n("Maximize")); + maxBtn->setPixmap(*maxPix); + connect(maxBtn, TQT_SIGNAL(clicked()), this, TQT_SLOT(maximize())); + hb->addWidget(maxBtn); + maxBtn->setFixedSize(20, 20); + } + else if((val == "Close") && isCloseable()){ + btn = new MyButton(widget(), "close"); + TQToolTip::add( btn, i18n("Close")); + btn->setPixmap(*closePix); + connect(btn, TQT_SIGNAL(clicked()), this, TQT_SLOT(closeWindow())); + hb->addWidget(btn); + btn->setFixedSize(20, 20); + } + else{ + if((val != "Off") && + ((val == "Iconify") && !isMinimizable()) && + ((val == "Maximize") && !isMaximizable())) + kdWarning() << "KWin: Unrecognized button value: " << val << endl; + + } + } + if(titleGradient){ + aGradient = new KPixmap; + iGradient = new KPixmap; + } + else{ + aGradient = 0; + iGradient = 0; + } + widget()->setBackgroundMode(NoBackground); +} + +void KWMThemeClient::drawTitle(TQPainter &dest) +{ + TQRect titleRect = titlebar->geometry(); + TQRect r(0, 0, titleRect.width(), titleRect.height()); + TQPixmap buffer; + + if(buffer.width() == r.width()) + return; + + buffer.resize(r.size()); + TQPainter p; + p.begin(&buffer); + + if(titleSunken){ + qDrawShadeRect(&p, r, options()->colorGroup(KDecorationOptions::ColorFrame, isActive()), + true, 1, 0); + r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2); + } + + KPixmap *fill = isActive() ? aTitlePix : iTitlePix; + if(fill) + p.drawTiledPixmap(r, *fill); + else if(titleGradient){ + fill = isActive() ? aGradient : iGradient; + if(fill->width() != r.width()){ + fill->resize(r.width(), 20); + KPixmapEffect::gradient(*fill, + options()->color(KDecorationOptions::ColorTitleBar, isActive()), + options()->color(KDecorationOptions::ColorTitleBlend, isActive()), + grType); + } + p.drawTiledPixmap(r, *fill); + } + else{ + p.fillRect(r, options()->colorGroup(KDecorationOptions::ColorTitleBar, isActive()). + brush(TQColorGroup::Button)); + } + p.setFont(options()->font(isActive())); + p.setPen(options()->color(KDecorationOptions::ColorFont, isActive())); + // Add left & right margin + r.setLeft(r.left()+5); + r.setRight(r.right()-5); + p.drawText(r, titleAlign, caption()); + p.end(); + + dest.drawPixmap(titleRect.x(), titleRect.y(), buffer); +} + + +void KWMThemeClient::resizeEvent( TQResizeEvent* ) +{ + doShape(); + widget()->repaint(); +} + +void KWMThemeClient::captionChange() +{ + widget()->repaint( titlebar->geometry(), false ); +} + +void KWMThemeClient::paintEvent( TQPaintEvent *) +{ + TQPainter p; + p.begin(widget()); + int x,y; + // first the corners + int w1 = framePixmaps[FrameTopLeft]->width(); + int h1 = framePixmaps[FrameTopLeft]->height(); + if (w1 > width()/2) w1 = width()/2; + if (h1 > height()/2) h1 = height()/2; + p.drawPixmap(0,0,*framePixmaps[FrameTopLeft], + 0,0,w1, h1); + int w2 = framePixmaps[FrameTopRight]->width(); + int h2 = framePixmaps[FrameTopRight]->height(); + if (w2 > width()/2) w2 = width()/2; + if (h2 > height()/2) h2 = height()/2; + p.drawPixmap(width()-w2,0,*framePixmaps[FrameTopRight], + framePixmaps[FrameTopRight]->width()-w2,0,w2, h2); + + int w3 = framePixmaps[FrameBottomLeft]->width(); + int h3 = framePixmaps[FrameBottomLeft]->height(); + if (w3 > width()/2) w3 = width()/2; + if (h3 > height()/2) h3 = height()/2; + p.drawPixmap(0,height()-h3,*framePixmaps[FrameBottomLeft], + 0,framePixmaps[FrameBottomLeft]->height()-h3,w3, h3); + + int w4 = framePixmaps[FrameBottomRight]->width(); + int h4 = framePixmaps[FrameBottomRight]->height(); + if (w4 > width()/2) w4 = width()/2; + if (h4 > height()/2) h4 = height()/2; + p.drawPixmap(width()-w4,height()-h4,*(framePixmaps[FrameBottomRight]), + framePixmaps[FrameBottomRight]->width()-w4, + framePixmaps[FrameBottomRight]->height()-h4, + w4, h4); + + TQPixmap pm; + TQWMatrix m; + int n,s,w; + //top + pm = *framePixmaps[FrameTop]; + + if (pm.width() > 0){ + s = width()-w2-w1; + n = s/pm.width(); + w = n>0?s/n:s; + m.reset(); + m.scale(w/(float)pm.width(), 1); + pm = pm.xForm(m); + + x = w1; + while (1){ + if (pm.width() < width()-w2-x){ + p.drawPixmap(x,maxExtent-pm.height()-1, + pm); + x += pm.width(); + } + else { + p.drawPixmap(x,maxExtent-pm.height()-1, + pm, + 0,0,width()-w2-x,pm.height()); + break; + } + } + } + + //bottom + pm = *framePixmaps[FrameBottom]; + + if (pm.width() > 0){ + s = width()-w4-w3; + n = s/pm.width(); + w = n>0?s/n:s; + m.reset(); + m.scale(w/(float)pm.width(), 1); + pm = pm.xForm(m); + + x = w3; + while (1){ + if (pm.width() < width()-w4-x){ + p.drawPixmap(x,height()-maxExtent+1,pm); + x += pm.width(); + } + else { + p.drawPixmap(x,height()-maxExtent+1,pm, + 0,0,width()-w4-x,pm.height()); + break; + } + } + } + + //left + pm = *framePixmaps[FrameLeft]; + + if (pm.height() > 0){ + s = height()-h3-h1; + n = s/pm.height(); + w = n>0?s/n:s; + m.reset(); + m.scale(1, w/(float)pm.height()); + pm = pm.xForm(m); + + y = h1; + while (1){ + if (pm.height() < height()-h3-y){ + p.drawPixmap(maxExtent-pm.width()-1, y, + pm); + y += pm.height(); + } + else { + p.drawPixmap(maxExtent-pm.width()-1, y, + pm, + 0,0, pm.width(), + height()-h3-y); + break; + } + } + } + + //right + pm = *framePixmaps[FrameRight]; + + if (pm.height() > 0){ + s = height()-h4-h2; + n = s/pm.height(); + w = n>0?s/n:s; + m.reset(); + m.scale(1, w/(float)pm.height()); + pm = pm.xForm(m); + + y = h2; + while (1){ + if (pm.height() < height()-h4-y){ + p.drawPixmap(width()-maxExtent+1, y, + pm); + y += pm.height(); + } + else { + p.drawPixmap(width()-maxExtent+1, y, + pm, + 0,0, pm.width(), + height()-h4-y); + break; + } + } + } + drawTitle(p); + + TQColor c = widget()->colorGroup().background(); + + // KWM evidently had a 1 pixel border around the client window. We + // emulate it here, but should be removed at some point in order to + // seamlessly mesh widget themes + p.setPen(c); + p.drawRect(maxExtent-1, maxExtent-1, width()-(maxExtent-1)*2, + height()-(maxExtent-1)*2); + + // We fill the area behind the wrapped widget to ensure that + // shading animation is drawn as smoothly as possible + TQRect r(layout->cellGeometry(2, 1)); + p.fillRect( r.x(), r.y(), r.width(), r.height(), c); + p.end(); +} + +void KWMThemeClient::doShape() +{ + + TQBitmap shapemask(width(), height()); + shapemask.fill(color0); + TQPainter p; + p.begin(&shapemask); + p.setBrush(color1); + p.setPen(color1); + int x,y; + // first the corners + int w1 = framePixmaps[FrameTopLeft]->width(); + int h1 = framePixmaps[FrameTopLeft]->height(); + if (w1 > width()/2) w1 = width()/2; + if (h1 > height()/2) h1 = height()/2; + if (framePixmaps[FrameTopLeft]->mask()) + p.drawPixmap(0,0,*framePixmaps[FrameTopLeft]->mask(), + 0,0,w1, h1); + else + p.fillRect(0,0,w1,h1,color1); + int w2 = framePixmaps[FrameTopRight]->width(); + int h2 = framePixmaps[FrameTopRight]->height(); + if (w2 > width()/2) w2 = width()/2; + if (h2 > height()/2) h2 = height()/2; + if (framePixmaps[FrameTopRight]->mask()) + p.drawPixmap(width()-w2,0,*framePixmaps[FrameTopRight]->mask(), + framePixmaps[FrameTopRight]->width()-w2,0,w2, h2); + else + p.fillRect(width()-w2,0,w2, h2,color1); + + int w3 = framePixmaps[FrameBottomLeft]->width(); + int h3 = framePixmaps[FrameBottomLeft]->height(); + if (w3 > width()/2) w3 = width()/2; + if (h3 > height()/2) h3 = height()/2; + if (framePixmaps[FrameBottomLeft]->mask()) + p.drawPixmap(0,height()-h3,*framePixmaps[FrameBottomLeft]->mask(), + 0,framePixmaps[FrameBottomLeft]->height()-h3,w3, h3); + else + p.fillRect(0,height()-h3,w3,h3,color1); + + int w4 = framePixmaps[FrameBottomRight]->width(); + int h4 = framePixmaps[FrameBottomRight]->height(); + if (w4 > width()/2) w4 = width()/2; + if (h4 > height()/2) h4 = height()/2; + if (framePixmaps[FrameBottomRight]->mask()) + p.drawPixmap(width()-w4,height()-h4,*framePixmaps[FrameBottomRight]->mask(), + framePixmaps[FrameBottomRight]->width()-w4, + framePixmaps[FrameBottomRight]->height()-h4, + w4, h4); + else + p.fillRect(width()-w4,height()-h4,w4,h4,color1); + + TQPixmap pm; + TQWMatrix m; + int n,s,w; + //top + if (framePixmaps[FrameTop]->mask()) + { + pm = *framePixmaps[FrameTop]->mask(); + + s = width()-w2-w1; + n = s/pm.width(); + w = n>0?s/n:s; + m.reset(); + m.scale(w/(float)pm.width(), 1); + pm = pm.xForm(m); + + x = w1; + while (1){ + if (pm.width() < width()-w2-x){ + p.drawPixmap(x,maxExtent-pm.height()-1, + pm); + x += pm.width(); + } + else { + p.drawPixmap(x,maxExtent-pm.height()-1, + pm, + 0,0,width()-w2-x,pm.height()); + break; + } + } + } + + //bottom + if (framePixmaps[FrameBottom]->mask()) + { + pm = *framePixmaps[FrameBottom]->mask(); + + s = width()-w4-w3; + n = s/pm.width(); + w = n>0?s/n:s; + m.reset(); + m.scale(w/(float)pm.width(), 1); + pm = pm.xForm(m); + + x = w3; + while (1){ + if (pm.width() < width()-w4-x){ + p.drawPixmap(x,height()-maxExtent+1,pm); + x += pm.width(); + } + else { + p.drawPixmap(x,height()-maxExtent+1,pm, + 0,0,width()-w4-x,pm.height()); + break; + } + } + } + + //left + if (framePixmaps[FrameLeft]->mask()) + { + pm = *framePixmaps[FrameLeft]->mask(); + + s = height()-h3-h1; + n = s/pm.height(); + w = n>0?s/n:s; + m.reset(); + m.scale(1, w/(float)pm.height()); + pm = pm.xForm(m); + + y = h1; + while (1){ + if (pm.height() < height()-h3-y){ + p.drawPixmap(maxExtent-pm.width()-1, y, + pm); + y += pm.height(); + } + else { + p.drawPixmap(maxExtent-pm.width()-1, y, + pm, + 0,0, pm.width(), + height()-h3-y); + break; + } + } + } + + //right + if (framePixmaps[FrameRight]->mask()) + { + pm = *framePixmaps[FrameRight]->mask(); + + s = height()-h4-h2; + n = s/pm.height(); + w = n>0?s/n:s; + m.reset(); + m.scale(1, w/(float)pm.height()); + pm = pm.xForm(m); + + y = h2; + while (1){ + if (pm.height() < height()-h4-y){ + p.drawPixmap(width()-maxExtent+1, y, + pm); + y += pm.height(); + } + else { + p.drawPixmap(width()-maxExtent+1, y, + pm, + 0,0, pm.width(), + height()-h4-y); + break; + } + } + } + p.fillRect(maxExtent-1, maxExtent-1, width()-2*maxExtent+2, height()-2*maxExtent+2, color1); + setMask(shapemask); +} + + +void KWMThemeClient::showEvent(TQShowEvent *) +{ + doShape(); + widget()->repaint(false); +} + +void KWMThemeClient::mouseDoubleClickEvent( TQMouseEvent * e ) +{ + if (e->button() == LeftButton && titlebar->geometry().contains( e->pos() ) ) + titlebarDblClickOperation(); +} + +void KWMThemeClient::desktopChange() +{ + if (stickyBtn) { + bool on = isOnAllDesktops(); + stickyBtn->setPixmap(on ? *pindownPix : *pinupPix); + TQToolTip::remove( stickyBtn ); + TQToolTip::add( stickyBtn, on ? i18n("Unsticky") : i18n("Sticky") ); + } +} + +void KWMThemeClient::maximizeChange() +{ + if (maxBtn) { + bool m = maximizeMode() == MaximizeFull; + maxBtn->setPixmap(m ? *minmaxPix : *maxPix); + TQToolTip::remove( maxBtn ); + TQToolTip::add( maxBtn, m ? i18n("Restore") : i18n("Maximize")); + } +} + +void KWMThemeClient::slotMaximize() +{ + maximize( maximizeMode() == MaximizeFull ? MaximizeRestore : MaximizeFull ); +} + +void KWMThemeClient::activeChange() +{ + widget()->update(); +} + +KDecoration::Position KWMThemeClient::mousePosition(const TQPoint &p) const +{ + Position m = KDecoration::mousePosition(p); + // corners + if(p.y() < framePixmaps[FrameTop]->height() && + p.x() < framePixmaps[FrameLeft]->width()){ + m = PositionTopLeft; + } + else if(p.y() < framePixmaps[FrameTop]->height() && + p.x() > width()-framePixmaps[FrameRight]->width()){ + m = PositionTopRight; + } + else if(p.y() > height()-framePixmaps[FrameBottom]->height() && + p.x() < framePixmaps[FrameLeft]->width()){ + m = PositionBottomLeft; + } + else if(p.y() > height()-framePixmaps[FrameBottom]->height() && + p.x() > width()-framePixmaps[FrameRight]->width()){ + m = PositionBottomRight; + } // edges + else if(p.y() < framePixmaps[FrameTop]->height()) + m = PositionTop; + else if(p.y() > height()-framePixmaps[FrameBottom]->height()) + m = PositionBottom; + else if(p.x() < framePixmaps[FrameLeft]->width()) + m = PositionLeft; + else if(p.x() > width()-framePixmaps[FrameRight]->width()) + m = PositionRight; + return(m); +} + +void KWMThemeClient::menuButtonPressed() +{ + mnuBtn->setDown(false); // will stay down if I don't do this + TQPoint pos = mnuBtn->mapToGlobal(mnuBtn->rect().bottomLeft()); + showWindowMenu( pos ); +} + +void KWMThemeClient::iconChange() +{ + if(mnuBtn){ + if( icon().pixmap( TQIconSet::Small, TQIconSet::Normal ).isNull()){ + mnuBtn->setPixmap(*menuPix); + } + else{ + mnuBtn->setPixmap(icon().pixmap( TQIconSet::Small, TQIconSet::Normal )); + } + } +} + +bool KWMThemeClient::eventFilter( TQObject* o, TQEvent* e ) +{ + if ( o != widget() ) + return false; + + switch ( e->type() ) + { + case TQEvent::Resize: + resizeEvent( static_cast< TQResizeEvent* >( e ) ); + return true; + + case TQEvent::Paint: + paintEvent( static_cast< TQPaintEvent* >( e ) ); + return true; + + case TQEvent::MouseButtonDblClick: + mouseDoubleClickEvent( static_cast< TQMouseEvent* >( e ) ); + return true; + + case TQEvent::MouseButtonPress: + processMousePressEvent( static_cast< TQMouseEvent* >( e ) ); + return true; + + case TQEvent::Show: + showEvent( static_cast< TQShowEvent* >( e ) ); + return true; + + default: + return false; + } +} + +TQSize KWMThemeClient::minimumSize() const +{ + return widget()->minimumSize().expandedTo( TQSize( 100, 50 )); +} + +void KWMThemeClient::resize( const TQSize& s ) +{ + widget()->resize( s ); +} + +void KWMThemeClient::borders( int& left, int& right, int& top, int& bottom ) const +{ + left = + right = + top = + bottom = + +TODO +} + +KWMThemeFactory::KWMThemeFactory() +{ + create_pixmaps(); +} + +KWMThemeFactory::~KWMThemeFactory() +{ + delete_pixmaps(); +} + +KDecoration* KWMThemeFactory::createDecoration( KDecorationBridge* b ) +{ + return new KWMThemeClient( b, this ); +} + +bool KWMThemeFactory::reset( unsigned long mask ) +{ + bool needHardReset = false; + +TODO + + // doesn't obey the Border size setting + if( mask & ( SettingFont | SettingButtons )) + needHardReset = true; + + if( mask & ( SettingFont | SettingColors )) { + KWMTheme::delete_pixmaps(); + KWMTheme::create_pixmaps(); + } + + if( !needHardReset ) + resetDecorations( mask ); + return needHardReset; +} + +} + +extern "C" +{ + KDE_EXPORT KDecorationFactory *create_factory() + { + return new KWMTheme::KWMThemeFactory(); + } +} + +#include "kwmthemeclient.moc" diff --git a/twin/clients/kwmtheme/kwmthemeclient.h b/twin/clients/kwmtheme/kwmthemeclient.h new file mode 100644 index 000000000..58db3d14f --- /dev/null +++ b/twin/clients/kwmtheme/kwmthemeclient.h @@ -0,0 +1,74 @@ +#ifndef __KWMTHEMECLIENT_H +#define __KWMTHEMECLIENT_H + +#include <tqbutton.h> +#include <tqtoolbutton.h> +#include <kpixmap.h> +#include <kdecoration.h> +#include <kdecorationfactory.h> + +class TQLabel; +class TQSpacerItem; +class TQGridLayout; + +namespace KWMTheme { + +class MyButton : public TQToolButton +{ +public: + MyButton(TQWidget *parent=0, const char *name=0) + : TQToolButton(parent, name){setAutoRaise(true);setCursor( arrowCursor ); } +protected: + void drawButtonLabel(TQPainter *p); +}; + +class KWMThemeClient : public KDecoration +{ + Q_OBJECT +public: + KWMThemeClient( KDecorationBridge* b, KDecorationFactory* f ); + ~KWMThemeClient(){;} + void init(); + void resize( const TQSize& s ); + TQSize minimumSize() const; + void borders( int& left, int& right, int& top, int& bottom ) const; +protected: + void doShape(); + void drawTitle(TQPainter &p); + void resizeEvent( TQResizeEvent* ); + void paintEvent( TQPaintEvent* ); + void showEvent( TQShowEvent* ); + void mouseDoubleClickEvent( TQMouseEvent * ); + bool eventFilter( TQObject* o, TQEvent* e ); + void captionChange(); + void desktopChange(); + void maximizeChange(); + void iconChange(); + void activeChange(); + void shadeChange() {}; + Position mousePosition(const TQPoint &) const; +protected slots: + //void slotReset(); + void menuButtonPressed(); + void slotMaximize(); +private: + TQPixmap buffer; + KPixmap *aGradient, *iGradient; + MyButton *maxBtn, *stickyBtn, *mnuBtn; + TQSpacerItem *titlebar; + TQGridLayout* layout; +}; + +class KWMThemeFactory : public KDecorationFactory +{ +public: + KWMThemeFactory(); + ~KWMThemeFactory(); + KDecoration* createDecoration( KDecorationBridge* b ); + bool reset( unsigned long mask ); +}; + +} + +#endif + diff --git a/twin/clients/laptop/CMakeLists.txt b/twin/clients/laptop/CMakeLists.txt new file mode 100644 index 000000000..a06afdafc --- /dev/null +++ b/twin/clients/laptop/CMakeLists.txt @@ -0,0 +1,35 @@ +################################################# +# +# (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} + ${CMAKE_SOURCE_DIR}/twin/lib + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES laptop.desktop DESTINATION ${DATA_INSTALL_DIR}/twin ) + + +##### twin3_laptop (module) ##################### + +tde_add_kpart( twin3_laptop AUTOMOC + SOURCES laptopclient.cpp + LINK tdecorations-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/twin/clients/laptop/Makefile.am b/twin/clients/laptop/Makefile.am new file mode 100644 index 000000000..ccf1d359b --- /dev/null +++ b/twin/clients/laptop/Makefile.am @@ -0,0 +1,17 @@ + +INCLUDES = -I$(srcdir)/../../lib $(all_includes) + +kde_module_LTLIBRARIES = twin3_laptop.la + +twin3_laptop_la_SOURCES = laptopclient.cpp +twin3_laptop_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +twin3_laptop_la_LIBADD = ../../lib/libtdecorations.la + +METASOURCES = AUTO +noinst_HEADERS = laptopclient.h + +lnkdir = $(kde_datadir)/twin +lnk_DATA = laptop.desktop + +EXTRA_DIST = $(lnk_DATA) + diff --git a/twin/clients/laptop/laptop.desktop b/twin/clients/laptop/laptop.desktop new file mode 100644 index 000000000..b1c78ca90 --- /dev/null +++ b/twin/clients/laptop/laptop.desktop @@ -0,0 +1,69 @@ +[Desktop Entry] +Name=Laptop +Name[af]=Draagbare rekenaar +Name[ar]=الحاسوب النقّال +Name[az]=Dizüstü Kompüter +Name[be]=Ноўтбук +Name[bg]=Лаптоп +Name[bn]=ল্যাপটপ +Name[br]=Hezoug +Name[ca]=Portàtil +Name[cs]=Notebook +Name[cy]=Gluniadur +Name[da]=Bærbar +Name[el]=Φορητό +Name[eo]=Tekokomputilo +Name[es]=Portátil +Name[eu]=Ordenagailu eramangarria +Name[fa]=رایانۀ کیفی +Name[fi]=Kannettava +Name[fr]=Ordinateur portable +Name[fy]=Skoatkompjûter +Name[ga]=Ríomhaire Glúine +Name[gl]=Portátil +Name[he]=מחשב נייד +Name[hi]=लैपटॉप +Name[hsb]=laptop +Name[hu]=Noteszgép +Name[is]=Ferðavél +Name[it]=Portatile +Name[ja]=ラップトップ +Name[ka]=ლეპტოპი +Name[kk]=Ноутбук +Name[km]=កុំព្យូទ័រយួរដៃ +Name[ko]=랩탑 +Name[lo]=ແລບທອບ +Name[lt]=Nešiojamas kompiuteris +Name[lv]=Laptops +Name[mk]=Лаптоп +Name[mn]=Лаптоп +Name[ms]=Komputer riba +Name[nb]=Bærbar +Name[nds]=Klappreekner +Name[ne]=ल्यापटप +Name[nn]=Berbar +Name[oc]=Portatil +Name[pa]=ਲੈਪਟਾਪ +Name[pt]=Portátil +Name[ru]=Ноутбук +Name[rw]=Mudasobwa Igendanwa +Name[se]=Mátkedihtor +Name[sl]=Prenosnik +Name[sr]=Лаптоп +Name[sv]=Bärbar dator +Name[ta]=மடிக்கணினி +Name[te]=లాప్ టాప్ +Name[tg]=Ноутбук +Name[th]=แลปทอป +Name[tr]=Dizüstü +Name[tt]=Qulsanaq +Name[uk]=Мобільний комп'ютер (лептоп) +Name[uz@cyrillic]=Лаптоп +Name[ven]=Khomupwutha pfarwa +Name[vi]=Máy xách tay +Name[wa]=Poirtåve +Name[xh]=Umphezulu osongiweyo +Name[zh_CN]=笔记本电脑 +Name[zh_TW]=筆記型電腦 +Name[zu]=Ikhomputha ephathwayo eyisicaba +X-TDE-Library=twin3_laptop diff --git a/twin/clients/laptop/laptopclient.cpp b/twin/clients/laptop/laptopclient.cpp new file mode 100644 index 000000000..34c79b2d6 --- /dev/null +++ b/twin/clients/laptop/laptopclient.cpp @@ -0,0 +1,761 @@ +/* + * Laptop KWin Decoration + * + * Copyright (c) 2005 Sandro Giessl <sandro@giessl.com> + * Port of this decoration to KDE 3.2, accessibility enhancement are + * Copyright (c) 2003 Luciano Montanaro <mikelima@cirulla.net> + */ + +#include <tdeconfig.h> // up here to avoid X11 header conflict :P +#include "laptopclient.h" +#include <tqdrawutil.h> +#include <kpixmapeffect.h> +#include <kdrawutil.h> +#include <tdeglobal.h> +#include <tdelocale.h> +#include <tqbitmap.h> + +namespace Laptop { + +static const unsigned char iconify_bits[] = { + 0xff, 0xff, 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18}; + +static const unsigned char close_bits[] = { + 0x42, 0xe7, 0x7e, 0x3c, 0x3c, 0x7e, 0xe7, 0x42}; + +static const unsigned char maximize_bits[] = { + 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0xff, 0xff }; + +static const unsigned char r_minmax_bits[] = { + 0x0c, 0x18, 0x33, 0x67, 0xcf, 0x9f, 0x3f, 0x3f}; + +static const unsigned char l_minmax_bits[] = { + 0x30, 0x18, 0xcc, 0xe6, 0xf3, 0xf9, 0xfc, 0xfc}; + +static const unsigned char question_bits[] = { + 0x3c, 0x66, 0x60, 0x30, 0x18, 0x00, 0x18, 0x18}; + +static const unsigned char unsticky_bits[] = { + 0x3c, 0x42, 0x99, 0xbd, 0xbd, 0x99, 0x42, 0x3c}; + +static const unsigned char sticky_bits[] = { + 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c}; + +static TQPixmap *titlePix; +static KPixmap *aUpperGradient; +static KPixmap *iUpperGradient; +// buttons active, inactive, up, down, and 2 sizes :P +static KPixmap *btnPix1; +static KPixmap *iBtnPix1; +static KPixmap *btnDownPix1; +static KPixmap *iBtnDownPix1; +static KPixmap *btnPix2; +static KPixmap *btnDownPix2; +static KPixmap *iBtnPix2; +static KPixmap *iBtnDownPix2; +static TQColor btnForeground; + +static int titleHeight = 14; +static int btnWidth1 = 17; +static int btnWidth2 = 27; + +static int handleSize = 8; // the resize handle size in pixels + +static bool pixmaps_created = false; + +// ===================================== + +extern "C" KDE_EXPORT KDecorationFactory* create_factory() +{ + return new Laptop::LaptopClientFactory(); +} + +// ===================================== + +static inline const KDecorationOptions* options() +{ + return KDecoration::options(); +} + +static void drawButtonFrame(KPixmap *pix, const TQColorGroup &g, bool sunken) +{ + TQPainter p; + int w = pix->width(); + int h = pix->height(); + int x2 = w-1; + int y2 = h-1; + p.begin(pix); + + if(sunken){ + qDrawShadePanel(&p, 0, 0, w, h, g, true, 2); + } + else{ + p.setPen(g.dark()); + p.drawRect(0, 0, w-1, h-1); + p.setPen(g.light()); + p.drawLine(x2, 0, x2, y2); + p.drawLine(0, y2, x2, y2); + p.drawLine(1, 1, x2-2, 1); + p.drawLine(1, 1, 1, y2-2); + p.end(); + } +} + +static void create_pixmaps() +{ + if(pixmaps_created) + return; + pixmaps_created = true; + + titleHeight = TQFontMetrics(options()->font(true)).height() + 2; + if (titleHeight < handleSize) titleHeight = handleSize; + titleHeight &= ~1; // Make title height even + if (titleHeight < 14) titleHeight = 14; + + btnWidth1 = titleHeight + 3; + btnWidth2 = 3*titleHeight/2 + 6; + + // titlebar + TQPainter p; + TQPainter maskPainter; + int i, x, y; + titlePix = new TQPixmap(33, 12); + TQBitmap mask(33, 12); + mask.fill(Qt::color0); + + p.begin(titlePix); + maskPainter.begin(&mask); + maskPainter.setPen(Qt::color1); + for(i=0, y=2; i < 3; ++i, y+=4){ + for(x=1; x <= 33; x+=3){ + p.setPen(options()->color(KDecoration::ColorTitleBar, true).light(150)); + p.drawPoint(x, y); + maskPainter.drawPoint(x, y); + p.setPen(options()->color(KDecoration::ColorTitleBar, true).dark(150)); + p.drawPoint(x+1, y+1); + maskPainter.drawPoint(x+1, y+1); + } + } + p.end(); + maskPainter.end(); + titlePix->setMask(mask); + + if(TQPixmap::defaultDepth() > 8){ + aUpperGradient = new KPixmap; + aUpperGradient->resize(32, titleHeight+2); + iUpperGradient = new KPixmap; + iUpperGradient->resize(32, titleHeight+2); + TQColor bgColor = options()->color(KDecoration::ColorTitleBar, true); + KPixmapEffect::gradient(*aUpperGradient, + bgColor.light(120), + bgColor.dark(120), + KPixmapEffect::VerticalGradient); + bgColor = options()->color(KDecoration::ColorTitleBar, false); + KPixmapEffect::gradient(*iUpperGradient, + bgColor.light(120), + bgColor.dark(120), + KPixmapEffect::VerticalGradient); + } + // buttons (active/inactive, sunken/unsunken, 2 sizes each) + TQColorGroup g = options()->colorGroup(KDecoration::ColorButtonBg, true); + TQColor c = g.background(); + btnPix1 = new KPixmap; + btnPix1->resize(btnWidth1, titleHeight); + btnDownPix1 = new KPixmap; + btnDownPix1->resize(btnWidth1, titleHeight); + btnPix2 = new KPixmap; + btnPix2->resize(btnWidth2, titleHeight); + btnDownPix2 = new KPixmap; + btnDownPix2->resize(btnWidth2, titleHeight); + iBtnPix1 = new KPixmap; + iBtnPix1->resize(btnWidth1, titleHeight); + iBtnDownPix1 = new KPixmap; + iBtnDownPix1->resize(btnWidth1, titleHeight); + iBtnPix2 = new KPixmap; + iBtnPix2->resize(btnWidth2, titleHeight); + iBtnDownPix2 = new KPixmap; + iBtnDownPix2->resize(btnWidth2, titleHeight); + if(TQPixmap::defaultDepth() > 8){ + KPixmapEffect::gradient(*btnPix1, c.light(120), c.dark(130), + KPixmapEffect::DiagonalGradient); + KPixmapEffect::gradient(*btnDownPix1, c.dark(130), c.light(120), + KPixmapEffect::DiagonalGradient); + KPixmapEffect::gradient(*btnPix2, c.light(120), c.dark(130), + KPixmapEffect::DiagonalGradient); + KPixmapEffect::gradient(*btnDownPix2, c.dark(130), c.light(120), + KPixmapEffect::DiagonalGradient); + g = options()->colorGroup(KDecoration::ColorButtonBg, false); + c = g.background(); + KPixmapEffect::gradient(*iBtnPix1, c.light(120), c.dark(130), + KPixmapEffect::DiagonalGradient); + KPixmapEffect::gradient(*iBtnDownPix1, c.dark(130), c.light(120), + KPixmapEffect::DiagonalGradient); + KPixmapEffect::gradient(*iBtnPix2, c.light(120), c.dark(130), + KPixmapEffect::DiagonalGradient); + KPixmapEffect::gradient(*iBtnDownPix2, c.dark(130), c.light(120), + KPixmapEffect::DiagonalGradient); + } + else{ + btnPix1->fill(c.rgb()); + btnDownPix1->fill(c.rgb()); + btnPix2->fill(c.rgb()); + btnDownPix2->fill(c.rgb()); + g = options()->colorGroup(KDecoration::ColorButtonBg, false); + c = g.background(); + iBtnPix1->fill(c.rgb()); + iBtnDownPix1->fill(c.rgb()); + iBtnPix2->fill(c.rgb()); + iBtnDownPix2->fill(c.rgb()); + } + g = options()->colorGroup(KDecoration::ColorButtonBg, true); + c = g.background(); + drawButtonFrame(btnPix1, g, false); + drawButtonFrame(btnDownPix1, g, true); + drawButtonFrame(btnPix2, g, false); + drawButtonFrame(btnDownPix2, g, true); + g = options()->colorGroup(KDecoration::ColorButtonBg, false); + c = g.background(); + drawButtonFrame(iBtnPix1, g, false); + drawButtonFrame(iBtnDownPix1, g, true); + drawButtonFrame(iBtnPix2, g, false); + drawButtonFrame(iBtnDownPix2, g, true); + + if(tqGray(options()->color(KDecoration::ColorButtonBg, true).rgb()) > 128) + btnForeground = Qt::black; + else + btnForeground = Qt::white; +} + +static void delete_pixmaps() +{ + delete titlePix; + if(aUpperGradient){ + delete aUpperGradient; + delete iUpperGradient; + delete btnPix1; + delete btnDownPix1; + delete iBtnPix1; + delete iBtnDownPix1; + delete btnPix2; + delete btnDownPix2; + delete iBtnPix2; + delete iBtnDownPix2; + } + pixmaps_created = false; +} + +// ===================================== + +LaptopButton::LaptopButton(ButtonType type, LaptopClient *parent, const char *name) + : KCommonDecorationButton(type, parent, name) +{ + setBackgroundMode(TQWidget::NoBackground); +} + +void LaptopButton::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: + if (isOn() ) { + setBitmap(isLeft() ? l_minmax_bits : r_minmax_bits); + } else { + setBitmap(maximize_bits); + } + break; + case OnAllDesktopsButton: + setBitmap( isOn() ? unsticky_bits : sticky_bits ); + break; + default: + setBitmap(0); + break; + } + + this->update(); + } +} + +void LaptopButton::setBitmap(const unsigned char *bitmap) +{ + if (bitmap) + deco = TQBitmap(8, 8, bitmap, true); + else { + deco = TQBitmap(8,8); + deco.fill(Qt::color0); + } + deco.setMask(deco); + repaint(); +} + +void LaptopButton::drawButton(TQPainter *p) +{ + bool smallBtn = width() == btnWidth1; + if(btnPix1){ + if(decoration()->isActive()){ + if(isDown()) + p->drawPixmap(0, 0, smallBtn ? *btnDownPix1 : *btnDownPix2); + else + p->drawPixmap(0, 0, smallBtn ? *btnPix1 : *btnPix2); + } + else{ + if(isDown()) + p->drawPixmap(0, 0, smallBtn ? *iBtnDownPix1 : *iBtnDownPix2); + else + p->drawPixmap(0, 0, smallBtn ? *iBtnPix1 : *iBtnPix2); + } + } + else{ + TQColorGroup g = options()->colorGroup(KDecoration::ColorButtonBg, decoration()->isActive()); + int w = width(); + int h = height(); + p->fillRect(1, 1, w-2, h-2, isDown() ? g.mid() : g.button()); + p->setPen(isDown() ? g.dark() : g.light()); + p->drawLine(0, 0, w-1, 0); + p->drawLine(0, 0, 0, w-1); + p->setPen(isDown() ? g.light() : g.dark()); + p->drawLine(w-1, 0, w-1, h-1); + p->drawLine(0, h-1, w-1, h-1); + } + + p->setPen(btnForeground); + int xOff = (width()-8)/2; + int yOff = (height()-8)/2; + p->drawPixmap(isDown() ? xOff+1: xOff, isDown() ? yOff+1 : yOff, deco); +} + +// ===================================== + +void LaptopClient::reset(unsigned long changed) +{ + KCommonDecoration::reset(changed); +} + +LaptopClient::LaptopClient(KDecorationBridge *b, KDecorationFactory *f) + : KCommonDecoration(b, f) +{ +} + +LaptopClient::~LaptopClient() +{ +} + +TQString LaptopClient::visibleName() const +{ + return i18n("Laptop"); +} + +TQString LaptopClient::defaultButtonsLeft() const +{ + return "X"; +} + +TQString LaptopClient::defaultButtonsRight() const +{ + return "HSIA"; +} + +bool LaptopClient::decorationBehaviour(DecorationBehaviour behaviour) const +{ + switch (behaviour) { + case DB_MenuClose: + return false; + + case DB_WindowMask: + return true; + + case DB_ButtonHide: + return true; + + default: + return KCommonDecoration::decorationBehaviour(behaviour); + } +} + +int LaptopClient::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *btn) const +{ + switch (lm) { + case LM_TitleEdgeLeft: + case LM_TitleEdgeRight: + case LM_BorderLeft: + case LM_BorderRight: + return 4; + + case LM_BorderBottom: + return mustDrawHandle() ? handleSize : 4; + + case LM_TitleEdgeTop: + return 3; + + case LM_TitleEdgeBottom: + return 1; + + case LM_TitleBorderLeft: + case LM_TitleBorderRight: + return 0; + + case LM_ButtonWidth: + { + if (btn && (btn->type()==HelpButton||btn->type()==OnAllDesktopsButton) ) { + return btnWidth1; + } else { + return btnWidth2; + } + } + + case LM_ButtonHeight: + case LM_TitleHeight: + if (isToolWindow() ) + return titleHeight-2; + else + return titleHeight; + + case LM_ButtonSpacing: + return 0; + + case LM_ExplicitButtonSpacer: + return 0; + + default: + return KCommonDecoration::layoutMetric(lm, respectWindowState, btn); + } +} + +KCommonDecorationButton *LaptopClient::createButton(ButtonType type) +{ + switch (type) { + case OnAllDesktopsButton: + return new LaptopButton(OnAllDesktopsButton, this, "on_all_desktops"); + + case HelpButton: + return new LaptopButton(HelpButton, this, "help"); + + case MinButton: + return new LaptopButton(MinButton, this, "minimize"); + + case MaxButton: + return new LaptopButton(MaxButton, this, "maximize"); + + case CloseButton: + return new LaptopButton(CloseButton, this, "close"); + + default: + return 0; + } +} + +void LaptopClient::init() +{ + bufferDirty = true; + + KCommonDecoration::init(); +} + +void LaptopClient::captionChange() +{ + bufferDirty = true; + + KCommonDecoration::captionChange(); +} + +void LaptopClient::paintEvent( TQPaintEvent* ) +{ + TQPainter p(widget()); + TQColorGroup g = options()->colorGroup(KDecoration::ColorFrame, isActive()); + + TQRect r(widget()->rect()); + p.setPen(Qt::black); + p.drawRect(r); + + // fill mid frame... + p.setPen(g.background() ); + p.drawLine(r.x()+2, r.y()+2, r.right()-2, r.y()+2); + p.drawLine(r.left()+2, r.y()+3, r.left()+2, r.bottom()-layoutMetric(LM_BorderBottom)+1 ); + p.drawLine(r.right()-2, r.y()+3, r.right()-2, r.bottom()-layoutMetric(LM_BorderBottom)+1 ); + p.drawLine(r.left()+3, r.y()+3, r.left()+3, r.y()+layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)+layoutMetric(LM_TitleEdgeTop) ); + p.drawLine(r.right()-3, r.y()+3, r.right()-3, r.y()+layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)+layoutMetric(LM_TitleEdgeTop) ); + if (!mustDrawHandle() ) + p.drawLine(r.left()+1, r.bottom()-2, r.right()-1, r.bottom()-2); + + // outer frame + p.setPen(g.light()); + p.drawLine(r.x()+1, r.y()+1, r.right()-1, r.y()+1); + p.drawLine(r.x()+1, r.y()+1, r.x()+1, r.bottom()-1); + p.setPen(g.dark()); + p.drawLine(r.right()-1, r.y()+1, r.right()-1, r.bottom()-1); + p.drawLine(r.x()+1, r.bottom()-1, r.right()-1, r.bottom()-1); + + int th = titleHeight; + int bb = handleSize + 2; // Bottom border + int bs = handleSize - 2; // inner size of bottom border + if (!mustDrawHandle()) { + bb = 6; + bs = 0; + } + if ( isToolWindow() ) + th -= 2; + + // inner rect + p.drawRect(r.x() + 3, r.y() + th + 3, r.width() - 6, r.height() - th - bb); + + // handles + if (mustDrawHandle()) { + if (r.width() > 3*handleSize + 20) { + int range = 8 + 3*handleSize/2; + qDrawShadePanel(&p, r.x() + 1, r.bottom() - bs, range, + handleSize - 2, g, false, 1, &g.brush(TQColorGroup::Mid)); + qDrawShadePanel(&p, r.x() + range + 1, r.bottom() - bs, + r.width() - 2*range - 2, handleSize - 2, g, false, 1, + isActive() ? &g.brush(TQColorGroup::Background) : + &g.brush(TQColorGroup::Mid)); + qDrawShadePanel(&p, r.right() - range, r.bottom() - bs, + range, bs, g, false, 1, &g.brush(TQColorGroup::Mid)); + } else { + qDrawShadePanel(&p, r.x() + 1, r.bottom() - bs, + r.width() - 2, bs, g, false, 1, + isActive() ? &g.brush(TQColorGroup::Background) : + &g.brush(TQColorGroup::Mid)); + } + } + + r = titleRect(); + + if(isActive()){ + updateActiveBuffer(); + p.drawPixmap(r.x(), r.y(), activeBuffer); + p.setPen(g.background()); + p.drawPoint(r.x(), r.y()); + p.drawPoint(r.right(), r.y()); + p.drawLine(r.right()+1, r.y(), r.right()+1, r.bottom()); + } + else{ + if(iUpperGradient) + p.drawTiledPixmap(r.x(), r.y(), r.width(), r.height()-1, + *iUpperGradient); + else + p.fillRect(r.x(), r.y(), r.width(), r.height()-1, + options()->color(KDecoration::ColorTitleBar, false)); + + p.setFont(options()->font(false, isToolWindow() )); + TQFontMetrics fm(options()->font(false)); + g = options()->colorGroup(KDecoration::ColorTitleBar, false); + if(iUpperGradient) + p.drawTiledPixmap(r.x()+((r.width()-fm.width(caption()))/2)-4, + r.y(), fm.width(caption())+8, r.height()-1, + *iUpperGradient); + else + p.fillRect(r.x()+((r.width()-fm.width(caption()))/2)-4, r.y(), + fm.width(caption())+8, r.height()-1, + g.brush(TQColorGroup::Background)); + p.setPen(g.mid()); + p.drawLine(r.x(), r.y(), r.right(), r.y()); + p.drawLine(r.x(), r.y(), r.x(), r.bottom()); + p.setPen(g.button()); + p.drawLine(r.right(), r.y(), r.right(), r.bottom()); + p.drawLine(r.x(), r.bottom(), r.right(), r.bottom()); + p.setPen(options()->color(KDecoration::ColorFont, false)); + p.drawText(r.x(), r.y(), r.width(), r.height()-1, + AlignCenter, caption() ); + g = options()->colorGroup(KDecoration::ColorFrame, true); + p.setPen(g.background()); + p.drawPoint(r.x(), r.y()); + p.drawPoint(r.right(), r.y()); + p.drawLine(r.right()+1, r.y(), r.right()+1, r.bottom()); + } +} + +TQRegion LaptopClient::cornerShape(WindowCorner corner) +{ + switch (corner) { + case WC_TopLeft: + return TQRect(0, 0, 1, 1); + + case WC_TopRight: + return TQRect(width()-1, 0, 1, 1); + + case WC_BottomLeft: + return TQRect(0, height()-1, 1, 1); + + case WC_BottomRight: + return TQRect(width()-1, height()-1, 1, 1); + + default: + return TQRegion(); + } + +} + +bool LaptopClient::mustDrawHandle() const +{ + bool drawSmallBorders = !options()->moveResizeMaximizedWindows(); + if (drawSmallBorders && (maximizeMode() & MaximizeVertical)) { + return false; + } else { + return isResizable(); + } +} + +void LaptopClient::updateActiveBuffer( ) +{ + TQRect rTitle = titleRect(); + if( !bufferDirty && (lastBufferWidth == rTitle.width())) + return; + if ( rTitle.width() <= 0 || rTitle.height() <= 0 ) + return; + lastBufferWidth = rTitle.width(); + bufferDirty = false; + + activeBuffer.resize(rTitle.width(), + rTitle.height()); + TQPainter p; + TQRect r(0, 0, activeBuffer.width(), activeBuffer.height()); + p.begin(&activeBuffer); + if(aUpperGradient){ + p.drawTiledPixmap(r, *aUpperGradient); + } + else{ + p.fillRect(r, options()->color(KDecoration::ColorTitleBar, true)); + } + if(titlePix) + p.drawTiledPixmap(r, *titlePix); + + p.setFont(options()->font(true, isToolWindow() )); + TQFontMetrics fm(options()->font(true)); + TQColorGroup g = options()->colorGroup(KDecoration::ColorTitleBar, true); + if(aUpperGradient) + p.drawTiledPixmap(r.x()+((r.width()-fm.width(caption()))/2)-4, + r.y(), fm.width(caption())+8, r.height()-1, + *aUpperGradient); + else + p.fillRect(r.x()+((r.width()-fm.width(caption()))/2)-4, 0, + fm.width(caption())+8, r.height(), + g.brush(TQColorGroup::Background)); + p.setPen(g.mid()); + p.drawLine(r.x(), r.y(), r.right(), r.y()); + p.drawLine(r.x(), r.y(), r.x(), r.bottom()); + p.setPen(g.button()); + p.drawLine(r.right(), r.y(), r.right(), r.bottom()); + p.drawLine(r.x(), r.bottom(), r.right(), r.bottom()); + p.setPen(options()->color(KDecoration::ColorFont, true)); + p.drawText(r.x(), r.y(), r.width(), r.height()-1, + AlignCenter, caption() ); + g = options()->colorGroup(KDecoration::ColorFrame, true); + p.setPen(g.background()); + p.drawPoint(r.x(), r.y()); + p.drawPoint(r.right(), r.y()); + p.drawLine(r.right()+1, r.y(), r.right()+1, r.bottom()); + p.end(); +} + +static const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | + NET::DesktopMask | NET::DockMask | NET::ToolbarMask | NET::MenuMask | + NET::DialogMask | /*NET::OverrideMask |*/ NET::TopMenuMask | + NET::UtilityMask | NET::SplashMask; + +bool LaptopClient::isTransient() const +{ + NET::WindowType type = windowType(SUPPORTED_WINDOW_TYPES_MASK); + return type == NET::Dialog; +} + +// ===================================== + +LaptopClientFactory::LaptopClientFactory() +{ + create_pixmaps(); +} + +LaptopClientFactory::~LaptopClientFactory() +{ + delete_pixmaps(); +} + +KDecoration *LaptopClientFactory::createDecoration(KDecorationBridge *b) +{ + findPreferredHandleSize(); + return new Laptop::LaptopClient(b, this); +} + +bool LaptopClientFactory::reset(unsigned long changed) +{ + findPreferredHandleSize(); + + // TODO Do not recreate decorations if it is not needed. Look at + // ModernSystem for how to do that + Laptop::delete_pixmaps(); + Laptop::create_pixmaps(); + + bool needHardReset = true; + if (changed & SettingButtons) { + // handled by KCommonDecoration + needHardReset = false; + } + + if (needHardReset) { + return true; + } else { + resetDecorations(changed); + return false; + } +} + +bool LaptopClientFactory::supports( Ability ability ) +{ + switch( ability ) + { + case AbilityAnnounceButtons: + case AbilityButtonOnAllDesktops: + case AbilityButtonHelp: + case AbilityButtonMinimize: + case AbilityButtonMaximize: + case AbilityButtonClose: + return true; + default: + return false; + }; +} + +TQValueList< LaptopClientFactory::BorderSize > +LaptopClientFactory::borderSizes() const +{ + // the list must be sorted + return TQValueList< BorderSize >() << BorderNormal << BorderLarge << + BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized; +} + +void LaptopClientFactory::findPreferredHandleSize() +{ + switch (options()->preferredBorderSize(this)) { + case KDecoration::BorderLarge: + handleSize = 11; + break; + case KDecoration::BorderVeryLarge: + handleSize = 16; + break; + case KDecoration::BorderHuge: + handleSize = 24; + break; + case KDecoration::BorderVeryHuge: + handleSize = 32; + break; + case KDecoration::BorderOversized: + handleSize = 40; + break; + case KDecoration::BorderTiny: + case KDecoration::BorderNormal: + default: + handleSize = 8; + } +} + +} // Laptop namespace + +// vim: sw=4 diff --git a/twin/clients/laptop/laptopclient.h b/twin/clients/laptop/laptopclient.h new file mode 100644 index 000000000..de6e742f6 --- /dev/null +++ b/twin/clients/laptop/laptopclient.h @@ -0,0 +1,76 @@ +/* + * Laptop KWin Client + * + * Copyright (c) 2005 Sandro Giessl <sandro@giessl.com> + * Ported to the trinity.2 API by Luciano Montanaro <mikelima@cirulla.net> + */ +#ifndef __KDECLIENT_H +#define __KDECLIENT_H + +#include <tqbitmap.h> +#include <kpixmap.h> +#include <kcommondecoration.h> +#include <kdecorationfactory.h> + +namespace Laptop { + +class LaptopClient; + +class LaptopButton : public KCommonDecorationButton +{ +public: + LaptopButton(ButtonType type, LaptopClient *parent, const char *name); + void setBitmap(const unsigned char *bitmap); + virtual void reset(unsigned long changed); + +protected: + virtual void drawButton(TQPainter *p); + TQBitmap deco; +}; + +class LaptopClient : public KCommonDecoration +{ +public: + LaptopClient( KDecorationBridge* b, KDecorationFactory* f ); + ~LaptopClient(); + + virtual TQString visibleName() const; + virtual TQString defaultButtonsLeft() const; + virtual TQString 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 TQRegion cornerShape(WindowCorner corner); + + void init(); +protected: + void paintEvent( TQPaintEvent* ); + void reset( unsigned long ); + void updateActiveBuffer(); + void captionChange(); +private: + bool mustDrawHandle() const; + bool isTransient() const; +private: + KPixmap activeBuffer; + int lastBufferWidth; + bool bufferDirty; +}; + +class LaptopClientFactory : public TQObject, public KDecorationFactory +{ +public: + LaptopClientFactory(); + virtual ~LaptopClientFactory(); + virtual KDecoration* createDecoration( KDecorationBridge* ); + virtual bool reset( unsigned long changed ); + virtual bool supports( Ability ability ); + virtual TQValueList< BorderSize > borderSizes() const; +private: + void findPreferredHandleSize(); +}; + +} + +#endif diff --git a/twin/clients/modernsystem/CMakeLists.txt b/twin/clients/modernsystem/CMakeLists.txt new file mode 100644 index 000000000..62c2d766c --- /dev/null +++ b/twin/clients/modernsystem/CMakeLists.txt @@ -0,0 +1,36 @@ +################################################# +# +# (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_SOURCE_DIR}/twin/lib + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES modernsystem.desktop DESTINATION ${DATA_INSTALL_DIR}/twin ) + + +##### twin3_modernsys (module) ################## + +tde_add_kpart( twin3_modernsys + SOURCES modernsys.cpp + LINK tdecorations-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/twin/clients/modernsystem/Makefile.am b/twin/clients/modernsystem/Makefile.am new file mode 100644 index 000000000..e4c21d7a3 --- /dev/null +++ b/twin/clients/modernsystem/Makefile.am @@ -0,0 +1,19 @@ + +INCLUDES = -I$(srcdir)/../../lib $(all_includes) + +SUBDIRS = config + +kde_module_LTLIBRARIES = twin3_modernsys.la + +twin3_modernsys_la_SOURCES = modernsys.cpp +twin3_modernsys_la_LIBADD = ../../lib/libtdecorations.la +twin3_modernsys_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module + +METASOURCES = AUTO +noinst_HEADERS = modernsys.h + +lnkdir = $(kde_datadir)/twin/ +lnk_DATA = modernsystem.desktop + +EXTRA_DIST = $(lnk_DATA) + diff --git a/twin/clients/modernsystem/btnhighcolor.h b/twin/clients/modernsystem/btnhighcolor.h new file mode 100644 index 000000000..fa323b9eb --- /dev/null +++ b/twin/clients/modernsystem/btnhighcolor.h @@ -0,0 +1,93 @@ +/* XPM */ +static const char * btnhighcolor_xpm[] = { +"14 15 75 1", +" c None", +". c #6E6E6E", +"+ c #757575", +"@ c #878787", +"# c #7D7D7D", +"$ c #9E9E9E", +"% c #B9B9B9", +"& c #C6C6C6", +"* c #BABABA", +"= c #A5A5A5", +"- c #7F7F7F", +"; c #848484", +"> c #A7A7A7", +", c #BFBFBF", +"' c #D1D1D1", +") c #D7D7D7", +"! c #DADADA", +"~ c #CBCBCB", +"{ c #ABABAB", +"] c #B3B3B3", +"^ c #C2C2C2", +"/ c #CACACA", +"( c #C9C9C9", +"_ c #B6B6B6", +": c #9A9A9A", +"< c #999999", +"[ c #B0B0B0", +"} c #C4C4C4", +"| c #C3C3C3", +"1 c #C0C0C0", +"2 c #AEAEAE", +"3 c #969696", +"4 c #C1C1C1", +"5 c #CCCCCC", +"6 c #C5C5C5", +"7 c #BEBEBE", +"8 c #AAAAAA", +"9 c #CECECE", +"0 c #D4D4D4", +"a c #DBDBDB", +"b c #DEDEDE", +"c c #D5D5D5", +"d c #D3D3D3", +"e c #BCBCBC", +"f c #CDCDCD", +"g c #E0E0E0", +"h c #E4E4E4", +"i c #E8E8E8", +"j c #EBEBEB", +"k c #E9E9E9", +"l c #E6E6E6", +"m c #DDDDDD", +"n c #E1E1E1", +"o c #EDEDED", +"p c #F1F1F1", +"q c #F5F5F5", +"r c #F8F8F8", +"s c #F6F6F6", +"t c #F3F3F3", +"u c #EEEEEE", +"v c #E5E5E5", +"w c #DCDCDC", +"x c #B7B7B7", +"y c #E2E2E2", +"z c #FDFDFD", +"A c #FFFFFF", +"B c #FCFCFC", +"C c #F7F7F7", +"D c #B5B5B5", +"E c #F2F2F2", +"F c #FAFAFA", +"G c #9B9B9B", +"H c #FBFBFB", +"I c #A9A9A9", +"J c #747474", +" .... ", +" ..+@@+.. ", +" .#$%&&*=-. ", +" .;>,')!)~{#. ", +" .$]^///(&_:. ", +".<[*^}||11*23.", +".[4&5555~(678.", +".,90!aba)cd~e.", +".faghijklhm06.", +".'nopqrstuvw/.", +".xyprzAzBCunD.", +" .'EzAAAAFpf. ", +" .GcHAAAAF0<. ", +" ..I5kk5I.. ", +" J..... "}; diff --git a/twin/clients/modernsystem/buttondata.h b/twin/clients/modernsystem/buttondata.h new file mode 100644 index 000000000..1af5fb8dd --- /dev/null +++ b/twin/clients/modernsystem/buttondata.h @@ -0,0 +1,42 @@ +/* Image bits processed by KPixmap2Bitmaps */ + +#define lowcolor_mask_width 14 +#define lowcolor_mask_height 15 +static const unsigned char lowcolor_mask_bits[] = { + 0xf0,0x03,0xf8,0x07,0xfc,0xcf,0xfe,0x1f,0xfe,0x1f,0xff,0xff,0xff,0xff,0xff, + 0x3f,0xff,0x3f,0xff,0xbf,0xfe,0xdf,0xfe,0x9f,0xfc,0x0f,0xf8,0x07,0xf0,0x03, + 0x00,0x40,0x80,0x00,0x00,0x00,0x29,0x00,0x00,0x00,0x7c,0xfe,0x87,0x40,0x00, + 0x00,0x64,0x00,0x20,0x00,0x64,0x00,0x86,0xfe,0x87,0x40,0x00,0x00,0x65,0x00 }; + +#define lowcolor_6a696a_width 14 +#define lowcolor_6a696a_height 15 +static const unsigned char lowcolor_6a696a_bits[] = { + 0xf0,0x03,0x18,0x06,0x04,0xcc,0x06,0x18,0x02,0x10,0x00,0xc0,0x00,0xc0,0x00, + 0x00,0x00,0x00,0x00,0xc0,0x00,0xc0,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x80,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03, + 0x00,0x00,0x00,0x80,0x24,0x0e,0x08,0x61,0x00,0x00,0x00,0xf0,0xd9,0x0c,0x08 }; + +#define lowcolor_949194_width 14 +#define lowcolor_949194_height 15 +static const unsigned char lowcolor_949194_bits[] = { + 0x00,0x40,0xe0,0x01,0x08,0x02,0x00,0x04,0x04,0x08,0x07,0x78,0x03,0xf0,0x01, + 0xe0,0x01,0x60,0x01,0x20,0x00,0xc0,0x02,0x90,0x04,0x08,0x08,0x04,0xf0,0x03, + 0x00,0x40,0x80,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0xc8,0x51,0x0c,0x08,0x0e, + 0x01,0x00,0x00,0x37,0x00,0x00,0x00,0x58,0x5f,0x49,0x6d,0x61,0x67,0x65,0x54 }; + +#define lowcolor_b4b6b4_width 14 +#define lowcolor_b4b6b4_height 15 +static const unsigned char lowcolor_b4b6b4_bits[] = { + 0x00,0x40,0x00,0x00,0x10,0x00,0x08,0x02,0x18,0x06,0xb8,0x47,0x0c,0xce,0x0e, + 0xd8,0x06,0x58,0x02,0x10,0x02,0xd0,0x00,0x80,0x00,0x00,0x10,0x02,0x00,0x00, + 0x00,0x40,0x80,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01, + 0x00,0x08,0x00,0x02,0x00,0x00,0x00,0x61,0x00,0x00,0x00,0x38,0x5b,0x0c,0x08 }; + +#define lowcolor_e6e6e6_width 14 +#define lowcolor_e6e6e6_height 15 +static const unsigned char lowcolor_e6e6e6_bits[] = { + 0x00,0x40,0x00,0x00,0x00,0x00,0xe0,0x01,0x00,0x00,0x00,0x40,0x00,0xc0,0x00, + 0xc0,0x00,0x40,0xe0,0xc0,0xe0,0xc1,0xe0,0x81,0xf0,0x03,0xc0,0x00,0x00,0x00, + 0x00,0x40,0x80,0x00,0x00,0x00,0x39,0x00,0x00,0x00,0x08,0x19,0x0d,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00 }; + diff --git a/twin/clients/modernsystem/config/CMakeLists.txt b/twin/clients/modernsystem/config/CMakeLists.txt new file mode 100644 index 000000000..8a6d6db43 --- /dev/null +++ b/twin/clients/modernsystem/config/CMakeLists.txt @@ -0,0 +1,30 @@ +################################################# +# +# (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_modernsys_config (module) ############ + +tde_add_kpart( twin_modernsys_config AUTOMOC + SOURCES config.cpp + LINK tdeui-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) + diff --git a/twin/clients/modernsystem/config/Makefile.am b/twin/clients/modernsystem/config/Makefile.am new file mode 100644 index 000000000..aaae38b2a --- /dev/null +++ b/twin/clients/modernsystem/config/Makefile.am @@ -0,0 +1,14 @@ + +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = twin_modernsys_config.la + +twin_modernsys_config_la_SOURCES = config.cpp +twin_modernsys_config_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +twin_modernsys_config_la_LIBADD = $(LIB_TDEUI) + +METASOURCES = AUTO +noinst_HEADERS = config.h + +lnkdir = $(kde_datadir)/twin/ + diff --git a/twin/clients/modernsystem/config/config.cpp b/twin/clients/modernsystem/config/config.cpp new file mode 100644 index 000000000..18d6870f7 --- /dev/null +++ b/twin/clients/modernsystem/config/config.cpp @@ -0,0 +1,130 @@ +// Melchior FRANZ <mfranz@kde.org> -- 2001-04-22 + +#include <tdeapplication.h> +#include <tdeconfig.h> +#include <kdialog.h> +#include <tdelocale.h> +#include <tdeglobal.h> +#include <tqlayout.h> +#include <tqwhatsthis.h> +#include "config.h" + + +extern "C" +{ + KDE_EXPORT TQObject* allocate_config(TDEConfig* conf, TQWidget* parent) + { + return(new ModernSysConfig(conf, parent)); + } +} + + +// '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 + +ModernSysConfig::ModernSysConfig(TDEConfig* conf, TQWidget* parent) : TQObject(parent) +{ + clientrc = new TDEConfig("twinmodernsysrc"); + TDEGlobal::locale()->insertCatalogue("twin_clients"); + mainw = new TQWidget(parent); + vbox = new TQVBoxLayout(mainw); + vbox->setSpacing(6); + vbox->setMargin(0); + + handleBox = new TQWidget(mainw); + TQGridLayout* layout = new TQGridLayout(handleBox, 0, KDialog::spacingHint()); + + cbShowHandle = new TQCheckBox(i18n("&Show window resize handle"), handleBox); + TQWhatsThis::add(cbShowHandle, + i18n("When selected, all windows are drawn with a resize " + "handle at the lower right corner. This makes window resizing " + "easier, especially for trackballs and other mouse replacements " + "on laptops.")); + layout->addMultiCellWidget(cbShowHandle, 0, 0, 0, 1); + connect(cbShowHandle, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotSelectionChanged())); + + sliderBox = new TQVBox(handleBox); + handleSizeSlider = new TQSlider(0, 4, 1, 0, Qt::Horizontal, sliderBox); + TQWhatsThis::add(handleSizeSlider, + i18n("Here you can change the size of the resize handle.")); + handleSizeSlider->setTickInterval(1); + handleSizeSlider->setTickmarks(TQSlider::Below); + connect(handleSizeSlider, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotSelectionChanged())); + + hbox = new TQHBox(sliderBox); + hbox->setSpacing(6); + + bool rtl = kapp->reverseLayout(); + label1 = new TQLabel(i18n("Small"), hbox); + label1->setAlignment(rtl ? AlignRight : AlignLeft); + label2 = new TQLabel(i18n("Medium"), hbox); + label2->setAlignment(AlignHCenter); + label3 = new TQLabel(i18n("Large"), hbox); + label3->setAlignment(rtl ? AlignLeft : AlignRight); + + vbox->addWidget(handleBox); + vbox->addStretch(1); + +// layout->setColSpacing(0, 30); + layout->addItem(new TQSpacerItem(30, 10, TQSizePolicy::Fixed, TQSizePolicy::Fixed), 1, 0); + layout->addWidget(sliderBox, 1, 1); + + load(conf); + mainw->show(); +} + + +ModernSysConfig::~ModernSysConfig() +{ + delete mainw; + delete clientrc; +} + + +void ModernSysConfig::slotSelectionChanged() +{ + bool i = cbShowHandle->isChecked(); + if (i != hbox->isEnabled()) { + hbox->setEnabled(i); + handleSizeSlider->setEnabled(i); + } + emit changed(); +} + + +void ModernSysConfig::load(TDEConfig* /*conf*/) +{ + clientrc->setGroup("General"); + bool i = clientrc->readBoolEntry("ShowHandle", true ); + cbShowHandle->setChecked(i); + hbox->setEnabled(i); + handleSizeSlider->setEnabled(i); + handleWidth = clientrc->readUnsignedNumEntry("HandleWidth", 6); + handleSize = clientrc->readUnsignedNumEntry("HandleSize", 30); + handleSizeSlider->setValue(TQMIN((handleWidth - 6) / 2, 4)); + +} + + +void ModernSysConfig::save(TDEConfig* /*conf*/) +{ + clientrc->setGroup("General"); + clientrc->writeEntry("ShowHandle", cbShowHandle->isChecked()); + clientrc->writeEntry("HandleWidth", 6 + 2 * handleSizeSlider->value()); + clientrc->writeEntry("HandleSize", 30 + 4 * handleSizeSlider->value()); + clientrc->sync(); +} + + +void ModernSysConfig::defaults() +{ + cbShowHandle->setChecked(true); + hbox->setEnabled(true); + handleSizeSlider->setEnabled(true); + handleSizeSlider->setValue(0); +} + +#include "config.moc" diff --git a/twin/clients/modernsystem/config/config.h b/twin/clients/modernsystem/config/config.h new file mode 100644 index 000000000..20ce5539e --- /dev/null +++ b/twin/clients/modernsystem/config/config.h @@ -0,0 +1,50 @@ +#ifndef __KDE_MODSYSTEMCONFIG_H +#define __KDE_MODSYSTEMCONFIG_H + +#include <tqcheckbox.h> +#include <tqgroupbox.h> +#include <tqlayout.h> +#include <tqvbox.h> +#include <tqslider.h> +#include <tqlabel.h> + +class ModernSysConfig : public TQObject +{ + Q_OBJECT + + public: + ModernSysConfig(TDEConfig* conf, TQWidget* parent); + ~ModernSysConfig(); + + // These public signals/slots work similar to KCM modules + signals: + void changed(); + + public slots: + void load(TDEConfig* conf); + void save(TDEConfig* conf); + void defaults(); + + protected slots: + void slotSelectionChanged(); // Internal use + + private: + TDEConfig *clientrc; + TQWidget *mainw; + TQVBoxLayout *vbox; + TQWidget *handleBox; + TQCheckBox *cbShowHandle; + TQVBox *sliderBox; + TQSlider *handleSizeSlider; + TQHBox *hbox; + TQLabel *label1; + TQLabel *label2; + TQLabel *label3; + + unsigned handleWidth; + unsigned handleSize; + +}; + + +#endif diff --git a/twin/clients/modernsystem/modernsys.cpp b/twin/clients/modernsystem/modernsys.cpp new file mode 100644 index 000000000..68c8716c4 --- /dev/null +++ b/twin/clients/modernsystem/modernsys.cpp @@ -0,0 +1,739 @@ +// Daniel M. DULEY <mosfet@kde.org> original work +// Melchior FRANZ <a8603365@unet.univie.ac.at> configuration options + +#include <tdeconfig.h> +#include <tdeglobal.h> +#include <tdelocale.h> +#include <tqlayout.h> +#include <tqdrawutil.h> +#include <kpixmapeffect.h> +#include <kdrawutil.h> +#include <tqbitmap.h> +#include <tqtooltip.h> +#include <tqapplication.h> +#include <tqlabel.h> +#include "modernsys.h" + +#include "buttondata.h" +#include "btnhighcolor.h" +#include <tqimage.h> + +namespace ModernSystem { + +static unsigned char iconify_bits[] = { + 0x00, 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00}; + +static unsigned char close_bits[] = { + 0x00, 0x66, 0x7e, 0x3c, 0x3c, 0x7e, 0x66, 0x00}; + +static unsigned char maximize_bits[] = { + 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00}; + +static unsigned char r_minmax_bits[] = { + 0x0c, 0x18, 0x33, 0x67, 0xcf, 0x9f, 0x3f, 0x3f}; + +static unsigned char l_minmax_bits[] = { + 0x30, 0x18, 0xcc, 0xe6, 0xf3, 0xf9, 0xfc, 0xfc}; + +static unsigned char unsticky_bits[] = { + 0x3c, 0x42, 0x99, 0xbd, 0xbd, 0x99, 0x42, 0x3c}; + +static unsigned char sticky_bits[] = { + 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c}; + +static unsigned char question_bits[] = { + 0x3c, 0x66, 0x60, 0x30, 0x18, 0x00, 0x18, 0x18}; + +static unsigned char above_on_bits[] = { + 0x7e, 0x00, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00}; + +static unsigned char above_off_bits[] = { + 0x18, 0x3c, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00}; + +static unsigned char below_off_bits[] = { + 0x00, 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x3c, 0x18}; + +static unsigned char below_on_bits[] = { + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x00, 0x7e}; + +static unsigned char shade_off_bits[] = { + 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static unsigned char shade_on_bits[] = { + 0x00, 0x7e, 0x7e, 0x42, 0x42, 0x42, 0x7e, 0x00}; + +static unsigned char menu_bits[] = { + 0xff, 0x81, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff}; + +static unsigned char btnhighcolor_mask_bits[] = { + 0xe0,0x41,0xf8,0x07,0xfc,0x0f,0xfe,0xdf,0xfe,0x1f,0xff,0x3f,0xff,0xff,0xff, + 0x3f,0xff,0x3f,0xff,0xff,0xff,0xff,0xfe,0x9f,0xfe,0x1f,0xfc,0x0f,0xf0,0x03, + 0x00,0x40,0x80,0x00,0x00,0x00,0x39,0x00,0x00,0x00,0x20,0x99,0x0f,0x08,0xc4, + 0x00,0x00,0x00,0x67,0x00,0x00,0x00,0x58,0x5f,0x43,0x68,0x61,0x6e,0x67,0x65 }; + +static KPixmap *aUpperGradient=0; +static KPixmap *iUpperGradient=0; +static TQPixmap *buttonPix=0; +static TQPixmap *buttonPixDown=0; +static TQPixmap *iButtonPix=0; +static TQPixmap *iButtonPixDown=0; + +static TQColor *buttonFg; +static bool pixmaps_created = false; + +static TQBitmap *lcDark1; +static TQBitmap *lcDark2; +static TQBitmap *lcDark3; +static TQBitmap *lcLight1; +static TQImage *btnSource; + +static bool show_handle; +static int handle_size; +static int handle_width; +static int border_width; +static int title_height; + +static inline const KDecorationOptions* options() +{ + return KDecoration::options(); +} + +static void make_button_fx(const TQColorGroup &g, TQPixmap *pix, bool light=false) +{ + pix->fill(g.background()); + TQPainter p(pix); + + if(TQPixmap::defaultDepth() > 8){ + int i, destH, destS, destV, srcH, srcS, srcV; + TQColor btnColor = g.background(); + + if(btnSource->depth() < 32) + *btnSource = btnSource->convertDepth(32); + if(light) + btnColor = btnColor.light(120); + btnColor.hsv(&destH, &destS, &destV); + TQImage btnDest(14, 15, 32); + + unsigned int *srcData = (unsigned int *)btnSource->bits(); + unsigned int *destData = (unsigned int *)btnDest.bits(); + TQColor srcColor; + for(i=0; i < btnSource->width()*btnSource->height(); ++i){ + srcColor.setRgb(srcData[i]); + srcColor.hsv(&srcH, &srcS, &srcV); + srcColor.setHsv(destH, destS, srcV); + destData[i] = srcColor.rgb(); + } + pix->convertFromImage(btnDest); + + } + else{ + if(!lcDark1->mask()){ + lcDark1->setMask(*lcDark1); + lcDark2->setMask(*lcDark2); + lcDark3->setMask(*lcDark3); + lcLight1->setMask(*lcLight1); + } + p.setPen(g.dark()); + p.drawPixmap(0, 0, *lcDark2); + p.drawPixmap(0, 0, *lcDark1); + p.setPen(g.mid()); + p.drawPixmap(0, 0, *lcDark3); + p.setPen(g.light()); + p.drawPixmap(0, 0, *lcLight1); + } +} + + +static void create_pixmaps() +{ + if(pixmaps_created) + return; + pixmaps_created = true; + + lcDark1 = new TQBitmap(14, 15, lowcolor_6a696a_bits, true); + lcDark2 = new TQBitmap(14, 15, lowcolor_949194_bits, true); + lcDark3 = new TQBitmap(14, 15, lowcolor_b4b6b4_bits, true); + lcLight1 = new TQBitmap(14, 15, lowcolor_e6e6e6_bits, true); + btnSource = new TQImage(btnhighcolor_xpm); + + if(TQPixmap::defaultDepth() > 8){ + aUpperGradient = new KPixmap; + aUpperGradient->resize(32, title_height+2); + iUpperGradient = new KPixmap; + iUpperGradient->resize(32, title_height+2); + KPixmapEffect::gradient(*aUpperGradient, + options()->color(KDecoration::ColorTitleBar, true).light(130), + options()->color(KDecoration::ColorTitleBlend, true), + KPixmapEffect::VerticalGradient); + KPixmapEffect::gradient(*iUpperGradient, + options()->color(KDecoration::ColorTitleBar, false).light(130), + options()->color(KDecoration::ColorTitleBlend, false), + KPixmapEffect::VerticalGradient); + } + // buttons + TQColorGroup btnColor(options()->colorGroup(KDecoration::ColorButtonBg, true)); + buttonPix = new TQPixmap(14, 15); + make_button_fx(btnColor, buttonPix); + buttonPixDown = new TQPixmap(14, 15); + make_button_fx(btnColor, buttonPixDown, true); + + btnColor = options()->colorGroup(KDecoration::ColorButtonBg, false); + iButtonPix = new TQPixmap(14, 15); + make_button_fx(btnColor, iButtonPix); + iButtonPixDown = new TQPixmap(14, 15); + make_button_fx(btnColor, iButtonPixDown, true); + + + if(tqGray(btnColor.background().rgb()) < 150) + buttonFg = new TQColor(Qt::white); + else + buttonFg = new TQColor(Qt::black); + + delete lcDark1; + delete lcDark2; + delete lcDark3; + delete lcLight1; + delete btnSource; +} + +static void delete_pixmaps() +{ + if(aUpperGradient){ + delete aUpperGradient; + delete iUpperGradient; + } + delete buttonPix; + delete buttonPixDown; + delete iButtonPix; + delete iButtonPixDown; + + delete buttonFg; + + pixmaps_created = false; +} + +void ModernSysFactory::read_config() +{ + bool showh; + int hsize, hwidth, bwidth, theight; + + TDEConfig c("twinmodernsysrc"); + c.setGroup("General"); + showh = c.readBoolEntry("ShowHandle", true); + + hwidth = c.readUnsignedNumEntry("HandleWidth", 6); + hsize = c.readUnsignedNumEntry("HandleSize", 30); + if (!(showh && hsize && hwidth)) { + showh = false; + hwidth = hsize = 0; + } + + switch(options()->preferredBorderSize( this )) { + case BorderLarge: + bwidth = 8; + hwidth = hwidth * 7/5; + hsize = hsize * 7/5; + break; + case BorderVeryLarge: + bwidth = 12; + hwidth = hwidth * 17/10 + 2; + hsize = hsize * 17/10; + break; + case BorderHuge: + bwidth = 18; + hwidth = hwidth * 2 + 6; + hsize = hsize * 2; + break; + /* + // If we allow these large sizes we need to change the + // correlation between the border width and the handle size. + case BorderVeryHuge: + bwidth = 27; + hwidth = hwidth * 5/2 + 15; + hsize = hsize * 5/2; + break; + case BorderOversized: + bwidth = 40; + hwidth = hwidth * 3 + 22; + hsize = hsize * 3; + break; + */ + case BorderNormal: + default: + bwidth = 4; + } + + theight = TQFontMetrics(options()->font(true)).height() + 2; + if (theight < 16) + theight = 16; + if (theight < bwidth) + theight = bwidth; + + show_handle = showh; + handle_width = hwidth; + handle_size = hsize; + border_width = bwidth; + title_height = theight; +} + +TQValueList< ModernSysFactory::BorderSize > ModernSysFactory::borderSizes() const +{ // the list must be sorted + return TQValueList< BorderSize >() << BorderNormal << BorderLarge << + BorderVeryLarge << BorderHuge; + // as long as the buttons don't scale don't offer the largest two sizes. + // BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized; +} + +ModernButton::ModernButton(ButtonType type, ModernSys *parent, const char *name) + : KCommonDecorationButton(type, parent, name) +{ + setBackgroundMode( NoBackground ); + + TQBitmap mask(14, 15, TQPixmap::defaultDepth() > 8 ? + btnhighcolor_mask_bits : lowcolor_mask_bits, true); + resize(14, 15); + + setMask(mask); +} + +void ModernButton::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() ? (isLeft()?l_minmax_bits:r_minmax_bits) : maximize_bits ); + break; + case OnAllDesktopsButton: + setBitmap( isOn() ? unsticky_bits : sticky_bits ); + 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; + case MenuButton: + setBitmap(menu_bits); + break; + default: + setBitmap(0); + break; + } + + this->update(); + } +} + +void ModernButton::setBitmap(const unsigned char *bitmap) +{ + if (bitmap) + deco = TQBitmap(8, 8, bitmap, true); + else { + deco = TQBitmap(8,8); + deco.fill(Qt::color0); + } + deco.setMask(deco); +} + +void ModernButton::drawButton(TQPainter *p) +{ + if(decoration()->isActive()){ + if(buttonPix) + p->drawPixmap(0, 0, isDown() ? *buttonPixDown : *buttonPix); + } + else{ + if(iButtonPix) + p->drawPixmap(0, 0, isDown() ? *iButtonPixDown : *iButtonPix); + } + if(!deco.isNull()){ + p->setPen(*buttonFg); + p->drawPixmap(isDown() ? 4 : 3, isDown() ? 5 : 4, deco); + } +} + +void ModernSys::reset( unsigned long changed) +{ + KCommonDecoration::reset(changed); + + titleBuffer.resize(0, 0); + recalcTitleBuffer(); + resetButtons(); + widget()->update(); +} + +ModernSys::ModernSys( KDecorationBridge* b, KDecorationFactory* f ) + : KCommonDecoration( b, f ) +{ +} + +TQString ModernSys::visibleName() const +{ + return i18n("Modern System"); +} + +TQString ModernSys::defaultButtonsLeft() const +{ + return "X"; +} + +TQString ModernSys::defaultButtonsRight() const +{ + return "HSIA"; +} + +bool ModernSys::decorationBehaviour(DecorationBehaviour behaviour) const +{ + switch (behaviour) { + case DB_MenuClose: + return false; + + case DB_WindowMask: + return true; + + case DB_ButtonHide: + return true; + + default: + return KCommonDecoration::decorationBehaviour(behaviour); + } +} + +int ModernSys::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *btn) const +{ + // bool maximized = maximizeMode()==MaximizeFull && !options()->moveResizeMaximizedWindows(); + + switch (lm) { + case LM_BorderLeft: + return border_width + (reverse ? handle_width : 0); + + case LM_BorderRight: + return border_width + (reverse ? 0 : handle_width); + + case LM_BorderBottom: + return border_width + handle_width; + + case LM_TitleEdgeLeft: + return layoutMetric(LM_BorderLeft,respectWindowState)+3; + case LM_TitleEdgeRight: + return layoutMetric(LM_BorderRight,respectWindowState)+3; + + case LM_TitleEdgeTop: + return 2; + + case LM_TitleEdgeBottom: + return 2; + + case LM_TitleBorderLeft: + case LM_TitleBorderRight: + return 4; + + case LM_TitleHeight: + return title_height; + + case LM_ButtonWidth: + return 14; + case LM_ButtonHeight: + return 15; + + case LM_ButtonSpacing: + return 1; + + case LM_ExplicitButtonSpacer: + return 3; + + default: + return KCommonDecoration::layoutMetric(lm, respectWindowState, btn); + } +} + +KCommonDecorationButton *ModernSys::createButton(ButtonType type) +{ + switch (type) { + case MenuButton: + return new ModernButton(MenuButton, this, "menu"); + + case OnAllDesktopsButton: + return new ModernButton(OnAllDesktopsButton, this, "on_all_desktops"); + + case HelpButton: + return new ModernButton(HelpButton, this, "help"); + + case MinButton: + return new ModernButton(MinButton, this, "minimize"); + + case MaxButton: + return new ModernButton(MaxButton, this, "maximize"); + + case CloseButton: + return new ModernButton(CloseButton, this, "close"); + + case AboveButton: + return new ModernButton(AboveButton, this, "above"); + + case BelowButton: + return new ModernButton(BelowButton, this, "below"); + + case ShadeButton: + return new ModernButton(ShadeButton, this, "shade"); + + default: + return 0; + } +} + +void ModernSys::init() +{ + reverse = TQApplication::reverseLayout(); + + KCommonDecoration::init(); + + recalcTitleBuffer(); +} + +void ModernSys::recalcTitleBuffer() +{ + if(oldTitle == caption() && width() == titleBuffer.width()) + return; + + TQFontMetrics fm(options()->font(true)); + titleBuffer.resize(width(), title_height+2); + TQPainter p; + p.begin(&titleBuffer); + if(aUpperGradient) + p.drawTiledPixmap(0, 0, width(), title_height+2, *aUpperGradient); + else + p.fillRect(0, 0, width(), title_height+2, + options()->colorGroup(ColorTitleBar, true). + brush(TQColorGroup::Button)); + + TQRect t = titleRect(); // titlebar->geometry(); + t.setTop( 2 ); + t.setLeft( t.left() ); + t.setRight( t.right() - 2 ); + + TQRegion r(t.x(), 0, t.width(), title_height+2); + r -= TQRect(t.x()+((t.width()-fm.width(caption()))/2)-4, + 0, fm.width(caption())+8, title_height+2); + p.setClipRegion(r); + int i, ly; + ly = (title_height % 3 == 0) ? 3 : 4; + for(i=0; i < (title_height-2)/3; ++i, ly+=3){ + p.setPen(options()->color(ColorTitleBar, true).light(150)); + p.drawLine(0, ly, width()-1, ly); + p.setPen(options()->color(ColorTitleBar, true).dark(120)); + p.drawLine(0, ly+1, width()-1, ly+1); + } + p.setClipRect(t); + p.setPen(options()->color(ColorFont, true)); + p.setFont(options()->font(true)); + + p.drawText(t.x()+((t.width()-fm.width(caption()))/2)-4, + 0, fm.width(caption())+8, title_height+2, AlignCenter, caption()); + p.setClipping(false); + p.end(); + oldTitle = caption(); +} + +void ModernSys::updateCaption() +{ + widget()->update(titleRect() ); +} + +void ModernSys::drawRoundFrame(TQPainter &p, int x, int y, int w, int h) +{ + kDrawRoundButton(&p, x, y, w, h, + options()->colorGroup(ColorFrame, isActive()), false); + +} + +void ModernSys::paintEvent( TQPaintEvent* ) +{ + // update title buffer... + if (oldTitle != caption() || width() != titleBuffer.width() ) + recalcTitleBuffer(); + + int hs = handle_size; + int hw = handle_width; + + TQPainter p( widget() ); + TQRect t = titleRect(); // titlebar->geometry(); + + TQBrush fillBrush(widget()->colorGroup().brush(TQColorGroup::Background).pixmap() ? + widget()->colorGroup().brush(TQColorGroup::Background) : + options()->colorGroup(ColorFrame, isActive()). + brush(TQColorGroup::Button)); + + p.fillRect(1, title_height+3, width()-2, height()-(title_height+3), fillBrush); + p.fillRect(width()-6, 0, width()-1, height(), fillBrush); + + t.setTop( 2 ); + t.setLeft( t.left() ); + t.setRight( t.right() - 2 ); + + int w = width() - hw; // exclude handle + int h = height() - hw; + + // titlebar + TQColorGroup g = options()->colorGroup(ColorTitleBar, isActive()); + if(isActive()){ + p.drawPixmap(1, 1, titleBuffer, 0, 0, w-2, title_height+2); + } + else{ + if(iUpperGradient) + p.drawTiledPixmap(1, 1, w-2, title_height+2, *iUpperGradient); + else + p.fillRect(1, 1, w-2, title_height+2, fillBrush); + p.setPen(options()->color(ColorFont, isActive())); + p.setFont(options()->font(isActive())); + p.drawText(t, AlignCenter, caption() ); + } + + // titlebar highlight + p.setPen(g.light()); + p.drawLine(1, 1, 1, title_height+3); + p.drawLine(1, 1, w-3, 1); + p.setPen(g.dark()); + p.drawLine(w-2, 1, w-2, title_height+3); + p.drawLine(0, title_height+2, w-2, title_height+2); + + // frame + g = options()->colorGroup(ColorFrame, isActive()); + p.setPen(g.light()); + p.drawLine(1, title_height+3, 1, h-2); + p.setPen(g.dark()); + p.drawLine(2, h-2, w-2, h-2); + p.drawLine(w-2, title_height+3, w-2, h-2); + //p.drawPoint(w-3, title_height+3); + //p.drawPoint(2, title_height+3); + + qDrawShadePanel(&p, border_width-1, title_height+3, w-2*border_width+2, h-title_height-border_width-2, g, true); + + if (show_handle) { + p.setPen(g.dark()); + p.drawLine(width()-3, height()-hs-1, width()-3, height()-3); + p.drawLine(width()-hs-1, height()-3, width()-3, height()-3); + + p.setPen(g.light()); + p.drawLine(width()-hw, height()-hs-1, width()-hw, height()-hw); + p.drawLine(width()-hs-1, height()-hw, width()-hw, height()-hw); + p.drawLine(width()-hw, height()-hs-1, width()-4, height()-hs-1); + p.drawLine(width()-hs-1, height()-hw, width()-hs-1, height()-4); + + p.setPen(Qt::black); + p.drawRect(0, 0, w, h); + + // handle outline + p.drawLine(width()-hw, height()-hs, width(), height()-hs); + p.drawLine(width()-2, height()-hs, width()-2, height()-2); + p.drawLine(width()-hs, height()-2, width()-2, height()-2); + p.drawLine(width()-hs, height()-hw, width()-hs, height()-2); + } else { + p.setPen(Qt::black); + p.drawRect(0, 0, w, h); + } +} + +void ModernSys::updateWindowShape() +{ + int hs = handle_size; + int hw = handle_width; + TQRegion mask; + mask += TQRect(0, 0, width()-hw, height()-hw); + //single points + mask -= TQRect(0, 0, 1, 1); + mask -= TQRect(width()-hw-1, 0, 1, 1); + mask -= TQRect(0, height()-hw-1, 1, 1); + + if (show_handle) { + mask += TQRect(width()-hs, height()-hs, hs-1, hs-1); + mask -= TQRect(width()-2, height()-2, 1, 1); + mask -= TQRect(width()-2, height()-hs, 1, 1); + mask -= TQRect(width()-hs, height()-2, 1, 1); + } else + mask -= TQRect(width()-1, height()-1, 1, 1); + + setMask(mask); +} + +ModernSysFactory::ModernSysFactory() +{ + read_config(); + create_pixmaps(); +} + +ModernSysFactory::~ModernSysFactory() +{ + ModernSystem::delete_pixmaps(); +} + +KDecoration* ModernSysFactory::createDecoration( KDecorationBridge* b ) +{ + return(new ModernSys(b, this)); +} + +bool ModernSysFactory::reset( unsigned long changed ) +{ + read_config(); + + bool needHardReset = true; + if( changed & (SettingColors | SettingBorder | SettingFont) ) + { + delete_pixmaps(); + create_pixmaps(); + needHardReset = false; + } else if (changed & SettingButtons) { + // handled by KCommonDecoration + needHardReset = false; + } + + if( needHardReset ) + return true; + else + { + resetDecorations( changed ); + return false; // no recreating of decorations + } +} + +bool ModernSysFactory::supports( Ability ability ) +{ + switch( ability ) + { + case AbilityAnnounceButtons: + case AbilityButtonOnAllDesktops: + case AbilityButtonSpacer: + case AbilityButtonHelp: + case AbilityButtonMinimize: + case AbilityButtonMaximize: + case AbilityButtonClose: + case AbilityButtonAboveOthers: + case AbilityButtonBelowOthers: + case AbilityButtonShade: + case AbilityButtonMenu: + return true; + default: + return false; + }; +} + +} + +// KWin extended plugin interface +extern "C" KDE_EXPORT KDecorationFactory* create_factory() +{ + return new ModernSystem::ModernSysFactory(); +} + +// vim:ts=4:sw=4 diff --git a/twin/clients/modernsystem/modernsys.h b/twin/clients/modernsystem/modernsys.h new file mode 100644 index 000000000..3e0cf02fd --- /dev/null +++ b/twin/clients/modernsystem/modernsys.h @@ -0,0 +1,72 @@ +#ifndef __MODSYSTEMCLIENT_H +#define __MODSYSTEMCLIENT_H + +#include <tqbitmap.h> +#include <kpixmap.h> +#include <kcommondecoration.h> +#include <kdecorationfactory.h> + +class TQLabel; +class TQSpacerItem; + +namespace ModernSystem { + +class ModernSys; + +class ModernButton : public KCommonDecorationButton +{ +public: + ModernButton(ButtonType type, ModernSys *parent, const char *name); + void setBitmap(const unsigned char *bitmap); + virtual void reset(unsigned long changed); +protected: + + virtual void drawButton(TQPainter *p); + void drawButtonLabel(TQPainter *){;} + TQBitmap deco; +}; + +class ModernSys : public KCommonDecoration +{ +public: + ModernSys( KDecorationBridge* b, KDecorationFactory* f ); + ~ModernSys(){;} + + virtual TQString visibleName() const; + virtual TQString defaultButtonsLeft() const; + virtual TQString 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 updateWindowShape(); + virtual void updateCaption(); + + void init(); +protected: + void drawRoundFrame(TQPainter &p, int x, int y, int w, int h); + void paintEvent( TQPaintEvent* ); + void recalcTitleBuffer(); + void reset( unsigned long ); +private: + TQPixmap titleBuffer; + TQString oldTitle; + bool reverse; +}; + +class ModernSysFactory : public TQObject, public KDecorationFactory +{ +public: + ModernSysFactory(); + virtual ~ModernSysFactory(); + virtual KDecoration* createDecoration( KDecorationBridge* ); + virtual bool reset( unsigned long changed ); + virtual bool supports( Ability ability ); + TQValueList< BorderSize > borderSizes() const; +private: + void read_config(); +}; + +} + +#endif diff --git a/twin/clients/modernsystem/modernsystem.desktop b/twin/clients/modernsystem/modernsystem.desktop new file mode 100644 index 000000000..703d6e3e2 --- /dev/null +++ b/twin/clients/modernsystem/modernsystem.desktop @@ -0,0 +1,69 @@ +[Desktop Entry] +Name=Modern System +Name[af]=Moderne Stelsel +Name[ar]=نظام معاصر +Name[az]=Modern Sistem +Name[be]=Сучасная сістэма +Name[bn]=মডার্ন সিস্টেম +Name[br]=Reizhiad Nevez +Name[ca]=Sistema modern +Name[cs]=Moderní systém +Name[csb]=Mòdernô systema +Name[cy]=Cysawd Cyfoes +Name[da]=Moderne system +Name[el]=Μοντέρνο σύστημα +Name[eo]=Moderna Sistemo +Name[es]=Sistema moderno +Name[eu]=Sistema modernoa +Name[fa]=سیستم نوین +Name[fi]=Moderni järjestelmä +Name[fr]=Système Moderne +Name[fy]=Modern systeem +Name[ga]=Córas Nua-Aimseartha +Name[gl]=Sistema Moderno +Name[hi]=आधुनिक तंत्र +Name[hr]=Suvremeni sustav +Name[is]=Nútímaleg vél +Name[it]=Sistema Moderno +Name[ja]=モダンシステム +Name[ka]=თანამედროვე სისტემა +Name[kk]=Заманауи жүйе +Name[km]=ប្រព័ន្ធទំនើប +Name[ko]=모던 시스템 +Name[lt]=Moderni sistema +Name[lv]=Moderna sistēma +Name[mk]=Модерен систем +Name[ms]=Sistem Moden +Name[mt]=Sistema Moderna +Name[nb]=Moderne System +Name[nds]=Modeern Systeem +Name[ne]=आधुनिक प्रणाली +Name[nl]=Modern systeem +Name[nn]=Moderne System +Name[pa]=ਨਵਾਂ ਸਿਸਟਮ +Name[pl]=Nowoczesny system +Name[pt]=Sistema Moderno +Name[pt_BR]=Sistema Moderno +Name[ro]=Sistem moderm +Name[ru]=Современная система +Name[rw]=Sisitemu Igezweho +Name[se]=Áigeguovdilis vuogádat +Name[sk]=Moderný systém +Name[sl]=Moderni sistem +Name[sr]=Модерни систем +Name[sr@Latn]=Moderni sistem +Name[sv]=Modernt system +Name[ta]=நவீன அமைப்பு +Name[te]=ఆధునిక వ్యవస్థ +Name[tg]=Системаи навтарин +Name[th]=แบบ Moden System +Name[tr]=Modern Sistem +Name[tt]=Zamança Sistem +Name[uk]=Сучасна система +Name[uz]=Zamonaviy tizim +Name[uz@cyrillic]=Замонавий тизим +Name[vi]=Hệ thống Hiện đại +Name[wa]=Sistinme modiene +Name[zh_CN]=现代系统 +Name[zh_TW]=現代系統 +X-TDE-Library=twin3_modernsys diff --git a/twin/clients/plastik/CMakeLists.txt b/twin/clients/plastik/CMakeLists.txt new file mode 100644 index 000000000..d782413ce --- /dev/null +++ b/twin/clients/plastik/CMakeLists.txt @@ -0,0 +1,39 @@ +################################################# +# +# (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 ) + +add_definitions( -DQT_PLUGIN ) + +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 plastik.desktop DESTINATION ${DATA_INSTALL_DIR}/twin ) + + +##### twin3_plastik (module) #################### + +tde_add_kpart( twin3_plastik AUTOMOC + SOURCES plastik.cpp plastikclient.cpp plastikbutton.cpp misc.cpp + LINK tdecorations-shared tdeui-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/twin/clients/plastik/Makefile.am b/twin/clients/plastik/Makefile.am new file mode 100644 index 000000000..c1757891d --- /dev/null +++ b/twin/clients/plastik/Makefile.am @@ -0,0 +1,19 @@ +AUTOMAKE_OPTIONS = foreign + +SUBDIRS = config + +KDE_CXXFLAGS = -DQT_PLUGIN + +INCLUDES = -I$(srcdir)/../../lib $(all_includes) + +twindir = $(kde_datadir)/twin/ +twin_DATA = plastik.desktop + +kde_module_LTLIBRARIES = twin3_plastik.la +twin3_plastik_la_SOURCES = plastik.cpp plastikclient.cpp plastikbutton.cpp misc.cpp +twin3_plastik_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +twin3_plastik_la_LIBADD = $(LIB_TDEUI) ../../lib/libtdecorations.la +twin3_plastik_la_METASOURCES = AUTO + +DISTCLEANFILES = $(twin3_plastik_la_METASOURCES) + diff --git a/twin/clients/plastik/config/CMakeLists.txt b/twin/clients/plastik/config/CMakeLists.txt new file mode 100644 index 000000000..49066000e --- /dev/null +++ b/twin/clients/plastik/config/CMakeLists.txt @@ -0,0 +1,33 @@ +################################################# +# +# (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} +) + +##### other data ################################ + +install( FILES DESTINATION ${XDG_APPS_INSTALL_DIR} ) + + +##### twin_plastik_config (module) ############## + +tde_add_kpart( twin_plastik_config AUTOMOC + SOURCES config.cpp configdialog.ui + LINK tdeui-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/twin/clients/plastik/config/Makefile.am b/twin/clients/plastik/config/Makefile.am new file mode 100644 index 000000000..b21a1d26b --- /dev/null +++ b/twin/clients/plastik/config/Makefile.am @@ -0,0 +1,14 @@ +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = twin_plastik_config.la + +twin_plastik_config_la_SOURCES = config.cpp configdialog.ui +twin_plastik_config_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +twin_plastik_config_la_LIBADD = $(LIB_TDEUI) + +METASOURCES = AUTO +noinst_HEADERS = config.h +DISTCLEANFILES = $(METASOURCES) + +lnkdir = $(kde_datadir)/twin + diff --git a/twin/clients/plastik/config/config.cpp b/twin/clients/plastik/config/config.cpp new file mode 100644 index 000000000..04658796c --- /dev/null +++ b/twin/clients/plastik/config/config.cpp @@ -0,0 +1,123 @@ +/* Plastik KWin window decoration + Copyright (C) 2003 Sandro Giessl <ceebx@users.sourceforge.net> + + based on the window decoration "Web": + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@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 <tqbuttongroup.h> +#include <tqcheckbox.h> +#include <tqradiobutton.h> +#include <tqslider.h> +#include <tqspinbox.h> +#include <tqwhatsthis.h> + +#include <tdeconfig.h> +#include <tdelocale.h> +#include <tdeglobal.h> + +#include "config.h" +#include "configdialog.h" + +PlastikConfig::PlastikConfig(TDEConfig* config, TQWidget* parent) + : TQObject(parent), m_config(0), m_dialog(0) +{ + // create the configuration object + m_config = new TDEConfig("twinplastikrc"); + TDEGlobal::locale()->insertCatalogue("twin_clients"); + + // create and show the configuration dialog + m_dialog = new ConfigDialog(parent); + m_dialog->show(); + + // load the configuration + load(config); + + // setup the connections + connect(m_dialog->titleAlign, TQT_SIGNAL(clicked(int)), + this, TQT_SIGNAL(changed())); + connect(m_dialog->animateButtons, TQT_SIGNAL(toggled(bool)), + this, TQT_SIGNAL(changed())); + connect(m_dialog->menuClose, TQT_SIGNAL(toggled(bool)), + this, TQT_SIGNAL(changed())); + connect(m_dialog->titleShadow, TQT_SIGNAL(toggled(bool)), + this, TQT_SIGNAL(changed())); + connect(m_dialog->coloredBorder, TQT_SIGNAL(toggled(bool)), + this, TQT_SIGNAL(changed())); +} + +PlastikConfig::~PlastikConfig() +{ + if (m_dialog) delete m_dialog; + if (m_config) delete m_config; +} + +void PlastikConfig::load(TDEConfig*) +{ + m_config->setGroup("General"); + + + TQString value = m_config->readEntry("TitleAlignment", "AlignLeft"); + TQRadioButton *button = (TQRadioButton*)m_dialog->titleAlign->child(value.latin1()); + if (button) button->setChecked(true); + bool animateButtons = m_config->readBoolEntry("AnimateButtons", true); + m_dialog->animateButtons->setChecked(animateButtons); + bool menuClose = m_config->readBoolEntry("CloseOnMenuDoubleClick", true); + m_dialog->menuClose->setChecked(menuClose); + bool titleShadow = m_config->readBoolEntry("TitleShadow", true); + m_dialog->titleShadow->setChecked(titleShadow); + bool coloredBorder = m_config->readBoolEntry("ColoredBorder", true); + m_dialog->coloredBorder->setChecked(coloredBorder); +} + +void PlastikConfig::save(TDEConfig*) +{ + m_config->setGroup("General"); + + TQRadioButton *button = (TQRadioButton*)m_dialog->titleAlign->selected(); + if (button) m_config->writeEntry("TitleAlignment", TQString(button->name())); + m_config->writeEntry("AnimateButtons", m_dialog->animateButtons->isChecked() ); + m_config->writeEntry("CloseOnMenuDoubleClick", m_dialog->menuClose->isChecked() ); + m_config->writeEntry("TitleShadow", m_dialog->titleShadow->isChecked() ); + m_config->writeEntry("ColoredBorder", m_dialog->coloredBorder->isChecked() ); + m_config->sync(); +} + +void PlastikConfig::defaults() +{ + TQRadioButton *button = + (TQRadioButton*)m_dialog->titleAlign->child("AlignLeft"); + if (button) button->setChecked(true); + m_dialog->animateButtons->setChecked(true); + m_dialog->menuClose->setChecked(false); + m_dialog->titleShadow->setChecked(true); + m_dialog->coloredBorder->setChecked(true); +} + +////////////////////////////////////////////////////////////////////////////// +// Plugin Stuff // +////////////////////////////////////////////////////////////////////////////// + +extern "C" +{ + KDE_EXPORT TQObject* allocate_config(TDEConfig* config, TQWidget* parent) { + return (new PlastikConfig(config, parent)); + } +} + +#include "config.moc" diff --git a/twin/clients/plastik/config/config.h b/twin/clients/plastik/config/config.h new file mode 100644 index 000000000..73231c50f --- /dev/null +++ b/twin/clients/plastik/config/config.h @@ -0,0 +1,53 @@ +/* Plastik KWin window decoration + Copyright (C) 2003 Sandro Giessl <ceebx@users.sourceforge.net> + + based on the window decoration "Web": + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@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 KNIFTYCONFIG_H +#define KNIFTYCONFIG_H + +#include <tqobject.h> + +class TQButtonGroup; +class TQGroupBox; +class TDEConfig; +class ConfigDialog; + +class PlastikConfig : public TQObject +{ + Q_OBJECT +public: + PlastikConfig(TDEConfig* config, TQWidget* parent); + ~PlastikConfig(); + +signals: + void changed(); + +public slots: + void load(TDEConfig *config); + void save(TDEConfig *config); + void defaults(); + +private: + TDEConfig *m_config; + ConfigDialog *m_dialog; +}; + +#endif // KNIFTYCONFIG_H diff --git a/twin/clients/plastik/config/configdialog.ui b/twin/clients/plastik/config/configdialog.ui new file mode 100644 index 000000000..f751d8024 --- /dev/null +++ b/twin/clients/plastik/config/configdialog.ui @@ -0,0 +1,119 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>ConfigDialog</class> +<widget class="TQWidget"> + <property name="name"> + <cstring>ConfigDialog</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>541</width> + <height>170</height> + </rect> + </property> + <property name="caption"> + <string>Config Dialog</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="TQButtonGroup"> + <property name="name"> + <cstring>titleAlign</cstring> + </property> + <property name="title"> + <string>Title &Alignment</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQRadioButton"> + <property name="name"> + <cstring>AlignLeft</cstring> + </property> + <property name="text"> + <string>Left</string> + </property> + </widget> + <widget class="TQRadioButton"> + <property name="name"> + <cstring>AlignHCenter</cstring> + </property> + <property name="text"> + <string>Center</string> + </property> + </widget> + <widget class="TQRadioButton"> + <property name="name"> + <cstring>AlignRight</cstring> + </property> + <property name="text"> + <string>Right</string> + </property> + </widget> + </hbox> + </widget> + <widget class="TQCheckBox"> + <property name="name"> + <cstring>coloredBorder</cstring> + </property> + <property name="text"> + <string>Colored window border</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="whatsThis" stdset="0"> + <string>Check this option if the window border should be painted in the titlebar color. Otherwise it will be painted in the background color.</string> + </property> + </widget> + <widget class="TQCheckBox"> + <property name="name"> + <cstring>titleShadow</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> + <widget class="TQCheckBox"> + <property name="name"> + <cstring>animateButtons</cstring> + </property> + <property name="text"> + <string>Animate buttons</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Check this option if you want the buttons to fade in when the mouse pointer hovers over them and fade out again when it moves away.</string> + </property> + </widget> + <widget class="TQCheckBox"> + <property name="name"> + <cstring>menuClose</cstring> + </property> + <property name="text"> + <string>Close windows by double clicking the menu button</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Check this option if you want windows to be closed when you double click the menu button, similar to Microsoft Windows.</string> + </property> + </widget> + </vbox> +</widget> +<tabstops> + <tabstop>AlignLeft</tabstop> + <tabstop>AlignHCenter</tabstop> + <tabstop>AlignRight</tabstop> + <tabstop>animateButtons</tabstop> + <tabstop>titleShadow</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/twin/clients/plastik/misc.cpp b/twin/clients/plastik/misc.cpp new file mode 100644 index 000000000..1b259d383 --- /dev/null +++ b/twin/clients/plastik/misc.cpp @@ -0,0 +1,85 @@ +/* Plastik KWin window decoration + Copyright (C) 2003 Sandro Giessl <ceebx@users.sourceforge.net> + + based on the window decoration "Web": + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@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 <kpixmap.h> +#include <kpixmapeffect.h> + +#include <tqcolor.h> +#include <tqimage.h> +#include <tqpainter.h> + +#include "misc.h" + +TQColor hsvRelative(const TQColor& baseColor, int relativeH, int relativeS, int relativeV) +{ + int h, s, v; + baseColor.hsv(&h, &s, &v); + + h += relativeH; + s += relativeS; + v += relativeV; + + if(h < 0) { h = 0; } + else if(h > 359) { h = 359; } + if(s < 0) { s = 0; } + else if(s > 255) { s = 255; } + if(v < 0) { v = 0; } + else if(v > 255) { v = 255; } + + TQColor c; + c.setHsv( h, s, v ); + return c; +} + +TQColor alphaBlendColors(const TQColor &bgColor, const TQColor &fgColor, const int a) +{ + + // normal button... + QRgb rgb = bgColor.rgb(); + QRgb rgb_b = fgColor.rgb(); + int alpha = a; + if(alpha>255) alpha = 255; + if(alpha<0) alpha = 0; + int inv_alpha = 255 - alpha; + + TQColor result = TQColor( tqRgb(tqRed(rgb_b)*inv_alpha/255 + tqRed(rgb)*alpha/255, + tqGreen(rgb_b)*inv_alpha/255 + tqGreen(rgb)*alpha/255, + tqBlue(rgb_b)*inv_alpha/255 + tqBlue(rgb)*alpha/255) ); + + return result; +} + +TQImage recolorImage(TQImage *img, TQColor color) { + TQImage destImg(img->width(),img->height(),32); + destImg.setAlphaBuffer(true); + for (int x = 0; x < img->width(); x++) { + for (int y = 0; y < img->height(); y++) { + if(img->pixel(x,y) == tqRgb(0,0,255) ) { + destImg.setPixel(x,y,color.rgb() ); // set to the new color + } else { + destImg.setPixel(x,y,tqRgba(0,0,0,0) ); // set transparent... + } + } + } + + return destImg; +} diff --git a/twin/clients/plastik/misc.h b/twin/clients/plastik/misc.h new file mode 100644 index 000000000..985b405e8 --- /dev/null +++ b/twin/clients/plastik/misc.h @@ -0,0 +1,30 @@ +/* Plastik KWin window decoration + Copyright (C) 2003 Sandro Giessl <ceebx@users.sourceforge.net> + + based on the window decoration "Web": + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@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 MISC_H +#define MISC_H + +TQColor hsvRelative(const TQColor& baseColor, int relativeH, int relativeS = 0, int relativeV = 0); +TQColor alphaBlendColors(const TQColor &backgroundColor, const TQColor &foregroundColor, const int alpha); +TQImage recolorImage(TQImage *img, TQColor color); + +#endif // MISC_H diff --git a/twin/clients/plastik/plastik.cpp b/twin/clients/plastik/plastik.cpp new file mode 100644 index 000000000..b5cdeb85b --- /dev/null +++ b/twin/clients/plastik/plastik.cpp @@ -0,0 +1,598 @@ +/* Plastik KWin window decoration + Copyright (C) 2003-2005 Sandro Giessl <sandro@giessl.com> + + based on the window decoration "Web": + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@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 <tqbitmap.h> +#include <tqpainter.h> +#include <tqimage.h> + +#include <tdeconfig.h> +#include <kpixmap.h> +#include <kpixmapeffect.h> + +#include "misc.h" +#include "plastik.h" +#include "plastik.moc" +#include "plastikclient.h" +#include "plastikbutton.h" + +namespace KWinPlastik +{ + +PlastikHandler::PlastikHandler() +{ + memset(m_pixmaps, 0, sizeof(TQPixmap*)*NumPixmaps*2*2); // set elements to 0 + memset(m_bitmaps, 0, sizeof(TQBitmap*)*NumButtonIcons*2); + + reset(0); +} + +PlastikHandler::~PlastikHandler() +{ + for (int t=0; t < 2; ++t) + for (int a=0; a < 2; ++a) + for (int i=0; i < NumPixmaps; ++i) + delete m_pixmaps[t][a][i]; + for (int t=0; t < 2; ++t) + for (int i=0; i < NumButtonIcons; ++i) + delete m_bitmaps[t][i]; +} + +bool PlastikHandler::reset(unsigned long changed) +{ + // we assume the active font to be the same as the inactive font since the control + // center doesn't offer different settings anyways. + m_titleFont = KDecoration::options()->font(true, false); // not small + m_titleFontTool = KDecoration::options()->font(true, true); // small + + switch(KDecoration::options()->preferredBorderSize( this )) { + case BorderTiny: + m_borderSize = 3; + break; + case BorderLarge: + m_borderSize = 8; + break; + case BorderVeryLarge: + m_borderSize = 12; + break; + case BorderHuge: + m_borderSize = 18; + break; + case BorderVeryHuge: + m_borderSize = 27; + break; + case BorderOversized: + m_borderSize = 40; + break; + case BorderNormal: + default: + m_borderSize = 4; + } + + // check if we are in reverse layout mode + m_reverse = TQApplication::reverseLayout(); + + // read in the configuration + readConfig(); + + // pixmaps probably need to be updated, so delete the cache. + for (int t=0; t < 2; ++t) { + for (int a=0; a < 2; ++a) { + for (int i=0; i < NumPixmaps; i++) { + if (m_pixmaps[t][a][i]) { + delete m_pixmaps[t][a][i]; + m_pixmaps[t][a][i] = 0; + } + } + } + } + for (int t=0; t < 2; ++t) { + for (int i=0; i < NumButtonIcons; i++) { + if (m_bitmaps[t][i]) { + delete m_bitmaps[t][i]; + m_bitmaps[t][i] = 0; + } + } + } + + // Do we need to "hit the wooden hammer" ? + bool needHardReset = true; + // TODO: besides the Color and Font settings I can maybe handle more changes + // without a hard reset. I will do this later... + if (changed & SettingColors || changed & SettingFont) + { + needHardReset = false; + } else if (changed & SettingButtons) { + // handled by KCommonDecoration + needHardReset = false; + } + + if (needHardReset) { + return true; + } else { + resetDecorations(changed); + return false; + } +} + +KDecoration* PlastikHandler::createDecoration( KDecorationBridge* bridge ) +{ + return new PlastikClient( bridge, this ); +} + +bool PlastikHandler::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; + }; +} + +void PlastikHandler::readConfig() +{ + // create a config object + TDEConfig config("twinplastikrc"); + config.setGroup("General"); + + // grab settings + m_titleShadow = config.readBoolEntry("TitleShadow", true); + + TQFontMetrics fm(m_titleFont); // active font = inactive font + int titleHeightMin = config.readNumEntry("MinTitleHeight", 16); + // The title should strech with bigger font sizes! + m_titleHeight = TQMAX(titleHeightMin, fm.height() + 4); // 4 px for the shadow etc. + // have an even title/button size so the button icons are fully centered... + if ( m_titleHeight%2 == 0) + m_titleHeight++; + + fm = TQFontMetrics(m_titleFontTool); // active font = inactive font + int titleHeightToolMin = config.readNumEntry("MinTitleHeightTool", 13); + // The title should strech with bigger font sizes! + m_titleHeightTool = TQMAX(titleHeightToolMin, fm.height() ); // don't care about the shadow etc. + // have an even title/button size so the button icons are fully centered... + if ( m_titleHeightTool%2 == 0) + m_titleHeightTool++; + + TQString value = config.readEntry("TitleAlignment", "AlignLeft"); + if (value == "AlignLeft") m_titleAlign = Qt::AlignLeft; + else if (value == "AlignHCenter") m_titleAlign = Qt::AlignHCenter; + else if (value == "AlignRight") m_titleAlign = Qt::AlignRight; + + m_coloredBorder = config.readBoolEntry("ColoredBorder", true); + m_animateButtons = config.readBoolEntry("AnimateButtons", true); + m_menuClose = config.readBoolEntry("CloseOnMenuDoubleClick", true); +} + +TQColor PlastikHandler::getColor(KWinPlastik::ColorType type, const bool active) +{ + switch (type) { + case WindowContour: + return KDecoration::options()->color(ColorTitleBar, active).dark(200); + case TitleGradient1: + return hsvRelative(KDecoration::options()->color(ColorTitleBar, active), 0,-10,+10); + break; + case TitleGradient2: + return hsvRelative(KDecoration::options()->color(ColorTitleBar, active), 0,0,-25); + break; + case TitleGradient3: + return KDecoration::options()->color(ColorTitleBar, active); + break; + case ShadeTitleLight: + return alphaBlendColors(KDecoration::options()->color(ColorTitleBar, active), + Qt::white, active?205:215); + break; + case ShadeTitleDark: + return alphaBlendColors(KDecoration::options()->color(ColorTitleBar, active), + Qt::black, active?205:215); + break; + case Border: + return KDecoration::options()->color(ColorFrame, active); + case TitleFont: + return KDecoration::options()->color(ColorFont, active); + default: + return Qt::black; + } +} + +void PlastikHandler::pretile( TQPixmap *&pix, int size, Qt::Orientation dir ) const +{ + 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; +} + +const TQPixmap &PlastikHandler::pixmap(Pixmaps type, bool active, bool toolWindow) +{ + if (m_pixmaps[toolWindow][active][type]) + return *m_pixmaps[toolWindow][active][type]; + + TQPixmap *pm = 0; + + switch (type) { + case TitleBarTileTop: + case TitleBarTile: + { + const int titleBarTileHeight = (toolWindow ? m_titleHeightTool : m_titleHeight) + 2; + // gradient used as well in TitleBarTileTop as TitleBarTile + const int gradientHeight = 2 + titleBarTileHeight-1; + TQPixmap gradient(1, gradientHeight); + TQPainter painter(&gradient); + KPixmap tempPixmap; + tempPixmap.resize(1, 4); + KPixmapEffect::gradient(tempPixmap, + getColor(TitleGradient1, active), + getColor(TitleGradient2, active), + KPixmapEffect::VerticalGradient); + painter.drawPixmap(0,0, tempPixmap); + tempPixmap.resize(1, gradientHeight-4); + KPixmapEffect::gradient(tempPixmap, + getColor(TitleGradient2, active), + getColor(TitleGradient3, active), + KPixmapEffect::VerticalGradient); + painter.drawPixmap(0,4, tempPixmap); + painter.end(); + + // actual titlebar tiles + if (type == TitleBarTileTop) { + pm = new TQPixmap(1, 4); + painter.begin(pm); + // contour + painter.setPen(getColor(WindowContour, active) ); + painter.drawPoint(0,0); + // top highlight + painter.setPen(getColor(ShadeTitleLight, active) ); + painter.drawPoint(0,1); + // gradient + painter.drawPixmap(0, 2, gradient); + painter.end(); + } else { + pm = new TQPixmap(1, titleBarTileHeight); + painter.begin(pm); + painter.drawPixmap(0, 0, gradient, 0,2); + if (m_coloredBorder) { + painter.setPen(getColor(TitleGradient3, active).dark(110) ); + } else { + painter.setPen(getColor(TitleGradient3, active) ); + } + painter.drawPoint(0,titleBarTileHeight-1); + painter.end(); + } + + pretile(pm, 64, Qt::Horizontal); + + break; + } + + case TitleBarLeft: + { + const int w = m_borderSize; + const int h = 4 + (toolWindow ? m_titleHeightTool : m_titleHeight) + 2; + + pm = new TQPixmap(w, h); + TQPainter painter(pm); + + painter.drawTiledPixmap(0,0, w, 4, pixmap(TitleBarTileTop, active, toolWindow) ); + painter.drawTiledPixmap(0,4, w, h-4, pixmap(TitleBarTile, active, toolWindow) ); + + painter.setPen(getColor(WindowContour, active) ); + painter.drawLine(0,0, 0,h); + painter.drawPoint(1,1); + + const TQColor highlightTitleLeft = getColor(ShadeTitleLight, active); + painter.setPen(highlightTitleLeft); + painter.drawLine(1,2, 1,h); + + if (m_coloredBorder) { + painter.setPen(getColor(TitleGradient3, active) ); + painter.drawLine(2,h-1, w-1,h-1); + } + + // outside the region normally masked by doShape + painter.setPen(TQColor(0,0,0) ); + painter.drawLine(0, 0, 1, 0 ); + painter.drawPoint(0, 1); + + break; + } + + case TitleBarRight: + { + const int w = m_borderSize; + const int h = 4 + (toolWindow ? m_titleHeightTool : m_titleHeight) + 2; + + pm = new TQPixmap(w, h); + TQPainter painter(pm); + + painter.drawTiledPixmap(0,0, w, 4, pixmap(TitleBarTileTop, active, toolWindow) ); + painter.drawTiledPixmap(0,4, w, h-4, pixmap(TitleBarTile, active, toolWindow) ); + + painter.setPen(getColor(WindowContour, active) ); + painter.drawLine(w-1,0, w-1,h); + painter.drawPoint(w-2,1); + + const TQColor highlightTitleRight = getColor(ShadeTitleDark, active); + painter.setPen(highlightTitleRight); + painter.drawLine(w-2,2, w-2,h); + + if (m_coloredBorder) { + painter.setPen(getColor(TitleGradient3, active) ); + painter.drawLine(0,h-1, w-3,h-1); + } + + // outside the region normally masked by doShape + painter.setPen(TQColor(0,0,0) ); + painter.drawLine(w-2, 0, w-1, 0 ); + painter.drawPoint(w-1, 1); + + break; + } + + case BorderLeftTile: + { + const int w = m_borderSize; + + pm = new TQPixmap(w, 1); + TQPainter painter(pm); + if (m_coloredBorder) { + painter.setPen(getColor(WindowContour, active) ); + painter.drawPoint(0, 0); + painter.setPen(getColor(ShadeTitleLight, active) ); + painter.drawPoint(1, 0); + if (w > 3) { + painter.setPen(getColor(TitleGradient3, active) ); + painter.drawLine(2,0, w-2,0); + } + painter.setPen(getColor(TitleGradient3, active).dark(110) ); + painter.drawPoint(w-1,0); + } else { + painter.setPen(getColor(WindowContour, active) ); + painter.drawPoint(0, 0); + painter.setPen( + alphaBlendColors(getColor(Border, active), + getColor(ShadeTitleLight, active), 130) ); + painter.drawPoint(1, 0); + painter.setPen(getColor(Border, active) ); + painter.drawLine(2,0, w-1,0); + } + + painter.end(); + + pretile(pm, 64, Qt::Vertical); + + break; + } + + case BorderRightTile: + { + const int w = m_borderSize; + + pm = new TQPixmap(w, 1); + TQPainter painter(pm); + if (m_coloredBorder) { + painter.setPen(getColor(TitleGradient3, active).dark(110) ); + painter.drawPoint(0,0); + if (w > 3) { + painter.setPen(getColor(TitleGradient3, active) ); + painter.drawLine(1,0, w-3,0); + } + painter.setPen(getColor(ShadeTitleDark, active) ); + painter.drawPoint(w-2, 0); + painter.setPen(getColor(WindowContour, active) ); + painter.drawPoint(w-1, 0); + } else { + painter.setPen(getColor(Border, active) ); + painter.drawLine(0,0, w-3,0); + painter.setPen( + alphaBlendColors(getColor(Border, active), + getColor(ShadeTitleDark, active), 130) ); + painter.drawPoint(w-2, 0); + painter.setPen(getColor(WindowContour, active) ); + painter.drawPoint(w-1, 0); + } + painter.end(); + + pretile(pm, 64, Qt::Vertical); + + break; + } + + case BorderBottomLeft: + { + const int w = m_borderSize; + const int h = m_borderSize; + + pm = new TQPixmap(w, h); + TQPainter painter(pm); + painter.drawTiledPixmap(0,0,w,h, pixmap(BorderBottomTile, active, toolWindow) ); + painter.setPen(getColor(WindowContour, active) ); + painter.drawLine(0,0, 0,h); + if (m_coloredBorder) { + if (h > 3) { + painter.setPen(getColor(ShadeTitleLight, active) ); + painter.drawLine(1,0, 1,h-2); + } + + painter.setPen(getColor(TitleGradient3, active) ); + painter.drawLine(2,0, w-1,0); + } else { + painter.setPen( + alphaBlendColors(getColor(Border, active), + getColor(ShadeTitleLight, active), 130) ); + painter.drawLine(1,0, 1,h-2); + } + + painter.end(); + + break; + } + + case BorderBottomRight: + { + const int w = m_borderSize; + const int h = m_borderSize; + + pm = new TQPixmap(w, h); + TQPainter painter(pm); + painter.drawTiledPixmap(0,0,w,h, pixmap(BorderBottomTile, active, toolWindow) ); + painter.setPen(getColor(WindowContour, active) ); + painter.drawLine(w-1,0, w-1,h); + if (m_coloredBorder) { + painter.setPen(getColor(ShadeTitleDark, active) ); + painter.drawLine(w-2,0, w-2,h-2); + + painter.setPen(getColor(TitleGradient3, active) ); + painter.drawLine(0,0, w-3,0); + } else { + painter.setPen( + alphaBlendColors(getColor(Border, active), + getColor(ShadeTitleDark, active), 130) ); + painter.drawLine(w-2,0, w-2,h-2); + } + + painter.end(); + + break; + } + + case BorderBottomTile: + default: + { + const int h = m_borderSize; + + pm = new TQPixmap(1, m_borderSize); + TQPainter painter(pm); + + if (m_coloredBorder) { + painter.setPen(getColor(TitleGradient3, active).dark(110) ); + painter.drawPoint(0,0); + painter.setPen(getColor(TitleGradient3, active) ); + painter.drawLine(0,1, 0,h-3); + painter.setPen(getColor(ShadeTitleDark, active) ); + painter.drawPoint(0, h-2); + } else { + painter.setPen(getColor(Border, active) ); + painter.drawLine(0,0, 0,h-3); + painter.setPen( + alphaBlendColors(getColor(Border, active), + getColor(ShadeTitleDark, active), 130) ); + painter.drawPoint(0, h-2); + } + painter.setPen(getColor(WindowContour, active) ); + painter.drawPoint(0, h-1); + painter.end(); + + pretile(pm, 64, Qt::Horizontal); + + break; + } + } + + m_pixmaps[toolWindow][active][type] = pm; + return *pm; +} + +const TQBitmap &PlastikHandler::buttonBitmap(ButtonIcon type, const TQSize &size, bool toolWindow) +{ + int typeIndex = type; + + // btn icon size... + int reduceW = 0, reduceH = 0; + if(size.width()>14) { + reduceW = static_cast<int>(2*(size.width()/3.5) ); + } + else + reduceW = 6; + if(size.height()>14) + reduceH = static_cast<int>(2*(size.height()/3.5) ); + else + reduceH = 6; + + int w = size.width() - reduceW; + int h = size.height() - reduceH; + + if (m_bitmaps[toolWindow][typeIndex] && m_bitmaps[toolWindow][typeIndex]->size()==TQSize(w,h) ) + return *m_bitmaps[toolWindow][typeIndex]; + + // no matching pixmap found, create a new one... + + delete m_bitmaps[toolWindow][typeIndex]; + m_bitmaps[toolWindow][typeIndex] = 0; + + TQBitmap bmp = IconEngine::icon(type /*icon*/, TQMIN(w,h) ); + TQBitmap *bitmap = new TQBitmap(bmp); + m_bitmaps[toolWindow][typeIndex] = bitmap; + return *bitmap; +} + +TQValueList< PlastikHandler::BorderSize > +PlastikHandler::borderSizes() const +{ + // the list must be sorted + return TQValueList< BorderSize >() << BorderTiny << BorderNormal << + BorderLarge << BorderVeryLarge << BorderHuge << + BorderVeryHuge << BorderOversized; +} + +// make the handler accessible to other classes... +static PlastikHandler *handler = 0; +PlastikHandler* Handler() +{ + return handler; +} + +} // KWinPlastik + +////////////////////////////////////////////////////////////////////////////// +// Plugin Stuff // +////////////////////////////////////////////////////////////////////////////// + +extern "C" +{ + KDE_EXPORT KDecorationFactory *create_factory() + { + KWinPlastik::handler = new KWinPlastik::PlastikHandler(); + return KWinPlastik::handler; + } +} diff --git a/twin/clients/plastik/plastik.desktop b/twin/clients/plastik/plastik.desktop new file mode 100644 index 000000000..907c56148 --- /dev/null +++ b/twin/clients/plastik/plastik.desktop @@ -0,0 +1,37 @@ +[Desktop Entry] +Icon= +Name=Plastik +Name[af]=Plastiek +Name[ar]=بلاستيك +Name[be]=Пластык +Name[bn]=প্লাস্টিক +Name[eo]=Plastiko +Name[fa]=پلاستیک +Name[fy]=Plastyk +Name[hi]=प्लास्टिक +Name[hr]=Plastika +Name[is]=Plast +Name[it]=Plastica +Name[ka]=Пластик +Name[kk]=Пластик +Name[km]=ប្ល៉ាស្ទិក +Name[lt]=Plastikinis +Name[lv]=Plastika +Name[mk]=Пластик +Name[nb]=Plast +Name[ne]=प्लास्टिक +Name[nn]=Plast +Name[pa]=ਪਲਾਸਟਿਕ +Name[ro]=Plastic +Name[ru]=Пластик +Name[se]=Plastihkka +Name[sr]=Пластика +Name[sr@Latn]=Plastika +Name[ta]=திட்டம் +Name[te]=ప్లాస్టిక్ +Name[th]=พลาสติก +Name[uk]=Пластик +Name[uz@cyrillic]=Пластик +Name[vi]=Chất dẻo +Name[zh_CN]=塑料 +X-TDE-Library=twin3_plastik diff --git a/twin/clients/plastik/plastik.h b/twin/clients/plastik/plastik.h new file mode 100644 index 000000000..a4c1bc5b7 --- /dev/null +++ b/twin/clients/plastik/plastik.h @@ -0,0 +1,127 @@ +/* Plastik KWin window decoration + Copyright (C) 2003-2005 Sandro Giessl <sandro@giessl.com> + + based on the window decoration "Web": + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@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 PLASTIK_H +#define PLASTIK_H + +#include <tqfont.h> + +#include <kdecoration.h> +#include <kdecorationfactory.h> + +namespace KWinPlastik { + +enum ColorType { + WindowContour=0, + TitleGradient1, // top + TitleGradient2, + TitleGradient3, // bottom + ShadeTitleLight, + ShadeTitleDark, + Border, + TitleFont +}; + +enum Pixmaps { + TitleBarTileTop=0, + TitleBarTile, + TitleBarLeft, + TitleBarRight, + BorderLeftTile, + BorderRightTile, + BorderBottomTile, + BorderBottomLeft, + BorderBottomRight, + NumPixmaps +}; + +enum ButtonIcon { + CloseIcon = 0, + MaxIcon, + MaxRestoreIcon, + MinIcon, + HelpIcon, + OnAllDesktopsIcon, + NotOnAllDesktopsIcon, + KeepAboveIcon, + NoKeepAboveIcon, + KeepBelowIcon, + NoKeepBelowIcon, + ShadeIcon, + UnShadeIcon, + NumButtonIcons +}; + +class PlastikHandler: public TQObject, public KDecorationFactory +{ + Q_OBJECT +public: + PlastikHandler(); + ~PlastikHandler(); + virtual bool reset( unsigned long changed ); + + virtual KDecoration* createDecoration( KDecorationBridge* ); + virtual bool supports( Ability ability ); + + const TQPixmap &pixmap(Pixmaps type, bool active, bool toolWindow); + const TQBitmap &buttonBitmap(ButtonIcon type, const TQSize &size, bool toolWindow); + + int titleHeight() { return m_titleHeight; } + int titleHeightTool() { return m_titleHeightTool; } + const TQFont &titleFont() { return m_titleFont; } + const TQFont &titleFontTool() { return m_titleFontTool; } + bool titleShadow() { return m_titleShadow; } + int borderSize() { return m_borderSize; } + bool animateButtons() { return m_animateButtons; } + bool menuClose() { return m_menuClose; } + TQ_Alignment titleAlign() { return m_titleAlign; } + bool reverseLayout() { return m_reverse; } + TQColor getColor(KWinPlastik::ColorType type, const bool active = true); + + TQValueList< PlastikHandler::BorderSize > borderSizes() const; +private: + void readConfig(); + + void pretile(TQPixmap *&pix, int size, Qt::Orientation dir) const; + + bool m_coloredBorder; + bool m_titleShadow; + bool m_animateButtons; + bool m_menuClose; + bool m_reverse; + int m_borderSize; + int m_titleHeight; + int m_titleHeightTool; + TQFont m_titleFont; + TQFont m_titleFontTool; + TQ_Alignment m_titleAlign; + + // pixmap cache + TQPixmap *m_pixmaps[2][2][NumPixmaps]; // button pixmaps have normal+pressed state... + TQBitmap *m_bitmaps[2][NumButtonIcons]; +}; + +PlastikHandler* Handler(); + +} // KWinPlastik + +#endif // PLASTIK_H diff --git a/twin/clients/plastik/plastikbutton.cpp b/twin/clients/plastik/plastikbutton.cpp new file mode 100644 index 000000000..3a097be15 --- /dev/null +++ b/twin/clients/plastik/plastikbutton.cpp @@ -0,0 +1,629 @@ +/* Plastik KWin window decoration + Copyright (C) 2003-2005 Sandro Giessl <sandro@giessl.com> + + based on the window decoration "Web": + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@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 <twin/options.h> + +#include <tqbitmap.h> +#include <tqpainter.h> +#include <tqpixmap.h> +#include <kpixmap.h> +#include <kpixmapeffect.h> +#include <tqtimer.h> + +#include "plastikbutton.h" +#include "plastikbutton.moc" +#include "plastikclient.h" +#include "misc.h" + +namespace KWinPlastik +{ + +static const uint TIMERINTERVAL = 50; // msec +static const uint ANIMATIONSTEPS = 4; + +PlastikButton::PlastikButton(ButtonType type, PlastikClient *parent, const char *name) + : KCommonDecorationButton(type, parent, name), + m_client(parent), + m_iconType(NumButtonIcons), + hover(false) +{ + setBackgroundMode(NoBackground); + + // no need to reset here as the button will be resetted on first resize. + + animTmr = new TQTimer(this); + connect(animTmr, TQT_SIGNAL(timeout() ), this, TQT_SLOT(animate() ) ); + animProgress = 0; +} + +PlastikButton::~PlastikButton() +{ +} + +void PlastikButton::reset(unsigned long changed) +{ + if (changed&DecorationReset || changed&ManualReset || changed&SizeChange || changed&StateChange) { + switch (type() ) { + case CloseButton: + m_iconType = CloseIcon; + break; + case HelpButton: + m_iconType = HelpIcon; + break; + case MinButton: + m_iconType = MinIcon; + break; + case MaxButton: + if (isOn()) { + m_iconType = MaxRestoreIcon; + } else { + m_iconType = MaxIcon; + } + break; + case OnAllDesktopsButton: + if (isOn()) { + m_iconType = NotOnAllDesktopsIcon; + } else { + m_iconType = OnAllDesktopsIcon; + } + break; + case ShadeButton: + if (isOn()) { + m_iconType = UnShadeIcon; + } else { + m_iconType = ShadeIcon; + } + break; + case AboveButton: + if (isOn()) { + m_iconType = NoKeepAboveIcon; + } else { + m_iconType = KeepAboveIcon; + } + break; + case BelowButton: + if (isOn()) { + m_iconType = NoKeepBelowIcon; + } else { + m_iconType = KeepBelowIcon; + } + break; + default: + m_iconType = NumButtonIcons; // empty... + break; + } + + this->update(); + } +} + +void PlastikButton::animate() +{ + animTmr->stop(); + + if(hover) { + if(animProgress < ANIMATIONSTEPS) { + if (Handler()->animateButtons() ) { + animProgress++; + } else { + animProgress = ANIMATIONSTEPS; + } + animTmr->start(TIMERINTERVAL, true); // single-shot + } + } else { + if(animProgress > 0) { + if (Handler()->animateButtons() ) { + animProgress--; + } else { + animProgress = 0; + } + animTmr->start(TIMERINTERVAL, true); // single-shot + } + } + + repaint(false); +} + +void PlastikButton::enterEvent(TQEvent *e) +{ + TQButton::enterEvent(e); + + hover = true; + animate(); +} + +void PlastikButton::leaveEvent(TQEvent *e) +{ + TQButton::leaveEvent(e); + + hover = false; + animate(); +} + +void PlastikButton::drawButton(TQPainter *painter) +{ + TQRect r(0,0,width(),height()); + + bool active = m_client->isActive(); + KPixmap tempKPixmap; + + TQColor highlightColor; + if(type() == CloseButton) { + highlightColor = TQColor(255,64,0); + } else { + highlightColor = Qt::white; + } + + TQColor contourTop = alphaBlendColors(Handler()->getColor(TitleGradient2, active), + Qt::black, 215); + TQColor contourBottom = alphaBlendColors(Handler()->getColor(TitleGradient3, active), + Qt::black, 215); + TQColor sourfaceTop = alphaBlendColors(Handler()->getColor(TitleGradient2, active), + Qt::white, 210); + TQColor sourfaceBottom = alphaBlendColors(Handler()->getColor(TitleGradient3, active), + Qt::white, 210); + + int highlightAlpha = static_cast<int>(255-((60/static_cast<double>(ANIMATIONSTEPS))* + static_cast<double>(animProgress) ) ); + contourTop = alphaBlendColors(contourTop, highlightColor, highlightAlpha ); + contourBottom = alphaBlendColors(contourBottom, highlightColor, highlightAlpha); + sourfaceTop = alphaBlendColors(sourfaceTop, highlightColor, highlightAlpha); + sourfaceBottom = alphaBlendColors(sourfaceBottom, highlightColor, highlightAlpha); + + if (isDown() ) { + contourTop = alphaBlendColors(contourTop, Qt::black, 200); + contourBottom = alphaBlendColors(contourBottom, Qt::black, 200); + sourfaceTop = alphaBlendColors(sourfaceTop, Qt::black, 200); + sourfaceBottom = alphaBlendColors(sourfaceBottom, Qt::black, 200); + } + + TQPixmap buffer; + buffer.resize(width(), height()); + TQPainter bP(&buffer); + + // fake the titlebar background + bP.drawTiledPixmap(0, 0, width(), width(), m_client->getTitleBarTile(active) ); + + if (type() != MenuButton || hover || animProgress != 0) { + // contour + bP.setPen(contourTop); + bP.drawLine(r.x()+2, r.y(), r.right()-2, r.y() ); + bP.drawPoint(r.x()+1, r.y()+1); + bP.drawPoint(r.right()-1, r.y()+1); + bP.setPen(contourBottom); + bP.drawLine(r.x()+2, r.bottom(), r.right()-2, r.bottom() ); + bP.drawPoint(r.x()+1, r.bottom()-1); + bP.drawPoint(r.right()-1, r.bottom()-1); + // sides of the contour + tempKPixmap.resize(1, r.height()-2*2); + KPixmapEffect::gradient(tempKPixmap, + contourTop, + contourBottom, + KPixmapEffect::VerticalGradient); + bP.drawPixmap(r.x(), r.y()+2, tempKPixmap); + bP.drawPixmap(r.right(), r.y()+2, tempKPixmap); + // sort of anti-alias for the contour + bP.setPen(alphaBlendColors(Handler()->getColor(TitleGradient2, active), + contourTop, 150) ); + bP.drawPoint(r.x()+1, r.y()); + bP.drawPoint(r.right()-1, r.y()); + bP.drawPoint(r.x(), r.y()+1); + bP.drawPoint(r.right(), r.y()+1); + bP.setPen(alphaBlendColors(Handler()->getColor(TitleGradient3, active), + contourBottom, 150) ); + bP.drawPoint(r.x()+1, r.bottom()); + bP.drawPoint(r.right()-1, r.bottom()); + bP.drawPoint(r.x(), r.bottom()-1); + bP.drawPoint(r.right(), r.bottom()-1); + // sourface + // fill top and bottom + bP.setPen(sourfaceTop); + bP.drawLine(r.x()+2, r.y()+1, r.right()-2, r.y()+1 ); + bP.setPen(sourfaceBottom); + bP.drawLine(r.x()+2, r.bottom()-1, r.right()-2, r.bottom()-1 ); + // fill the rest! :) + tempKPixmap.resize(1, r.height()-2*2); + KPixmapEffect::gradient(tempKPixmap, + sourfaceTop, + sourfaceBottom, + KPixmapEffect::VerticalGradient); + bP.drawTiledPixmap(r.x()+1, r.y()+2, r.width()-2, r.height()-4, tempKPixmap); + } + + if (type() == MenuButton) + { + TQPixmap menuIcon(m_client->icon().pixmap( TQIconSet::Small, TQIconSet::Normal)); + if (width() < menuIcon.width() || height() < menuIcon.height() ) { + menuIcon.convertFromImage( TQImage(menuIcon.convertToImage()).smoothScale(width(), height())); + } + bP.drawPixmap((width()-menuIcon.width())/2, (height()-menuIcon.height())/2, menuIcon); + } + else + { + int dX,dY; + const TQBitmap &icon = Handler()->buttonBitmap(m_iconType, size(), decoration()->isToolWindow() ); + dX = r.x()+(r.width()-icon.width())/2; + dY = r.y()+(r.height()-icon.height())/2; + if (isDown() ) { + dY++; + } + + if(!isDown() && Handler()->titleShadow() ) { + TQColor shadowColor; + if (tqGray(Handler()->getColor(TitleFont,active).rgb()) < 100) + shadowColor = TQColor(255, 255, 255); + else + shadowColor = TQColor(0,0,0); + bP.setPen(alphaBlendColors(sourfaceTop, shadowColor, 180) ); + bP.drawPixmap(dX+1, dY+1, icon); + } + + bP.setPen(Handler()->getColor(TitleFont,active) ); + bP.drawPixmap(dX, dY, icon); + } + + bP.end(); + painter->drawPixmap(0, 0, buffer); +} + +TQBitmap IconEngine::icon(ButtonIcon icon, int size) +{ + if (size%2 == 0) + --size; + + TQBitmap bitmap(size,size); + bitmap.fill(Qt::color0); + TQPainter p(&bitmap); + + p.setPen(Qt::color1); + + TQRect r = bitmap.rect(); + + // line widths + int lwTitleBar = 1; + if (r.width() > 16) { + lwTitleBar = 4; + } else if (r.width() > 4) { + lwTitleBar = 2; + } + int lwArrow = 1; + if (r.width() > 16) { + lwArrow = 4; + } else if (r.width() > 7) { + lwArrow = 2; + } + + switch(icon) { + case CloseIcon: + { + int lineWidth = 1; + if (r.width() > 16) { + lineWidth = 3; + } else if (r.width() > 4) { + lineWidth = 2; + } + + drawObject(p, DiagonalLine, r.x(), r.y(), r.width(), lineWidth); + drawObject(p, CrossDiagonalLine, r.x(), r.bottom(), r.width(), lineWidth); + + break; + } + + case MaxIcon: + { + int lineWidth2 = 1; // frame + if (r.width() > 16) { + lineWidth2 = 2; + } else if (r.width() > 4) { + lineWidth2 = 1; + } + + drawObject(p, HorizontalLine, r.x(), r.top(), r.width(), lwTitleBar); + drawObject(p, HorizontalLine, r.x(), r.bottom()-(lineWidth2-1), r.width(), lineWidth2); + drawObject(p, VerticalLine, r.x(), r.top(), r.height(), lineWidth2); + drawObject(p, VerticalLine, r.right()-(lineWidth2-1), r.top(), r.height(), lineWidth2); + + break; + } + + case MaxRestoreIcon: + { + int lineWidth2 = 1; // frame + if (r.width() > 16) { + lineWidth2 = 2; + } else if (r.width() > 4) { + lineWidth2 = 1; + } + + int margin1, margin2; + margin1 = margin2 = lineWidth2*2; + if (r.width() < 8) + margin1 = 1; + + // background window + drawObject(p, HorizontalLine, r.x()+margin1, r.top(), r.width()-margin1, lineWidth2); + drawObject(p, HorizontalLine, r.right()-margin2, r.bottom()-(lineWidth2-1)-margin1, margin2, lineWidth2); + drawObject(p, VerticalLine, r.x()+margin1, r.top(), margin2, lineWidth2); + drawObject(p, VerticalLine, r.right()-(lineWidth2-1), r.top(), r.height()-margin1, lineWidth2); + + // foreground window + drawObject(p, HorizontalLine, r.x(), r.top()+margin2, r.width()-margin2, lwTitleBar); + drawObject(p, HorizontalLine, r.x(), r.bottom()-(lineWidth2-1), r.width()-margin2, lineWidth2); + drawObject(p, VerticalLine, r.x(), r.top()+margin2, r.height(), lineWidth2); + drawObject(p, VerticalLine, r.right()-(lineWidth2-1)-margin2, r.top()+margin2, r.height(), lineWidth2); + + break; + } + + case MinIcon: + { + drawObject(p, HorizontalLine, r.x(), r.bottom()-(lwTitleBar-1), r.width(), lwTitleBar); + + break; + } + + case HelpIcon: + { + int center = r.x()+r.width()/2 -1; + int side = r.width()/4; + + // paint a question mark... code is quite messy, to be cleaned up later...! :o + + if (r.width() > 16) { + int lineWidth = 3; + + // top bar + drawObject(p, HorizontalLine, center-side+3, r.y(), 2*side-3-1, lineWidth); + // top bar rounding + drawObject(p, CrossDiagonalLine, center-side-1, r.y()+5, 6, lineWidth); + drawObject(p, DiagonalLine, center+side-3, r.y(), 5, lineWidth); + // right bar + drawObject(p, VerticalLine, center+side+2-lineWidth, r.y()+3, r.height()-(2*lineWidth+side+2+1), lineWidth); + // bottom bar + drawObject(p, CrossDiagonalLine, center, r.bottom()-2*lineWidth, side+2, lineWidth); + drawObject(p, HorizontalLine, center, r.bottom()-3*lineWidth+2, lineWidth, lineWidth); + // the dot + drawObject(p, HorizontalLine, center, r.bottom()-(lineWidth-1), lineWidth, lineWidth); + } else if (r.width() > 8) { + int lineWidth = 2; + + // top bar + drawObject(p, HorizontalLine, center-(side-1), r.y(), 2*side-1, lineWidth); + // top bar rounding + if (r.width() > 9) { + drawObject(p, CrossDiagonalLine, center-side-1, r.y()+3, 3, lineWidth); + } else { + drawObject(p, CrossDiagonalLine, center-side-1, r.y()+2, 3, lineWidth); + } + drawObject(p, DiagonalLine, center+side-1, r.y(), 3, lineWidth); + // right bar + drawObject(p, VerticalLine, center+side+2-lineWidth, r.y()+2, r.height()-(2*lineWidth+side+1), lineWidth); + // bottom bar + drawObject(p, CrossDiagonalLine, center, r.bottom()-2*lineWidth+1, side+2, lineWidth); + // the dot + drawObject(p, HorizontalLine, center, r.bottom()-(lineWidth-1), lineWidth, lineWidth); + } else { + int lineWidth = 1; + + // top bar + drawObject(p, HorizontalLine, center-(side-1), r.y(), 2*side, lineWidth); + // top bar rounding + drawObject(p, CrossDiagonalLine, center-side-1, r.y()+1, 2, lineWidth); + // right bar + drawObject(p, VerticalLine, center+side+1, r.y(), r.height()-(side+2+1), lineWidth); + // bottom bar + drawObject(p, CrossDiagonalLine, center, r.bottom()-2, side+2, lineWidth); + // the dot + drawObject(p, HorizontalLine, center, r.bottom(), 1, 1); + } + + break; + } + + case NotOnAllDesktopsIcon: + { + int lwMark = r.width()-lwTitleBar*2-2; + if (lwMark < 1) + lwMark = 3; + + drawObject(p, HorizontalLine, r.x()+(r.width()-lwMark)/2, r.y()+(r.height()-lwMark)/2, lwMark, lwMark); + + // Fall through to OnAllDesktopsIcon intended! + } + case OnAllDesktopsIcon: + { + // horizontal bars + drawObject(p, HorizontalLine, r.x()+lwTitleBar, r.y(), r.width()-2*lwTitleBar, lwTitleBar); + drawObject(p, HorizontalLine, r.x()+lwTitleBar, r.bottom()-(lwTitleBar-1), r.width()-2*lwTitleBar, lwTitleBar); + // vertical bars + drawObject(p, VerticalLine, r.x(), r.y()+lwTitleBar, r.height()-2*lwTitleBar, lwTitleBar); + drawObject(p, VerticalLine, r.right()-(lwTitleBar-1), r.y()+lwTitleBar, r.height()-2*lwTitleBar, lwTitleBar); + + + break; + } + + case NoKeepAboveIcon: + { + int center = r.x()+r.width()/2; + + // arrow + drawObject(p, CrossDiagonalLine, r.x(), center+2*lwArrow, center-r.x(), lwArrow); + drawObject(p, DiagonalLine, r.x()+center, r.y()+1+2*lwArrow, center-r.x(), lwArrow); + if (lwArrow>1) + drawObject(p, HorizontalLine, center-(lwArrow-2), r.y()+2*lwArrow, (lwArrow-2)*2, lwArrow); + + // Fall through to KeepAboveIcon intended! + } + case KeepAboveIcon: + { + int center = r.x()+r.width()/2; + + // arrow + drawObject(p, CrossDiagonalLine, r.x(), center, center-r.x(), lwArrow); + drawObject(p, DiagonalLine, r.x()+center, r.y()+1, center-r.x(), lwArrow); + if (lwArrow>1) + drawObject(p, HorizontalLine, center-(lwArrow-2), r.y(), (lwArrow-2)*2, lwArrow); + + break; + } + + case NoKeepBelowIcon: + { + int center = r.x()+r.width()/2; + + // arrow + drawObject(p, DiagonalLine, r.x(), center-2*lwArrow, center-r.x(), lwArrow); + drawObject(p, CrossDiagonalLine, r.x()+center, r.bottom()-1-2*lwArrow, center-r.x(), lwArrow); + if (lwArrow>1) + drawObject(p, HorizontalLine, center-(lwArrow-2), r.bottom()-(lwArrow-1)-2*lwArrow, (lwArrow-2)*2, lwArrow); + + // Fall through to KeepBelowIcon intended! + } + case KeepBelowIcon: + { + int center = r.x()+r.width()/2; + + // arrow + drawObject(p, DiagonalLine, r.x(), center, center-r.x(), lwArrow); + drawObject(p, CrossDiagonalLine, r.x()+center, r.bottom()-1, center-r.x(), lwArrow); + if (lwArrow>1) + drawObject(p, HorizontalLine, center-(lwArrow-2), r.bottom()-(lwArrow-1), (lwArrow-2)*2, lwArrow); + + break; + } + + case ShadeIcon: + { + drawObject(p, HorizontalLine, r.x(), r.y(), r.width(), lwTitleBar); + + break; + } + + case UnShadeIcon: + { + int lw1 = 1; + int lw2 = 1; + if (r.width() > 16) { + lw1 = 4; + lw2 = 2; + } else if (r.width() > 7) { + lw1 = 2; + lw2 = 1; + } + + int h = TQMAX( (r.width()/2), (lw1+2*lw2) ); + + // horizontal bars + drawObject(p, HorizontalLine, r.x(), r.y(), r.width(), lw1); + drawObject(p, HorizontalLine, r.x(), r.x()+h-(lw2-1), r.width(), lw2); + // vertical bars + drawObject(p, VerticalLine, r.x(), r.y(), h, lw2); + drawObject(p, VerticalLine, r.right()-(lw2-1), r.y(), h, lw2); + + break; + } + + default: + break; + } + + p.end(); + + bitmap.setMask(bitmap); + + return bitmap; +} + +void IconEngine::drawObject(TQPainter &p, Object object, int x, int y, int length, int lineWidth) +{ + switch(object) { + case DiagonalLine: + if (lineWidth <= 1) { + for (int i = 0; i < length; ++i) { + p.drawPoint(x+i,y+i); + } + } else if (lineWidth <= 2) { + for (int i = 0; i < length; ++i) { + p.drawPoint(x+i,y+i); + } + for (int i = 0; i < (length-1); ++i) { + p.drawPoint(x+1+i,y+i); + p.drawPoint(x+i,y+1+i); + } + } else { + for (int i = 1; i < (length-1); ++i) { + p.drawPoint(x+i,y+i); + } + for (int i = 0; i < (length-1); ++i) { + p.drawPoint(x+1+i,y+i); + p.drawPoint(x+i,y+1+i); + } + for (int i = 0; i < (length-2); ++i) { + p.drawPoint(x+2+i,y+i); + p.drawPoint(x+i,y+2+i); + } + } + break; + case CrossDiagonalLine: + if (lineWidth <= 1) { + for (int i = 0; i < length; ++i) { + p.drawPoint(x+i,y-i); + } + } else if (lineWidth <= 2) { + for (int i = 0; i < length; ++i) { + p.drawPoint(x+i,y-i); + } + for (int i = 0; i < (length-1); ++i) { + p.drawPoint(x+1+i,y-i); + p.drawPoint(x+i,y-1-i); + } + } else { + for (int i = 1; i < (length-1); ++i) { + p.drawPoint(x+i,y-i); + } + for (int i = 0; i < (length-1); ++i) { + p.drawPoint(x+1+i,y-i); + p.drawPoint(x+i,y-1-i); + } + for (int i = 0; i < (length-2); ++i) { + p.drawPoint(x+2+i,y-i); + p.drawPoint(x+i,y-2-i); + } + } + break; + case HorizontalLine: + for (int i = 0; i < lineWidth; ++i) { + p.drawLine(x,y+i, x+length-1, y+i); + } + break; + case VerticalLine: + for (int i = 0; i < lineWidth; ++i) { + p.drawLine(x+i,y, x+i, y+length-1); + } + break; + default: + break; + } +} + +} // KWinPlastik diff --git a/twin/clients/plastik/plastikbutton.h b/twin/clients/plastik/plastikbutton.h new file mode 100644 index 000000000..dbebcf63f --- /dev/null +++ b/twin/clients/plastik/plastikbutton.h @@ -0,0 +1,90 @@ +/* Plastik KWin window decoration + Copyright (C) 2003-2005 Sandro Giessl <sandro@giessl.com> + + based on the window decoration "Web": + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@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 PLASTIKBUTTON_H +#define PLASTIKBUTTON_H + +#include <tqbutton.h> +#include <tqimage.h> +#include "plastik.h" + +#include <kcommondecoration.h> + +class TQTimer; + +namespace KWinPlastik { + +class PlastikClient; + +class PlastikButton : public KCommonDecorationButton +{ + Q_OBJECT +public: + PlastikButton(ButtonType type, PlastikClient *parent, const char *name); + ~PlastikButton(); + + void reset(unsigned long changed); + PlastikClient * client() { return m_client; } + +protected slots: + void animate(); + +private: + void enterEvent(TQEvent *e); + void leaveEvent(TQEvent *e); + void drawButton(TQPainter *painter); + +private: + PlastikClient *m_client; + ButtonIcon m_iconType; + bool hover; + + TQTimer *animTmr; + uint animProgress; +}; + +/** + * This class creates bitmaps which can be used as icons on buttons. The icons + * are "hardcoded". + * Over the previous "Gimp->xpm->QImage->recolor->SmoothScale->TQPixmap" solution + * it has the important advantage that icons are more scalable and at the same + * time sharp and not blurred. + */ +class IconEngine +{ + public: + static TQBitmap icon(ButtonIcon icon, int size); + + private: + enum Object { + HorizontalLine, + VerticalLine, + DiagonalLine, + CrossDiagonalLine + }; + + static void drawObject(TQPainter &p, Object object, int x, int y, int length, int lineWidth); +}; + +} // namespace KWinPlastik + +#endif // PLASTIKBUTTON_H diff --git a/twin/clients/plastik/plastikclient.cpp b/twin/clients/plastik/plastikclient.cpp new file mode 100644 index 000000000..31c9e2ad9 --- /dev/null +++ b/twin/clients/plastik/plastikclient.cpp @@ -0,0 +1,529 @@ +/* Plastik KWin window decoration + Copyright (C) 2003-2005 Sandro Giessl <sandro@giessl.com> + + based on the window decoration "Web": + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@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 <tdelocale.h> + +#include <tqbitmap.h> +#include <tqdatetime.h> +#include <tqfontmetrics.h> +#include <tqimage.h> +#include <tqlabel.h> +#include <tqlayout.h> +#include <tqpainter.h> +#include <tqpixmap.h> +#include <tqdesktopwidget.h> + +#include "plastikclient.h" +#include "plastikbutton.h" +#include "misc.h" + +namespace KWinPlastik +{ + +PlastikClient::PlastikClient(KDecorationBridge* bridge, KDecorationFactory* factory) + : KCommonDecoration (bridge, factory), + s_titleFont(TQFont() ) +{ + memset(m_captionPixmaps, 0, sizeof(TQPixmap*)*2); +} + +PlastikClient::~PlastikClient() +{ + clearCaptionPixmaps(); +} + +TQString PlastikClient::visibleName() const +{ + return i18n("Plastik"); +} + +TQString PlastikClient::defaultButtonsLeft() const +{ + return "M"; +} + +TQString PlastikClient::defaultButtonsRight() const +{ + return "HIAX"; +} + +bool PlastikClient::decorationBehaviour(DecorationBehaviour behaviour) const +{ + switch (behaviour) { + case DB_MenuClose: + return Handler()->menuClose(); + + case DB_WindowMask: + return true; + + default: + return KCommonDecoration::decorationBehaviour(behaviour); + } +} + +int PlastikClient::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *btn) const +{ + bool maximized = maximizeMode()==MaximizeFull && !options()->moveResizeMaximizedWindows(); + + switch (lm) { + case LM_BorderLeft: + case LM_BorderRight: + case LM_BorderBottom: + { + if (respectWindowState && maximized) { + return 0; + } else { + return Handler()->borderSize(); + } + } + + case LM_TitleEdgeTop: + { + if (respectWindowState && maximized) { + return 0; + } else { + return 4; + } + } + + case LM_TitleEdgeBottom: + { +// if (respectWindowState && maximized) { +// return 1; +// } else { + return 2; +// } + } + + case LM_TitleEdgeLeft: + case LM_TitleEdgeRight: + { + if (respectWindowState && maximized) { + return 0; + } else { + return 6; + } + } + + case LM_TitleBorderLeft: + case LM_TitleBorderRight: + return 5; + + case LM_ButtonWidth: + case LM_ButtonHeight: + case LM_TitleHeight: + { + if (respectWindowState && isToolWindow()) { + return Handler()->titleHeightTool(); + } else { + return Handler()->titleHeight(); + } + } + + case LM_ButtonSpacing: + return 1; + + case LM_ButtonMarginTop: + return 0; + + case LM_ExplicitButtonSpacer: + return 3; + + default: + return KCommonDecoration::layoutMetric(lm, respectWindowState, btn); + } +} + +KCommonDecorationButton *PlastikClient::createButton(ButtonType type) +{ + switch (type) { + case MenuButton: + return new PlastikButton(MenuButton, this, "menu"); + + case OnAllDesktopsButton: + return new PlastikButton(OnAllDesktopsButton, this, "on_all_desktops"); + + case HelpButton: + return new PlastikButton(HelpButton, this, "help"); + + case MinButton: + return new PlastikButton(MinButton, this, "minimize"); + + case MaxButton: + return new PlastikButton(MaxButton, this, "maximize"); + + case CloseButton: + return new PlastikButton(CloseButton, this, "close"); + + case AboveButton: + return new PlastikButton(AboveButton, this, "above"); + + case BelowButton: + return new PlastikButton(BelowButton, this, "below"); + + case ShadeButton: + return new PlastikButton(ShadeButton, this, "shade"); + + default: + return 0; + } +} + +void PlastikClient::init() +{ + s_titleFont = isToolWindow() ? Handler()->titleFontTool() : Handler()->titleFont(); + + clearCaptionPixmaps(); + + KCommonDecoration::init(); +} + +TQRegion PlastikClient::cornerShape(WindowCorner corner) +{ + int w = widget()->width(); + int h = widget()->height(); + + switch (corner) { + case WC_TopLeft: + if (layoutMetric(LM_TitleEdgeLeft) > 0) + return TQRegion(0, 0, 1, 2) + TQRegion(1, 0, 1, 1); + else + return TQRegion(); + + case WC_TopRight: + if (layoutMetric(LM_TitleEdgeRight) > 0) + return TQRegion(w-1, 0, 1, 2) + TQRegion(w-2, 0, 1, 1); + else + return TQRegion(); + + case WC_BottomLeft: + if (layoutMetric(LM_BorderBottom) > 0) + return TQRegion(0, h-1, 1, 1); + else + return TQRegion(); + + case WC_BottomRight: + if (layoutMetric(LM_BorderBottom) > 0) + return TQRegion(w-1, h-1, 1, 1); + else + return TQRegion(); + + default: + return TQRegion(); + } + +} + +void PlastikClient::paintEvent(TQPaintEvent *e) +{ + TQRegion region = e->region(); + + PlastikHandler *handler = Handler(); + + if (oldCaption != caption() ) + clearCaptionPixmaps(); + + bool active = isActive(); + bool toolWindow = isToolWindow(); + + TQPainter painter(widget() ); + + // often needed coordinates + TQRect r = widget()->rect(); + + int r_w = r.width(); +// int r_h = r.height(); + int r_x, r_y, r_x2, r_y2; + r.coords(&r_x, &r_y, &r_x2, &r_y2); + const int borderLeft = layoutMetric(LM_BorderLeft); + const int borderRight = layoutMetric(LM_BorderRight); + const int borderBottom = layoutMetric(LM_BorderBottom); + const int titleHeight = layoutMetric(LM_TitleHeight); + const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop); + const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom); + const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft); + const int titleEdgeRight = layoutMetric(LM_TitleEdgeRight); + + const int borderBottomTop = r_y2-borderBottom+1; + const int borderLeftRight = r_x+borderLeft-1; + const int borderRightLeft = r_x2-borderRight+1; + const int titleEdgeBottomBottom = r_y+titleEdgeTop+titleHeight+titleEdgeBottom-1; + + const int sideHeight = borderBottomTop-titleEdgeBottomBottom-1; + + TQRect Rtitle = TQRect(r_x+titleEdgeLeft+buttonsLeftWidth(), r_y+titleEdgeTop, + r_x2-titleEdgeRight-buttonsRightWidth()-(r_x+titleEdgeLeft+buttonsLeftWidth()), + titleEdgeBottomBottom-(r_y+titleEdgeTop) ); + + TQRect tempRect; + + // topSpacer + if(titleEdgeTop > 0) + { + tempRect.setRect(r_x+2, r_y, r_w-2*2, titleEdgeTop ); + if (tempRect.isValid() && region.contains(tempRect) ) { + painter.drawTiledPixmap(tempRect, handler->pixmap(TitleBarTileTop, active, toolWindow) ); + } + } + + // leftTitleSpacer + int titleMarginLeft = 0; + int titleMarginRight = 0; + if(titleEdgeLeft > 0) + { + tempRect.setRect(r_x, r_y, borderLeft, titleEdgeTop+titleHeight+titleEdgeBottom); + if (tempRect.isValid() && region.contains(tempRect) ) { + painter.drawTiledPixmap(tempRect, handler->pixmap(TitleBarLeft, active, toolWindow) ); + titleMarginLeft = borderLeft; + } + } + + // rightTitleSpacer + if(titleEdgeRight > 0) + { + tempRect.setRect(borderRightLeft, r_y, borderRight, titleEdgeTop+titleHeight+titleEdgeBottom); + if (tempRect.isValid() && region.contains(tempRect) ) { + painter.drawTiledPixmap(tempRect, handler->pixmap(TitleBarRight, active, toolWindow) ); + titleMarginRight = borderRight; + } + } + + // titleSpacer + const TQPixmap &caption = captionPixmap(); + if(Rtitle.width() > 0) + { + m_captionRect = captionRect(); // also update m_captionRect! + if (m_captionRect.isValid() && region.contains(m_captionRect) ) + { + painter.drawTiledPixmap(m_captionRect, caption); + } + + // left to the title + tempRect.setRect(r_x+titleMarginLeft, m_captionRect.top(), + m_captionRect.left() - (r_x+titleMarginLeft), m_captionRect.height() ); + if (tempRect.isValid() && region.contains(tempRect) ) { + painter.drawTiledPixmap(tempRect, handler->pixmap(TitleBarTile, active, toolWindow) ); + } + + // right to the title + tempRect.setRect(m_captionRect.right()+1, m_captionRect.top(), + (r_x2-titleMarginRight) - m_captionRect.right(), m_captionRect.height() ); + if (tempRect.isValid() && region.contains(tempRect) ) { + painter.drawTiledPixmap(tempRect, handler->pixmap(TitleBarTile, active, toolWindow) ); + } + + } + + // leftSpacer + if(borderLeft > 0 && sideHeight > 0) + { + tempRect.setCoords(r_x, titleEdgeBottomBottom+1, borderLeftRight, borderBottomTop-1); + if (tempRect.isValid() && region.contains(tempRect) ) { + painter.drawTiledPixmap(tempRect, handler->pixmap(BorderLeftTile, active, toolWindow) ); + } + } + + // rightSpacer + if(borderRight > 0 && sideHeight > 0) + { + tempRect.setCoords(borderRightLeft, titleEdgeBottomBottom+1, r_x2, borderBottomTop-1); + if (tempRect.isValid() && region.contains(tempRect) ) { + painter.drawTiledPixmap(tempRect, handler->pixmap(BorderRightTile, active, toolWindow) ); + } + } + + // bottomSpacer + if(borderBottom > 0) + { + int l = r_x; + int r = r_x2; + + tempRect.setRect(r_x, borderBottomTop, borderLeft, borderBottom); + if (tempRect.isValid() && region.contains(tempRect) ) { + painter.drawTiledPixmap(tempRect, handler->pixmap(BorderBottomLeft, active, toolWindow) ); + l = tempRect.right()+1; + } + + tempRect.setRect(borderRightLeft, borderBottomTop, borderLeft, borderBottom); + if (tempRect.isValid() && region.contains(tempRect) ) { + painter.drawTiledPixmap(tempRect, handler->pixmap(BorderBottomRight, active, toolWindow) ); + r = tempRect.left()-1; + } + + tempRect.setCoords(l, borderBottomTop, r, r_y2); + if (tempRect.isValid() && region.contains(tempRect) ) { + painter.drawTiledPixmap(tempRect, handler->pixmap(BorderBottomTile, active, toolWindow) ); + } + } +} + +TQRect PlastikClient::captionRect() const +{ + const TQPixmap &caption = captionPixmap(); + TQRect r = widget()->rect(); + + const int titleHeight = layoutMetric(LM_TitleHeight); + const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom); + const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop); + const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft); + const int marginLeft = layoutMetric(LM_TitleBorderLeft); + const int marginRight = layoutMetric(LM_TitleBorderRight); + + const int titleLeft = r.left() + titleEdgeLeft + buttonsLeftWidth() + marginLeft; + const int titleWidth = r.width() - + titleEdgeLeft - layoutMetric(LM_TitleEdgeRight) - + buttonsLeftWidth() - buttonsRightWidth() - + marginLeft - marginRight; + + TQ_Alignment a = Handler()->titleAlign(); + + int tX, tW; // position/width of the title buffer + if (caption.width() > titleWidth) { + tW = titleWidth; + } else { + tW = caption.width(); + } + if (a == Qt::AlignLeft || (caption.width() > titleWidth) ) { + // Align left + tX = titleLeft; + } else if (a == Qt::AlignHCenter) { + // Align center + tX = titleLeft+(titleWidth- caption.width() )/2; + } else { + // Align right + tX = titleLeft+titleWidth-caption.width(); + } + + return TQRect(tX, r.top()+titleEdgeTop, tW, titleHeight+titleEdgeBottom); +} + +void PlastikClient::updateCaption() +{ + TQRect oldCaptionRect = m_captionRect; + + if (oldCaption != caption() ) + clearCaptionPixmaps(); + + m_captionRect = PlastikClient::captionRect(); + + if (oldCaptionRect.isValid() && m_captionRect.isValid() ) + widget()->update(oldCaptionRect|m_captionRect); + else + widget()->update(); +} + +void PlastikClient::reset( unsigned long changed ) +{ + if (changed & SettingColors) + { + // repaint the whole thing + clearCaptionPixmaps(); + widget()->update(); + updateButtons(); + } else if (changed & SettingFont) { + // font has changed -- update title height and font + s_titleFont = isToolWindow() ? Handler()->titleFontTool() : Handler()->titleFont(); + + updateLayout(); + + // then repaint + clearCaptionPixmaps(); + widget()->update(); + } + + KCommonDecoration::reset(changed); +} + +const TQPixmap &PlastikClient::getTitleBarTile(bool active) const +{ + return Handler()->pixmap(TitleBarTile, active, isToolWindow() ); +} + +const TQPixmap &PlastikClient::captionPixmap() const +{ + bool active = isActive(); + + if (m_captionPixmaps[active]) { + return *m_captionPixmaps[active]; + } + + // not found, create new pixmap... + + const uint maxCaptionLength = 300; // truncate captions longer than this! + TQString c(caption() ); + if (c.length() > maxCaptionLength) { + c.truncate(maxCaptionLength); + c.append(" [...]"); + } + + TQFontMetrics fm(s_titleFont); + int captionWidth = fm.width(c); + int captionHeight = fm.height(); + + const int th = layoutMetric(LM_TitleHeight, false) + layoutMetric(LM_TitleEdgeBottom, false); + + TQPainter painter; + + const int thickness = 2; + + TQPixmap *captionPixmap = new TQPixmap(captionWidth+2*thickness, th); + + painter.begin(captionPixmap); + painter.drawTiledPixmap(captionPixmap->rect(), + Handler()->pixmap(TitleBarTile, active, isToolWindow()) ); + + painter.setFont(s_titleFont); + TQPoint tp(1, captionHeight-1); + if(Handler()->titleShadow()) + { + TQColor shadowColor; + if (tqGray(Handler()->getColor(TitleFont,active).rgb()) < 100) + shadowColor = TQColor(255, 255, 255); + else + shadowColor = TQColor(0,0,0); + + painter.setPen(alphaBlendColors(options()->color(ColorTitleBar, active), shadowColor, 205) ); + painter.drawText(tp+TQPoint(1,2), c); + painter.setPen(alphaBlendColors(options()->color(ColorTitleBar, active), shadowColor, 225) ); + painter.drawText(tp+TQPoint(2,2), c); + painter.setPen(alphaBlendColors(options()->color(ColorTitleBar, active), shadowColor, 165) ); + painter.drawText(tp+TQPoint(1,1), c); + } + painter.setPen(Handler()->getColor(TitleFont,active) ); + painter.drawText(tp, c ); + painter.end(); + + m_captionPixmaps[active] = captionPixmap; + return *captionPixmap; +} + +void PlastikClient::clearCaptionPixmaps() +{ + for (int i = 0; i < 2; ++i) { + delete m_captionPixmaps[i]; + m_captionPixmaps[i] = 0; + } + + oldCaption = caption(); +} + +} // KWinPlastik diff --git a/twin/clients/plastik/plastikclient.h b/twin/clients/plastik/plastikclient.h new file mode 100644 index 000000000..e83bf75a5 --- /dev/null +++ b/twin/clients/plastik/plastikclient.h @@ -0,0 +1,73 @@ +/* Plastik KWin window decoration + Copyright (C) 2003-2005 Sandro Giessl <sandro@giessl.com> + + based on the window decoration "Web": + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@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 PLASTIKCLIENT_H +#define PLASTIKCLIENT_H + +#include <kcommondecoration.h> + +#include "plastik.h" + +namespace KWinPlastik { + +class PlastikButton; + +class PlastikClient : public KCommonDecoration +{ +public: + PlastikClient(KDecorationBridge* bridge, KDecorationFactory* factory); + ~PlastikClient(); + + virtual TQString visibleName() const; + virtual TQString defaultButtonsLeft() const; + virtual TQString defaultButtonsRight() const; + virtual bool decorationBehaviour(DecorationBehaviour behaviour) const; + virtual int layoutMetric(LayoutMetric lm, bool respectWindowState = true, const KCommonDecorationButton * = 0) const; + virtual TQRegion cornerShape(WindowCorner corner); + virtual KCommonDecorationButton *createButton(ButtonType type); + + virtual void init(); + virtual void reset( unsigned long changed ); + + virtual void paintEvent(TQPaintEvent *e); + virtual void updateCaption(); + + const TQPixmap &getTitleBarTile(bool active) const; + +private: + TQRect captionRect() const; + + const TQPixmap &captionPixmap() const; + void clearCaptionPixmaps(); + + mutable TQPixmap *m_captionPixmaps[2]; + + TQRect m_captionRect; + TQString oldCaption; + + // settings... + TQFont s_titleFont; +}; + +} // KWinPlastik + +#endif // PLASTIKCLIENT_H diff --git a/twin/clients/quartz/CMakeLists.txt b/twin/clients/quartz/CMakeLists.txt new file mode 100644 index 000000000..c521bc19c --- /dev/null +++ b/twin/clients/quartz/CMakeLists.txt @@ -0,0 +1,37 @@ +################################################# +# +# (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 quartz.desktop DESTINATION ${DATA_INSTALL_DIR}/twin ) + + +##### twin3_quartz (module) ##################### + +tde_add_kpart( twin3_quartz AUTOMOC + SOURCES quartz.cpp + LINK tdecorations-shared tdeui-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/twin/clients/quartz/Makefile.am b/twin/clients/quartz/Makefile.am new file mode 100644 index 000000000..3a5709773 --- /dev/null +++ b/twin/clients/quartz/Makefile.am @@ -0,0 +1,23 @@ + +INCLUDES = -I$(srcdir)/../../lib $(all_includes) + +SUBDIRS = . config + +kde_module_LTLIBRARIES = twin3_quartz.la + +twin3_quartz_la_SOURCES = quartz.cpp +twin3_quartz_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +twin3_quartz_la_LIBADD = $(LIB_TDEUI) ../../lib/libtdecorations.la + +METASOURCES = AUTO +noinst_HEADERS = quartz.h + +lnkdir = $(kde_datadir)/twin/ +lnk_DATA = quartz.desktop + +EXTRA_DIST = $(lnk_DATA) + + +###KMAKE-start (don't edit or delete this block) + +###KMAKE-end diff --git a/twin/clients/quartz/config/CMakeLists.txt b/twin/clients/quartz/config/CMakeLists.txt new file mode 100644 index 000000000..e5554bb40 --- /dev/null +++ b/twin/clients/quartz/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_quartz_config (module) ############### + +tde_add_kpart( twin_quartz_config AUTOMOC + SOURCES config.cpp + LINK tdeui-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/twin/clients/quartz/config/Makefile.am b/twin/clients/quartz/config/Makefile.am new file mode 100644 index 000000000..8a96e85a3 --- /dev/null +++ b/twin/clients/quartz/config/Makefile.am @@ -0,0 +1,16 @@ +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = twin_quartz_config.la + +twin_quartz_config_la_SOURCES = config.cpp +twin_quartz_config_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +twin_quartz_config_la_LIBADD = $(LIB_TDEUI) + +METASOURCES = AUTO +noinst_HEADERS = config.h + +lnkdir = $(kde_datadir)/twin/ + +###KMAKE-start (don't edit or delete this block) + +###KMAKE-end diff --git a/twin/clients/quartz/config/config.cpp b/twin/clients/quartz/config/config.cpp new file mode 100644 index 000000000..3ce86239b --- /dev/null +++ b/twin/clients/quartz/config/config.cpp @@ -0,0 +1,104 @@ +/* + * + * This file contains the quartz configuration widget + * + * Copyright (c) 2001 + * Karol Szwed <gallium@kde.org> + * http://gallium.n3.net/ + */ + +#include "config.h" +#include <tdeglobal.h> +#include <tqwhatsthis.h> +#include <tdelocale.h> + + +extern "C" +{ + KDE_EXPORT TQObject* allocate_config( TDEConfig* conf, TQWidget* parent ) + { + return(new QuartzConfig(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 + */ + +QuartzConfig::QuartzConfig( TDEConfig* conf, TQWidget* parent ) + : TQObject( parent ) +{ + quartzConfig = new TDEConfig("twinquartzrc"); + TDEGlobal::locale()->insertCatalogue("twin_clients"); + gb = new TQVBox( parent ); + cbColorBorder = new TQCheckBox( + i18n("Draw window frames using &titlebar colors"), gb ); + TQWhatsThis::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 TQCheckBox( i18n("Quartz &extra slim"), gb ); + TQWhatsThis::add( cbExtraSmall, + i18n("Quartz window decorations with extra-small title bar.") ); + // Load configuration options + load( conf ); + + // Ensure we track user changes properly + connect( cbColorBorder, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotSelectionChanged()) ); + connect( cbExtraSmall, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotSelectionChanged()) ); + + // Make the widgets visible in twindecoration + gb->show(); +} + + +QuartzConfig::~QuartzConfig() +{ + delete gb; + delete quartzConfig; +} + + +void QuartzConfig::slotSelectionChanged() +{ + emit changed(); +} + + +// Loads the configurable options from the twinrc config file +// It is passed the open config from twindecoration to improve efficiency +void QuartzConfig::load( TDEConfig* /*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 twinrc config file +void QuartzConfig::save( TDEConfig* /*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/twin/clients/quartz/config/config.h b/twin/clients/quartz/config/config.h new file mode 100644 index 000000000..f68b9ef27 --- /dev/null +++ b/twin/clients/quartz/config/config.h @@ -0,0 +1,47 @@ +/* + * + * This file contains the quartz configuration widget + * + * Copyright (c) 2001 + * Karol Szwed <gallium@kde.org> + * http://gallium.n3.net/ + */ + +#ifndef __KDE_QUARTZCONFIG_H +#define __KDE_QUARTZCONFIG_H + +#include <tqcheckbox.h> +#include <tqvbox.h> +#include <tdeconfig.h> + +class QuartzConfig: public TQObject +{ + Q_OBJECT + + public: + QuartzConfig( TDEConfig* conf, TQWidget* parent ); + ~QuartzConfig(); + + // These public signals/slots work similar to KCM modules + signals: + void changed(); + + public slots: + void load( TDEConfig* conf ); + void save( TDEConfig* conf ); + void defaults(); + + protected slots: + void slotSelectionChanged(); // Internal use + + private: + TDEConfig* quartzConfig; + TQCheckBox* cbColorBorder; + TQCheckBox* cbExtraSmall; + TQVBox* gb; +}; + + +#endif + +// vim: ts=4 diff --git a/twin/clients/quartz/quartz.cpp b/twin/clients/quartz/quartz.cpp new file mode 100644 index 000000000..511fafa6f --- /dev/null +++ b/twin/clients/quartz/quartz.cpp @@ -0,0 +1,797 @@ +/* + * + * Gallium-Quartz KWin client + * + * Copyright (C) 2005 Sandro Giessl <sandro@giessl.com> + * Copyright 2001 + * Karol Szwed <gallium@kde.org> + * http://gallium.n3.net/ + * + * Based on the KDE default client. + * + * Includes mini titlebars for ToolWindow Support. + * Button positions are now customizable. + * + */ + +#include <tdeconfig.h> +#include <kdrawutil.h> +#include <tdeglobal.h> +#include <tdelocale.h> +#include <kpixmapeffect.h> +#include <tqbitmap.h> +#include <tqdrawutil.h> +#include <tqimage.h> +#include <tqapplication.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() +{ + TDEConfig conf("twinquartzrc"); + 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 ( TQApplication::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 = TQFontMetrics(options()->font(true)).height(); + int nTH_limit=extraSlim?14:18; + normalTitleHeight = TQFontMetrics(options()->font(true)).height()-(extraSlim?1:0); + if (normalTitleHeight < nTH_limit) normalTitleHeight = nTH_limit; + if (normalTitleHeight < borderWidth) normalTitleHeight = borderWidth; + + toolTitleHeight = TQFontMetrics(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 TQColor &c1, const TQColor &c2 ) +{ + TQPainter 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. + TQColorGroup g2 = options()->colorGroup(ColorTitleBlend, true); + TQColor c2 = g2.background(); + g2 = options()->colorGroup(ColorTitleBar, true ); + TQColor 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; + TQColorGroup g; + TQPainter p; + + g = options()->colorGroup( onAllDesktopsButtonOnLeft ? ColorTitleBar : ColorTitleBlend, true ); + c = onAllDesktopsButtonOnLeft ? TQColor(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 ? TQColor(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; +} + + +TQValueList< QuartzHandler::BorderSize > QuartzHandler::borderSizes() const +{ // the list must be sorted + return TQValueList< 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( TQWidget::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 TQBitmap(10, 10, bitmap, true); + deco->setMask( *deco ); + repaint( false ); + } +} + +void QuartzButton::drawButton(TQPainter *p) +{ + // Never paint if the pixmaps have not been created + if (!quartz_initialized) + return; + + TQColor 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 + { + TQPixmap 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( TQIconSet::Small, TQIconSet::Normal); + + // Shrink the miniIcon for tiny titlebars. + if ( height() < 16) + { + TQPixmap tmpPix; + + // Smooth scale the image + tmpPix.convertFromImage( TQImage(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) +{ +} + +TQString QuartzClient::visibleName() const +{ + return i18n("Quartz"); +} + +TQString QuartzClient::defaultButtonsLeft() const +{ + return "M"; +} + +TQString 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( TQPaintEvent* ) +{ + // Never paint if the pixmaps have not been created + if (!quartz_initialized) + return; + + const bool maxFull = (maximizeMode()==MaximizeFull) && !options()->moveResizeMaximizedWindows(); + + TQColorGroup g; + TQPainter p(widget()); + + // Obtain widget bounds. + TQRect 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 + TQColor 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; + TQT_TQRECT_OBJECT(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 = TQRect(r_x+titleEdgeLeft+buttonsLeftWidth(), r_y+titleEdgeTop, + r_x2-titleEdgeRight-buttonsRightWidth()-(r_x+titleEdgeLeft+buttonsLeftWidth()), + titleEdgeBottomBottom-(r_y+titleEdgeTop) ); + + // Obtain titlebar blend colours + TQColor c1 = options()->color(ColorTitleBar, isActive() ).light(130); + TQColor 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 ); + + TQPainter 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. + TQFont fnt; + if ( largeButtons ) { + fnt = options()->font(true, false); // font not small + } else { + fnt = options()->font(true, true); // font small + fnt.setWeight( TQFont::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/twin/clients/quartz/quartz.desktop b/twin/clients/quartz/quartz.desktop new file mode 100644 index 000000000..078e86ba6 --- /dev/null +++ b/twin/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-TDE-Library=twin3_quartz diff --git a/twin/clients/quartz/quartz.h b/twin/clients/quartz/quartz.h new file mode 100644 index 000000000..ddb68ced3 --- /dev/null +++ b/twin/clients/quartz/quartz.h @@ -0,0 +1,95 @@ +/* + * Gallium-Quartz KWin client + * + * Copyright (C) 2005 Sandro Giessl <sandro@giessl.com> + * Copyright 2001 + * Karol Szwed <gallium@kde.org> + * 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 <tqbitmap.h> +#include <kpixmap.h> +#include "../../lib/kcommondecoration.h" +#include "../../lib/kdecorationfactory.h" + +class TQSpacerItem; +class TQBoxLayout; + +namespace Quartz { + +class QuartzClient; + +class QuartzHandler: public TQObject, public KDecorationFactory +{ + Q_OBJECT + public: + QuartzHandler(); + ~QuartzHandler(); + + virtual KDecoration* createDecoration( KDecorationBridge* ); + virtual bool reset(unsigned long changed); + virtual bool supports( Ability ability ); + virtual TQValueList< BorderSize > borderSizes() const; + + private: + void readConfig(); + void createPixmaps(); + void freePixmaps(); + void drawBlocks(KPixmap* pi, KPixmap &p, const TQColor &c1, const TQColor &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(TQPainter *p); + + TQBitmap* deco; +}; + + +class QuartzClient : public KCommonDecoration +{ + public: + QuartzClient(KDecorationBridge* bridge, KDecorationFactory* factory); + ~QuartzClient() {;} + + virtual TQString visibleName() const; + virtual TQString defaultButtonsLeft() const; + virtual TQString 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( TQPaintEvent* ); + + private: + int titleHeight, borderSize; + bool largeButtons; +}; + +} + +#endif +// vim: ts=4 +// kate: space-indent off; tab-width 4; diff --git a/twin/clients/redmond/CMakeLists.txt b/twin/clients/redmond/CMakeLists.txt new file mode 100644 index 000000000..b382af454 --- /dev/null +++ b/twin/clients/redmond/CMakeLists.txt @@ -0,0 +1,35 @@ +################################################# +# +# (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} + ${CMAKE_SOURCE_DIR}/twin/lib + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES redmond.desktop DESTINATION ${DATA_INSTALL_DIR}/twin ) + + +##### twin3_redmond (module) #################### + +tde_add_kpart( twin3_redmond AUTOMOC + SOURCES redmond.cpp + LINK tdecorations-shared tdecore-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/twin/clients/redmond/Makefile.am b/twin/clients/redmond/Makefile.am new file mode 100644 index 000000000..39985f347 --- /dev/null +++ b/twin/clients/redmond/Makefile.am @@ -0,0 +1,17 @@ + +INCLUDES = -I$(srcdir)/../../lib $(all_includes) + +kde_module_LTLIBRARIES = twin3_redmond.la + +twin3_redmond_la_SOURCES = redmond.cpp +twin3_redmond_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +twin3_redmond_la_LIBADD = $(LIB_TDECORE) ../../lib/libtdecorations.la + +METASOURCES = AUTO +noinst_HEADERS = redmond.h + +lnkdir = $(kde_datadir)/twin +lnk_DATA = redmond.desktop + +EXTRA_DIST = $(lnk_DATA) + diff --git a/twin/clients/redmond/redmond.cpp b/twin/clients/redmond/redmond.cpp new file mode 100644 index 000000000..f3689af52 --- /dev/null +++ b/twin/clients/redmond/redmond.cpp @@ -0,0 +1,699 @@ +/* + * + * Redmond KWin client + * + * Copyright 2001 + * Karol Szwed <gallium@kde.org> + * http://gallium.n3.net/ + * + * Based on the default KWin client. + * + * Updated to support toolwindows 3/2001 (KS) + * + */ + +#include "redmond.h" + +#include <tqdrawutil.h> +#include <tqdatetime.h> +#include <kpixmapeffect.h> +#include <kimageeffect.h> +#include <kdrawutil.h> +#include <tdelocale.h> + +#include <tqbitmap.h> +#include <tqimage.h> +#include <tqapplication.h> + +namespace Redmond { + +static const char *kdelogo[] = { +/* columns rows colors chars-per-pixel */ +"16 16 8 1", +" c None", +". c #000000", +"+ c #A0A0A4", +"@ c #FFFFFF", +"# c #585858", +"$ c #C0C0C0", +"% c #808080", +"& c #DCDCDC", +" ", +" .. .. ", +" .+@. .@#. ", +" .@@@. .@@@# ", +" .@@@..$@@$. ", +" .@@@.@@@$. ", +" .@@@%@@$. ", +" .@@@&@@. ", +" .@@@@@@. ", +" .@@@$@@&. ", +" .@@@.@@@. ", +" .@@@.+@@@. ", +" .@@@..$@@&. ", +" .@@%. .@@@. ", +" .... ... ", +" "}; + +static unsigned char iconify_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00}; + +static 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 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 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 unsigned char question_bits[] = { + 0x00, 0x00, 0x3c, 0x00, 0x66, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00}; + + +// Up / Down titlebar button images +static KPixmap *btnPix1; +static KPixmap *iBtnPix1; +static KPixmap *btnDownPix1; +static KPixmap *iBtnDownPix1; + +static KPixmap *miniBtnPix1; +static KPixmap *iMiniBtnPix1; +static KPixmap *miniBtnDownPix1; +static KPixmap *iMiniBtnDownPix1; + +static TQPixmap *defaultMenuPix; +static TQColor *btnForeground; +static bool pixmaps_created = false; + +static int toolTitleHeight; +static int normalTitleHeight; +static int borderWidth; + +static inline const KDecorationOptions *options() +{ + return KDecoration::options(); +} + +static void drawButtonFrame( KPixmap *pix, const TQColorGroup &g, bool sunken ) +{ + TQPainter p; + int x2 = pix->width() - 1; + int y2 = pix->height() - 1; + p.begin(pix); + + // titlebar button frame + p.setPen( sunken ? TQColor(g.dark().dark(155)) : g.light()); + p.drawLine(0, 0, x2-1, 0); + p.drawLine(0, 0, 0, y2-1); + + if (sunken) + { + p.setPen( g.mid().dark(135) ); + p.drawLine(1, 1, x2-2, 1); + p.drawLine(1, 1, 1, y2-2); + } + + p.setPen( sunken ? g.light() : TQColor(g.mid().dark(135))); + p.drawLine(1, y2-1, x2-1, y2-1); + p.drawLine(x2-1, 1, x2-1, y2-1); + + p.setPen( sunken ? g.light() : TQColor(g.dark().dark(155))); + p.drawLine(0, y2, x2, y2); + p.drawLine(x2, 0, x2, y2); +} + + +static void create_pixmaps () +{ + if (pixmaps_created) + return; + + pixmaps_created = true; + + bool highcolor = TQPixmap::defaultDepth() > 8; + + btnPix1 = new KPixmap; + btnDownPix1 = new KPixmap; + iBtnPix1 = new KPixmap; + iBtnDownPix1 = new KPixmap; + miniBtnPix1 = new KPixmap; + miniBtnDownPix1 = new KPixmap; + iMiniBtnPix1 = new KPixmap; + iMiniBtnDownPix1 = new KPixmap; + defaultMenuPix = new TQPixmap(kdelogo); + + // buttons (active/inactive, sunken/unsunken) + TQColorGroup g = options()->colorGroup(KDecoration::ColorButtonBg, true); + TQColor c = g.background(); + btnPix1->resize(normalTitleHeight, normalTitleHeight-2); + btnDownPix1->resize(normalTitleHeight, normalTitleHeight-2); + iBtnPix1->resize(normalTitleHeight, normalTitleHeight-2); + iBtnDownPix1->resize(normalTitleHeight, normalTitleHeight-2); + + miniBtnPix1->resize(toolTitleHeight, toolTitleHeight); + miniBtnDownPix1->resize(toolTitleHeight, toolTitleHeight); + iMiniBtnPix1->resize(toolTitleHeight, toolTitleHeight); + iMiniBtnDownPix1->resize(toolTitleHeight, toolTitleHeight); + + if (highcolor && false) { + KPixmapEffect::gradient(*btnPix1, c.light(130), c.dark(130), + KPixmapEffect::VerticalGradient); + KPixmapEffect::gradient(*btnDownPix1, c.dark(130), c.light(130), + KPixmapEffect::VerticalGradient); + + KPixmapEffect::gradient(*miniBtnPix1, c.light(130), c.dark(130), + KPixmapEffect::VerticalGradient); + KPixmapEffect::gradient(*miniBtnDownPix1, c.dark(130), c.light(130), + KPixmapEffect::VerticalGradient); + + g = options()->colorGroup(KDecoration::ColorButtonBg, false); + c = g.background(); + KPixmapEffect::gradient(*iBtnPix1, c.light(130), c.dark(130), + KPixmapEffect::VerticalGradient); + KPixmapEffect::gradient(*iBtnDownPix1, c.dark(130), c.light(130), + KPixmapEffect::VerticalGradient); + KPixmapEffect::gradient(*iMiniBtnPix1, c.light(130), c.dark(130), + KPixmapEffect::VerticalGradient); + KPixmapEffect::gradient(*iMiniBtnDownPix1, c.dark(130), c.light(130), + KPixmapEffect::VerticalGradient); + } else { + btnPix1->fill(c.rgb()); + btnDownPix1->fill(c.rgb()); + miniBtnPix1->fill(c.rgb()); + miniBtnDownPix1->fill(c.rgb()); + + g = options()->colorGroup(KDecoration::ColorButtonBg, false); + c = g.background(); + iBtnPix1->fill(c.rgb()); + iBtnDownPix1->fill(c.rgb()); + iMiniBtnPix1->fill(c.rgb()); + iMiniBtnDownPix1->fill(c.rgb()); + } + + g = options()->colorGroup(KDecoration::ColorButtonBg, true); + drawButtonFrame(btnPix1, g, false); + drawButtonFrame(btnDownPix1, g, true); + drawButtonFrame(miniBtnPix1, g, false); + drawButtonFrame(miniBtnDownPix1, g, true); + + g = options()->colorGroup(KDecoration::ColorButtonBg, false); + drawButtonFrame(iBtnPix1, g, false); + drawButtonFrame(iBtnDownPix1, g, true); + drawButtonFrame(iMiniBtnPix1, g, false); + drawButtonFrame(iMiniBtnDownPix1, g, true); + + // Make sure button pixmaps contrast with the current colour scheme. + if (tqGray(options()->color(KDecoration::ColorButtonBg, true).rgb()) > 127) + btnForeground = new TQColor(Qt::black); + else + btnForeground = new TQColor(Qt::white); +} + +void delete_pixmaps() +{ + delete btnPix1; + delete btnDownPix1; + delete iBtnPix1; + delete iBtnDownPix1; + delete miniBtnPix1; + delete miniBtnDownPix1; + delete iMiniBtnPix1; + delete iMiniBtnDownPix1; + delete defaultMenuPix; + delete btnForeground; + pixmaps_created = false; +} + +RedmondButton::RedmondButton(ButtonType type, RedmondDeco *parent, const char *name) + : KCommonDecorationButton(type, parent, name) +{ + // Eliminate background flicker + setBackgroundMode( NoBackground ); + + miniBtn = decoration()->isToolWindow(); +} + +void RedmondButton::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 MenuButton: + { + TQPixmap miniIcon = decoration()->icon().pixmap(TQIconSet::Small, TQIconSet::Normal); + if (!miniIcon.isNull()) { + setPixmap(miniIcon); + } else { + setPixmap(*defaultMenuPix); + } + break; + } + default: + setBitmap(0); + break; + } + + this->update(); + } +} + + +void RedmondButton::setBitmap(const unsigned char *bitmap) +{ + pix.resize(0, 0); + + if (bitmap) + deco = TQBitmap(10, 10, bitmap, true); + else { + deco = TQBitmap(10,10); + deco.fill(Qt::color0); + } + deco.setMask(deco); +} + + +void RedmondButton::setPixmap( const TQPixmap &p ) +{ + deco.resize(0, 0); + pix = p; + + repaint(false); +} + + +void RedmondButton::drawButton(TQPainter *p) +{ + if ( pix.isNull() ) { + if ( decoration()->isActive() ) { + if ( isDown() ) + p->drawPixmap(0, 0, miniBtn ? *miniBtnDownPix1 : *btnDownPix1); + else + p->drawPixmap(0, 0, miniBtn ? *miniBtnPix1 : *btnPix1); + } else { + if ( isDown() ) + p->drawPixmap(0, 0, miniBtn ? *iMiniBtnDownPix1 : *iBtnDownPix1); + else + p->drawPixmap(0, 0, miniBtn ? *iMiniBtnPix1 : *iBtnPix1); + } + + p->setPen( *btnForeground ); + int xOff = (width()-10)/2; + int yOff = (height()-10)/2; + p->drawPixmap(isDown() ? xOff+1: xOff, isDown() ? yOff+1 : yOff, deco); + } else { + if (isLeft() ) { + p->fillRect(0, 0, width(), height(), + options()->color(KDecoration::ColorTitleBar, decoration()->isActive())); + } else { + p->fillRect(0, 0, width(), height(), + options()->color(KDecoration::ColorTitleBlend, decoration()->isActive())); + } + + if ( type()==MenuButton && height() < 16) { + TQPixmap tmpPix; + + // Smooth scale the menu button pixmap + tmpPix.convertFromImage( + TQImage(pix.convertToImage()).smoothScale(height(), height() )); + + p->drawPixmap( 0, 0, tmpPix ); + } else { + int xOff = (width() -pix.width() )/2; + int yOff = (height()-pix.height())/2; + p->drawPixmap(xOff, yOff, pix ); + } + } +} + + +RedmondDeco::RedmondDeco(KDecorationBridge *b, KDecorationFactory *f) + : KCommonDecoration(b, f) +{ +} + +TQString RedmondDeco::visibleName() const +{ + return i18n("Redmond"); +} + +TQString RedmondDeco::defaultButtonsLeft() const +{ + return "M"; +} + +TQString RedmondDeco::defaultButtonsRight() const +{ + return "HIA_X"; +} + +bool RedmondDeco::decorationBehaviour(DecorationBehaviour behaviour) const +{ + switch (behaviour) { + case DB_MenuClose: + return true; + + case DB_WindowMask: + return false; + + case DB_ButtonHide: + return true; + + default: + return KCommonDecoration::decorationBehaviour(behaviour); + } +} + +int RedmondDeco::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *btn) const +{ + bool border = !(maximizeMode()==MaximizeFull && !options()->moveResizeMaximizedWindows()); + + switch (lm) { + case LM_BorderLeft: + case LM_BorderRight: + case LM_BorderBottom: + return border ? borderWidth : 0; + + case LM_TitleEdgeLeft: + case LM_TitleEdgeRight: + return border ? borderWidth+2 : 2; + + case LM_TitleEdgeTop: + return border ? borderWidth+1 : 1; + + case LM_TitleEdgeBottom: + return border ? 1 : 0; + + case LM_TitleBorderLeft: + case LM_TitleBorderRight: + return border ? 1 : 0; + + case LM_TitleHeight: + return border ? titleHeight-2 : titleHeight-1; + + case LM_ButtonWidth: + return titleHeight-2; + case LM_ButtonHeight: + if (isToolWindow() || (btn && btn->type()==MenuButton) ) { + return titleHeight-2; + } else { + return titleHeight-2-2; + } + + case LM_ButtonSpacing: + return 0; + + case LM_ExplicitButtonSpacer: + return 2; + + case LM_ButtonMarginTop: + return 0; + + case LM_RightButtonsMarginTop: + return 1; + + default: + return KCommonDecoration::layoutMetric(lm, respectWindowState, btn); + } +} + +KCommonDecorationButton *RedmondDeco::createButton(ButtonType type) +{ + switch (type) { + case MenuButton: + return new RedmondButton(MenuButton, this, "menu"); + case HelpButton: + return new RedmondButton(HelpButton, this, "help"); + case MinButton: + return new RedmondButton(MinButton, this, "minimize"); + case MaxButton: + return new RedmondButton(MaxButton, this, "maximize"); + case CloseButton: + return new RedmondButton(CloseButton, this, "close"); + + default: + return 0; + } +} + +void RedmondDeco::init() +{ +// Finally, toolwindows look small + if ( isToolWindow() ) { + titleHeight = toolTitleHeight+2; + } else { + titleHeight = normalTitleHeight+2; + } + + KCommonDecoration::init(); +} + +void RedmondDeco::reset( unsigned long changed ) +{ + KCommonDecoration::reset(changed); +} + +void RedmondDeco::paintEvent( TQPaintEvent* ) +{ + bool hicolor = TQPixmap::defaultDepth() > 8; + int fontoffset = 1; + + // Modify borderWith used by titlebar to 0, when maximized and not move or resize able + bool border = !(maximizeMode()==MaximizeFull && !options()->moveResizeMaximizedWindows()); + int modBorderWidth = border ? borderWidth : 0; + + TQPainter p(widget()); + + // Obtain widget bounds. + TQRect 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 frame color + // ============================================== + TQColorGroup g = options()->colorGroup(KDecoration::ColorFrame, isActive()); + p.setPen( g.background() ); + p.drawLine( x, y, x2-1, y ); + p.drawLine( x, y, x, y2-1 ); + + // Draw line under title bar + p.drawLine( x+borderWidth, y+titleHeight+borderWidth, x2-borderWidth, y+titleHeight+borderWidth ); + // Draw a hidden line that appears during shading + p.drawLine( x+borderWidth, y2-borderWidth, x2-borderWidth, y2-borderWidth ); + + // Fill out the border edges + for (int i = 1; i < borderWidth; i++) + p.drawRect( x+i, y+i, w-2*i, h-2*i ); + + // Draw highlights and lowlights + p.setPen(g.light()); + for (int i = 1; i <= borderWidth/3; i++) { + p.drawLine( x+i, y+i, x2-i-1, y+i); + p.drawLine( x+i, y+i, x+i, y2-i-1); + } + + p.setPen(g.mid().dark(135)); + for (int i = 1; i <= borderWidth/3; i++) { + p.drawLine( x2-i, y+i+1, x2-i, y2-i); + p.drawLine( x+i+1, y2-i, x2-i, y2-i); + } + + // Draw black edges + p.setPen( g.dark().dark(155) ); + p.drawLine(x2, y, x2, y2); + p.drawLine(x, y2, x2, y2); + + // Draw the title bar. + // =================== + r = titleRect(); +// TQFontMetrics fm(options()->font(true)); + + // Obtain blend colours. + TQColor c1 = options()->color(KDecoration::ColorTitleBar, isActive() ); + TQColor c2 = options()->color(KDecoration::ColorTitleBlend, isActive() ); + + TQFont fnt = options()->font(true, isToolWindow() ); + if (isToolWindow() ) { + fnt.setWeight( TQFont::Normal ); + fontoffset = 0; + } + + // Paint without a buffer if the colours are the same to + // improve performance, and only draw gradients on hicolor displays. + if ((c1 != c2) && hicolor) { + // KS - Add gradient caching if needed at a later stage. + + // Create a disposable pixmap buffer for the title blend + KPixmap* titleBuffer = new KPixmap; + titleBuffer->resize(w-2*modBorderWidth, titleHeight); + + if (titleBuffer->depth() > 16) { + KPixmapEffect::gradient(*titleBuffer, c1, c2, + KPixmapEffect::HorizontalGradient); + } else { + // This enables dithering on 15 and 16bit displays, preventing + // some pretty horrible banding effects + TQImage image = KImageEffect::gradient(titleBuffer->size(), c1, c2, + KImageEffect::HorizontalGradient); + + titleBuffer->convertFromImage(image, Qt::OrderedDither); + } + + TQPainter p2( titleBuffer, this ); + + // Since drawing the gradient is (relatively) slow, it is best + // to draw the title text on the pixmap. + + p2.setFont( fnt ); + p2.setPen( options()->color(KDecoration::ColorFont, isActive() )); + if (border) + p2.drawText( r.x()-3, fontoffset, r.width(), r.height()+1, + AlignLeft | AlignVCenter, caption() ); + else + p2.drawText( r.x()+1, fontoffset, r.width()-4, r.height()+1, + AlignLeft | AlignVCenter, caption() ); + p2.end(); + + p.drawPixmap( modBorderWidth, modBorderWidth, *titleBuffer ); + + delete titleBuffer; + + } else { + // Assume lower ended hardware, so don't use buffers. + // Don't draw a gradient either. + p.fillRect( modBorderWidth, modBorderWidth, w-2*modBorderWidth, titleHeight, c1 ); + + // Draw the title text. + p.setFont( fnt ); + p.setPen(options()->color(KDecoration::ColorFont, isActive() )); + p.drawText(r.x()+4, r.y()+fontoffset-2, r.width()-3, r.height()+1, + AlignLeft | AlignVCenter, caption() ); + } + +} + +void RedmondDecoFactory::readConfig() { + normalTitleHeight = TQFontMetrics(options()->font(true)).height(); + TQFont toolFont = options()->font(true, true); + toolFont.setWeight(TQFont::Normal); + toolTitleHeight = TQFontMetrics(toolFont).height(); + switch(options()->preferredBorderSize(this)) { + case BorderLarge: + borderWidth = 8; + if (normalTitleHeight < 20) normalTitleHeight = 20; + if (toolTitleHeight < 20) toolTitleHeight = 20; + break; + case BorderVeryLarge: + borderWidth = 12; + if (normalTitleHeight < 24) normalTitleHeight = 24; + if (toolTitleHeight < 24) toolTitleHeight = 24; + break; + case BorderHuge: + borderWidth = 18; + if (normalTitleHeight < 28) normalTitleHeight = 28; + if (toolTitleHeight < 28) toolTitleHeight = 28; + break; + case BorderVeryHuge: + borderWidth = 27; + if (normalTitleHeight < 33) normalTitleHeight = 33; + if (toolTitleHeight < 33) toolTitleHeight = 33; + break; + case BorderOversized: + borderWidth = 40; + if (normalTitleHeight < 40) normalTitleHeight = 40; + if (toolTitleHeight < 40) toolTitleHeight = 40; + break; + case BorderTiny: + case BorderNormal: + default: + borderWidth = 3; + if (normalTitleHeight < 16) normalTitleHeight = 16; + if (toolTitleHeight < 16) toolTitleHeight = 16; + } +} + +RedmondDecoFactory::RedmondDecoFactory() +{ + readConfig(); + create_pixmaps(); +} + +RedmondDecoFactory::~RedmondDecoFactory() +{ + Redmond::delete_pixmaps(); +} + +KDecoration *RedmondDecoFactory::createDecoration( KDecorationBridge *b ) +{ + return new RedmondDeco(b, this); +} + +bool RedmondDecoFactory::reset( unsigned long changed ) +{ + // SettingButtons is handled by KCommonDecoration + if ( changed & ( SettingFont | SettingBorder | SettingColors | SettingButtons ) ) { + delete_pixmaps(); + readConfig(); + create_pixmaps(); + resetDecorations(changed); + return true; + } else { + resetDecorations(changed); + return false; + } +} + +bool RedmondDecoFactory::supports( Ability ability ) +{ + switch( ability ) + { + case AbilityAnnounceButtons: + case AbilityButtonMenu: + case AbilityButtonHelp: + case AbilityButtonMinimize: + case AbilityButtonMaximize: + case AbilityButtonClose: + case AbilityButtonSpacer: + return true; + default: + return false; + } +} + +TQValueList< RedmondDecoFactory::BorderSize > RedmondDecoFactory::borderSizes() const +{ // the list must be sorted + return TQValueList< BorderSize >() << BorderNormal << BorderLarge << + BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized; +} + +} + +extern "C" KDE_EXPORT KDecorationFactory *create_factory() +{ + return new Redmond::RedmondDecoFactory(); +} + + +#include "redmond.moc" +// vim: ts=4 +// kate: space-indent off; tab-width 4; diff --git a/twin/clients/redmond/redmond.desktop b/twin/clients/redmond/redmond.desktop new file mode 100644 index 000000000..366f58ae3 --- /dev/null +++ b/twin/clients/redmond/redmond.desktop @@ -0,0 +1,19 @@ +[Desktop Entry] +Name=Redmond +Name[bn]=রেডমন্ড +Name[eo]=Redmondo +Name[fa]=ردموند +Name[hi]=रेडमण्ड +Name[ka]=რედმონდი +Name[ko]=레드몬드 +Name[lo]=ເລດມອນ +Name[lv]=Redmonda +Name[mk]=Редмонд +Name[ne]=रेडमोन्ड +Name[pa]=ਰੀਡਮੋਂਡ +Name[ta]=ரெட்மான்ட் +Name[te]=రెడ్ మండ్ +Name[tg]=Райдмонд +Name[th]=แบบเรดมอนด์ +Name[uz@cyrillic]=Редмонд +X-TDE-Library=twin3_redmond diff --git a/twin/clients/redmond/redmond.h b/twin/clients/redmond/redmond.h new file mode 100644 index 000000000..e5f15b8ba --- /dev/null +++ b/twin/clients/redmond/redmond.h @@ -0,0 +1,91 @@ +/* + * + * Redmond KWin client + * + * Copyright 2001-2003 + * Ported to twin_iii by Chris Lee <clee@kde.org> + * Karol Szwed <gallium@kde.org> + * http://gallium.n3.net/ + * + * Based on the default KWin client. + * + * Updated to support the new API 9/2003 (CL) + * Updated to emulate More Accurately 9/2003 (CL) + * Updated to support toolwindows 3/2001 (KS) + * + */ + +#ifndef __KDE_REDMOND_H +#define __KDE_REDMOND_H + +#include <tqbitmap.h> +#include <kpixmap.h> +#include <kcommondecoration.h> +#include <kdecorationfactory.h> + +namespace Redmond { + +class RedmondDeco; + +class RedmondButton : public KCommonDecorationButton +{ + Q_OBJECT +public: + RedmondButton(ButtonType type, RedmondDeco *parent, const char *name); + void setBitmap(const unsigned char *bitmap); + void setPixmap(const TQPixmap &p); + void reset(unsigned long changed); + +protected: + virtual void drawButton(TQPainter *p); + void drawButtonLabel(TQPainter *){;} + + TQBitmap deco; + TQPixmap pix; + bool miniBtn; +}; + + +class RedmondDeco : public KCommonDecoration +{ +public: + RedmondDeco(KDecorationBridge *, KDecorationFactory *); + ~RedmondDeco() {;} + + virtual TQString visibleName() const; + virtual TQString defaultButtonsLeft() const; + virtual TQString 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); + + void init(); + +protected: + virtual void reset( unsigned long changed ); + + void paintEvent(TQPaintEvent*); + +private: + int titleHeight; +}; + +class RedmondDecoFactory : public TQObject, public KDecorationFactory +{ + Q_OBJECT +public: + RedmondDecoFactory(); + virtual ~RedmondDecoFactory(); + virtual KDecoration *createDecoration(KDecorationBridge *); + virtual bool reset(unsigned long); + virtual bool supports( Ability ability ); + virtual TQValueList< BorderSize > borderSizes() const; +private: + void readConfig(); +}; + +} + +#endif +// vim: ts=4 +// kate: space-indent off; tab-width 4; diff --git a/twin/clients/test/Makefile.am b/twin/clients/test/Makefile.am new file mode 100644 index 000000000..07ac72c02 --- /dev/null +++ b/twin/clients/test/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I$(srcdir)/../../lib $(all_includes) + +kde_module_LTLIBRARIES = twin3_test.la + +twin3_test_la_SOURCES = test.cpp +twin3_test_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +twin3_test_la_LIBADD = $(LIB_TDEUI) ../../lib/libtdecorations.la +#twin_keramik_la_LDFLAGS = $(all_libraries) -avoid-version -module $(KDE_RPATH) $(KDE_MT_LDFLAGS) + +METASOURCES = AUTO + +twin_test_lnkdir = $(kde_datadir)/twin +twin_test_lnk_DATA = test.desktop + +EXTRA_DIST = $(twin_test_lnk_DATA) diff --git a/twin/clients/test/test.cpp b/twin/clients/test/test.cpp new file mode 100644 index 000000000..e01d1d98e --- /dev/null +++ b/twin/clients/test/test.cpp @@ -0,0 +1,343 @@ +#include "test.h" + +#include <tqtooltip.h> +#include <tdeglobal.h> +#include <kdebug.h> + +namespace KWinTest +{ + +Decoration::Decoration( KDecorationBridge* bridge, KDecorationFactory* factory ) + : KDecoration( bridge, factory ), + button( NULL ) + { + } + +void Decoration::init() + { + createMainWidget(); + widget()->setEraseColor( red ); + widget()->installEventFilter( this ); + if( isCloseable()) + { + button = new TQPushButton( widget()); + button->show(); + button->setCursor( tqarrowCursor ); + button->move( 0, 0 ); + connect( button, TQT_SIGNAL( clicked()), TQT_SLOT( closeWindow())); + TQToolTip::add( button, "Zelva Mana" ); + } + } + +Decoration::MousePosition Decoration::mousePosition( const TQPoint& p ) const + { + const int range = 16; + const int border = 4; + + MousePosition m = Nowhere; + + int width = widget()->width(); + int height = widget()->height(); + if ( ( p.x() > border && p.x() < width - border ) + && ( p.y() > border && p.y() < height - border ) ) + return Center; + + if ( p.y() <= range && p.x() <= range) + m = TopLeft2; + else if ( p.y() >= height-range && p.x() >= width-range) + m = BottomRight2; + else if ( p.y() >= height-range && p.x() <= range) + m = BottomLeft2; + else if ( p.y() <= range && p.x() >= width-range) + m = TopRight2; + else if ( p.y() <= border ) + m = Top; + else if ( p.y() >= height-border ) + m = Bottom; + else if ( p.x() <= border ) + m = Left; + else if ( p.x() >= width-border ) + m = Right; + else + m = Center; + return m; + } + +void Decoration::borders( int& left, int& right, int& top, int& bottom ) const + { + if( options()->preferredBorderSize( factory()) == BorderTiny ) + { + left = right = bottom = 1; + top = 5; + } + else + { + left = right = options()->preferredBorderSize( factory()) * 5; + top = options()->preferredBorderSize( factory()) * 10; + bottom = options()->preferredBorderSize( factory()) * 2; + } + if( isShade()) + bottom = 0; + if( ( maximizeMode() & MaximizeHorizontal ) && !options()->moveResizeMaximizedWindows()) + left = right = 0; + if( ( maximizeMode() & MaximizeVertical ) && !options()->moveResizeMaximizedWindows()) + bottom = 0; + } + +void Decoration::reset( unsigned long ) + { + } + +void Decoration::resize( const TQSize& s ) + { + widget()->resize( s ); + } + +TQSize Decoration::minimumSize() const + { + return TQSize( 100, 50 ); + } + +bool Decoration::eventFilter( TQObject* o, TQEvent* e ) + { + if( TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(widget())) + { + switch( e->type()) + { + case TQEvent::MouseButtonPress: + { // FRAME + processMousePressEvent( TQT_TQMOUSEEVENT( e )); + return true; + } + case TQEvent::Show: + break; + case TQEvent::Hide: + break; + default: + break; + } + } + return false; + } + +} +#include <tqapplication.h> +#include <tqpainter.h> +#include <X11/Xlib.h> +#include <math.h> +#include <unistd.h> +namespace KWinTest +{ + +// taken from riscos +bool Decoration::animateMinimize(bool iconify) +{ + int style = 1; + switch (style) { + + case 1: + { + // Double twisting double back, with pike ;) + + if (!iconify) // No animation for restore. + return true; + + // Go away quick. + helperShowHide( false ); + tqApp->syncX(); + + TQRect r = iconGeometry(); + + if (!r.isValid()) + return true; + + // Algorithm taken from Window Maker (http://www.windowmaker.org) + + int sx = geometry().x(); + int sy = geometry().y(); + int sw = width(); + int sh = height(); + int dx = r.x(); + int dy = r.y(); + int dw = r.width(); + int dh = r.height(); + + double steps = 12; + + double xstep = double((dx-sx)/steps); + double ystep = double((dy-sy)/steps); + double wstep = double((dw-sw)/steps); + double hstep = double((dh-sh)/steps); + + double cx = sx; + double cy = sy; + double cw = sw; + double ch = sh; + + double finalAngle = 3.14159265358979323846; + + double delta = finalAngle / steps; + + TQPainter p( workspaceWidget()); + p.setRasterOp(TQt::NotROP); + + for (double angle = 0; ; angle += delta) { + + if (angle > finalAngle) + angle = finalAngle; + + double dx = (cw / 10) - ((cw / 5) * sin(angle)); + double dch = (ch / 2) * cos(angle); + double midy = cy + (ch / 2); + + TQPoint p1(int(cx + dx), int(midy - dch)); + TQPoint p2(int(cx + cw - dx), p1.y()); + TQPoint p3(int(cx + dw + dx), int(midy + dch)); + TQPoint p4(int(cx - dx), p3.y()); + + grabXServer(); + + p.drawLine(p1, p2); + p.drawLine(p2, p3); + p.drawLine(p3, p4); + p.drawLine(p4, p1); + + p.flush(); + + usleep(500); + + p.drawLine(p1, p2); + p.drawLine(p2, p3); + p.drawLine(p3, p4); + p.drawLine(p4, p1); + + ungrabXServer(); + +// FRAME tqApp->processEvents(); // FRAME ??? + + cx += xstep; + cy += ystep; + cw += wstep; + ch += hstep; + + if (angle >= finalAngle) + break; + } + } + break; + + case 2: + { + // KVirc style ? Maybe. For qwertz. + + if (!iconify) // No animation for restore. + return true; + + // Go away quick. + helperShowHide( false ); + + tqApp->syncX(); + + int stepCount = 12; + + TQRect r(geometry()); + + int dx = r.width() / (stepCount * 2); + int dy = r.height() / (stepCount * 2); + + TQPainter p( workspaceWidget()); + p.setRasterOp(TQt::NotROP); + + for (int step = 0; step < stepCount; step++) { + + r.moveBy(dx, dy); + r.setWidth(r.width() - 2 * dx); + r.setHeight(r.height() - 2 * dy); + + grabXServer(); + + p.drawRect(r); + p.flush(); + usleep(200); + p.drawRect(r); + + ungrabXServer(); + +// FRAME tqApp->processEvents(); + } + } + break; + + + default: + { + TQRect icongeom = iconGeometry(); + + if (!icongeom.isValid()) + return true; + + TQRect wingeom = geometry(); + + TQPainter p( workspaceWidget()); + + p.setRasterOp(TQt::NotROP); + +#if 0 + if (iconify) + p.setClipRegion( + TQRegion( workspaceWidget()->rect()) - wingeom + ); +#endif + + grabXServer(); + + p.drawLine(wingeom.bottomRight(), icongeom.bottomRight()); + p.drawLine(wingeom.bottomLeft(), icongeom.bottomLeft()); + p.drawLine(wingeom.topLeft(), icongeom.topLeft()); + p.drawLine(wingeom.topRight(), icongeom.topRight()); + + p.flush(); + + tqApp->syncX(); + + usleep(30000); + + p.drawLine(wingeom.bottomRight(), icongeom.bottomRight()); + p.drawLine(wingeom.bottomLeft(), icongeom.bottomLeft()); + p.drawLine(wingeom.topLeft(), icongeom.topLeft()); + p.drawLine(wingeom.topRight(), icongeom.topRight()); + + ungrabXServer(); + } + break; + } + return true; +} + +KDecoration* Factory::createDecoration( KDecorationBridge* bridge ) + { + NET::WindowType type = windowType( SUPPORTED_WINDOW_TYPES_MASK, bridge ); + if( type == NET::Dialog ) + ; + return new Decoration( bridge, this ); + } + +bool Factory::reset( unsigned long changed ) + { + resetDecorations( changed ); + return false; + } + +} // namespace + +extern "C" +{ + +KDE_EXPORT KDecorationFactory *create_factory() + { + return new KWinTest::Factory(); + } + +} + +#include "test.moc" diff --git a/twin/clients/test/test.desktop b/twin/clients/test/test.desktop new file mode 100644 index 000000000..118ab82c5 --- /dev/null +++ b/twin/clients/test/test.desktop @@ -0,0 +1,67 @@ +[Desktop Entry] +Name=KWin test +Name[af]=KWin toets +Name[ar]=اختبار KWin +Name[az]=KWin sınağı +Name[be]=Тэст KWin +Name[bn]=Kwin পরীক্ষা +Name[ca]=Test de KWin +Name[csb]=Test KWin +Name[cy]=arbrawf KWin +Name[da]=KWin-test +Name[de]=KWin-Test +Name[el]=KWin τεστ +Name[eo]=Testo de TDE-fenestroadministrilo +Name[es]=Prueba de KWin +Name[eu]=KWin froga +Name[fa]=آزمون KWin +Name[fi]=KWin-testi +Name[fr]=Test de KWin +Name[ga]=Tástáil KWim +Name[gl]=Proba de KWin +Name[he]=ניסיון KWin +Name[hi]=के-विन जांच +Name[hr]=KWina proba +Name[hu]=KWin-teszt +Name[is]=KWin prófun +Name[it]=Prova KWin +Name[ja]=KWin テスト +Name[ka]=KWin შემოწმება +Name[kk]=KWin сынауы +Name[km]=សាកល្បង KWin +Name[ko]=KWin 테스트 +Name[lt]=KWin patikrinimas +Name[lv]=KWin tests +Name[mk]=Тест за KWin +Name[mn]=KWin шалгалт +Name[ms]=Ujian KWin +Name[nds]=KWin-Test +Name[ne]=के विन परीक्षण +Name[nn]=KWin-test +Name[pa]=KWin ਜਾਂਚ +Name[pl]=Test KWin +Name[pt]=Teste do KWin +Name[pt_BR]=Teste do KWin +Name[ro]=Test KWin +Name[ru]=Проверка KWin +Name[rw]= Isuzuma rya KWin +Name[se]=KWin-geahččaleapmi +Name[sk]=Test KWin +Name[sl]=Preizkus KWin +Name[sr]=Проба KWin-а +Name[sr@Latn]=Proba KWin-a +Name[sv]=Kwin-test +Name[ta]=KWin சோதனை +Name[te]=కెవిన్ పరిక్ష +Name[tg]=Тафтиши KWin +Name[th]=ทดสอบ KWin +Name[tr]=KWin Testi +Name[tt]=KWin sınaw +Name[uk]=Тест KWin +Name[uz]=KWin sinash +Name[uz@cyrillic]=KWin синаш +Name[vi]=Thử KWin +Name[wa]=Saye KPurnea +Name[zh_CN]=KWin 测试 +Name[zh_TW]=KWin 測試 +X-TDE-Library=twin3_test diff --git a/twin/clients/test/test.h b/twin/clients/test/test.h new file mode 100644 index 000000000..bfe36fa7c --- /dev/null +++ b/twin/clients/test/test.h @@ -0,0 +1,49 @@ +#ifndef KWIN_TEST +#define KWIN_TEST + +#include <kdecoration.h> +#include <kdecorationfactory.h> +#include <tqpushbutton.h> + +namespace KWinTest +{ + +const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask + | NET::ToolbarMask | NET::MenuMask | NET::DialogMask /*| NET::OverrideMask*/ | NET::TopMenuMask + | NET::UtilityMask | NET::SplashMask; + +class Decoration + : public KDecoration + { + Q_OBJECT + public: + Decoration( KDecorationBridge* bridge, KDecorationFactory* factory ); + virtual void init(); + virtual MousePosition 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 minimumSize() const; + virtual void activeChange() {}; + virtual void captionChange() {}; + virtual void maximizeChange() {}; + virtual void desktopChange() {}; + virtual void shadeChange() {}; + virtual void iconChange() {}; + virtual bool eventFilter( TQObject* o, TQEvent* e ); + virtual void reset( unsigned long changed ); + virtual bool animateMinimize( bool minimize ); + private: + TQPushButton* button; + }; + +class Factory + : public KDecorationFactory + { + public: + virtual KDecoration* createDecoration( KDecorationBridge* ); + virtual bool reset( unsigned long changed ); + }; + +} // namespace + +#endif diff --git a/twin/clients/web/CMakeLists.txt b/twin/clients/web/CMakeLists.txt new file mode 100644 index 000000000..badbd0467 --- /dev/null +++ b/twin/clients/web/CMakeLists.txt @@ -0,0 +1,34 @@ +################################################# +# +# (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} +) + + +##### other data ################################ + +install( FILES web.desktop DESTINATION ${DATA_INSTALL_DIR}/twin ) + + +##### twin3_web (module) ######################## + +tde_add_kpart( twin3_web AUTOMOC + SOURCES Web.cpp WebButton.cpp + LINK tdecorations-shared tdeui-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/twin/clients/web/Makefile.am b/twin/clients/web/Makefile.am new file mode 100644 index 000000000..4855602ca --- /dev/null +++ b/twin/clients/web/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I$(top_srcdir) $(all_includes) +kde_module_LTLIBRARIES = twin3_web.la + +twin3_web_la_SOURCES = Web.cpp WebButton.cpp + +noinst_HEADERS = Web.h WebButton.h + +twin3_web_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +twin3_web_la_LIBADD = $(LIB_TDEUI) ../../lib/libtdecorations.la +METASOURCES = AUTO + +linkdir = $(kde_datadir)/twin/ +link_DATA = web.desktop +EXTRA_DIST = $(link_DATA) + diff --git a/twin/clients/web/Web.cpp b/twin/clients/web/Web.cpp new file mode 100644 index 000000000..496187d3b --- /dev/null +++ b/twin/clients/web/Web.cpp @@ -0,0 +1,385 @@ +/* + 'Web' twin client + + Copyright (C) 2005 Sandro Giessl <sandro@giessl.com> + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@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 <tqpainter.h> + +#include <tdeconfig.h> + +#include "Web.h" +#include "WebButton.h" + +extern "C" +{ + KDE_EXPORT KDecorationFactory *create_factory() + { + return new Web::WebFactory(); + } +} + +namespace Web { + +WebClient::WebClient(KDecorationBridge* bridge, KDecorationFactory* factory) + : KCommonDecoration(bridge, factory) +{ + // Empty. +} + +WebClient::~WebClient() +{ + // Empty. +} + +TQString WebClient::visibleName() const +{ + return i18n("Web"); +} + +TQString WebClient::defaultButtonsLeft() const +{ + return "S"; +} + +TQString WebClient::defaultButtonsRight() const +{ + return "HIAX"; +} + +bool WebClient::decorationBehaviour(DecorationBehaviour behaviour) const +{ + switch (behaviour) { + case DB_MenuClose: + return false; + + case DB_WindowMask: + return true; + + case DB_ButtonHide: + return true; + + default: + return KCommonDecoration::decorationBehaviour(behaviour); + } +} + +int WebClient::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: + return borderSize_; + + case LM_TitleEdgeLeft: + case LM_TitleEdgeRight: + case LM_TitleEdgeTop: + case LM_TitleEdgeBottom: + return 0; + + case LM_TitleBorderLeft: + case LM_TitleBorderRight: + return 0; + + case LM_TitleHeight: + case LM_ButtonWidth: + case LM_ButtonHeight: + return titleHeight_; + + case LM_ButtonSpacing: + return 0; + + case LM_ExplicitButtonSpacer: + return 0; + + default: + return KCommonDecoration::layoutMetric(lm, respectWindowState, btn); + } +} + +KCommonDecorationButton *WebClient::createButton(ButtonType type) +{ + switch (type) { + case MenuButton: + return new WebButton(MenuButton, this, "menu", shape_); + + case OnAllDesktopsButton: + return new WebButton(OnAllDesktopsButton, this, "on_all_desktops", shape_); + + case HelpButton: + return new WebButton(HelpButton, this, "help", shape_); + + case MinButton: + return new WebButton(MinButton, this, "minimize", shape_); + + case MaxButton: + return new WebButton(MaxButton, this, "maximize", shape_); + + case CloseButton: + return new WebButton(CloseButton, this, "close", shape_); + + case AboveButton: + return new WebButton(AboveButton, this, "above", shape_); + + case BelowButton: + return new WebButton(BelowButton, this, "below", shape_); + + case ShadeButton: + return new WebButton(ShadeButton, this, "shade", shape_); + + default: + return 0; + } +} + + void +WebClient::init() +{ + // title height + const int textVMargin = 2; + TQFontMetrics fm(options()->font(isActive(), isToolWindow())); + + // border size + switch(options()->preferredBorderSize( factory())) { + case BorderLarge: + borderSize_ = 8; + break; + case BorderVeryLarge: + borderSize_ = 12; + break; + case BorderHuge: + borderSize_ = 18; + break; + case BorderVeryHuge: + borderSize_ = 27; + break; + case BorderOversized: + borderSize_ = 40; + break; + case BorderNormal: + default: + borderSize_ = 4; + } + titleHeight_ = TQMAX(TQMAX(14, fm.height() + textVMargin * 2), borderSize_); + if (0 != titleHeight_ % 2) + titleHeight_ += 1; + + TDEConfig c("twinwebrc"); + c.setGroup("General"); + shape_ = c.readBoolEntry("Shape", true); + + KCommonDecoration::init(); +} + + void +WebClient::reset( unsigned long changed ) +{ + if (changed & SettingColors) + { + // repaint the whole thing + widget()->repaint(false); + } else if (changed & SettingFont) { + // font has changed -- update title height + // title height + const int textVMargin = 2; + TQFontMetrics fm(options()->font(isActive(), isToolWindow())); + titleHeight_ = TQMAX(TQMAX(14, fm.height() + textVMargin * 2), borderSize_); + if (0 != titleHeight_ % 2) + titleHeight_ += 1; + + widget()->repaint(false); + } + + KCommonDecoration::reset(changed); +} + + void +WebClient::paintEvent(TQPaintEvent * pe) +{ + int r_x, r_y, r_x2, r_y2; + TQT_TQRECT_OBJECT(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; + TQRect titleRect = TQRect(r_x+titleEdgeLeft+buttonsLeftWidth(), r_y+titleEdgeTop, + r_x2-titleEdgeRight-buttonsRightWidth()-(r_x+titleEdgeLeft+buttonsLeftWidth()), + titleEdgeBottomBottom-(r_y+titleEdgeTop) ); + titleRect.setTop(1); + + TQPainter p(widget()); + + p.setPen(Qt::black); + p.setBrush(options()->colorGroup(ColorFrame, isActive()).background()); + + p.setClipRegion(pe->region() - titleRect); + + p.drawRect(widget()->rect()); + + p.setClipRegion(pe->region()); + + p.fillRect(titleRect, options()->color(ColorTitleBar, isActive())); + + if (shape_) + { + int r(width()); + int b(height()); + + // Draw edge of top-left corner inside the area removed by the mask. + + p.drawPoint(3, 1); + p.drawPoint(4, 1); + p.drawPoint(2, 2); + p.drawPoint(1, 3); + p.drawPoint(1, 4); + + // Draw edge of top-right corner inside the area removed by the mask. + + p.drawPoint(r - 5, 1); + p.drawPoint(r - 4, 1); + p.drawPoint(r - 3, 2); + p.drawPoint(r - 2, 3); + p.drawPoint(r - 2, 4); + + // Draw edge of bottom-left corner inside the area removed by the mask. + + p.drawPoint(1, b - 5); + p.drawPoint(1, b - 4); + p.drawPoint(2, b - 3); + p.drawPoint(3, b - 2); + p.drawPoint(4, b - 2); + + // Draw edge of bottom-right corner inside the area removed by the mask. + + p.drawPoint(r - 2, b - 5); + p.drawPoint(r - 2, b - 4); + p.drawPoint(r - 3, b - 3); + p.drawPoint(r - 4, b - 2); + p.drawPoint(r - 5, b - 2); + } + + p.setFont(options()->font(isActive(), isToolWindow())); + + p.setPen(options()->color(ColorFont, isActive())); + + p.drawText(titleRect, AlignCenter, caption()); +} + +void WebClient::updateWindowShape() +{ + if (!shape_) + return; + + TQRegion mask(0, 0, width(), height()); + + int r(width()); + int b(height()); + + // Remove top-left corner. + + mask -= TQRegion(0, 0, 5, 1); + mask -= TQRegion(0, 1, 3, 1); + mask -= TQRegion(0, 2, 2, 1); + mask -= TQRegion(0, 3, 1, 2); + + // Remove top-right corner. + + mask -= TQRegion(r - 5, 0, 5, 1); + mask -= TQRegion(r - 3, 1, 3, 1); + mask -= TQRegion(r - 2, 2, 2, 1); + mask -= TQRegion(r - 1, 3, 1, 2); + + // Remove bottom-left corner. + + mask -= TQRegion(0, b - 5, 1, 3); + mask -= TQRegion(0, b - 3, 2, 1); + mask -= TQRegion(0, b - 2, 3, 1); + mask -= TQRegion(0, b - 1, 5, 1); + + // Remove bottom-right corner. + + mask -= TQRegion(r - 5, b - 1, 5, 1); + mask -= TQRegion(r - 3, b - 2, 3, 1); + mask -= TQRegion(r - 2, b - 3, 2, 1); + mask -= TQRegion(r - 1, b - 5, 1, 2); + + setMask(mask); +} + +KDecoration* WebFactory::createDecoration( KDecorationBridge* b ) +{ + return(new WebClient(b, this)); +} + +bool WebFactory::reset(unsigned long changed) +{ + // Do we need to "hit the wooden hammer" ? + bool needHardReset = true; + if (changed & SettingColors || changed & SettingFont) + { + needHardReset = false; + } else if (changed & SettingButtons) { + // handled by KCommonDecoration + needHardReset = false; + } + + if (needHardReset) { + return true; + } else { + resetDecorations(changed); + return false; + } +} + +bool WebFactory::supports( Ability ability ) +{ + switch( ability ) + { + case AbilityAnnounceButtons: + case AbilityButtonOnAllDesktops: + case AbilityButtonHelp: + case AbilityButtonMinimize: + case AbilityButtonMaximize: + case AbilityButtonClose: + case AbilityButtonMenu: + case AbilityButtonAboveOthers: + case AbilityButtonBelowOthers: + case AbilityButtonShade: + return true; + default: + return false; + }; +} + +TQValueList< WebFactory::BorderSize > WebFactory::borderSizes() const +{ // the list must be sorted + return TQValueList< BorderSize >() << BorderNormal << BorderLarge << + BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized; +} + +} + +#include "Web.moc" +// vim:ts=2:sw=2:tw=78:set et: +// kate: indent-width 2; replace-tabs on; tab-width 2; space-indent on; diff --git a/twin/clients/web/Web.h b/twin/clients/web/Web.h new file mode 100644 index 000000000..ec1b08dc5 --- /dev/null +++ b/twin/clients/web/Web.h @@ -0,0 +1,87 @@ +/* + 'Web' twin client + + Copyright (C) 2005 Sandro Giessl <sandro@giessl.com> + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@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_WEB_H +#define KWIN_WEB_H + +#include "../../lib/kcommondecoration.h" +#include "../../lib/kdecorationfactory.h" + +class TQLabel; +class TQSpacerItem; +class TQBoxLayout; + +namespace Web +{ + + class WebButton; + + class WebClient : public KCommonDecoration + { + public: + + WebClient(KDecorationBridge* bridge, KDecorationFactory* factory); + ~WebClient(); + + virtual TQString visibleName() const; + virtual TQString defaultButtonsLeft() const; + virtual TQString 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 updateWindowShape(); + + virtual void init(); + + protected: + virtual void reset( unsigned long changed ); + + virtual void paintEvent(TQPaintEvent *); + + private: + + int titleHeight_, borderSize_; + + bool shape_; + + TQBitmap _buttonBitmap(ButtonType t) const; + }; + + class WebFactory : public TQObject, public KDecorationFactory + { + Q_OBJECT + + public: + + WebFactory() {}; + virtual ~WebFactory() {}; + virtual KDecoration* createDecoration( KDecorationBridge* ); + virtual bool reset( unsigned long changed ); + virtual bool supports( Ability ability ); + virtual TQValueList< BorderSize > borderSizes() const; + }; +} + +#endif +// vim:ts=2:sw=2:tw=78:set et: +// kate: indent-width 2; replace-tabs on; tab-width 2; space-indent on; diff --git a/twin/clients/web/WebButton.cpp b/twin/clients/web/WebButton.cpp new file mode 100644 index 000000000..785abe699 --- /dev/null +++ b/twin/clients/web/WebButton.cpp @@ -0,0 +1,287 @@ +/* + 'Web' twin client + + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@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 <tqpainter.h> + +#include "WebButton.h" +#include "Web.h" + +namespace Web { + + static unsigned char close_bits[] = { + 0x42, 0xe7, 0x7e, 0x3c, 0x3c, 0x7e, 0xe7, 0x42 + }; + static unsigned char iconify_bits[] = { + 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x3c, 0x18, 0x00 + }; + static unsigned char maximize_bits[] = { + 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00 + }; + static unsigned char unmaximize_bits[] = { + 0x00, 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f + }; + static unsigned char sticky_bits[] = { + 0x20, 0x70, 0xfa, 0x7e, 0x3c, 0x1c, 0x32, 0x01 + }; + static unsigned char unsticky_bits[] = { + 0x1c, 0x1c, 0x1c, 0x3e, 0x7f, 0x08, 0x08, 0x08 + }; + static unsigned char help_bits[] = { + 0x18, 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x3c + }; + static unsigned char shade_on_bits[] = { + 0xff, 0xff, 0x81, 0x81, 0x99, 0xbd, 0x81, 0xff + }; + static unsigned char shade_off_bits[] = { + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + static unsigned char above_on_bits[] = { + 0xff, 0x7e, 0x3c, 0x18, 0x00, 0xff, 0xff, 0x00 + }; + static unsigned char above_off_bits[] = { + 0x18, 0x3c, 0x7e, 0xff, 0x00, 0xff, 0xff, 0x00 + }; + static unsigned char below_on_bits[] = { + 0x00, 0xff, 0xff, 0x00, 0x18, 0x3c, 0x7e, 0xff + }; + static unsigned char below_off_bits[] = { + 0x00, 0xff, 0xff, 0x00, 0xff, 0x7e, 0x3c, 0x18 + }; + static unsigned char menu_bits[] = { + 0xff, 0x81, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff + }; + +WebButton::WebButton(ButtonType type, WebClient *parent, const char *name, bool shape) + : KCommonDecorationButton (type, parent, name), + mouseOver_ (false), + shape_ (shape), + deco_ (parent) +{ + setBackgroundMode(NoBackground); +} + +WebButton::~WebButton() +{ + // Empty. +} + +void WebButton::reset(unsigned long changed) +{ + if (changed&DecorationReset || changed&ManualReset || changed&SizeChange || changed&StateChange) { + switch (type() ) { + case CloseButton: + setBitmap(close_bits); + break; + case HelpButton: + setBitmap(help_bits); + break; + case MinButton: + setBitmap(iconify_bits); + break; + case MaxButton: + setBitmap( isOn() ? unmaximize_bits : maximize_bits ); + break; + case OnAllDesktopsButton: + setBitmap( isOn() ? unsticky_bits : sticky_bits ); + 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; + case MenuButton: + setBitmap(menu_bits); + break; + default: + setBitmap(0); + break; + } + + this->update(); + } +} + + void +WebButton::enterEvent(TQEvent * e) +{ + mouseOver_ = true; + repaint(); + TQButton::enterEvent(e); +} + + void +WebButton::leaveEvent(TQEvent * e) +{ + mouseOver_ = false; + repaint(); + TQButton::leaveEvent(e); +} + + void +WebButton::drawButton(TQPainter *p) +{ + TQPen highlightPen; + + if (isDown() ) + highlightPen = TQPen(colorGroup().light()); + + else + { + if (mouseOver_) + highlightPen = TQPen(colorGroup().highlight()); + else + highlightPen = TQPen(NoPen); + } + + p->fillRect(rect(), colorGroup().background()); + + Position position_; + if (0 == mapToParent(rect().topLeft() ).x() ) + position_ = Left; + else if (deco_->width()-1 == mapToParent(rect().topRight() ).x() ) + position_ = Right; + else + position_ = Mid; + switch ( position_ ) + { + case Left: + { + // Draw edge. + + p->setPen(Qt::black); + + p->drawLine(0, 0, width(), 0); + p->drawLine(0, 1, 0, height() - 1); + if (shape_) + { + p->drawPoint(3, 1); + p->drawPoint(4, 1); + p->drawPoint(2, 2); + p->drawPoint(1, 3); + p->drawPoint(1, 4); + } + // Draw highlight. + + p->setBrush(NoBrush); + p->setPen(highlightPen); + + if (shape_) + p->setClipRegion(TQRegion(rect()) - TQRect(0, 0, 6, 6)); + + p->drawRect(2, 2, width() - 4, height() - 4); + if (shape_) + { + p->setClipRect(rect()); + p->drawPoint(4, 3); + p->drawPoint(5, 3); + p->drawPoint(3, 4); + p->drawPoint(3, 5); + } + } + + break; + + case Right: + { + // Draw edge. + + p->setPen(Qt::black); + p->drawLine(0, 0, width(), 0); + p->drawLine(width() - 1, 1, width() - 1, height() - 1); + if (shape_) + { + p->drawPoint(width() - 5, 1); + p->drawPoint(width() - 4, 1); + p->drawPoint(width() - 3, 2); + p->drawPoint(width() - 2, 3); + p->drawPoint(width() - 2, 4); + } + // Draw highlight. + + p->setBrush(NoBrush); + p->setPen(highlightPen); + + if (shape_) + p->setClipRegion(TQRegion(rect()) - TQRect(width() - 6, 0, 6, 6)); + + p->drawRect(2, 2, width() - 4, height() - 4); + if (shape_) + { + p->setClipRect(rect()); + p->drawPoint(width() - 5, 3); + p->drawPoint(width() - 6, 3); + p->drawPoint(width() - 4, 4); + p->drawPoint(width() - 4, 5); + } + } + + break; + + case Mid: + default: + { + // Draw edge. + + p->setPen(Qt::black); + p->drawLine(0, 0, width(), 0); + + // Draw highlight. + + p->setBrush(NoBrush); + p->setPen(highlightPen); + + p->drawRect(2, 2, width() - 4, height() - 4); + } + + break; + } + + // Draw icon. + + TQPoint center(rect().center()); + + int bwby2(bitmap_.width() / 2); // Bitmap Width BY 2 + int bhby2(bitmap_.height() / 2); // Bitmap Height BY 2 + + p->setBrush(NoBrush); + p->setPen(Qt::black); + + p->drawPixmap(center.x() - bwby2 + 1, center.y() - bhby2 + 1, bitmap_); +} + + void +WebButton::setBitmap(const unsigned char *bitmap) +{ + if (bitmap) + bitmap_ = TQBitmap(8,8, bitmap, true); + else + bitmap_ = TQBitmap(8,8); + bitmap_.setMask(bitmap_); +} + +} + +// vim:ts=2:sw=2:tw=78:set et: +// kate: indent-width 2; replace-tabs on; tab-width 2; space-indent on; diff --git a/twin/clients/web/WebButton.h b/twin/clients/web/WebButton.h new file mode 100644 index 000000000..a5eb8867e --- /dev/null +++ b/twin/clients/web/WebButton.h @@ -0,0 +1,70 @@ +/* + 'Web' twin client + + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@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_WEB_BUTTON_H +#define KWIN_WEB_BUTTON_H + +#include <tqwidget.h> +#include <tqbitmap.h> +#include <tdelocale.h> + +#include "../../lib/kcommondecoration.h" + +namespace Web +{ + class WebClient; + + class WebButton : public KCommonDecorationButton + { + public: + + enum Position + { + Left, Mid, Right + }; + + WebButton(ButtonType type, WebClient *parent, const char *name, bool shape); + + virtual ~WebButton(); + + virtual void reset(unsigned long changed); + + protected: + void setBitmap(const unsigned char *bitmap); + + void enterEvent(TQEvent *); + void leaveEvent(TQEvent *); + void drawButton(TQPainter *p); + + private: + TQBitmap bitmap_; + + bool mouseOver_; + + bool shape_; + WebClient* deco_; + }; +} + +#endif + +// vim:ts=2:sw=2:tw=78:set et: +// kate: indent-width 2; replace-tabs on; tab-width 2; space-indent on; diff --git a/twin/clients/web/web.desktop b/twin/clients/web/web.desktop new file mode 100644 index 000000000..b86134904 --- /dev/null +++ b/twin/clients/web/web.desktop @@ -0,0 +1,47 @@ +[Desktop Entry] +Name=Web +Name[ar]=الشبكة +Name[az]=Veb +Name[be]=Сеціва +Name[bn]=ওয়েব +Name[br]=Gwiad +Name[csb]=Séc +Name[cy]=Gwe +Name[da]=Net +Name[el]=Ιστός +Name[eo]=TTT +Name[et]=Veeb +Name[fa]=وب +Name[ga]=Gréasán +Name[hi]=वेब +Name[hr]=Internet +Name[is]=Vefur +Name[km]=បណ្ដាញ +Name[lo]=ແບບເວ໊ບ +Name[lv]=Tīmekļa +Name[mk]=Веб +Name[mn]=Веб +Name[nb]=Nett +Name[ne]=वेब +Name[nn]=Vev +Name[pa]=ਵੈੱਬ +Name[pl]=Sieć +Name[rw]=Urubugamakuru +Name[se]=Fierpmádat +Name[sl]=Splet +Name[sr]=Веб +Name[sr@Latn]=Veb +Name[sv]=Webb +Name[ta]=வலை +Name[te]=వెబ్ +Name[tg]=Вэб +Name[th]=แบบเว็บ +Name[uk]=Тенета +Name[uz]=Veb +Name[uz@cyrillic]=Веб +Name[ven]=Webu +Name[vi]=Mạng +Name[wa]=Waibe +Name[zh_TW]=網頁 +Name[zu]=I-Web +X-TDE-Library=twin3_web |