summaryrefslogtreecommitdiffstats
path: root/twin-styles/kstep/nextclient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'twin-styles/kstep/nextclient.cpp')
-rw-r--r--twin-styles/kstep/nextclient.cpp987
1 files changed, 987 insertions, 0 deletions
diff --git a/twin-styles/kstep/nextclient.cpp b/twin-styles/kstep/nextclient.cpp
new file mode 100644
index 00000000..08867a62
--- /dev/null
+++ b/twin-styles/kstep/nextclient.cpp
@@ -0,0 +1,987 @@
+#include "nextclient.h"
+#include <tqdatetime.h>
+#include <tqdrawutil.h>
+#include <tqlayout.h>
+#include <tqpainter.h>
+#include <tqbitmap.h>
+#include <tqlabel.h>
+#include <tqtooltip.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kpixmapeffect.h>
+
+namespace KStep {
+
+static const unsigned char close_bits[] = {
+ 0x03, 0x03, 0x87, 0x03, 0xce, 0x01, 0xfc, 0x00, 0x78, 0x00, 0x78, 0x00,
+ 0xfc, 0x00, 0xce, 0x01, 0x87, 0x03, 0x03, 0x03};
+
+static const unsigned char iconify_bits[] = {
+ 0xff, 0x03, 0xff, 0x03, 0xff, 0x03, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0xff, 0x03, 0xff, 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 sticky_bits[] = {
+ 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xfe, 0x01, 0xfe, 0x01,
+ 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00};
+
+static const unsigned char unsticky_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+static const unsigned char maximize_bits[] = {
+ 0x30, 0x00, 0x78, 0x00, 0xfc, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x01,
+ 0x02, 0x01, 0x84, 0x00, 0x48, 0x00, 0x30, 0x00 };
+
+static const unsigned char shade_bits[] = {
+ 0xff,0x03,
+ 0xff,0x03,
+ 0x03,0x03,
+ 0xff,0x03,
+ 0xff,0x03,
+ 0x00,0x00,
+ 0x00,0x00,
+ 0x00,0x00,
+ 0x00,0x00,
+ 0x00,0x00
+};
+
+static const unsigned char unshade_bits[] = {
+ 0xff,0x03,
+ 0xff,0x03,
+ 0x03,0x03,
+ 0x03,0x03,
+ 0x03,0x03,
+ 0x03,0x03,
+ 0x03,0x03,
+ 0x03,0x03,
+ 0xff,0x03,
+ 0xff,0x03
+};
+
+static const unsigned char keep_above_bits[] = {
+ 0x30,0x00,
+ 0x78,0x00,
+ 0xfc,0x00,
+ 0x00,0x00,
+ 0xff,0x03,
+ 0xff,0x03,
+ 0x00,0x00,
+ 0x00,0x00,
+ 0x00,0x00,
+ 0x00,0x00
+};
+
+static const unsigned char from_above_bits[] = {
+ 0xff,0x03,
+ 0xff,0x03,
+ 0x00,0x00,
+ 0xfc,0x00,
+ 0x78,0x00,
+ 0x30,0x00,
+ 0x00,0x00,
+ 0x00,0x00,
+ 0x00,0x00,
+ 0x00,0x00
+};
+
+static const unsigned char keep_below_bits[] = {
+ 0x00,0x00,
+ 0x00,0x00,
+ 0x00,0x00,
+ 0x00,0x00,
+ 0xff,0x03,
+ 0xff,0x03,
+ 0x00,0x00,
+ 0xfc,0x00,
+ 0x78,0x00,
+ 0x30,0x00
+};
+
+static const unsigned char from_below_bits[] = {
+ 0x00,0x00,
+ 0x00,0x00,
+ 0x00,0x00,
+ 0x00,0x00,
+ 0x30,0x00,
+ 0x78,0x00,
+ 0xfc,0x00,
+ 0x00,0x00,
+ 0xff,0x03,
+ 0xff,0x03
+};
+
+static const unsigned char resize_bits[] = {
+ 0xff, 0x03,
+ 0xff, 0x03,
+ 0x33, 0x03,
+ 0x33, 0x03,
+ 0xf3, 0x03,
+ 0xf3, 0x03,
+ 0x03, 0x03,
+ 0x03, 0x03,
+ 0xff, 0x03,
+ 0xff, 0x03
+};
+
+
+// If the maximize graphic above (which I did quickly in about a
+// minute, just so I could have something) doesn't please, maybe one
+// of the following would be better. IMO it doesn't matter, as long
+// as it's not offensive---people will get used to whatever you use.
+// True NeXT fans won't turn on the maximize button anyway.
+//
+// static const unsigned char maximize_bits[] = {
+// 0xcf, 0x03, 0x87, 0x03, 0xcf, 0x03, 0xfd, 0x02, 0x48, 0x00, 0x48, 0x00,
+// 0xfd, 0x02, 0xcf, 0x03, 0x87, 0x03, 0xcf, 0x03 };
+//
+// static const unsigned char maximize_bits[] = {
+// 0xcf, 0x03, 0x87, 0x03, 0x87, 0x03, 0x79, 0x02, 0x48, 0x00, 0x48, 0x00,
+// 0x79, 0x02, 0x87, 0x03, 0x87, 0x03, 0xcf, 0x03 };
+//
+// static const unsigned char maximize_bits[] = {
+// 0x87, 0x03, 0x03, 0x03, 0xfd, 0x02, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00,
+// 0x84, 0x00, 0xfd, 0x02, 0x03, 0x03, 0x87, 0x03 };
+//
+// static const unsigned char maximize_bits[] = {
+// 0x30, 0x00, 0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x33, 0x03, 0x79, 0x02,
+// 0xcd, 0x02, 0x87, 0x03, 0x03, 0x03, 0x01, 0x02 };
+//
+// static const unsigned char maximize_bits[] = {
+// 0x30, 0x00, 0x78, 0x00, 0x78, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfe, 0x01,
+// 0xfe, 0x01, 0xff, 0x03, 0xff, 0x03, 0xff, 0x03 };
+
+
+static KPixmap *aTitlePix;
+static KPixmap *iTitlePix;
+static KPixmap *aFramePix;
+static KPixmap *iFramePix;
+static KPixmap *aHandlePix;
+static KPixmap *iHandlePix;
+static KPixmap *aBtn;
+static KPixmap *aBtnDown;
+static KPixmap *iBtn;
+static KPixmap *iBtnDown;
+static TQColor *btnForeground;
+static bool pixmaps_created = false;
+
+static int titleHeight = 16;
+
+// Precomputed border sizes for accessibility
+// The sizes are applied for tiny -> normal -> large -> very large -> huge -> very huge -> oversized
+static const int borderSizes[] = { 4, 6, 9, 14, 21, 32, 48 };
+
+static int handleSize = 6; // the resize handle size in pixels
+
+static inline const KDecorationOptions* options()
+{
+ return KDecoration::options();
+}
+
+static void create_pixmaps(NextClientFactory *f)
+{
+ if(pixmaps_created)
+ return;
+ pixmaps_created = true;
+
+ // find preferred border size
+ int i = options()->preferredBorderSize(f);
+ if (i >= 0 && i <= 6) handleSize = borderSizes[i];
+
+ titleHeight = TQFontMetrics(options()->font(true)).height() + 4;
+ if (titleHeight < handleSize) titleHeight = handleSize;
+ titleHeight &= ~1; // Make title height even
+ if (titleHeight < 16) titleHeight = 16;
+
+ aTitlePix = new KPixmap();
+ aTitlePix->resize(32, titleHeight - 2);
+ KPixmapEffect::gradient(*aTitlePix,
+ options()->color(KDecoration::ColorTitleBar, true),
+ options()->color(KDecoration::ColorTitleBlend, true),
+ KPixmapEffect::VerticalGradient);
+ iTitlePix = new KPixmap();
+ iTitlePix->resize(32, titleHeight - 2);
+ KPixmapEffect::gradient(*iTitlePix,
+ options()->color(KDecoration::ColorTitleBar, false),
+ options()->color(KDecoration::ColorTitleBlend, false),
+ KPixmapEffect::VerticalGradient);
+ // Bottom frame gradient
+ aFramePix = new KPixmap();
+ aFramePix->resize(32, handleSize);
+ KPixmapEffect::gradient(*aFramePix,
+ options()->color(KDecoration::ColorFrame, true).light(150),
+ options()->color(KDecoration::ColorFrame, true).dark(120),
+ KPixmapEffect::VerticalGradient);
+ iFramePix = new KPixmap();
+ iFramePix->resize(32, handleSize);
+ KPixmapEffect::gradient(*iFramePix,
+ options()->color(KDecoration::ColorFrame, false).light(150),
+ options()->color(KDecoration::ColorFrame, false).dark(120),
+ KPixmapEffect::VerticalGradient);
+
+ // Handle gradient
+ aHandlePix = new KPixmap();
+ aHandlePix->resize(32, handleSize);
+ KPixmapEffect::gradient(*aHandlePix,
+ options()->color(KDecoration::ColorHandle, true).light(150),
+ options()->color(KDecoration::ColorHandle, true).dark(120),
+ KPixmapEffect::VerticalGradient);
+ iHandlePix = new KPixmap();
+ iHandlePix->resize(32, handleSize);
+ KPixmapEffect::gradient(*iHandlePix,
+ options()->color(KDecoration::ColorHandle, false).light(150),
+ options()->color(KDecoration::ColorHandle, false).dark(120),
+ KPixmapEffect::VerticalGradient);
+
+ int btnWidth = titleHeight;
+ iBtn = new KPixmap;
+ iBtn->resize(btnWidth, btnWidth);
+ iBtnDown = new KPixmap;
+ iBtnDown->resize(btnWidth, btnWidth);
+ aBtn = new KPixmap;
+ aBtn->resize(btnWidth, btnWidth);
+ aBtnDown = new KPixmap;
+ aBtnDown->resize(btnWidth, btnWidth);
+ KPixmap internal;
+ int internalHeight = btnWidth - 6;
+ internal.resize(internalHeight, internalHeight);
+
+ // inactive buttons
+ TQColor c(options()->color(KDecoration::ColorButtonBg, false));
+ KPixmapEffect::gradient(*iBtn, c.light(120), c.dark(120),
+ KPixmapEffect::DiagonalGradient);
+ KPixmapEffect::gradient(internal, c.dark(120), c.light(120),
+ KPixmapEffect::DiagonalGradient);
+ bitBlt(TQT_TQPAINTDEVICE(iBtn), 3, 3, TQT_TQPAINTDEVICE(&internal), 0, 0, internalHeight, internalHeight, TQt::CopyROP, true);
+
+ KPixmapEffect::gradient(*iBtnDown, c.dark(120), c.light(120),
+ KPixmapEffect::DiagonalGradient);
+ KPixmapEffect::gradient(internal, c.light(120), c.dark(120),
+ KPixmapEffect::DiagonalGradient);
+ bitBlt(TQT_TQPAINTDEVICE(iBtnDown), 3, 3, TQT_TQPAINTDEVICE(&internal), 0, 0, internalHeight, internalHeight, TQt::CopyROP, true);
+
+ // active buttons
+ c = options()->color(KDecoration::ColorButtonBg, true);
+ KPixmapEffect::gradient(*aBtn, c.light(120), c.dark(120),
+ KPixmapEffect::DiagonalGradient);
+ KPixmapEffect::gradient(internal, c.dark(120), c.light(120),
+ KPixmapEffect::DiagonalGradient);
+ bitBlt(TQT_TQPAINTDEVICE(aBtn), 3, 3, TQT_TQPAINTDEVICE(&internal), 0, 0, internalHeight, internalHeight, TQt::CopyROP, true);
+
+ KPixmapEffect::gradient(*aBtnDown, c.dark(120), c.light(120),
+ KPixmapEffect::DiagonalGradient);
+ KPixmapEffect::gradient(internal, c.light(120), c.dark(120),
+ KPixmapEffect::DiagonalGradient);
+ bitBlt(TQT_TQPAINTDEVICE(aBtnDown), 3, 3, TQT_TQPAINTDEVICE(&internal), 0, 0, internalHeight, internalHeight, TQt::CopyROP, true);
+
+ TQPainter p;
+ p.begin(aBtn);
+ p.setPen(TQt::black);
+ p.drawRect(0, 0, btnWidth, btnWidth);
+ p.end();
+ p.begin(iBtn);
+ p.setPen(TQt::black);
+ p.drawRect(0, 0, btnWidth, btnWidth);
+ p.end();
+ p.begin(aBtnDown);
+ p.setPen(TQt::black);
+ p.drawRect(0, 0, btnWidth, btnWidth);
+ p.end();
+ p.begin(iBtnDown);
+ p.setPen(TQt::black);
+ p.drawRect(0, 0, btnWidth, btnWidth);
+ p.end();
+
+ if(tqGray(options()->color(KDecoration::ColorButtonBg, true).rgb()) > 128)
+ btnForeground = new TQColor(TQt::black);
+ else
+ btnForeground = new TQColor(TQt::white);
+}
+
+static void delete_pixmaps()
+{
+ delete aTitlePix;
+ delete iTitlePix;
+ delete aFramePix;
+ delete iFramePix;
+ delete aHandlePix;
+ delete iHandlePix;
+ delete aBtn;
+ delete iBtn;
+ delete aBtnDown;
+ delete iBtnDown;
+ delete btnForeground;
+
+ pixmaps_created = false;
+}
+
+// =====================================
+
+NextButton::NextButton(NextClient *parent, const char *name,
+ const unsigned char *bitmap, int bw, int bh,
+ const TQString& tip, const int realizeBtns)
+ : TQButton(parent->widget(), name),
+ deco(NULL), client(parent), last_button(Qt::NoButton)
+{
+ realizeButtons = realizeBtns;
+
+ setBackgroundMode( NoBackground );
+ resize(titleHeight, titleHeight);
+ setFixedSize(titleHeight, titleHeight);
+
+ if(bitmap)
+ setBitmap(bitmap, bw, bh);
+
+ TQToolTip::add(this, tip);
+}
+
+void NextButton::reset()
+{
+ tqrepaint(false);
+}
+
+void NextButton::setBitmap(const unsigned char *bitmap, int w, int h)
+{
+ deco = new TQBitmap(w, h, bitmap, true);
+ deco->setMask(*deco);
+ tqrepaint();
+}
+
+void NextButton::drawButton(TQPainter *p)
+{
+ if(client->isActive())
+ p->drawPixmap(0, 0, isDown() ? *aBtnDown : *aBtn);
+ else
+ p->drawPixmap(0, 0, isDown() ? *iBtnDown : *iBtn);
+
+ // If we have a decoration, draw it; otherwise, we have the menu
+ // button (remember, we set the bitmap to NULL).
+ int offset;
+ if (deco) {
+ offset = (titleHeight - 10) / 2 + (isDown() ? 1 : 0);
+ p->setPen(*btnForeground);
+ p->drawPixmap(offset, offset, *deco);
+ } else {
+ offset = (titleHeight - 16) / 2;
+ KPixmap btnpix = client->icon().pixmap(TQIconSet::Small,
+ client->isActive() ? TQIconSet::Normal : TQIconSet::Disabled);
+ p->drawPixmap( offset, offset, btnpix );
+ }
+}
+
+void NextButton::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 NextButton::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 );
+}
+
+// =====================================
+
+NextClient::NextClient(KDecorationBridge *b, KDecorationFactory *f)
+ : KDecoration(b, f)
+{
+}
+
+void NextClient::init()
+{
+ createMainWidget(WResizeNoErase | WStaticContents);
+ widget()->installEventFilter(this);
+
+ widget()->setBackgroundMode( NoBackground );
+
+ TQVBoxLayout *mainLayout = new TQVBoxLayout(widget());
+ TQBoxLayout *titleLayout = new TQBoxLayout(0, TQBoxLayout::LeftToRight, 0, 0, 0);
+ TQHBoxLayout *windowLayout = new TQHBoxLayout();
+ mainLayout->addLayout(titleLayout);
+ mainLayout->addLayout(windowLayout, 1);
+ mainLayout->addSpacing(mustDrawHandle() ? handleSize : 1);
+
+ windowLayout->addSpacing(1);
+ if (isPreview())
+ windowLayout->addWidget(new TQLabel(i18n(
+ "<center><b>KStep preview</b></center>"), widget()));
+ else
+ windowLayout->addItem(new TQSpacerItem( 0, 0 ));
+
+ windowLayout->addSpacing(1);
+
+ initializeButtonsAndTitlebar(titleLayout);
+}
+
+/**
+ Preconditions:
+ + button is an array of length MAX_NUM_BUTTONS
+
+ Postconditions:
+ + Title bar and buttons have been initialized and laid out
+ + for all i in 0..(MAX_NUM_BUTTONS-1), button[i] points to
+ either (1) a valid NextButton instance, if the corresponding
+ button is selected in the current button scheme, or (2) null
+ otherwise.
+ */
+void NextClient::initializeButtonsAndTitlebar(TQBoxLayout* titleLayout)
+{
+ // Null the buttons to begin with (they are not guaranteed to be null).
+ for (int i=0; i<MAX_NUM_BUTTONS; i++) {
+ button[i] = NULL;
+ }
+
+ // The default button positions for other styles do not match the
+ // behavior of older versions of KStep, so we have to set these
+ // manually when customButtonPositions isn't enabled.
+ TQString left, right;
+ if (options()->customButtonPositions()) {
+ left = options()->titleButtonsLeft();
+ right = options()->titleButtonsRight();
+ } else {
+ left = TQString("I");
+ right = TQString("SX");
+ }
+
+ // Do actual creation and addition to titleLayout
+ addButtons(titleLayout, left);
+
+ titlebar = new TQSpacerItem(10, titleHeight, TQSizePolicy::Expanding,
+ TQSizePolicy::Minimum );
+ titleLayout->addItem(titlebar);
+ addButtons(titleLayout, right);
+
+ // Finally, activate all live buttons
+ for ( int i = 0; i < MAX_NUM_BUTTONS; i++) {
+ if (button[i]) {
+ button[i]->setMouseTracking( TRUE );
+ }
+ }
+}
+
+/** Adds the buttons for one side of the title bar, based on the spec
+ * string; see the KWinInternal::KDecoration class, methods
+ * titleButtonsLeft and titleBUttonsRight. */
+void NextClient::addButtons(TQBoxLayout* titleLayout, const TQString& spec)
+{
+ for (unsigned int i=0; i<spec.length(); i++) {
+ switch (spec[i].latin1()) {
+ case 'A':
+ if (isMaximizable()) {
+ button[MAXIMIZE_IDX] =
+ new NextButton(this, "maximize", maximize_bits, 10, 10,
+ i18n("Maximize"), Qt::LeftButton|Qt::MidButton|Qt::RightButton);
+ titleLayout->addWidget( button[MAXIMIZE_IDX] );
+ connect( button[MAXIMIZE_IDX], TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(maximizeButtonClicked()) );
+ }
+ break;
+
+ case 'H':
+ if (providesContextHelp()) {
+ button[HELP_IDX] = new NextButton(this,
+ "help", question_bits, 10, 10, i18n("Help"));
+ titleLayout->addWidget( button[HELP_IDX] );
+ connect( button[HELP_IDX], TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(showContextHelp()) );
+ }
+ break;
+
+ case 'I':
+ if (isMinimizable()) {
+ button[ICONIFY_IDX] =
+ new NextButton(this, "iconify", iconify_bits, 10, 10,
+ i18n("Minimize"));
+ titleLayout->addWidget( button[ICONIFY_IDX] );
+ connect( button[ICONIFY_IDX], TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(minimize()) );
+ }
+ break;
+
+ case 'M':
+ button[MENU_IDX] =
+ new NextButton(this, "menu", NULL, 10, 10, i18n("Menu"), Qt::LeftButton|Qt::RightButton);
+ titleLayout->addWidget( button[MENU_IDX] );
+ // NOTE DIFFERENCE: capture pressed(), not clicked()
+ connect( button[MENU_IDX], TQT_SIGNAL(pressed()),
+ this, TQT_SLOT(menuButtonPressed()) );
+ break;
+
+ case 'L':
+ button[SHADE_IDX] =
+ new NextButton(this, "shade", NULL, 0, 0, i18n("Shade"));
+ titleLayout->addWidget( button[SHADE_IDX] );
+ connect( button[SHADE_IDX], TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(shadeClicked()) );
+ // NOTE DIFFERENCE: set the pixmap separately (2 states)
+ shadeChange();
+ break;
+
+ case 'S':
+ button[STICKY_IDX] =
+ new NextButton(this, "sticky", NULL, 0, 0, i18n("On all desktops"));
+ titleLayout->addWidget( button[STICKY_IDX] );
+ connect( button[STICKY_IDX], TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(toggleOnAllDesktops()) );
+ // NOTE DIFFERENCE: set the pixmap separately (2 states)
+ desktopChange();
+ break;
+
+ case 'F':
+ button[ABOVE_IDX] = new NextButton(this, "above", NULL, 0, 0, "");
+ titleLayout->addWidget( button[ABOVE_IDX] );
+ connect( button[ABOVE_IDX], TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(aboveClicked()) );
+ connect(this, TQT_SIGNAL(keepAboveChanged(bool)),
+ TQT_SLOT(keepAboveChange(bool)));
+ keepAboveChange(keepAbove());
+ break;
+
+ case 'B':
+ button[BELOW_IDX] = new NextButton(this, "below", NULL, 0, 0, "");
+ titleLayout->addWidget( button[BELOW_IDX] );
+ connect( button[BELOW_IDX], TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(belowClicked()) );
+ connect(this, TQT_SIGNAL(keepBelowChanged(bool)),
+ TQT_SLOT(keepBelowChange(bool)));
+ keepBelowChange(keepBelow());
+ break;
+
+ case 'X':
+ if (isCloseable()) {
+ button[CLOSE_IDX] =
+ new NextButton(this, "close", close_bits, 10, 10,
+ i18n("Close"));
+ titleLayout->addWidget(button[CLOSE_IDX]);
+ connect(button[CLOSE_IDX], TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(closeWindow()));
+ }
+ break;
+
+ case 'R':
+ if (mustDrawHandle()) {
+ button[RESIZE_IDX] =
+ new NextButton(this, "resize", resize_bits, 10, 10,
+ i18n("Resize"));
+ titleLayout->addWidget(button[RESIZE_IDX]);
+ // NOTE DIFFERENCE: capture pressed(), not clicked()
+ connect(button[RESIZE_IDX], TQT_SIGNAL(pressed()),
+ this, TQT_SLOT(resizePressed()));
+ }
+ break;
+ case '_':
+ // TODO: Add spacer handling
+ break;
+
+ default:
+ kdDebug() << " Can't happen: unknown button code "
+ << TQString(spec[i]);
+ break;
+ }
+ }
+}
+
+bool NextClient::mustDrawHandle() const
+{
+ bool drawSmallBorders = !options()->moveResizeMaximizedWindows();
+ if (drawSmallBorders && (maximizeMode() & MaximizeVertical)) {
+ return false;
+ } else {
+ return isResizable();
+ }
+}
+
+void NextClient::iconChange()
+{
+ if (button[MENU_IDX] && button[MENU_IDX]->isVisible())
+ button[MENU_IDX]->tqrepaint(false);
+}
+
+void NextClient::menuButtonPressed()
+{
+ // Probably don't need this null check, but we might as well.
+ if (button[MENU_IDX]) {
+ TQRect menuRect = button[MENU_IDX]->rect();
+ TQPoint menuTop = button[MENU_IDX]->mapToGlobal(menuRect.topLeft());
+ TQPoint menuBottom = button[MENU_IDX]->mapToGlobal(menuRect.bottomRight());
+ menuTop += TQPoint(1, 1);
+ menuBottom += TQPoint(1, 1);
+ KDecorationFactory* f = factory();
+ showWindowMenu(TQRect(menuTop, menuBottom));
+ if( !f->exists( this )) // 'this' was deleted
+ return;
+ button[MENU_IDX]->setDown(false);
+ }
+}
+
+// Copied, with minor edits, from KDEDefaultClient::slotMaximize()
+void NextClient::maximizeButtonClicked()
+{
+ if (button[MAXIMIZE_IDX]) {
+ maximize(button[MAXIMIZE_IDX]->lastButton());
+ }
+}
+
+void NextClient::shadeClicked()
+{
+ setShade(!isSetShade());
+}
+
+void NextClient::aboveClicked()
+{
+ setKeepAbove(!keepAbove());
+}
+
+void NextClient::belowClicked()
+{
+ setKeepBelow(!keepBelow());
+ keepAboveChange(keepAbove());
+ keepBelowChange(keepBelow());
+}
+
+void NextClient::resizePressed()
+{
+ performWindowOperation(ResizeOp);
+}
+
+void NextClient::resizeEvent(TQResizeEvent *)
+{
+ if (widget()->isVisible()) {
+ // TODO ? update border area only?
+ widget()->update();
+#if 0
+ widget()->update(titlebar->tqgeometry());
+ TQPainter p(widget());
+ TQRect t = titlebar->tqgeometry();
+ t.setTop( 0 );
+ TQRegion r = widget()->rect();
+ r = r.subtract( t );
+ p.setClipRegion( r );
+ p.eraseRect(widget()->rect());
+#endif
+ }
+}
+
+void NextClient::captionChange()
+{
+ widget()->tqrepaint(titlebar->tqgeometry(), false);
+}
+
+
+void NextClient::paintEvent( TQPaintEvent* )
+{
+ TQPainter p(widget());
+
+ // Draw black frame
+ TQRect fr = widget()->rect();
+ p.setPen(TQt::black);
+ p.drawRect(fr);
+
+ // Draw title bar
+ TQRect t = titlebar->tqgeometry();
+ t.setTop(1);
+ p.drawTiledPixmap(t.x()+1, t.y()+1, t.width()-2, t.height()-2,
+ isActive() ? *aTitlePix : *iTitlePix);
+ qDrawShadePanel(&p, t.x(), t.y(), t.width(), t.height()-1,
+ options()->tqcolorGroup(KDecoration::ColorTitleBar, isActive()));
+ p.drawLine(t.x(), t.bottom(), t.right(), t.bottom());
+
+#if 0
+ // Why setting up a clipping region if it is not used? (setClipping(false))
+ TQRegion r = fr;
+ r = r.subtract( t );
+ p.setClipRegion( r );
+ p.setClipping(false);
+#endif
+
+ t.setTop( 1 );
+ t.setHeight(t.height()-2);
+ t.setLeft( t.left() + 4 );
+ t.setRight( t.right() - 2 );
+
+ p.setPen(options()->color(KDecoration::ColorFont, isActive()));
+ p.setFont(options()->font(isActive()));
+ p.drawText( t, AlignCenter | AlignVCenter, caption() );
+
+ // Draw resize handle
+ if (mustDrawHandle()) {
+ int corner = 16 + 3*handleSize/2;
+ qDrawShadePanel(&p,
+ fr.x() + 1, fr.bottom() - handleSize, corner-1, handleSize,
+ options()->tqcolorGroup(KDecoration::ColorHandle, isActive()),
+ false);
+ p.drawTiledPixmap(fr.x() + 2, fr.bottom() - handleSize + 1,
+ corner - 3, handleSize - 2, isActive() ? *aHandlePix : *iHandlePix);
+
+ qDrawShadePanel(&p,
+ fr.x() + corner, fr.bottom() - handleSize,
+ fr.width() - 2*corner, handleSize,
+ options()->tqcolorGroup(KDecoration::ColorFrame, isActive()),
+ false);
+ p.drawTiledPixmap(fr.x() + corner + 1, fr.bottom() - handleSize + 1,
+ fr.width() - 2*corner - 2, handleSize - 2,
+ isActive() ? *aFramePix : *iFramePix);
+
+ qDrawShadePanel(&p,
+ fr.right() - corner + 1, fr.bottom() - handleSize, corner - 1, handleSize,
+ options()->tqcolorGroup(KDecoration::ColorHandle, isActive()),
+ false);
+ p.drawTiledPixmap(fr.right() - corner + 2, fr.bottom() - handleSize + 1,
+ corner - 3, handleSize - 2, isActive() ? *aHandlePix : *iHandlePix);
+ }
+}
+
+void NextClient::mouseDoubleClickEvent( TQMouseEvent * e )
+{
+ if (e->button() == Qt::LeftButton && titlebar->tqgeometry().contains( e->pos() ) )
+ titlebarDblClickOperation();
+}
+
+void NextClient::wheelEvent( TQWheelEvent * e )
+{
+ if (isSetShade() || TQRect( 0, 0, width(), titleHeight ).contains( e->pos() ) )
+ titlebarMouseWheelOperation( e->delta());
+}
+
+void NextClient::showEvent(TQShowEvent *)
+{
+ widget()->tqrepaint();
+}
+
+void NextClient::desktopChange()
+{
+ bool on = isOnAllDesktops();
+ if (NextButton * b = button[STICKY_IDX]) {
+ b->setBitmap( on ? unsticky_bits : sticky_bits, 10, 10);
+ TQToolTip::remove(b);
+ TQToolTip::add(b, on ? i18n("Not on all desktops") : i18n("On all desktops"));
+ }
+}
+
+void NextClient::maximizeChange()
+{
+ if (button[MAXIMIZE_IDX]) {
+ bool m = maximizeMode() == MaximizeFull;
+ //button[MAXIMIZE_IDX]->setBitmap(m ? minmax_bits : maximize_bits);
+ TQToolTip::remove(button[MAXIMIZE_IDX]);
+ TQToolTip::add(button[MAXIMIZE_IDX],
+ m ? i18n("Restore") : i18n("Maximize"));
+ }
+ //spacer->changeSize(10, mustDrawHandle() ? handleSize : 1,
+ // TQSizePolicy::Expanding, TQSizePolicy::Minimum);
+ //mainLayout->activate();
+}
+
+void NextClient::activeChange()
+{
+ widget()->tqrepaint(false);
+ slotReset();
+}
+
+void NextClient::slotReset()
+{
+ for (int i=0; i<MAX_NUM_BUTTONS; i++) {
+ if (button[i]) {
+ button[i]->reset();
+ }
+ }
+}
+
+KDecoration::Position
+NextClient::mousePosition( const TQPoint& p ) const
+{
+ Position m = PositionCenter;
+
+ if (p.y() < (height() - handleSize))
+ m = KDecoration::mousePosition(p);
+
+ else {
+ int corner = 16 + 3*handleSize/2;
+ if (p.x() >= (width() - corner))
+ m = PositionBottomRight;
+ else if (p.x() <= corner)
+ m = PositionBottomLeft;
+ else
+ m = PositionBottom;
+ }
+
+ return m;
+}
+
+void NextClient::borders(int &left, int &right, int &top, int &bottom) const
+{
+ left = right = 1;
+ top = titleHeight; // FRAME is this ok?
+ bottom = mustDrawHandle() ? handleSize : 1;
+}
+
+void NextClient::shadeChange()
+{
+ if (NextButton *b = button[SHADE_IDX]) {
+ b->setBitmap(isSetShade() ? unshade_bits : shade_bits, 10, 10);
+ TQToolTip::remove(b);
+ TQToolTip::add(b, isSetShade() ? i18n("Unshade") : i18n("Shade"));
+ }
+}
+
+void NextClient::keepAboveChange(bool above)
+{
+ if (NextButton *b = button[ABOVE_IDX]) {
+ b->setBitmap(above ? from_above_bits : keep_above_bits, 10, 10);
+ TQToolTip::remove(b);
+ TQToolTip::add(b, above ?
+ i18n("Do not keep above others") : i18n("Keep above others"));
+ b->tqrepaint(false);
+ }
+}
+
+void NextClient::keepBelowChange(bool below)
+{
+ if (NextButton *b = button[BELOW_IDX]) {
+ b->setBitmap(below ? from_below_bits : keep_below_bits, 10, 10);
+ TQToolTip::remove(b);
+ TQToolTip::add(b, below ?
+ i18n("Do not keep below others") : i18n("Keep below others"));
+ b->tqrepaint(false);
+ }
+}
+
+TQSize NextClient::tqminimumSize() const
+{
+ return TQSize(titleHeight * 6 + 2, titleHeight + handleSize + 2);
+}
+
+void NextClient::resize(const TQSize& s)
+{
+ widget()->resize(s);
+}
+
+void NextClient::reset(unsigned long)
+{
+ for (int i = 0; i < MAX_NUM_BUTTONS; ++i) {
+ if (button[i])
+ button[i]->reset();
+ }
+ widget()->tqrepaint();
+}
+
+bool NextClient::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::Wheel:
+ 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;
+}
+
+bool NextClient::drawbound(const TQRect& geom, bool /* clear */)
+{
+ TQPainter p(workspaceWidget());
+ p.setPen(TQPen(TQt::white, 3));
+ p.setRasterOp(TQt::XorROP);
+ p.drawRect(geom);
+ int leftMargin = geom.left() + 2;
+ p.fillRect(leftMargin, geom.top() + titleHeight - 1,
+ geom.width() - 4, 3, TQt::white);
+ if (mustDrawHandle()) {
+ p.fillRect(leftMargin, geom.bottom() - handleSize - 1,
+ geom.width() - 4, 3, TQt::white);
+ }
+ return true;
+}
+
+// =====================================
+
+NextClientFactory::NextClientFactory()
+{
+ create_pixmaps(this);
+}
+
+NextClientFactory::~NextClientFactory()
+{
+ delete_pixmaps();
+}
+
+KDecoration *NextClientFactory::createDecoration(KDecorationBridge *b)
+{
+ return new NextClient(b, this);
+}
+
+bool NextClientFactory::reset(unsigned long /*changed*/)
+{
+ // TODO Do not recreate decorations if it is not needed. Look at
+ // ModernSystem for how to do that
+ delete_pixmaps();
+ create_pixmaps(this);
+ // For now just return true.
+ return true;
+}
+
+bool NextClientFactory::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 AbilityButtonResize:
+ return true;
+ default:
+ return false;
+ };
+}
+
+TQValueList< NextClientFactory::BorderSize >
+NextClientFactory::borderSizes() const
+{
+ // the list must be sorted
+ return TQValueList< BorderSize >() << BorderTiny << BorderNormal <<
+ BorderLarge << BorderVeryLarge << BorderHuge <<
+ BorderVeryHuge << BorderOversized;
+}
+
+} // KStep namespace
+
+extern "C" KDE_EXPORT KDecorationFactory* create_factory()
+{
+ return new KStep::NextClientFactory();
+}
+
+#include "nextclient.moc"
+
+// vim: sw=4