Added new Buttons for the Titlebar of a Window (Mathias)

- Shade - just like the "Stick"-button
  Styleresources:
    window.shade.pixmap, window.shade.unfocus.pixmap, window.shade.pressed.pixmap
    window.unshade.pixmap, window.unshade.unfocus.pixmap, window.unshade.pressed.pixmap
    etc.
- MenuIcon - click on it provides the windowmenu, if the app
  contains a pixmap (gvim, konqueror etc etc) the pixmap is displayed, a
  little menu otherwise. 
  Styleresources:
    windowmenu.pixmap, windowmenu.unfocus.pixmap windowmenu.pressed.pixmap
    etc.
Example ~/.fluxbox/init - entry:
  session.titlebar.left: MenuIcon Stick
  session.titlebar.right: Shade Minimize Maximize Close


hint: if the app HAS a pixmap i use window.title.focus.pixmap (look
WinButtonTheme for reference)in pixmap-based-styles. this looks excellent and dont need 
much extra-code to pipe that info into WinButtons.
This commit is contained in:
mathias 2005-05-06 18:04:14 +00:00
parent 783a390375
commit 4338fbec76
8 changed files with 251 additions and 55 deletions

View file

@ -1,6 +1,22 @@
(Format: Year/Month/Day)
Changes for 0.9.13
*05/05/06:
* Added new Buttons for the Titlebar of a Window (Mathias)
- Shade - just like the "Stick"-button
Styleresources:
window.shade.pixmap, window.shade.unfocus.pixmap, window.shade.pressed.pixmap
window.unshade.pixmap, window.unshade.unfocus.pixmap, window.unshade.pressed.pixmap
etc.
- MenuIcon - click on it provides the windowmenu, if the app
contains a pixmap (gvim, konqueror etc etc) the pixmap is displayed, a
little menu otherwise.
Styleresources:
windowmenu.pixmap, windowmenu.unfocus.pixmap windowmenu.pressed.pixmap
etc.
Example ~/.fluxbox/init - entry:
session.titlebar.left: MenuIcon Stick
session.titlebar.right: Shade Minimize Maximize Close
Window.cc Resources.cc fluxbox.hh WinButton.cc/hh WinButtonTheme.cc/hh
* xrestop should now display "Fluxbox" (Simon)
Ewmh.hh/cc
* Fix potential segfault menu bug, thanks chenfeng (Simon)

View file

