From 4484d326807c6e1cf4ec6b6beeb099eab979723e Mon Sep 17 00:00:00 2001
From: fluxgen <fluxgen>
Date: Sun, 5 Jan 2003 22:14:10 +0000
Subject: frame handling

---
 src/FbWinFrame.cc      | 621 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/FbWinFrame.hh      | 221 ++++++++++++++++++
 src/FbWinFrameTheme.cc |  85 +++++++
 src/FbWinFrameTheme.hh |  98 ++++++++
 4 files changed, 1025 insertions(+)
 create mode 100644 src/FbWinFrame.cc
 create mode 100644 src/FbWinFrame.hh
 create mode 100644 src/FbWinFrameTheme.cc
 create mode 100644 src/FbWinFrameTheme.hh

diff --git a/src/FbWinFrame.cc b/src/FbWinFrame.cc
new file mode 100644
index 0000000..caa6f8f
--- /dev/null
+++ b/src/FbWinFrame.cc
@@ -0,0 +1,621 @@
+// FbWinFrame.cc for Fluxbox Window Manager
+// Copyright (c) 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+// $Id: FbWinFrame.cc,v 1.1 2003/01/05 22:14:10 fluxgen Exp $
+
+#include "FbWinFrame.hh"
+#include "ImageControl.hh"
+#include "EventManager.hh"
+#include "App.hh"
+
+#include <iostream>
+using namespace std;
+
+FbWinFrame::FbWinFrame(FbWinFrameTheme &theme, BImageControl &imgctrl, int screen_num, int x, int y,
+                       unsigned int width, unsigned int height):
+    m_theme(theme),
+    m_imagectrl(imgctrl),
+    m_window(screen_num, x, y, width, height,  ButtonPressMask | ButtonReleaseMask |
+             ButtonMotionMask | EnterWindowMask, true),
+    m_titlebar(m_window, 0, 0, 100, 16, 
+               ButtonPressMask | ButtonReleaseMask |
+               ButtonMotionMask | ExposureMask |
+               EnterWindowMask | LeaveWindowMask),
+    m_label(m_titlebar, 0, 0, 100, 16,
+	    ButtonPressMask | ButtonReleaseMask |
+            ButtonMotionMask | ExposureMask |
+            EnterWindowMask | LeaveWindowMask),
+    m_grip_right(m_window, 0, 0, 10, 4,
+                 ButtonPressMask | ButtonReleaseMask |
+                 ButtonMotionMask | ExposureMask |
+                 EnterWindowMask | LeaveWindowMask),
+    m_grip_left(m_window, 0, 0, 10, 4,
+		ButtonPressMask | ButtonReleaseMask |
+		ButtonMotionMask | ExposureMask |
+		EnterWindowMask | LeaveWindowMask),
+    m_handle(m_window, 0, 0, 100, 5,
+             ButtonPressMask | ButtonReleaseMask |
+             ButtonMotionMask | ExposureMask |
+             EnterWindowMask | LeaveWindowMask),
+    m_clientarea(m_window, 0, 0, 100, 100,
+                 ButtonPressMask | ButtonReleaseMask |
+                 ButtonMotionMask | ExposureMask |
+                 EnterWindowMask | LeaveWindowMask),
+    m_clientwin(0),
+    m_bevel(1),
+    m_use_titlebar(true), 
+    m_use_handles(true),
+    m_button_pm(0) {
+    init();
+}
+/*
+  FbWinFrame::FbWinFrame(FbWinFrameTheme &theme, BImageControl &imgctrl, const FbTk::FbWindow &parent, int x, int y,
+  unsigned int width, unsigned int height):
+  m_theme(theme),
+  m_imagectrl(imgctrl),
+  m_window(parent, x, y, width, height, ExposureMask | StructureNotifyMask),
+  m_titlebar(m_window, 0, 0, 100, 16, 
+  ExposureMask | ButtonPressMask | ButtonReleaseMask),
+  m_label(m_titlebar, 0, 0, 100, 16,
+  ExposureMask | ButtonPressMask | ButtonReleaseMask),
+  m_grip_right(m_window, 0, 0, 100, 100, ExposureMask | ButtonPressMask | ButtonReleaseMask),
+  m_grip_left(m_window, 0, 0, 100, 100, ExposureMask | ButtonPressMask | ButtonReleaseMask),
+  m_handle(m_window, 0, 0, 100, 100, ExposureMask | ButtonPressMask | ButtonReleaseMask),
+  m_clientarea(m_window, 0, 0, 100, 100, SubstructureRedirectMask),
+  m_clientwin(0),
+  m_bevel(1),
+  m_use_titlebar(true), 
+  m_use_handles(true),
+  m_button_pm(0) {
+
+  init();
+  }
+*/
+
+FbWinFrame::~FbWinFrame() {
+    removeEventHandler();
+    removeAllButtons();
+
+}
+
+void FbWinFrame::hide() {
+    m_window.hide();
+}
+
+void FbWinFrame::show() {
+    m_window.showSubwindows();
+    m_window.show();
+    reconfigure();
+}
+
+/**
+ Toggle shade state, and resize window
+ */
+void FbWinFrame::shade() {
+    if (!m_shaded) {
+        m_width_before_shade = m_window.width();
+        m_height_before_shade = m_window.height();
+        m_window.resize(m_window.width(), m_titlebar.height() + 2*m_titlebar.borderWidth());
+    } else {
+        m_window.resize(m_width_before_shade, m_height_before_shade);
+        m_grip_left.clear();
+        m_grip_right.clear();
+        m_handle.clear();
+    }
+    // toggle shade
+    m_shaded = !m_shaded;
+}
+
+
+void FbWinFrame::move(int x, int y) {
+    m_window.move(x, y);
+}
+
+void FbWinFrame::resize(unsigned int width, unsigned int height) {
+    // update unshaded size if  we're in shaded state and just resize width
+    if (m_shaded) {
+        m_width_before_shade = width;
+        m_height_before_shade = height;
+        m_window.resize(width, m_window.height());
+    } else {
+        m_window.resize(width, height);
+    }
+
+    reconfigure();
+}
+
+void FbWinFrame::resizeForClient(unsigned int width, unsigned int height) {
+    // total height for frame without client
+    unsigned int total_height = m_handle.height() + m_titlebar.height();
+    // resize frame height with total height + specified height
+    resize(width, total_height + height);
+}
+
+void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int height) {
+    move(x, y);
+    resize(width, height);
+}
+
+void FbWinFrame::setTitle(const std::string &titletext) {
+    m_titletext = titletext;
+    redrawTitle();
+}
+
+void FbWinFrame::setFocus(bool newvalue) {
+    if (m_focused == newvalue) // no need to change focus
+        return;
+
+    m_focused = newvalue;
+    reconfigure(); // reconfigure rendering for new focus value
+}
+
+void FbWinFrame::setBevel(int bevel) {
+    m_bevel = bevel;
+    reconfigure();
+}
+
+void FbWinFrame::addLeftButton(FbTk::Button *btn) {
+    if (btn == 0) // valid button?
+        return;
+
+    setupButton(*btn); // setup theme and other stuff
+
+    m_buttons_left.push_back(btn);
+    reconfigureTitlebar();
+}
+
+void FbWinFrame::addRightButton(FbTk::Button *btn) {
+    if (btn == 0) // valid button?
+        return;
+
+    setupButton(*btn); // setup theme and other stuff
+
+    m_buttons_right.push_back(btn);
+    reconfigureTitlebar();
+}
+
+void FbWinFrame::removeAllButtons() {
+    // destroy left side
+    while (!m_buttons_left.empty()) {
+        delete m_buttons_left.back();
+        m_buttons_left.pop_back();
+    }
+    // destroy right side
+    while (!m_buttons_right.empty()) {
+        delete m_buttons_right.back();
+        m_buttons_right.pop_back();
+    }
+
+    // update titlebar
+    reconfigureTitlebar();
+}
+
+void FbWinFrame::setClientWindow(Window win) {
+    m_clientwin = win;
+    Display *display = FbTk::App::instance()->display();
+    XSetWindowBorderWidth(display, win, 0);
+
+    XChangeSaveSet(display, win, SetModeInsert);
+    XSetWindowAttributes attrib_set;
+    // no events for client window while we reparent it
+    XSelectInput(display, m_clientarea.window(), NoEventMask);
+    XReparentWindow(display, win, m_clientarea.window(), 0, 0);
+    XSelectInput(display, m_clientarea.window(), SubstructureRedirectMask);
+
+    XFlush(display);
+
+    attrib_set.event_mask = PropertyChangeMask | StructureNotifyMask | FocusChangeMask;
+    attrib_set.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask;
+
+    XChangeWindowAttributes(display, win, CWEventMask|CWDontPropagate, &attrib_set);
+
+    m_clientarea.raise();
+    m_clientarea.showSubwindows();
+
+}
+
+void FbWinFrame::removeClient() {
+    m_clientwin = 0;
+}
+
+void FbWinFrame::hideTitlebar() {
+    m_titlebar.hide();
+}
+
+void FbWinFrame::showTitlebar() {
+    m_titlebar.show();
+}
+
+void FbWinFrame::hideHandle() {
+    m_handle.hide();
+}
+
+void FbWinFrame::showHandle() {
+    m_handle.show();
+}
+
+/**
+   Set new event handler for the frame's windows
+*/
+void FbWinFrame::setEventHandler(FbTk::EventHandler &evh) {
+
+    FbTk::EventManager &evm = *FbTk::EventManager::instance();
+    evm.add(evh, m_label);
+    evm.add(evh, m_titlebar);
+    evm.add(evh, m_handle);
+    evm.add(evh, m_grip_right);
+    evm.add(evh, m_grip_left);
+    evm.add(evh, m_window);
+    evm.add(evh, m_clientarea);
+}
+
+/**
+   remove event handler from windows
+*/
+void FbWinFrame::removeEventHandler() {
+    FbTk::EventManager &evm = *FbTk::EventManager::instance();
+    evm.remove(m_label);
+    evm.remove(m_titlebar);
+    evm.remove(m_handle);
+    evm.remove(m_grip_right);
+    evm.remove(m_grip_left);
+    evm.remove(m_window);
+    evm.remove(m_clientarea);
+}
+
+void FbWinFrame::buttonPressEvent(XButtonEvent &event) {
+    m_window.raise();
+}
+
+void FbWinFrame::exposeEvent(XExposeEvent &event) {
+    if (m_titlebar == event.window)
+        redrawTitlebar();
+    else if (m_label == event.window) 
+        redrawTitle();
+}
+
+void FbWinFrame::handleEvent(XEvent &event) {
+    if (event.type == ConfigureNotify)
+        configureNotifyEvent(event.xconfigure);
+}
+
+void FbWinFrame::configureNotifyEvent(XConfigureEvent &event) {
+    resize(event.width, event.height);
+}
+
+void FbWinFrame::reconfigure() {
+    m_window.clear();
+	
+    // align titlebar and render it
+    reconfigureTitlebar();
+
+    m_clientarea.moveResize(0, m_titlebar.height() + 2*m_titlebar.borderWidth(),
+                            m_window.width(), 
+                            m_window.height() - m_titlebar.height() - m_handle.height());
+
+    if (m_clientwin != 0) {
+        XMoveResizeWindow(FbTk::App::instance()->display(), m_clientwin,
+                          0, 0,
+                          m_clientarea.width(), m_clientarea.height());
+    }
+
+    // align handle and grips
+    const int grip_height = m_handle.height();
+    const int grip_width = 20; //TODO
+    
+    const int ypos = m_window.height() - grip_height;
+
+    m_grip_left.moveResize(0, ypos,
+                           grip_width, grip_height);
+
+    m_handle.moveResize(grip_width, ypos,
+                        m_window.width() - grip_width*2, grip_height);
+   
+    m_grip_right.moveResize(m_window.width() - grip_width, ypos,
+                            grip_width, grip_height);
+
+    
+    // render the theme
+    renderButtons();
+    renderHandles();
+
+}
+
+unsigned int FbWinFrame::titleHeight() const {
+    return m_theme.font().height();
+}
+
+unsigned int FbWinFrame::buttonHeight() const {
+    return m_titlebar.height() - m_bevel*2;
+}
+
+
+//--------------------- private area
+
+/**
+   aligns and redraws title
+*/
+void FbWinFrame::redrawTitle() {
+    GC gc = m_theme.labelTextFocusGC();
+    m_label.clear(); // clear window
+    unsigned int textlen = m_titletext.size();
+    const FbTk::Font &font = m_theme.font();
+    // do text alignment
+    int align_x = FbTk::doAlignment(m_label.width(),
+                                    m_bevel,
+                                    m_theme.justify(),
+                                    font,
+                                    m_titletext.c_str(), m_titletext.size(),
+                                    textlen // return new text len
+                                    );
+
+    font.drawText(m_label.window(), // drawable
+                  m_window.screenNumber(),
+                  gc, // graphic context
+                  m_titletext.c_str(), textlen, // string and string size
+                  align_x, font.ascent());// position
+}
+
+void FbWinFrame::redrawTitlebar() {
+    m_titlebar.clear();
+    m_label.clear();
+    redrawTitle();
+}
+
+/**
+   Align buttons with title text window
+*/
+void FbWinFrame::reconfigureTitlebar() {
+    // resize titlebar to window size with font height
+    m_titlebar.resize(m_window.width() - m_titlebar.borderWidth(), m_theme.font().height() == 0 ? 
+                      16 : m_theme.font().height() + m_bevel*2 + 2);
+
+    // draw left buttons first
+    unsigned int next_x = m_bevel; 
+    unsigned int button_size = buttonHeight();
+    m_button_size = button_size;
+    for (size_t i=0; i < m_buttons_left.size(); i++, next_x += button_size + m_bevel) {
+        m_buttons_left[i]->moveResize(next_x, m_bevel, 
+                                      button_size, button_size);
+    }
+	
+    next_x += m_bevel;
+	
+    // space left on titlebar between left and right buttons
+    unsigned int space_left = m_titlebar.width() - next_x;
+    if (m_buttons_right.size() != 0)
+        space_left -= (m_buttons_right.size() + 1)*button_size;
+    space_left -= m_bevel;
+	
+    m_label.moveResize(
+                       next_x, m_bevel,
+                       space_left, button_size);
+
+    next_x += m_label.width() + m_bevel;;
+
+    // finaly set new buttons to the right
+    for (size_t i=0; i < m_buttons_right.size(); 
+         ++i, next_x += button_size + m_bevel) {
+        m_buttons_right[i]->moveResize(next_x, m_bevel,
+                                       button_size, button_size);
+    }
+
+    renderTitlebar();
+    m_titlebar.raise(); // always on top
+}
+
+void FbWinFrame::renderTitlebar() {
+    if (!m_use_titlebar)
+        return;
+
+    // render pixmaps
+
+    render(m_theme.titleFocusTexture(), m_title_focused_color, 
+           m_title_focused_pm,
+           m_titlebar.width(), m_titlebar.height());
+
+    render(m_theme.titleUnfocusTexture(), m_title_unfocused_color, 
+           m_title_unfocused_pm,
+           m_titlebar.width(), m_titlebar.height());
+
+
+    render(m_theme.labelFocusTexture(), m_label_focused_color, 
+           m_label_focused_pm,
+           m_label.width(), m_label.height());
+		
+    render(m_theme.labelUnfocusTexture(), m_label_unfocused_color, 
+           m_label_unfocused_pm,
+           m_label.width(), m_label.height());
+
+    // finaly set up pixmaps for titlebar windows
+
+    if (m_focused) {
+        if (m_label_focused_pm != 0)
+            m_label.setBackgroundPixmap(m_label_focused_pm);
+        else
+            m_label.setBackgroundColor(m_label_focused_color);
+			
+        if (m_title_focused_pm != 0)
+            m_titlebar.setBackgroundPixmap(m_title_focused_pm);
+        else
+            m_titlebar.setBackgroundColor(m_title_focused_color);
+			
+    } else {
+        if (m_label_unfocused_pm != 0)
+            m_label.setBackgroundPixmap(m_label_unfocused_pm);
+        else
+            m_label.setBackgroundColor(m_label_unfocused_color);
+			
+        if (m_title_unfocused_pm != 0)
+            m_titlebar.setBackgroundPixmap(m_title_unfocused_pm);
+        else
+            m_titlebar.setBackgroundColor(m_title_unfocused_color);
+
+    }
+
+    redrawTitle();
+}
+
+
+void FbWinFrame::renderHandles() {
+    if (!m_use_handles)
+        return;
+    render(m_theme.handleFocusTexture(), m_handle_focused_color, 
+           m_handle_focused_pm,
+           m_handle.width(), m_handle.height());
+	
+    render(m_theme.handleUnfocusTexture(), m_handle_unfocused_color, 
+           m_handle_unfocused_pm,
+           m_handle.width(), m_handle.height());
+
+    if (m_focused) {
+        if (m_handle_focused_pm) {
+            m_handle.setBackgroundPixmap(m_handle_focused_pm);
+        } else {
+            m_handle.setBackgroundColor(m_handle_focused_color);
+        }                
+    } else {
+        if (m_handle_unfocused_pm) {
+            m_handle.setBackgroundPixmap(m_handle_unfocused_pm);
+        } else {
+            m_handle.setBackgroundColor(m_handle_unfocused_color);
+        }                
+    }
+
+    render(m_theme.gripFocusTexture(), m_grip_focused_color, m_grip_focused_pm,
+           m_grip_left.width(), m_grip_left.height());
+
+    render(m_theme.gripUnfocusTexture(), m_grip_unfocused_color, 
+           m_grip_unfocused_pm,
+           m_grip_left.width(), m_grip_left.height());
+
+    if (m_focused) {
+        if (m_grip_focused_pm) {
+            m_grip_left.setBackgroundPixmap(m_grip_focused_pm);
+            m_grip_right.setBackgroundPixmap(m_grip_focused_pm);
+        } else {
+            m_grip_left.setBackgroundColor(m_grip_focused_color);
+            m_grip_right.setBackgroundColor(m_grip_focused_color);
+        }                
+    } else {
+        if (m_grip_unfocused_pm) {
+            m_grip_left.setBackgroundPixmap(m_grip_unfocused_pm);
+            m_grip_right.setBackgroundPixmap(m_grip_unfocused_pm);
+        } else {
+            m_grip_left.setBackgroundColor(m_grip_unfocused_color);
+            m_grip_right.setBackgroundColor(m_grip_unfocused_color);
+        }                
+    }
+    /*
+      TODO: set border color
+    */
+    m_grip_left.clear();
+    m_grip_right.clear();
+    m_handle.clear();
+}
+
+void FbWinFrame::renderButtons() {
+
+    render(m_theme.buttonFocusTexture(), m_button_color, m_button_pm,
+           m_button_size, m_button_size);
+		
+    render(m_theme.buttonUnfocusTexture(), m_button_unfocused_color, 
+           m_button_unfocused_pm,
+           m_button_size, m_button_size);
+		
+    render(m_theme.buttonPressedTexture(), m_button_pressed_color, 
+           m_button_pressed_pm,
+           m_button_size, m_button_size);
+
+    // setup left and right buttons
+    for (size_t i=0; i < m_buttons_left.size(); ++i)
+        setupButton(*m_buttons_left[i]);
+
+    for (size_t i=0; i < m_buttons_right.size(); ++i)
+        setupButton(*m_buttons_right[i]);
+
+}
+
+void FbWinFrame::init() {
+    // clear pixmaps
+    m_title_focused_pm = m_title_unfocused_pm = 0;
+    m_label_focused_pm = m_label_unfocused_pm = 0;
+    m_button_unfocused_pm = m_button_pressed_pm = 0;
+    
+    m_button_pm = 0;
+    m_button_size = 26;
+    m_handle_focused_pm = 
+        m_handle_unfocused_pm = 0;
+    m_grip_unfocused_pm = m_grip_focused_pm = 0;
+
+    m_shaded = false;
+
+    m_label.show();
+    m_titlebar.show();
+    m_handle.show();
+    m_grip_right.show();
+    m_grip_left.show();
+    // note: we don't show clientarea yet
+
+    setEventHandler(*this);
+
+    reconfigureTitlebar();
+    reconfigure();
+}
+
+/**
+   Setups upp background, pressed pixmap/color of the button to current theme
+*/
+void FbWinFrame::setupButton(FbTk::Button &btn) {
+    if (m_button_pressed_pm) {
+        btn.setPressedPixmap(m_button_pressed_pm);
+    } else {
+        //        cerr<<"No pixmap for button pressed"<<endl;
+    }
+    //TODO button pressed color
+
+    if (m_focused) {
+        if (m_button_pm)
+            btn.setBackgroundPixmap(m_button_pm);
+        else
+            btn.setBackgroundColor(m_button_color);
+    } else {
+        if (m_button_unfocused_pm)
+            btn.setBackgroundPixmap(m_button_unfocused_pm);
+        else
+            btn.setBackgroundColor(m_button_color);
+    }
+    btn.clear();
+}
+
+void FbWinFrame::render(const FbTk::Texture &tex, FbTk::Color &col, Pixmap &pm,
+                        unsigned int w, unsigned int h) {
+    Pixmap tmp = pm;
+    if (tex.type() == (FbTk::Texture::FLAT | FbTk::Texture::SOLID)) {
+        pm = None;
+        col = tex.color();
+    } else
+        pm = m_imagectrl.renderImage(w, h, tex);
+		
+    if (tmp) 
+        m_imagectrl.removeImage(tmp);
+
+}
diff --git a/src/FbWinFrame.hh b/src/FbWinFrame.hh
new file mode 100644
index 0000000..c74b73c
--- /dev/null
+++ b/src/FbWinFrame.hh
@@ -0,0 +1,221 @@
+// FbWinFrame.hh for Fluxbox Window Manager
+// Copyright (c) 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+// $Id: FbWinFrame.hh,v 1.1 2003/01/05 22:14:10 fluxgen Exp $
+
+#ifndef FBWINFRAME_HH
+#define FBWINFRAME_HH
+
+#include "FbWindow.hh"
+#include "Button.hh"
+#include "EventHandler.hh"
+#include "Font.hh"
+#include "Text.hh"
+#include "FbWinFrameTheme.hh"
+
+#include <vector>
+#include <string>
+
+class FbWinFrameTheme;
+class BImageControl;
+
+/// holds a window frame with a client window
+class FbWinFrame:public FbTk::EventHandler {
+public:
+
+    /// create a top level window
+    FbWinFrame(FbWinFrameTheme &theme, BImageControl &imgctrl, int screen_num, int x, int y,
+               unsigned int width, unsigned int height);
+
+    /// create a frame window inside another FbWindow, NOT IMPLEMENTED!
+    FbWinFrame(FbWinFrameTheme &theme, BImageControl &imgctrl, const FbTk::FbWindow &parent,
+               int x, int y, 
+               unsigned int width, unsigned int height);
+
+    /// destroy frame
+    ~FbWinFrame();
+
+    void hide();
+    void show();
+    /// shade frame (ie resize to titlebar size)
+    void shade();
+    void move(int x, int y);
+    void resize(unsigned int width, unsigned int height);
+    /// resize client to specified size and resize frame to it
+    void resizeForClient(unsigned int width, unsigned int height);
+    void moveResize(int x, int y, unsigned int width, unsigned int height);
+    /// sets title on the titlebar label
+    void setTitle(const std::string &title);
+    /// set focus/unfocus style
+    void setFocus(bool newvalue);
+    void setBevel(int bevel);
+    /// add a button to the left of the label
+    void addLeftButton(FbTk::Button *btn);
+    /// add a button to the right of the label
+    void addRightButton(FbTk::Button *btn);
+    /// remove all buttons from titlebar
+    void removeAllButtons();
+    /// attach a client window for client area
+    void setClientWindow(Window win);
+    /// same as above but with FbWindow, NOT IMPLEMENTED!
+    void setClientWindow(FbTk::FbWindow win);
+    /// remove attached client window
+    void removeClient();
+    /// redirect events to another eventhandler
+    void setEventHandler(FbTk::EventHandler &evh);
+    /// remove any handler for the windows
+    void removeEventHandler();
+    
+    void hideTitlebar();
+    void showTitlebar();
+    void hideHandle();
+    void showHandle();
+
+    /**
+       @name Event handlers
+    */
+    //@{
+    void buttonPressEvent(XButtonEvent &event);
+    void exposeEvent(XExposeEvent &event);
+    void configureNotifyEvent(XConfigureEvent &event);
+    void handleEvent(XEvent &event);
+    //@}
+ 
+    void reconfigure();
+
+    /**
+       @name accessors
+    */
+    //@{
+    inline int x() const { return m_window.x(); }
+    inline int y() const { return m_window.y(); }
+    inline unsigned int width() const { return m_window.width(); }
+    inline unsigned int height() const { return m_window.height(); }
+    inline const FbTk::FbWindow &window() const { return m_window; }
+    inline FbTk::FbWindow &window() { return m_window; }
+    /// @return titlebar window
+    inline const FbTk::FbWindow &titlebar() const { return m_titlebar; }
+    inline FbTk::FbWindow &titlebar() { return m_titlebar; }
+    inline const FbTk::FbWindow &label() const { return m_label; }
+    inline FbTk::FbWindow &label() { return m_label; }
+    /// @return clientarea window
+    inline const FbTk::FbWindow &clientArea() const { return m_clientarea; }
+    inline FbTk::FbWindow &clientArea() { return m_clientarea; }
+    /// @return handle window
+    inline const FbTk::FbWindow &handle() const { return m_handle; }
+    inline FbTk::FbWindow &handle() { return m_handle; }
+    inline const FbTk::FbWindow &gripLeft() const { return m_grip_left; }
+    inline FbTk::FbWindow &gripLeft() { return m_grip_left; }
+    inline const FbTk::FbWindow &gripRight() const { return m_grip_right; }
+    inline FbTk::FbWindow &gripRight() { return m_grip_right; }
+    inline bool focused() const { return m_focused; }
+    inline bool isShaded() const { return m_shaded; }
+    unsigned int titleHeight() const;
+    unsigned int buttonHeight() const;
+
+    //@}
+
+private:
+    void redrawTitle();
+    void redrawTitlebar();
+    /// reposition titlebar items
+    void reconfigureTitlebar();
+    /**
+       @name render helper functions
+    */
+    //@{
+    void renderTitlebar();
+    void renderHandles();
+    void renderButtons();
+    void renderLabel();
+    /// renders to pixmap or sets color
+    void render(const FbTk::Texture &tex, FbTk::Color &col, Pixmap &pm,
+                unsigned int width, unsigned int height);
+    //@}
+
+    /// initiate some commont variables
+    void init();
+    /// initiate inserted buttons for current theme
+    void setupButton(FbTk::Button &btn);
+
+    FbWinFrameTheme &m_theme; ///< theme to be used 
+    BImageControl &m_imagectrl; ///< Image control for rendering
+    /**
+       @name windows
+    */
+    //@{
+    FbTk::FbWindow m_window; ///< base window that holds each decorations (ie titlebar, handles)
+    FbTk::FbWindow m_titlebar; ///<  titlebar window
+    FbTk::FbWindow m_label; ///< holds title
+    FbTk::FbWindow m_grip_right,  ///< rightgrip
+        m_grip_left; ///< left grip
+    FbTk::FbWindow m_handle; ///< handle between grips
+    FbTk::FbWindow m_clientarea; ///< window that holds client window @see setClientWindow
+    Window m_clientwin; ///< client window in clientarea
+    //@}
+    typedef std::vector<FbTk::Button *> ButtonList;
+    ButtonList m_buttons_left, ///< buttons to the left
+        m_buttons_right; ///< buttons to the right
+    
+    std::string m_titletext; ///< text to be displayed int m_label
+    int m_bevel;  ///< bevel between titlebar items and titlebar
+    bool m_use_titlebar; ///< if we should use titlebar
+    bool m_use_handles; ///< if we should use handles
+    bool m_focused; ///< focused/unfocused mode
+    /**
+       @name pixmaps and colors for rendering
+    */
+    //@{
+    Pixmap m_title_focused_pm; ///< pixmap for focused title
+    FbTk::Color m_title_focused_color; ///< color for focused title
+    Pixmap m_title_unfocused_pm; ///< pixmap for unfocused title
+    FbTk::Color m_title_unfocused_color; ///< color for unfocued title
+
+    Pixmap m_label_focused_pm; ///< pixmap for focused label
+    FbTk::Color m_label_focused_color; ///< color for focused label
+    Pixmap m_label_unfocused_pm; ///< pixmap for unfocused label
+    FbTk::Color m_label_unfocused_color; ///< color for unfocued label
+    
+    FbTk::Color m_handle_focused_color, m_handle_unfocused_color;
+    Pixmap m_handle_focused_pm, m_handle_unfocused_pm;
+    
+
+    Pixmap m_button_pm;  ///< normal button     
+    FbTk::Color m_button_color; ///< normal color button
+    Pixmap m_button_unfocused_pm; ///< unfocused button
+    FbTk::Color m_button_unfocused_color; ///< unfocused color button
+    Pixmap m_button_pressed_pm; ///< pressed button
+    FbTk::Color m_button_pressed_color; ///< pressed button color
+
+    Pixmap m_grip_focused_pm;
+    FbTk::Color m_grip_focused_color; ///< if no pixmap is given for grip, use this color
+    Pixmap m_grip_unfocused_pm; ///< unfocused pixmap for grip
+    FbTk::Color m_grip_unfocused_color; ///< unfocused color for grip if no pixmap is given
+    //@}
+
+    int m_button_size; ///< size for all titlebar buttons
+    unsigned int m_width_before_shade,  ///< width before shade, so we can restore it when we unshade
+        m_height_before_shade; ///< height before shade, so we can restore it when we unshade
+    bool m_shaded; ///< wheter we're shaded or not
+
+};
+
+#endif // FBWINFRAME_HH
diff --git a/src/FbWinFrameTheme.cc b/src/FbWinFrameTheme.cc
new file mode 100644
index 0000000..8fc562f
--- /dev/null
+++ b/src/FbWinFrameTheme.cc
@@ -0,0 +1,85 @@
+// FbWinFrameTheme.cc for Fluxbox Window Manager
+// Copyright (c) 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+// $Id: FbWinFrameTheme.cc,v 1.1 2003/01/05 22:14:10 fluxgen Exp $
+
+#include "FbWinFrameTheme.hh"
+#include "App.hh"
+
+#include <iostream>
+
+FbWinFrameTheme::FbWinFrameTheme(int screen_num): 
+    FbTk::Theme(screen_num),
+    m_label_focus(*this, "window.label.focus", "Window.Label.Focus"),
+    m_label_unfocus(*this, "window.label.unfocus", "Window.Label.Unfocus"),
+
+    m_title_focus(*this, "window.title.focus", "Window.Title.Focus"),
+    m_title_unfocus(*this, "window.title.unfocus", "Window.Title.Unfocus"),
+
+    m_handle_focus(*this, "window.handle.focus", "Window.Handle.Focus"),
+    m_handle_unfocus(*this, "window.handle.unfocus", "Window.Handle.Unfocus"),
+
+    m_button_focus(*this, "window.button.focus", "Window.Button.Focus"),
+    m_button_unfocus(*this, "window.button.unfocus", "Window.Button.Unfocus"),
+    m_button_pressed(*this, "window.button.pressed", "Window.Button.Pressed"),
+    
+    m_grip_focus(*this, "window.grip.focus", "Window.Grip.Focus"),
+    m_grip_unfocus(*this, "window.grip.unfocus", "Window.Grip.Unfocus"),
+  
+    m_label_focus_color(*this, "window.label.focus.textColor", "Window.Label.Focus.TextColor"),
+    m_label_unfocus_color(*this, "window.label.unfocus.textColor", "Window.Label.Unfocus.TextColor"),
+    
+    m_frame_focus_color(*this, "window.frame.focusColor", "Window.Frame.FocusColor"), 
+    m_frame_unfocus_color(*this, "window.frame.unfocusColor", "Window.Frame.UnfocusColor"),
+
+    m_button_focus_color(*this, "window.button.focus.picColor", "Window.Button.Focus.PicColor"),
+    m_button_unfocus_color(*this, "window.button.unfocus.picColor", "Window.Button.Unfocus.PicColor"),
+
+    m_font(*this, "window.font", "Window.Font"),
+    m_textjustify(*this, "window.justify", "Window.Justify") {
+    // create GCs
+    Display *disp = FbTk::App::instance()->display();
+    Window rootwin = RootWindow(disp, screen_num);
+    m_label_text_focus_gc = XCreateGC(disp, rootwin, 0, 0);
+    m_label_text_unfocus_gc = XCreateGC(disp, rootwin, 0, 0);
+
+}
+
+FbWinFrameTheme::~FbWinFrameTheme() {
+    // destroy GCs
+    Display *disp = FbTk::App::instance()->display();
+    XFreeGC(disp, m_label_text_focus_gc);
+    XFreeGC(disp, m_label_text_unfocus_gc);
+}
+
+void FbWinFrameTheme::reconfigTheme() {
+
+    XGCValues gcv;
+    unsigned long gc_value_mask = GCForeground;
+    Display *disp = FbTk::App::instance()->display();
+
+    gcv.foreground = m_label_focus_color->pixel();
+    XChangeGC(disp, m_label_text_focus_gc, gc_value_mask, &gcv);
+
+    gcv.foreground = m_label_unfocus_color->pixel();
+    XChangeGC(disp, m_label_text_unfocus_gc, gc_value_mask, &gcv);
+}
+
diff --git a/src/FbWinFrameTheme.hh b/src/FbWinFrameTheme.hh
new file mode 100644
index 0000000..4c702c4
--- /dev/null
+++ b/src/FbWinFrameTheme.hh
@@ -0,0 +1,98 @@
+// FbWinFrameTheme.hh for Fluxbox Window Manager
+// Copyright (c) 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+// $Id: FbWinFrameTheme.hh,v 1.1 2003/01/05 22:14:10 fluxgen Exp $
+
+#ifndef FBWINFRAMETHEME_HH
+#define FBWINFRAMETHEME_HH
+
+#include "Font.hh"
+#include "Texture.hh"
+#include "Text.hh"
+#include "Color.hh"
+#include "FbTk/Theme.hh"
+
+class FbWinFrameTheme: public FbTk::Theme {
+public:
+    FbWinFrameTheme(int screen_num);
+    ~FbWinFrameTheme();
+
+    /**
+       @name textures
+    */
+    //@{
+    const FbTk::Texture &labelFocusTexture() const { return *m_label_focus; }
+    const FbTk::Texture &labelUnfocusTexture() const { return *m_label_unfocus; }
+
+    const FbTk::Texture &titleFocusTexture() const { return *m_title_focus; }
+    const FbTk::Texture &titleUnfocusTexture() const { return *m_title_unfocus; }
+
+    const FbTk::Texture &handleFocusTexture() const { return *m_handle_focus; }
+    const FbTk::Texture &handleUnfocusTexture() const { return *m_handle_unfocus; }
+
+    const FbTk::Texture &buttonFocusTexture() const { return *m_button_focus; }
+    const FbTk::Texture &buttonUnfocusTexture() const { return *m_button_unfocus; }
+    const FbTk::Texture &buttonPressedTexture() const { return *m_button_pressed; }    
+
+    const FbTk::Texture &gripFocusTexture() const { return *m_grip_focus; }
+    const FbTk::Texture &gripUnfocusTexture() const { return *m_grip_unfocus; }
+    //@}
+
+    /**
+       @name colors
+    */
+    //@{
+    const FbTk::Color &labelFocusColor() const { return *m_label_focus_color; }
+    const FbTk::Color &labelUnfocusColor() const { return *m_label_unfocus_color; }
+    const FbTk::Color &frameFocuscolor() const { return *m_frame_focus_color; }
+    const FbTk::Color &frameUnfocuscolor() const { return *m_frame_unfocus_color; }
+    const FbTk::Color &buttonFocuscolor() const { return *m_button_focus_color; }
+    const FbTk::Color &buttonUnfocuscolor() const { return *m_button_unfocus_color; }
+    //@}
+    const FbTk::Font &font() const {  return *m_font; }
+    FbTk::Font &font() { return *m_font; }
+
+    FbTk::Justify justify() const { return *m_textjustify; }
+
+    GC labelTextFocusGC() const { return m_label_text_focus_gc; }
+    GC labelTextUnfocusGC() const { return m_label_text_unfocus_gc; }
+
+    void reconfigTheme();
+private:
+    FbTk::ThemeItem<FbTk::Texture> m_label_focus, m_label_unfocus;
+    FbTk::ThemeItem<FbTk::Texture> m_title_focus, m_title_unfocus;
+    FbTk::ThemeItem<FbTk::Texture> m_handle_focus, m_handle_unfocus;
+    FbTk::ThemeItem<FbTk::Texture> m_button_focus, m_button_unfocus, m_button_pressed;
+    FbTk::ThemeItem<FbTk::Texture> m_grip_focus, m_grip_unfocus;
+
+    FbTk::ThemeItem<FbTk::Color> m_label_focus_color, m_label_unfocus_color;
+    FbTk::ThemeItem<FbTk::Color> m_frame_focus_color, m_frame_unfocus_color;
+    FbTk::ThemeItem<FbTk::Color> m_button_focus_color, m_button_unfocus_color;
+    
+    FbTk::ThemeItem<FbTk::Font> m_font;
+    FbTk::ThemeItem<FbTk::Justify> m_textjustify;
+
+    GC m_label_text_focus_gc, m_label_text_unfocus_gc;
+};
+
+#endif // FBWINFRAMETHEME_HH
+
+
-- 
cgit v0.11.2