all repos — fluxbox @ 4a3be045b28edac4953be9f195640654f8b5a1a1

custom fork of the fluxbox windowmanager

add tooltips for iconbar buttons when title is too long to fit
Matteo Galiazzo matteo@maltesenarrazioni.it
commit

4a3be045b28edac4953be9f195640654f8b5a1a1

parent

ba604ac821b7c1c89d10b0e8c9f85fde948856ef

M ChangeLogChangeLog

@@ -1,5 +1,8 @@

(Format: Year/Month/Day) Changes for 1.0.1: +*08/05/05: + * Add tooltips for iconbar buttons (thanks Matteo Galiazzo) + TooltipWindow.cc/hh *08/05/02: * Minor changes for fluxbox-generate_menu (thanks skiidoo) util/fluxbox-generate_menu.in
M src/FbTk/Button.ccsrc/FbTk/Button.cc

@@ -30,7 +30,8 @@

Button::Button(int screen_num, int x, int y, unsigned int width, unsigned int height): FbWindow(screen_num, x, y, width, height, - ExposureMask | ButtonPressMask | ButtonReleaseMask), + ExposureMask | ButtonPressMask | EnterWindowMask | + LeaveWindowMask | ButtonReleaseMask), m_background_pm(0), m_pressed_pm(0), m_pressed_color(),

@@ -45,7 +46,8 @@

Button::Button(const FbWindow &parent, int x, int y, unsigned int width, unsigned int height): FbWindow(parent, x, y, width, height, - ExposureMask | ButtonPressMask | ButtonReleaseMask), + ExposureMask | ButtonPressMask | ButtonReleaseMask | + EnterWindowMask | LeaveWindowMask), m_background_pm(0), m_pressed_pm(0), m_pressed_color(),

@@ -88,6 +90,14 @@

void Button::setBackgroundPixmap(Pixmap pm) { m_background_pm = pm; FbTk::FbWindow::setBackgroundPixmap(pm); +} + + +void Button::enterNotifyEvent(XCrossingEvent &ce){ + +} +void Button::leaveNotifyEvent(XCrossingEvent &ce){ + } void Button::buttonPressEvent(XButtonEvent &event) {
M src/FbTk/Button.hhsrc/FbTk/Button.hh

@@ -61,6 +61,8 @@ */

//@{ virtual void buttonPressEvent(XButtonEvent &event); virtual void buttonReleaseEvent(XButtonEvent &event); + virtual void enterNotifyEvent(XCrossingEvent &ce); + virtual void leaveNotifyEvent(XCrossingEvent &ce); virtual void exposeEvent(XExposeEvent &event); //@}
M src/FbTk/TextButton.ccsrc/FbTk/TextButton.cc

@@ -158,11 +158,9 @@ unsigned int textw = width(), texth = height();

translateSize(m_orientation, textw, texth); int align_x = FbTk::doAlignment(textw - x_offset - m_left_padding - m_right_padding, - bevel(), - justify(), - font(), + bevel(), justify(), font(), text().data(), text().size(), - textlen); // return new text lne + textlen); // return new text len // center text by default int center_pos = texth/2 + font().ascent()/2 - 1;

@@ -181,6 +179,23 @@ screenNumber(),

gc(), // graphic context text().data(), textlen, // string and string size textx, texty, m_orientation); // position +} + + +bool TextButton::textExceeds(int x_offset) { + + unsigned int textlen = text().size(); + // do text alignment + + unsigned int textw = width(), texth = height(); + translateSize(m_orientation, textw, texth); + + FbTk::doAlignment(textw - x_offset - m_left_padding - m_right_padding, + bevel(), justify(), font(), text().data(), text().size(), + textlen); // return new text len + + return text().size()>textlen; + } void TextButton::exposeEvent(XExposeEvent &event) {
M src/FbTk/TextButton.hhsrc/FbTk/TextButton.hh

@@ -80,6 +80,8 @@ void renderForeground(FbWindow &win, FbDrawable &drawable);

protected: virtual void drawText(int x_offset, int y_offset, FbDrawable *drawable_override); + // return true if the text will be truncated + bool textExceeds(int x_offset); private: FbTk::Font *m_font;
M src/IconButton.ccsrc/IconButton.cc

@@ -52,7 +52,8 @@ FbTk::ThemeProxy<IconbarTheme> &unfocused_theme, Focusable &win):