@ -75,8 +75,8 @@ setFromString(char const *strval) {
m_value.push_back(Fluxbox::SHADE);
else if (strcasecmp(val[i].c_str(), "Stick")==0)
m_value.push_back(Fluxbox::STICK);
else if (strcasecmp(val[i].c_str(), "Menu")==0)
m_value.push_back(Fluxbox::MENU);
else if (strcasecmp(val[i].c_str(), "MenuIcon")==0)
m_value.push_back(Fluxbox::MENUICON);
else if (strcasecmp(val[i].c_str(), "Close")==0)
m_value.push_back(Fluxbox::CLOSE);
}
@ -150,8 +150,8 @@ getString() {
case Fluxbox::STICK:
retval.append("Stick");
break;
case Fluxbox::MENU:
retval.append("Menu");
case Fluxbox::MENUICON:
retval.append("MenuIcon");
break;
default:
break;

View file

@ -21,22 +21,34 @@
/// $Id$
#include <X11/Xlib.h>
#include "WinButton.hh"
#include "App.hh"
#include "Window.hh"
#include "Screen.hh"
#include "WinClient.hh"
#include "WinButtonTheme.hh"
#include "FbTk/Color.hh"
#ifdef SHAPE
#include <X11/extensions/shape.h>
#endif // SHAPE
WinButton::WinButton(const FluxboxWindow &listen_to,
WinButtonTheme &theme,
Type buttontype, const FbTk::FbWindow &parent,
int x, int y,
unsigned int width, unsigned int height):
FbTk::Button(parent, x, y, width, height),
m_type(buttontype), m_listen_to(listen_to), m_theme(theme),
m_type(buttontype), m_listen_to(listen_to), m_theme(theme),
m_icon_pixmap(0), m_icon_mask(0),
overrode_bg(false), overrode_pressed(false) {
theme.reconfigSig().attach(this);
if (buttontype == MENUICON)
update(0);
}
void WinButton::exposeEvent(XExposeEvent &event) {
@ -51,7 +63,7 @@ void WinButton::buttonReleaseEvent(XButtonEvent &event) {
// when someone else tries to set the background, we may override it
void WinButton::setBackgroundPixmap(Pixmap pm) {
Pixmap my_pm = getBackgroundPixmap();
if (my_pm != 0) {
overrode_bg = true;
pm = my_pm;
@ -114,9 +126,8 @@ Pixmap WinButton::getBackgroundPixmap() const {
else
return m_theme.iconifyUnfocusPixmap().pixmap().drawable();
break;
case STICK: {
bool stuck = m_listen_to.isStuck();
if (stuck) {
case STICK:
if (m_listen_to.isStuck()) {
if (focused)
return m_theme.stuckPixmap().pixmap().drawable();
else
@ -127,7 +138,6 @@ Pixmap WinButton::getBackgroundPixmap() const {
else
return m_theme.stickUnfocusPixmap().pixmap().drawable();
}
}
break;
case CLOSE:
if (focused)
@ -135,11 +145,31 @@ Pixmap WinButton::getBackgroundPixmap() const {
else
return m_theme.closeUnfocusPixmap().pixmap().drawable();
break;
case SHADE:
if (focused)
return m_theme.shadePixmap().pixmap().drawable();
else
return m_theme.shadeUnfocusPixmap().pixmap().drawable();
case SHADE:
if (m_listen_to.isShaded()) {
if (focused)
return m_theme.unshadePixmap().pixmap().drawable();
else
return m_theme.unshadeUnfocusPixmap().pixmap().drawable();
} else {
if (focused)
return m_theme.shadePixmap().pixmap().drawable();
else
return m_theme.shadeUnfocusPixmap().pixmap().drawable();
}
break;
case MENUICON:
if (m_icon_pixmap.drawable()) {
if (focused)
return m_theme.titleFocusPixmap().pixmap().drawable();
else
return m_theme.titleUnfocusPixmap().pixmap().drawable();
} else {
if (focused)
return m_theme.menuiconPixmap().pixmap().drawable();
else
return m_theme.menuiconUnfocusPixmap().pixmap().drawable();
}
break;
}
return None;
@ -156,23 +186,33 @@ Pixmap WinButton::getPressedPixmap() const {
case CLOSE:
return m_theme.closePressedPixmap().pixmap().drawable();
case SHADE:
return m_theme.shadePressedPixmap().pixmap().drawable();
if (m_listen_to.isShaded())
return m_theme.unshadePressedPixmap().pixmap().drawable();
else
return m_theme.shadePressedPixmap().pixmap().drawable();
case MENUICON:
if (m_icon_pixmap.drawable())
if (m_listen_to.isFocused())
return m_theme.titleFocusPixmap().pixmap().drawable();
else
return m_theme.titleUnfocusPixmap().pixmap().drawable();
else
return m_theme.menuiconPressedPixmap().pixmap().drawable();
}
return None;
}
// clear is used to force this to clear the window (e.g. called from clear())
void WinButton::drawType() {
bool used = false;
// if it's odd and we're centring, we need to add one
int oddW = width()%2;
int oddH = height()%2;
bool is_pressed = pressed();
if (is_pressed && overrode_pressed)
if (is_pressed && overrode_pressed && !m_icon_pixmap.drawable())
return;
if (!is_pressed && overrode_bg)
if (!is_pressed && overrode_bg && !m_icon_pixmap.drawable())
return;
if (gc() == 0)
return;
@ -190,8 +230,7 @@ void WinButton::drawType() {
2, 3, width() - 3, 3);
break;
case MINIMIZE:
FbTk::FbWindow::drawRectangle(gc(),
2, height() - 5, width() - 5, 2);
drawRectangle(gc(), 2, height() - 5, width() - 5, 2);
break;
case STICK:
// width/4 != width/2, so we use /4*2 so that it's properly centred
@ -225,17 +264,106 @@ void WinButton::drawType() {
width() - 3, 2);
break;
case SHADE:
// no cute image defined
drawRectangle(gc(), 2, 2, width() - 5 - oddW, 2);
XPoint points[3];
if (m_listen_to.isShaded()) {
points[1].x = (width() / 2) - 3; points[1].y = 7;
points[2].x = (width() / 2) + 4 - oddW; points[2].y = 7;
points[0].x = (width() / 2); points[0].y = height() / 2 + 2;
} else {
points[0].x = (width() / 2); points[0].y = 6;
points[1].x = (width() / 2) - 4; points[1].y = height() / 2 + 2;
points[2].x = (width() / 2) + 4 - oddW; points[2].y = height() / 2 + 2;
}
fillPolygon(gc(), points, 3, Convex, CoordModeOrigin);
break;
case MENUICON:
if (m_icon_pixmap.drawable()) {
if (m_icon_mask.drawable()) {
XSetClipMask(m_listen_to.fbWindow().display(),
gc(), m_icon_mask.drawable());
XSetClipOrigin(m_listen_to.fbWindow().display(),
gc(), 2, 2);
}
copyArea(m_icon_pixmap.drawable(),
gc(),
0, 0,
2, 2,
m_icon_pixmap.width(), m_icon_pixmap.height());
if (m_icon_mask.drawable())
XSetClipMask(m_listen_to.fbWindow().display(), gc(), None);
} else {
for (int y = height()/3; y <= height() - height()/3; y+=3) {
drawLine(gc(), width()/4, y, width() - width()/4 - oddW - 1, y);
}
drawRectangle(gc(),
2, 2, width() - 5, height() - 5);
}
break;
}
}
void WinButton::clear() {
FbTk::Button::clear();
if (m_type == MENUICON && (
!m_icon_pixmap.drawable() ||
(m_icon_pixmap.width() != width() - 4 ||
m_icon_pixmap.height() != height() - 4))) {
Display* display = m_listen_to.fbWindow().display();
int screen = m_listen_to.screen().screenNumber();
XWMHints* hints = XGetWMHints(display, m_listen_to.winClient().window());
if (hints == 0) {
m_icon_pixmap.release();
m_icon_mask.release();
} else {
if ((hints->flags & IconPixmapHint) && hints->icon_pixmap != 0) {
m_icon_pixmap.copy(hints->icon_pixmap,
DefaultDepth(display, screen), screen);
m_icon_pixmap.scale(width() - 4, height() - 4);
} else
m_icon_pixmap.release();
if ((hints->flags & IconMaskHint)) {
m_icon_mask.copy(hints->icon_mask, 0, 0);
m_icon_mask.scale(width() - 4, height() - 4);
} else
m_icon_mask.release();
}
XFree(hints);
}
drawType();
}
void WinButton::update(FbTk::Subject *subj) {
// just checking, if we the app provides a pixmap.
if (m_type == MENUICON) {
XWMHints* hints = XGetWMHints(m_listen_to.fbWindow().display(),
m_listen_to.winClient().window());
if (hints == 0) {
m_icon_pixmap.release();
m_icon_mask.release();
} else {
if (!((hints->flags & IconPixmapHint) && hints->icon_pixmap != 0))
m_icon_pixmap.release();
if (!(hints->flags & IconMaskHint))
m_icon_mask.release();
}
XFree(hints);
}
// pressed_pixmap isn't stateful in any current buttons, so no need
// to potentially override that. Just make sure background pm is ok
Pixmap my_pm = getBackgroundPixmap();

View file

@ -21,8 +21,9 @@
/// $Id$
#include "Button.hh"
#include "Observer.hh"
#include "FbTk/Button.hh"
#include "FbTk/Observer.hh"
#include "FbTk/FbPixmap.hh"
class FluxboxWindow;
class WinButtonTheme;
@ -35,7 +36,7 @@ class Color;
class WinButton:public FbTk::Button, public FbTk::Observer {
public:
/// draw type for the button
enum Type {MAXIMIZE, MINIMIZE, SHADE, STICK, CLOSE};
enum Type {MAXIMIZE, MINIMIZE, SHADE, STICK, CLOSE, MENUICON};
WinButton(const FluxboxWindow &listen_to,
WinButtonTheme &theme,
Type buttontype, const FbTk::FbWindow &parent, int x, int y,
@ -58,5 +59,9 @@ private:
Type m_type; ///< the button type
const FluxboxWindow &m_listen_to;
WinButtonTheme &m_theme;
FbTk::FbPixmap m_icon_pixmap;
FbTk::FbPixmap m_icon_mask;
bool overrode_bg, overrode_pressed;
};

View file

@ -43,6 +43,14 @@ WinButtonTheme::WinButtonTheme(int screen_num, const FbWinFrameTheme &frame_them
m_shade_pm(*this, "window.shade.pixmap", "Window.Shade.Pixmap"),
m_shade_unfocus_pm(*this, "window.shade.unfocus.pixmap", "Window.Shade.Unfocus.Pixmap"),
m_shade_pressed_pm(*this, "window.shade.pressed.pixmap", "Window.Shade.Pressed.Pixmap"),
m_unshade_pm(*this, "window.unshade.pixmap", "Window.Unshade.Pixmap"),
m_unshade_unfocus_pm(*this, "window.unshade.unfocus.pixmap", "Window.Unhade.Unfocus.Pixmap"),
m_unshade_pressed_pm(*this, "window.unshade.pressed.pixmap", "Window.Unshade.Pressed.Pixmap"),
m_menuicon_pm(*this, "window.menuicon.pixmap", "Window.MenuIcon.Pixmap"),
m_menuicon_unfocus_pm(*this, "window.menuicon.unfocus.pixmap", "Window.MenuIcon.Unfocus.Pixmap"),
m_menuicon_pressed_pm(*this, "window.menuicon.pressed.pixmap", "Window.MenuIcon.Pressed.Pixmap"),
m_title_focus_pm(*this, "window.title.focus.pixmap", "Window.Title.Focus.Pixmap"),
m_title_unfocus_pm(*this, "window.title.unfocus.pixmap", "Window.Title.UnFocus.Pixmap"),
m_stick_pm(*this, "window.stick.pixmap", "Window.Stick.Pixmap"),
m_stick_unfocus_pm(*this, "window.stick.unfocus.pixmap", "Window.Stick.Unfocus.Pixmap"),
m_stick_pressed_pm(*this, "window.stick.pressed.pixmap", "Window.Stick.Pressed.Pixmap"),
@ -70,7 +78,7 @@ void WinButtonTheme::reconfigTheme() {
m_close_pm->scale(size, size);
m_close_unfocus_pm->scale(size, size);
m_close_pressed_pm->scale(size, size);
m_maximize_pm->scale(size, size);
m_maximize_unfocus_pm->scale(size, size);
m_maximize_pressed_pm->scale(size, size);
@ -83,6 +91,13 @@ void WinButtonTheme::reconfigTheme() {
m_shade_unfocus_pm->scale(size, size);
m_shade_pressed_pm->scale(size, size);
m_unshade_pm->scale(size, size);
m_unshade_unfocus_pm->scale(size, size);
m_unshade_pressed_pm->scale(size, size);
m_title_focus_pm->scale(size, size);
m_title_unfocus_pm->scale(size, size);
m_stick_pm->scale(size, size);
m_stick_unfocus_pm->scale(size, size);
m_stick_pressed_pm->scale(size, size);

View file

@ -36,38 +36,55 @@ public:
void reconfigTheme();
inline const FbTk::PixmapWithMask &closePixmap() const { return *m_close_pm; }
inline FbTk::PixmapWithMask &closePixmap() { return *m_close_pm; }
inline FbTk::PixmapWithMask &closeUnfocusPixmap() { return *m_close_unfocus_pm; }
inline const FbTk::PixmapWithMask &closePressedPixmap() const { return *m_close_pressed_pm; }
inline FbTk::PixmapWithMask &closePressedPixmap() { return *m_close_pressed_pm; }
const FbTk::PixmapWithMask &closePixmap() const { return *m_close_pm; }
FbTk::PixmapWithMask &closePixmap() { return *m_close_pm; }
FbTk::PixmapWithMask &closeUnfocusPixmap() { return *m_close_unfocus_pm; }
const FbTk::PixmapWithMask &closePressedPixmap() const { return *m_close_pressed_pm; }
FbTk::PixmapWithMask &closePressedPixmap() { return *m_close_pressed_pm; }
inline const FbTk::PixmapWithMask &maximizePixmap() const { return *m_maximize_pm; }
inline FbTk::PixmapWithMask &maximizePixmap() { return *m_maximize_pm; }
inline FbTk::PixmapWithMask &maximizeUnfocusPixmap() { return *m_maximize_unfocus_pm; }
inline const FbTk::PixmapWithMask &maximizePressedPixmap() const { return *m_maximize_pressed_pm; }
inline FbTk::PixmapWithMask &maximizePressedPixmap() { return *m_maximize_pressed_pm; }
const FbTk::PixmapWithMask &maximizePixmap() const { return *m_maximize_pm; }
FbTk::PixmapWithMask &maximizePixmap() { return *m_maximize_pm; }
FbTk::PixmapWithMask &maximizeUnfocusPixmap() { return *m_maximize_unfocus_pm; }
const FbTk::PixmapWithMask &maximizePressedPixmap() const { return *m_maximize_pressed_pm; }
FbTk::PixmapWithMask &maximizePressedPixmap() { return *m_maximize_pressed_pm; }
inline const FbTk::PixmapWithMask &iconifyPixmap() const { return *m_iconify_pm; }
inline FbTk::PixmapWithMask &iconifyPixmap() { return *m_iconify_pm; }
inline FbTk::PixmapWithMask &iconifyUnfocusPixmap() { return *m_iconify_unfocus_pm; }
inline const FbTk::PixmapWithMask &iconifyPressedPixmap() const { return *m_iconify_pressed_pm; }
inline FbTk::PixmapWithMask &iconifyPressedPixmap() { return *m_iconify_pressed_pm; }
const FbTk::PixmapWithMask &iconifyPixmap() const { return *m_iconify_pm; }
FbTk::PixmapWithMask &iconifyPixmap() { return *m_iconify_pm; }
FbTk::PixmapWithMask &iconifyUnfocusPixmap() { return *m_iconify_unfocus_pm; }
const FbTk::PixmapWithMask &iconifyPressedPixmap() const { return *m_iconify_pressed_pm; }
FbTk::PixmapWithMask &iconifyPressedPixmap() { return *m_iconify_pressed_pm; }
inline const FbTk::PixmapWithMask &stickPixmap() const { return *m_stick_pm; }
inline FbTk::PixmapWithMask &stickPixmap() { return *m_stick_pm; }
inline FbTk::PixmapWithMask &stickUnfocusPixmap() { return *m_stick_unfocus_pm; }
inline const FbTk::PixmapWithMask &stickPressedPixmap() const { return *m_stick_pressed_pm; }
inline FbTk::PixmapWithMask &stickPressedPixmap() { return *m_stick_pressed_pm; }
const FbTk::PixmapWithMask &stickPixmap() const { return *m_stick_pm; }
FbTk::PixmapWithMask &stickPixmap() { return *m_stick_pm; }
FbTk::PixmapWithMask &stickUnfocusPixmap() { return *m_stick_unfocus_pm; }
const FbTk::PixmapWithMask &stickPressedPixmap() const { return *m_stick_pressed_pm; }
FbTk::PixmapWithMask &stickPressedPixmap() { return *m_stick_pressed_pm; }
inline FbTk::PixmapWithMask &stuckPixmap() { return *m_stuck_pm; }
inline FbTk::PixmapWithMask &stuckUnfocusPixmap() { return *m_stuck_unfocus_pm; }
FbTk::PixmapWithMask &stuckPixmap() { return *m_stuck_pm; }
FbTk::PixmapWithMask &stuckUnfocusPixmap() { return *m_stuck_unfocus_pm; }
inline const FbTk::PixmapWithMask &shadePixmap() const { return *m_shade_pm; }
inline FbTk::PixmapWithMask &shadePixmap() { return *m_shade_pm; }
inline FbTk::PixmapWithMask &shadeUnfocusPixmap() { return *m_shade_unfocus_pm; }
inline const FbTk::PixmapWithMask &shadePressedPixmap() const { return *m_shade_pressed_pm; }
inline FbTk::PixmapWithMask &shadePressedPixmap() { return *m_shade_pressed_pm; }
const FbTk::PixmapWithMask &shadePixmap() const { return *m_shade_pm; }
FbTk::PixmapWithMask &shadePixmap() { return *m_shade_pm; }
FbTk::PixmapWithMask &shadeUnfocusPixmap() { return *m_shade_unfocus_pm; }
const FbTk::PixmapWithMask &shadePressedPixmap() const { return *m_shade_pressed_pm; }
FbTk::PixmapWithMask &shadePressedPixmap() { return *m_shade_pressed_pm; }
const FbTk::PixmapWithMask &unshadePixmap() const { return *m_unshade_pm; }
FbTk::PixmapWithMask &unshadePixmap() { return *m_unshade_pm; }
FbTk::PixmapWithMask &unshadeUnfocusPixmap() { return *m_unshade_unfocus_pm; }
const FbTk::PixmapWithMask &unshadePressedPixmap() const { return *m_unshade_pressed_pm; }
FbTk::PixmapWithMask &unshadePressedPixmap() { return *m_unshade_pressed_pm; }
const FbTk::PixmapWithMask &menuiconPixmap() const { return *m_menuicon_pm; }
FbTk::PixmapWithMask &menuiconPixmap() { return *m_menuicon_pm; }
FbTk::PixmapWithMask &menuiconUnfocusPixmap() { return *m_menuicon_unfocus_pm; }
const FbTk::PixmapWithMask &menuiconPressedPixmap() const { return *m_menuicon_pressed_pm; }
FbTk::PixmapWithMask &menuiconPressedPixmap() { return *m_menuicon_pressed_pm; }
FbTk::PixmapWithMask &titleFocusPixmap() { return *m_title_focus_pm; }
const FbTk::PixmapWithMask &titleFocusPixmap() const { return *m_title_focus_pm; }
FbTk::PixmapWithMask &titleUnfocusPixmap() { return *m_title_unfocus_pm; }
const FbTk::PixmapWithMask &titleUnfocusPixmap() const { return *m_title_unfocus_pm; }
private:
@ -75,6 +92,10 @@ private:
FbTk::ThemeItem<FbTk::PixmapWithMask> m_maximize_pm, m_maximize_unfocus_pm, m_maximize_pressed_pm;
FbTk::ThemeItem<FbTk::PixmapWithMask> m_iconify_pm, m_iconify_unfocus_pm, m_iconify_pressed_pm;
FbTk::ThemeItem<FbTk::PixmapWithMask> m_shade_pm, m_shade_unfocus_pm, m_shade_pressed_pm;
FbTk::ThemeItem<FbTk::PixmapWithMask> m_unshade_pm, m_unshade_unfocus_pm, m_unshade_pressed_pm;
FbTk::ThemeItem<FbTk::PixmapWithMask> m_menuicon_pm, m_menuicon_unfocus_pm, m_menuicon_pressed_pm;
// why this? we need this for the background of the appicon in WinButtons
FbTk::ThemeItem<FbTk::PixmapWithMask> m_title_focus_pm, m_title_unfocus_pm;
FbTk::ThemeItem<FbTk::PixmapWithMask> m_stick_pm, m_stick_unfocus_pm, m_stick_pressed_pm;
FbTk::ThemeItem<FbTk::PixmapWithMask> m_stuck_pm, m_stuck_unfocus_pm;

View file

@ -3834,7 +3834,18 @@ void FluxboxWindow::setupWindow() {
WinButton::SHADE,
frame().titlebar(),
0, 0, 10, 10);
stateSig().attach(winbtn);
winbtn->setOnClick(shade_cmd);
newbutton = winbtn;
} else if ((*dir)[i] == Fluxbox::MENUICON) {
WinButton* winbtn = new WinButton(*this, winbutton_theme,
WinButton::MENUICON,
frame().titlebar(),
0, 0, 10, 10);
hintSig().attach(winbtn);
titleSig().attach(winbtn);
winbtn->setOnClick(show_menu_cmd);
newbutton = winbtn;
}
if (newbutton != 0) {

View file

@ -109,7 +109,7 @@ public:
void removeAtomHandler(AtomHandler *atomh);
/// obsolete
enum Titlebar{SHADE=0, MINIMIZE, MAXIMIZE, CLOSE, STICK, MENU, EMPTY};
enum Titlebar{SHADE=0, MINIMIZE, MAXIMIZE, CLOSE, STICK, MENUICON, EMPTY};
enum TabsAttachArea{ATTACH_AREA_WINDOW= 0, ATTACH_AREA_TITLEBAR};