00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "IconButton.hh"
00026
00027
00028 #include "fluxbox.hh"
00029 #include "Screen.hh"
00030 #include "Window.hh"
00031 #include "WinClient.hh"
00032
00033 #include "FbTk/SimpleCommand.hh"
00034 #include "FbTk/App.hh"
00035 #include "FbTk/EventManager.hh"
00036 #include "FbTk/MacroCommand.hh"
00037 #include "FbTk/Command.hh"
00038 #include "FbTk/RefCount.hh"
00039
00040
00041 #ifdef HAVE_CONFIG_H
00042 #include "config.h"
00043 #endif // HAVE_CONFIG_H
00044
00045 #include <X11/Xutil.h>
00046 #ifdef SHAPE
00047 #include <X11/extensions/shape.h>
00048 #endif // SHAPE
00049
00050 namespace {
00051
00052 class ShowMenu: public FbTk::Command {
00053 public:
00054 explicit ShowMenu(FluxboxWindow &win):m_win(win) { }
00055 void execute() {
00056 m_win.screen().hideMenus();
00057
00058 const XEvent &event = Fluxbox::instance()->lastEvent();
00059 int x = event.xbutton.x_root - (m_win.menu().width() / 2);
00060 int y = event.xbutton.y_root - (m_win.menu().height() / 2);
00061
00062 m_win.showMenu(x, y);
00063 }
00064 private:
00065 FluxboxWindow &m_win;
00066 };
00067
00068 }
00069
00070 IconButton::IconButton(const FbTk::FbWindow &parent, const FbTk::Font &font,
00071 FluxboxWindow &win):
00072 FbTk::TextButton(parent, font, win.winClient().title()),
00073 m_win(win),
00074 m_icon_window(*this, 1, 1, 1, 1,
00075 ExposureMask | ButtonPressMask | ButtonReleaseMask),
00076 m_use_pixmap(true) {
00077
00078 FbTk::RefCount<FbTk::Command> focus(new FbTk::SimpleCommand<FluxboxWindow>(m_win, &FluxboxWindow::raiseAndFocus));
00079 FbTk::RefCount<FbTk::Command> hidemenus(new FbTk::SimpleCommand<BScreen>(win.screen(), &BScreen::hideMenus));
00081
00082
00083
00084
00085
00086 FbTk::RefCount<FbTk::Command> focus_cmd(focus);
00087 FbTk::RefCount<FbTk::Command> menu_cmd(new ::ShowMenu(m_win));
00088 setOnClick(focus_cmd, 1);
00089 setOnClick(menu_cmd, 3);
00090 m_win.hintSig().attach(this);
00091
00092 FbTk::EventManager::instance()->add(*this, m_icon_window);
00093
00094 update(0);
00095 }
00096
00097 IconButton::~IconButton() {
00098
00099 }
00100
00101
00102 void IconButton::exposeEvent(XExposeEvent &event) {
00103 if (m_icon_window == event.window)
00104 m_icon_window.clear();
00105 else
00106 FbTk::TextButton::exposeEvent(event);
00107 }
00108 void IconButton::moveResize(int x, int y,
00109 unsigned int width, unsigned int height) {
00110
00111 FbTk::TextButton::moveResize(x, y, width, height);
00112
00113 if (m_icon_window.width() != FbTk::Button::width() ||
00114 m_icon_window.height() != FbTk::Button::height())
00115 update(0);
00116 }
00117
00118 void IconButton::resize(unsigned int width, unsigned int height) {
00119 FbTk::TextButton::resize(width, height);
00120 if (m_icon_window.width() != FbTk::Button::width() ||
00121 m_icon_window.height() != FbTk::Button::height())
00122 update(0);
00123 }
00124
00125 void IconButton::clear() {
00126 setupWindow();
00127 }
00128
00129 void IconButton::clearArea(int x, int y,
00130 unsigned int width, unsigned int height,
00131 bool exposure) {
00132 FbTk::TextButton::clearArea(x, y,
00133 width, height, exposure);
00134 }
00135
00136 void IconButton::setPixmap(bool use) {
00137 if (m_use_pixmap != use) {
00138 m_use_pixmap = use;
00139 update(0);
00140 }
00141 }
00142
00143 void IconButton::update(FbTk::Subject *subj) {
00144
00145
00146
00147
00148
00149 if (m_win.clientList().size() == 0)
00150 return;
00151
00152 XWMHints *hints = XGetWMHints(FbTk::App::instance()->display(), m_win.winClient().window());
00153 if (hints == 0)
00154 return;
00155
00156 if (m_use_pixmap && (hints->flags & IconPixmapHint) && hints->icon_pixmap != 0) {
00157
00158 m_icon_window.show();
00159 int new_height = height() - 2*m_icon_window.y();
00160 int new_width = new_height;
00161 m_icon_window.resize((new_width>0) ? new_width : 1, (new_height>0) ? new_height : 1);
00162
00163 m_icon_pixmap.copy(hints->icon_pixmap);
00164 m_icon_pixmap.scale(m_icon_window.width(), m_icon_window.height());
00165
00166 m_icon_window.setBackgroundPixmap(m_icon_pixmap.drawable());
00167 } else {
00168
00169 m_icon_window.move(0, 0);
00170 m_icon_window.hide();
00171 m_icon_pixmap = 0;
00172 }
00173
00174 if(m_use_pixmap && (hints->flags & IconMaskHint)) {
00175 m_icon_mask.copy(hints->icon_mask);
00176 m_icon_mask.scale(m_icon_pixmap.width(), m_icon_pixmap.height());
00177 } else
00178 m_icon_mask = 0;
00179
00180 XFree(hints);
00181 hints = 0;
00182
00183 #ifdef SHAPE
00184
00185 if (m_icon_mask.drawable() != 0) {
00186 XShapeCombineMask(FbTk::App::instance()->display(),
00187 m_icon_window.drawable(),
00188 ShapeBounding,
00189 0, 0,
00190 m_icon_mask.drawable(),
00191 ShapeSet);
00192 }
00193
00194 #endif // SHAPE
00195
00196 setupWindow();
00197 }
00198
00199 void IconButton::setupWindow() {
00200
00201 m_icon_window.clear();
00202
00203 if (!m_win.clientList().empty()) {
00204 setText(m_win.winClient().title());
00205
00206 }
00207 FbTk::TextButton::clear();
00208 }
00209
00210 void IconButton::drawText(int x, int y) {
00211
00212 if (m_icon_pixmap.drawable() != 0)
00213 FbTk::TextButton::drawText(m_icon_window.x() + m_icon_window.width() + 1, y);
00214 else
00215 FbTk::TextButton::drawText(1, y);
00216 }
00217
00218