FbTk::TextButton(parent, focused_theme->text().font(), win.title()), m_win(win), m_icon_window(*this, 1, 1, 1, 1, - ExposureMask | ButtonPressMask | ButtonReleaseMask), + ExposureMask |EnterWindowMask | LeaveWindowMask | + ButtonPressMask | ButtonReleaseMask), m_use_pixmap(true), m_theme(win, focused_theme, unfocused_theme), m_pm(win.screen().imageControl()) {

@@ -77,6 +78,20 @@ if (m_icon_window == event.window)

m_icon_window.clear(); else FbTk::TextButton::exposeEvent(event); +} + +void IconButton::enterNotifyEvent(XCrossingEvent &ev) { + + int xoffset = 1; + if (m_icon_pixmap.drawable() != 0) + xoffset = m_icon_window.x() + m_icon_window.width() + 1; + + if (FbTk::TextButton::textExceeds(xoffset)) + m_win.screen().showTooltip(m_win.title()); +} + +void IconButton::leaveNotifyEvent(XCrossingEvent &ev) { + m_win.screen().hideTooltip(); } void IconButton::moveResize(int x, int y,
M src/IconButton.hhsrc/IconButton.hh

@@ -45,6 +45,8 @@ Focusable &window);

virtual ~IconButton(); void exposeEvent(XExposeEvent &event); + void enterNotifyEvent(XCrossingEvent &ce); + void leaveNotifyEvent(XCrossingEvent &ce); void clear(); void clearArea(int x, int y, unsigned int width, unsigned int height,
M src/Makefile.amsrc/Makefile.am

@@ -106,6 +106,7 @@ Keys.cc Keys.hh main.cc \

RootTheme.hh RootTheme.cc \ FbRootWindow.hh FbRootWindow.cc \ OSDWindow.hh OSDWindow.cc \ + TooltipWindow.hh TooltipWindow.cc \ Screen.cc Screen.hh ScreenResources.cc \ Slit.cc Slit.hh SlitTheme.hh SlitTheme.cc SlitClient.hh SlitClient.cc \ WinButton.hh WinButton.cc \
M src/OSDWindow.hhsrc/OSDWindow.hh

@@ -47,7 +47,7 @@ void hide();

bool isVisible() const { return m_visible; } -private: +protected: void show(); BScreen &m_screen;
M src/Screen.ccsrc/Screen.cc

@@ -290,6 +290,7 @@ menu_alpha(rm, 255, scrname+".menu.alpha", altscrname+".Menu.Alpha"),

menu_delay(rm, 0, scrname + ".menuDelay", altscrname+".MenuDelay"), menu_delay_close(rm, 0, scrname + ".menuDelayClose", altscrname+".MenuDelayClose"), tab_width(rm, 64, scrname + ".tab.width", altscrname+".Tab.Width"), + tooltip_delay(rm, 500, scrname + ".tooltipDelay", altscrname+".TooltipDelay"), menu_mode(rm, FbTk::MenuTheme::DELAY_OPEN, scrname+".menuMode", altscrname+".MenuMode"), gc_line_width(rm, 1, scrname+".overlay.lineWidth", altscrname+".Overlay.LineWidth"),

@@ -343,6 +344,7 @@ m_menutheme(new FbTk::MenuTheme(scrn)),

m_root_window(scrn), m_geom_window(m_root_window, *this, *m_focused_windowtheme), m_pos_window(m_root_window, *this, *m_focused_windowtheme), + m_tooltip_window(m_root_window, *this, *m_focused_windowtheme), m_dummy_window(scrn, -1, -1, 1, 1, 0, true, false, CopyFromParent, InputOnly), resource(rm, screenname, altscreenname),

@@ -484,6 +486,7 @@

renderGeomWindow(); renderPosWindow(); + m_tooltip_window.setDelay(*resource.tooltip_delay); // setup workspaces and workspace menu int nr_ws = *resource.workspaces;

@@ -1846,6 +1849,17 @@ "W: %4d x H: %4d",

"Format for width and height window, %4d for width, and %4d for height").c_str(), gx, gy); m_geom_window.showText(label); +} + + +void BScreen::showTooltip(const std::string &text) { + if (*resource.tooltip_delay >= 0) + m_tooltip_window.showText(text); +} + +void BScreen::hideTooltip() { + if (*resource.tooltip_delay >= 0) + m_tooltip_window.hide(); }
M src/Screen.hhsrc/Screen.hh

@@ -30,7 +30,7 @@ #include "FbRootWindow.hh"

#include "RootTheme.hh" #include "WinButtonTheme.hh" #include "FbWinFrameTheme.hh" -#include "OSDWindow.hh" +#include "TooltipWindow.hh" #include "FbTk/MenuTheme.hh" #include "FbTk/EventHandler.hh"

@@ -389,6 +389,9 @@ void hidePosition();

/// show geomentry with "width x height"-text, not size of window void showGeometry(int width, int height); void hideGeometry(); + + void showTooltip(const std::string &text); + void hideTooltip(); void setLayer(FbTk::XLayerItem &item, int layernum); // remove? no, items are never removed from their layer until they die

@@ -536,6 +539,7 @@ std::auto_ptr<RootTheme> m_root_theme;

FbRootWindow m_root_window; OSDWindow m_geom_window, m_pos_window; + TooltipWindow m_tooltip_window; FbTk::FbWindow m_dummy_window; struct ScreenResource {

@@ -554,7 +558,8 @@ FbTk::Resource<unsigned int> typing_delay;

FbTk::Resource<FollowModel> follow_model, user_follow_model; bool ordered_dither; FbTk::Resource<int> workspaces, edge_snap_threshold, focused_alpha, - unfocused_alpha, menu_alpha, menu_delay, menu_delay_close, tab_width; + unfocused_alpha, menu_alpha, menu_delay, menu_delay_close, + tab_width, tooltip_delay; FbTk::Resource<FbTk::MenuTheme::MenuMode> menu_mode; FbTk::Resource<int> gc_line_width;
A src/TooltipWindow.cc

@@ -0,0 +1,109 @@

+// TooltipWindow.hh +// Copyright (c) 2008 Fluxbox Team (fluxgen at fluxbox dot org) +// +// 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. + + +#include "TooltipWindow.hh" +#include "Screen.hh" +#include "FbWinFrameTheme.hh" + + +TooltipWindow::TooltipWindow(const FbTk::FbWindow &parent, BScreen &screen, + FbTk::ThemeProxy<FbWinFrameTheme> &theme): + OSDWindow(parent, screen, theme), + delay(-1) { + + FbTk::RefCount<FbTk::Command<void> > raisecmd(new FbTk::SimpleCommand<TooltipWindow>(*this, &TooltipWindow::raiseTooltip)); + timer.setCommand(raisecmd); + timer.fireOnce(true); + +} + +void TooltipWindow::showText(const std::string &text) { + + lastText = text.c_str(); + if (delay == 0) + raiseTooltip(); + else + timer.start(); + +} + +void TooltipWindow::raiseTooltip() { + + if (lastText.size() == 0) + return; + + resize(lastText); + reconfigTheme(); + int h = m_theme->font().height() + m_theme->bevelWidth() * 2; + int w = m_theme->font().textWidth(lastText, lastText.size()) + m_theme->bevelWidth() * 2; + + Window root_ret; // not used + Window window_ret; // not used + int rx = 0, ry = 0; + int wx, wy; // not used + unsigned int mask; // not used + + XQueryPointer(display(), m_screen.rootWindow().window(), + &root_ret, &window_ret, &rx, &ry, &wx, &wy, &mask); + + // mouse position + int mx = rx; + int my = ry; + + // center the mouse horizontally + rx -= w/2; + int yoffset = 10; + if (ry >= yoffset + h) + ry -= yoffset + h; + else + ry += yoffset; + + // check that we are not out of screen + int outOfBound = rx + w - m_screen.width(); + if (outOfBound > 0) + rx -= outOfBound; + if (rx < 0) + rx = 0; + + moveResize(rx,ry,w, h); + + show(); + clear(); + m_theme->font().drawText(*this, m_screen.screenNumber(), + m_theme->iconbarTheme().text().textGC(), lastText, + lastText.size(), m_theme->bevelWidth(), + m_theme->bevelWidth() + m_theme->font().ascent()); +} + + +void TooltipWindow::show() { + if (m_visible) + return; + m_visible = true; + raise(); + FbTk::FbWindow::show(); +} + +void TooltipWindow::hide() { + timer.stop(); + OSDWindow::hide(); +}
A src/TooltipWindow.hh

@@ -0,0 +1,53 @@

+// TooltipWindow.hh +// Copyright (c) 2008 Fluxbox Team (fluxgen at fluxbox dot org) +// +// 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.#ifndef TOOLTIPWINDOW_HH_ +#ifndef TOOLTIPWINDOW_HH_ +#define TOOLTIPWINDOW_HH_ + +#include "OSDWindow.hh" +#include "FbTk/Command.hh" +#include "FbTk/RefCount.hh" +#include "FbTk/Timer.hh" +#include "FbTk/SimpleCommand.hh" + + +class TooltipWindow : public OSDWindow { +public: + TooltipWindow(const FbTk::FbWindow &parent, BScreen &screen, + FbTk::ThemeProxy<FbWinFrameTheme> &theme); + + void showText(const std::string &text); + void setDelay(int iDelay) { + delay = iDelay; + timer.setTimeout(delay); + } + void hide() ; + +private: + void raiseTooltip(); + void show(); + int delay; + std::string lastText; + FbTk::Timer timer; +}; + + + +#endif /*TOOLTIPWINDOW_HH_*/