fluxbox/src/Toolbar.cc

942 lines
31 KiB
C++
Raw Normal View History

2002-03-19 14:30:43 +00:00
// Toolbar.cc for Fluxbox
2003-04-14 15:01:55 +00:00
// Copyright (c) 2002 - 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net)
2002-03-19 14:30:43 +00:00
//
2001-12-11 20:47:02 +00:00
// Toolbar.cc for Blackbox - an X11 Window manager
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
2001-12-11 20:47:02 +00:00
//
// 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,
2002-03-19 14:30:43 +00:00
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2001-12-11 20:47:02 +00:00
// 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: Toolbar.cc,v 1.123 2003/10/06 06:22:42 rathnor Exp $
2002-08-04 15:12:51 +00:00
#include "Toolbar.hh"
2002-02-07 15:12:23 +00:00
2003-08-16 12:10:19 +00:00
// themes
#include "ToolbarTheme.hh"
2003-08-29 00:44:41 +00:00
#include "WorkspaceNameTheme.hh"
2003-08-11 20:22:38 +00:00
2003-08-11 15:56:10 +00:00
// tools
#include "IconbarTool.hh"
#include "WorkspaceNameTool.hh"
2003-08-11 20:22:38 +00:00
#include "ClockTool.hh"
#include "SystemTray.hh"
2003-08-29 00:44:41 +00:00
2003-08-11 15:56:10 +00:00
2003-06-13 05:04:14 +00:00
#include "I18n.hh"
2001-12-11 20:47:02 +00:00
#include "fluxbox.hh"
#include "Screen.hh"
2003-04-16 12:53:14 +00:00
#include "IntResMenuItem.hh"
2003-05-12 23:05:19 +00:00
#include "BoolMenuItem.hh"
#include "Xinerama.hh"
2003-06-18 13:55:17 +00:00
#include "Strut.hh"
#include "FbCommands.hh"
2003-08-11 15:56:10 +00:00
2003-08-28 13:58:18 +00:00
#include "FbTk/ImageControl.hh"
#include "FbTk/MacroCommand.hh"
#include "FbTk/EventManager.hh"
#include "FbTk/SimpleCommand.hh"
#include "FbTk/StringUtil.hh"
// use GNU extensions
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif // _GNU_SOURCE
2002-10-13 21:51:12 +00:00
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H
2003-07-10 11:48:14 +00:00
#include "Shape.hh"
2001-12-11 20:47:02 +00:00
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <cstring>
#include <cstdio>
2003-08-28 13:58:18 +00:00
#include <iterator>
2001-12-11 20:47:02 +00:00
#include <iostream>
using namespace std;
2002-12-04 17:58:01 +00:00
template<>
void FbTk::Resource<Toolbar::Placement>::
setFromString(const char *strval) {
if (strcasecmp(strval, "TopLeft")==0)
m_value = Toolbar::TOPLEFT;
else if (strcasecmp(strval, "BottomLeft")==0)
m_value = Toolbar::BOTTOMLEFT;
else if (strcasecmp(strval, "TopCenter")==0)
m_value = Toolbar::TOPCENTER;
else if (strcasecmp(strval, "BottomCenter")==0)
m_value = Toolbar::BOTTOMCENTER;
else if (strcasecmp(strval, "TopRight")==0)
m_value = Toolbar::TOPRIGHT;
else if (strcasecmp(strval, "BottomRight")==0)
m_value = Toolbar::BOTTOMRIGHT;
else if (strcasecmp(strval, "LeftTop") == 0)
m_value = Toolbar::LEFTTOP;
else if (strcasecmp(strval, "LeftCenter") == 0)
m_value = Toolbar::LEFTCENTER;
else if (strcasecmp(strval, "LeftBottom") == 0)
m_value = Toolbar::LEFTBOTTOM;
else if (strcasecmp(strval, "RightTop") == 0)
m_value = Toolbar::RIGHTTOP;
else if (strcasecmp(strval, "RightCenter") == 0)
m_value = Toolbar::RIGHTCENTER;
else if (strcasecmp(strval, "RightBottom") == 0)
m_value = Toolbar::RIGHTBOTTOM;
else
setDefaultValue();
}
string FbTk::Resource<Toolbar::Placement>::
getString() {
switch (m_value) {
case Toolbar::TOPLEFT:
return string("TopLeft");
break;
case Toolbar::BOTTOMLEFT:
return string("BottomLeft");
break;
case Toolbar::TOPCENTER:
return string("TopCenter");
break;
case Toolbar::BOTTOMCENTER:
return string("BottomCenter");
break;
case Toolbar::TOPRIGHT:
return string("TopRight");
break;
case Toolbar::BOTTOMRIGHT:
return string("BottomRight");
break;
case Toolbar::LEFTTOP:
return string("LeftTop");
break;
case Toolbar::LEFTCENTER:
return string("LeftCenter");
break;
case Toolbar::LEFTBOTTOM:
return string("LeftBottom");
break;
case Toolbar::RIGHTTOP:
return string("RightTop");
break;
case Toolbar::RIGHTCENTER:
return string("RightCenter");
break;
case Toolbar::RIGHTBOTTOM:
return string("RightBottom");
break;
}
//default string
return string("BottomCenter");
}
2003-01-12 18:04:39 +00:00
namespace {
class SetToolbarPlacementCmd: public FbTk::Command {
public:
2003-08-23 15:42:48 +00:00
SetToolbarPlacementCmd(Toolbar &tbar, Toolbar::Placement place):m_tbar(tbar), m_place(place) { }
2003-01-12 18:04:39 +00:00
void execute() {
m_tbar.setPlacement(m_place);
m_tbar.reconfigure();
Fluxbox::instance()->save_rc();
2003-01-12 18:04:39 +00:00
}
private:
Toolbar &m_tbar;
Toolbar::Placement m_place;
};
2003-08-23 15:42:48 +00:00
class ShowMenuAboveToolbar: public FbTk::Command {
public:
explicit ShowMenuAboveToolbar(Toolbar &tbar):m_tbar(tbar) { }
void execute() {
// get last button pos
const XEvent &event = Fluxbox::instance()->lastEvent();
int x = event.xbutton.x_root - (m_tbar.menu().width() / 2);
int y = event.xbutton.y_root - (m_tbar.menu().height() / 2);
if (x < 0)
x = 0;
else if (x + m_tbar.menu().width() > m_tbar.screen().width())
x = m_tbar.screen().width() - m_tbar.menu().width();
if (y < 0)
y = 0;
else if (y + m_tbar.menu().height() > m_tbar.screen().height())
y = m_tbar.screen().height() - m_tbar.menu().height();
m_tbar.menu().move(x, y);
m_tbar.menu().show();
}
private:
Toolbar &m_tbar;
};
2003-01-12 18:04:39 +00:00
}; // end anonymous
2002-12-03 17:02:53 +00:00
// toolbar frame
Toolbar::Frame::Frame(FbTk::EventHandler &evh, int screen_num):
window(screen_num, // screen (parent)
0, 0, // pos
10, 10, // size
// event mask
2002-12-03 17:02:53 +00:00
ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask | SubstructureNotifyMask,
2003-08-11 20:22:38 +00:00
true) // override redirect
{
2002-12-03 17:02:53 +00:00
FbTk::EventManager &evm = *FbTk::EventManager::instance();
// add windows to eventmanager
2002-12-03 17:02:53 +00:00
evm.add(evh, window);
2003-08-11 15:56:10 +00:00
2002-12-03 17:02:53 +00:00
}
Toolbar::Frame::~Frame() {
FbTk::EventManager &evm = *FbTk::EventManager::instance();
// remove windows from eventmanager
2002-12-03 17:02:53 +00:00
evm.remove(window);
}
2001-12-11 20:47:02 +00:00
2003-03-03 21:51:13 +00:00
Toolbar::Toolbar(BScreen &scrn, FbTk::XLayer &layer, FbTk::Menu &menu, size_t width):
m_hidden(false),
2003-05-15 12:00:46 +00:00
frame(*this, scrn.screenNumber()),
2003-08-19 21:28:57 +00:00
m_window_pm(0),
2002-12-01 13:42:15 +00:00
m_screen(scrn),
2003-03-03 21:51:13 +00:00
m_toolbarmenu(menu),
m_placementmenu(*scrn.menuTheme(),
scrn.screenNumber(), scrn.imageControl(),
*scrn.layerManager().getLayer(Fluxbox::instance()->getMenuLayer())),
m_layermenu(*scrn.menuTheme(),
2003-05-15 12:00:46 +00:00
scrn.screenNumber(),
2003-05-15 23:30:07 +00:00
scrn.imageControl(),
*scrn.layerManager().getLayer(Fluxbox::instance()->getMenuLayer()),
this,
true),
2003-05-15 12:00:46 +00:00
m_theme(scrn.screenNumber()),
2003-08-19 21:28:57 +00:00
m_clock_theme(scrn.screenNumber(), "toolbar.clock", "Toolbar.Clock"),
2003-08-29 00:44:41 +00:00
m_workspace_theme(new WorkspaceNameTheme(scrn.screenNumber(), "toolbar.workspace", "Toolbar.Workspace")),
2003-08-19 21:28:57 +00:00
m_iconbar_theme(scrn.screenNumber(), "toolbar.iconbar", "Toolbar.Iconbar"),
2003-06-18 13:55:17 +00:00
m_layeritem(frame.window, layer),
m_strut(0),
// lock rcmanager here
m_rc_auto_hide(scrn.resourceManager().lock(), false,
scrn.name() + ".toolbar.autoHide", scrn.altName() + ".Toolbar.AutoHide"),
m_rc_maximize_over(scrn.resourceManager(), false,
scrn.name() + ".toolbar.maxOver", scrn.altName() + ".Toolbar.MaxOver"),
m_rc_width_percent(scrn.resourceManager(), 65,
scrn.name() + ".toolbar.widthPercent", scrn.altName() + ".Toolbar.WidthPercent"),
m_rc_layernum(scrn.resourceManager(), Fluxbox::Layer(Fluxbox::instance()->getDesktopLayer()),
scrn.name() + ".toolbar.layer", scrn.altName() + ".Toolbar.Layer"),
m_rc_on_head(scrn.resourceManager(), 0,
scrn.name() + ".toolbar.onhead", scrn.altName() + ".Toolbar.onHead"),
m_rc_placement(scrn.resourceManager(), Toolbar::BOTTOMCENTER,
2003-07-10 11:48:14 +00:00
scrn.name() + ".toolbar.placement", scrn.altName() + ".Toolbar.Placement"),
m_rc_height(scrn.resourceManager(), 0, scrn.name() + ".toolbar.height", scrn.altName() + ".Toolbar.Height"),
2003-08-28 15:04:47 +00:00
m_rc_tools(scrn.resourceManager(), "workspacename, iconbar, systemtray, clock",
scrn.name() + ".toolbar.tools", scrn.altName() + ".Toolbar.Tools"),
2003-08-11 15:56:10 +00:00
m_shape(new Shape(frame.window, 0)),
m_resize_lock(false) {
// we need to get notified when the theme is reloaded
2003-08-11 15:56:10 +00:00
m_theme.reconfigSig().attach(this);
2003-08-24 23:15:02 +00:00
// listen to screen size changes
2003-08-24 13:17:00 +00:00
screen().resizeSig().attach(this);
2003-08-30 01:02:09 +00:00
screen().reconfigureSig().attach(this); // if alpha value changes
moveToLayer((*m_rc_layernum).getNum());
// TODO: nls
m_layermenu.setLabel("Toolbar Layer");
m_placementmenu.setLabel("Toolbar Placement");
2003-05-24 13:13:22 +00:00
m_layermenu.setInternalMenu();
m_placementmenu.setInternalMenu();
setupMenus();
2003-01-12 18:04:39 +00:00
// geometry settings
frame.width = width;
2003-08-11 20:22:38 +00:00
frame.height = 10;
frame.bevel_w = 1;
2003-08-11 20:22:38 +00:00
frame.grab_x = frame.grab_y = 0;
2003-08-11 15:56:10 +00:00
2003-08-28 13:58:18 +00:00
// set antialias on themes
m_clock_theme.setAntialias(screen().antialias());
m_iconbar_theme.setAntialias(screen().antialias());
2003-08-29 00:44:41 +00:00
m_workspace_theme->setAntialias(screen().antialias());
2003-08-11 15:56:10 +00:00
// setup hide timer
2003-05-10 13:57:07 +00:00
m_hide_timer.setTimeout(Fluxbox::instance()->getAutoRaiseDelay());
2003-08-11 15:56:10 +00:00
FbTk::RefCount<FbTk::Command> toggle_hidden(new FbTk::SimpleCommand<Toolbar>(*this, &Toolbar::toggleHidden));
m_hide_timer.setCommand(toggle_hidden);
2003-05-10 13:57:07 +00:00
m_hide_timer.fireOnce(true);
2002-12-01 13:42:15 +00:00
2001-12-11 20:47:02 +00:00
2003-08-11 20:22:38 +00:00
// show all windows
2003-05-17 11:30:59 +00:00
frame.window.showSubwindows();
frame.window.show();
scrn.resourceManager().unlock();
2003-08-23 15:42:48 +00:00
// setup to listen to child events
FbTk::EventManager::instance()->addParent(*this, window());
// get everything together
reconfigure();
2001-12-11 20:47:02 +00:00
}
2002-08-04 15:12:51 +00:00
Toolbar::~Toolbar() {
2003-08-28 13:58:18 +00:00
FbTk::EventManager::instance()->remove(window());
deleteItems();
clearStrut();
2003-08-11 15:56:10 +00:00
2003-08-19 21:28:57 +00:00
if (m_window_pm)
screen().imageControl().removeImage(m_window_pm);
2002-12-03 17:02:53 +00:00
}
2001-12-11 20:47:02 +00:00
2003-06-18 13:55:17 +00:00
void Toolbar::clearStrut() {
if (m_strut) {
screen().clearStrut(m_strut);
m_strut = 0;
}
}
void Toolbar::updateStrut() {
2003-06-22 19:39:47 +00:00
bool had_strut = m_strut ? true : false;
2003-06-18 13:55:17 +00:00
clearStrut();
// we should request space if we're in autohide mode or
// if the user dont want to request space for toolbar.
if (doAutoHide() || *m_rc_maximize_over) {
2003-06-22 19:39:47 +00:00
if (had_strut)
screen().updateAvailableWorkspaceArea();
2003-06-18 13:55:17 +00:00
return;
2003-06-22 19:39:47 +00:00
}
2003-06-18 13:55:17 +00:00
// request area on screen
int top = 0, bottom = 0, left = 0, right = 0;
switch (placement()) {
2003-06-18 13:55:17 +00:00
case TOPLEFT:
case TOPCENTER:
case TOPRIGHT:
top = height();
break;
case BOTTOMLEFT:
case BOTTOMCENTER:
case BOTTOMRIGHT:
bottom = height();
break;
case RIGHTTOP:
case RIGHTCENTER:
case RIGHTBOTTOM:
right = width();
break;
case LEFTTOP:
case LEFTCENTER:
case LEFTBOTTOM:
left = width();
break;
};
m_strut = screen().requestStrut(left, right, top, bottom);
screen().updateAvailableWorkspaceArea();
}
2002-12-03 17:02:53 +00:00
bool Toolbar::isVertical() const {
return (placement() == RIGHTCENTER ||
placement() == RIGHTTOP ||
placement() == RIGHTBOTTOM ||
placement() == LEFTCENTER ||
placement() == LEFTTOP ||
placement() == LEFTBOTTOM);
2001-12-11 20:47:02 +00:00
}
2003-03-03 21:51:13 +00:00
void Toolbar::raise() {
m_layeritem.raise();
}
void Toolbar::lower() {
m_layeritem.lower();
}
2003-03-03 21:51:13 +00:00
2002-08-04 15:12:51 +00:00
void Toolbar::reconfigure() {
m_clock_theme.setAntialias(screen().antialias());
m_iconbar_theme.setAntialias(screen().antialias());
2003-08-29 00:44:41 +00:00
m_workspace_theme->setAntialias(screen().antialias());
2003-07-01 12:41:44 +00:00
2003-08-28 13:58:18 +00:00
// parse resource tools and determine if we need to rebuild toolbar
bool need_update = false;
// parse and transform to lower case
std::list<std::string> tools;
FbTk::StringUtil::stringtok(tools, *m_rc_tools, ", ");
transform(tools.begin(),
tools.end(),
tools.begin(),
FbTk::StringUtil::toLower);
if (tools.size() == m_tools.size() && tools.size() != 0) {
StringList::const_iterator tool_it = tools.begin();
StringList::const_iterator current_tool_it = m_tools.begin();
StringList::const_iterator tool_it_end = tools.end();
for (; tool_it != tool_it_end; ++tool_it, ++current_tool_it) {
if (*current_tool_it != *tool_it)
break;
}
// did we find anything that wasn't in the right place or new item?
if (tool_it != tool_it_end)
need_update = true;
} else // sizes does not match so we update
need_update = true;
if (need_update) {
// destroy tools and rebuild them
deleteItems();
m_tools = tools; // copy values
if (m_tools.size()) {
// make lower case
transform(m_tools.begin(), m_tools.end(),
m_tools.begin(),
FbTk::StringUtil::toLower);
// create items
StringList::const_iterator item_it = m_tools.begin();
StringList::const_iterator item_it_end = m_tools.end();
for (; item_it != item_it_end; ++item_it) {
if (*item_it == "workspacename") {
2003-08-29 00:44:41 +00:00
WorkspaceNameTool *item = new WorkspaceNameTool(frame.window, *m_workspace_theme, screen());
2003-08-28 13:58:18 +00:00
using namespace FbTk;
RefCount<Command> showmenu(new ShowMenuAboveToolbar(*this));
item->button().setOnClick(showmenu);
m_item_list.push_back(item);
} else if (*item_it == "iconbar") {
2003-09-08 18:17:19 +00:00
m_item_list.push_back(new IconbarTool(frame.window, m_iconbar_theme,
screen(), menu()));
2003-08-28 13:58:18 +00:00
} else if (*item_it == "systemtray") {
m_item_list.push_back(new SystemTray(frame.window));
} else if (*item_it == "clock") {
m_item_list.push_back(new ClockTool(frame.window, m_clock_theme, screen()));
}
}
// show all items
frame.window.showSubwindows();
}
}
if (doAutoHide())
2003-05-10 13:57:07 +00:00
m_hide_timer.start();
frame.bevel_w = theme().bevelWidth();
2003-07-10 11:48:14 +00:00
// destroy shape if the theme wasn't specified with one,
// or create one
if (theme().shape() == false && m_shape.get())
m_shape.reset(0);
else if (theme().shape() && m_shape.get() == 0) {
m_shape.reset(new Shape(frame.window, 0));
}
2003-08-11 15:56:10 +00:00
2002-12-03 17:02:53 +00:00
// recallibrate size
setPlacement(placement());
2001-12-11 20:47:02 +00:00
if (isHidden()) {
2002-12-03 17:02:53 +00:00
frame.window.moveResize(frame.x_hidden, frame.y_hidden,
frame.width, frame.height);
} else {
2002-12-03 17:02:53 +00:00
frame.window.moveResize(frame.x, frame.y,
frame.width, frame.height);
}
2003-08-19 21:28:57 +00:00
// render frame window
Pixmap tmp = m_window_pm;
if (theme().toolbar().type() == (FbTk::Texture::FLAT | FbTk::Texture::SOLID)) {
m_window_pm = 0;
frame.window.setBackgroundColor(theme().toolbar().color());
} else {
m_window_pm = screen().imageControl().renderImage(frame.window.width(), frame.window.height(),
theme().toolbar());
frame.window.setBackgroundPixmap(m_window_pm);
}
if (tmp)
screen().imageControl().removeImage(tmp);
2003-08-13 15:28:24 +00:00
frame.window.setBorderColor(theme().border().color());
frame.window.setBorderWidth(theme().border().width());
2002-12-03 17:02:53 +00:00
frame.window.clear();
2003-08-11 15:56:10 +00:00
2003-07-10 11:48:14 +00:00
if (theme().shape() && m_shape.get())
m_shape->update();
2002-12-01 13:42:15 +00:00
rearrangeItems();
2003-08-11 15:56:10 +00:00
2002-12-01 13:42:15 +00:00
m_toolbarmenu.reconfigure();
2003-06-18 13:55:17 +00:00
// we're done with all resizing and stuff now we can request a new
2003-08-11 20:22:38 +00:00
// area to be reserved on screen
2003-06-18 13:55:17 +00:00
updateStrut();
2003-08-13 15:28:24 +00:00
2001-12-11 20:47:02 +00:00
}
2002-11-27 12:20:23 +00:00
2003-08-11 20:22:38 +00:00
void Toolbar::buttonPressEvent(XButtonEvent &be) {
if (be.button != 3)
return;
2003-08-11 20:22:38 +00:00
if (! m_toolbarmenu.isVisible()) {
int x, y;
2001-12-11 20:47:02 +00:00
2003-08-11 20:22:38 +00:00
x = be.x_root - (m_toolbarmenu.width() / 2);
y = be.y_root - (m_toolbarmenu.height() / 2);
2001-12-11 20:47:02 +00:00
2003-08-11 20:22:38 +00:00
if (x < 0)
x = 0;
else if (x + m_toolbarmenu.width() > screen().width())
x = screen().width() - m_toolbarmenu.width();
2001-12-11 20:47:02 +00:00
2003-08-11 20:22:38 +00:00
if (y < 0)
y = 0;
else if (y + m_toolbarmenu.height() > screen().height())
y = screen().height() - m_toolbarmenu.height();
2003-08-11 20:22:38 +00:00
m_toolbarmenu.move(x, y);
m_toolbarmenu.show();
2002-12-01 13:42:15 +00:00
} else
2003-08-11 20:22:38 +00:00
m_toolbarmenu.hide();
2001-12-11 20:47:02 +00:00
}
void Toolbar::buttonReleaseEvent(XButtonEvent &re) {
2003-08-11 15:56:10 +00:00
if (re.button == 1)
raise();
2003-08-11 15:56:10 +00:00
else if (re.button == 4) //mousewheel scroll up
screen().nextWorkspace(1);
else if (re.button == 5) //mousewheel scroll down
screen().prevWorkspace(1);
2001-12-11 20:47:02 +00:00
}
void Toolbar::enterNotifyEvent(XCrossingEvent &not_used) {
if (! doAutoHide())
2002-12-01 13:42:15 +00:00
return;
if (isHidden()) {
2003-05-10 13:57:07 +00:00
if (! m_hide_timer.isTiming())
m_hide_timer.start();
2002-12-01 13:42:15 +00:00
} else {
2003-05-10 13:57:07 +00:00
if (m_hide_timer.isTiming())
m_hide_timer.stop();
2002-12-01 13:42:15 +00:00
}
2001-12-11 20:47:02 +00:00
}
void Toolbar::leaveNotifyEvent(XCrossingEvent &not_used) {
if (! doAutoHide())
2002-12-01 13:42:15 +00:00
return;
2001-12-11 20:47:02 +00:00
if (isHidden()) {
2003-05-10 13:57:07 +00:00
if (m_hide_timer.isTiming())
m_hide_timer.stop();
} else if (! m_toolbarmenu.isVisible() && ! m_hide_timer.isTiming())
m_hide_timer.start();
2002-11-27 12:20:23 +00:00
2001-12-11 20:47:02 +00:00
}
void Toolbar::exposeEvent(XExposeEvent &ee) {
2003-08-28 13:58:18 +00:00
if (ee.window == frame.window)
frame.window.clearArea(ee.x, ee.y,
ee.width, ee.height);
2001-12-11 20:47:02 +00:00
}
void Toolbar::keyPressEvent(XKeyEvent &ke) {
2002-12-01 13:42:15 +00:00
2001-12-11 20:47:02 +00:00
}
void Toolbar::handleEvent(XEvent &event) {
2003-08-28 13:58:18 +00:00
if (event.type == ConfigureNotify &&
event.xconfigure.window != window().window())
rearrangeItems();
}
2001-12-11 20:47:02 +00:00
2003-08-11 15:56:10 +00:00
void Toolbar::update(FbTk::Subject *subj) {
2003-08-11 20:22:38 +00:00
2003-08-11 15:56:10 +00:00
// either screen reconfigured or theme was reloaded
reconfigure();
2001-12-11 20:47:02 +00:00
}
void Toolbar::setPlacement(Toolbar::Placement where) {
2003-08-15 15:29:10 +00:00
// disable vertical toolbar
switch (where) {
case LEFTTOP:
case LEFTCENTER:
case LEFTBOTTOM:
case RIGHTTOP:
case RIGHTCENTER:
case RIGHTBOTTOM:
where = BOTTOMCENTER;
break;
default:
break;
}
*m_rc_placement = where;
int head_x = 0,
head_y = 0,
2003-08-13 15:28:24 +00:00
head_w = screen().width(),
head_h = screen().height();
if (screen().hasXinerama()) {
int head = *m_rc_on_head;
head_x = screen().getHeadX(head);
head_y = screen().getHeadY(head);
head_w = screen().getHeadWidth(head);
head_h = screen().getHeadHeight(head);
}
frame.width = head_w * (*m_rc_width_percent) / 100;
//!! TODO: change this
// max height of each toolbar items font...
unsigned int max_height = 0;
if (max_height < m_clock_theme.font().height())
max_height = m_clock_theme.font().height();
2003-08-29 00:44:41 +00:00
if (max_height < m_workspace_theme->font().height())
max_height = m_workspace_theme->font().height();
if (max_height < m_iconbar_theme.focusedText().font().height())
max_height = m_iconbar_theme.focusedText().font().height();
if (max_height < m_iconbar_theme.unfocusedText().font().height())
max_height = m_iconbar_theme.unfocusedText().font().height();
2003-08-27 19:56:56 +00:00
if (theme().height() > 0)
max_height = theme().height();
if (*m_rc_height > 0 && *m_rc_height < 100)
max_height = *m_rc_height;
frame.height = max_height;
frame.height += 2;
frame.height += (frame.bevel_w * 2);
int bevel_width = theme().bevelWidth();
2003-08-13 15:28:24 +00:00
int border_width = theme().border().width();
2002-12-03 17:02:53 +00:00
// should we flipp sizes?
if (isVertical()) {
frame.width = frame.height;
frame.height = head_h * (*m_rc_width_percent) / 100;
2002-12-03 17:02:53 +00:00
} // else horizontal toolbar
2002-12-03 17:02:53 +00:00
2003-06-25 12:33:28 +00:00
// So we get at least one pixel visible in hidden mode
if (bevel_width <= border_width)
bevel_width = border_width + 1;
switch (where) {
case TOPLEFT:
frame.x = head_x;
frame.y = head_y;
frame.x_hidden = head_x;
frame.y_hidden = head_y + bevel_width - border_width - frame.height;
2003-07-10 11:48:14 +00:00
if (m_shape.get())
m_shape->setPlaces(Shape::BOTTOMRIGHT | Shape::BOTTOMLEFT);
break;
case BOTTOMLEFT:
frame.x = head_x;
frame.y = head_y + head_h - frame.height - border_width*2;
frame.x_hidden = head_x;
frame.y_hidden = head_y + head_h - bevel_width - border_width;
2003-07-10 11:48:14 +00:00
if (m_shape.get())
m_shape->setPlaces(Shape::TOPRIGHT | Shape::TOPLEFT);
break;
case TOPCENTER:
2003-06-25 12:33:28 +00:00
frame.x = head_x + (head_w - frame.width) / 2;
frame.y = head_y;
frame.x_hidden = frame.x;
frame.y_hidden = head_y + bevel_width - border_width - frame.height;
2003-07-10 11:48:14 +00:00
if (m_shape.get())
m_shape->setPlaces(Shape::BOTTOMRIGHT | Shape::BOTTOMLEFT);
break;
case TOPRIGHT:
frame.x = head_x + head_w - frame.width - border_width*2;
frame.y = head_y;
frame.x_hidden = frame.x;
2003-07-10 11:48:14 +00:00
if (m_shape.get())
m_shape->setPlaces(Shape::BOTTOMRIGHT | Shape::BOTTOMLEFT);
break;
case BOTTOMRIGHT:
frame.x = head_x + head_w - frame.width - border_width*2;
frame.y = head_y + head_h - frame.height - border_width*2;
frame.x_hidden = frame.x;
frame.y_hidden = head_y + head_h - bevel_width - border_width;
2003-07-10 11:48:14 +00:00
if (m_shape.get())
m_shape->setPlaces(Shape::TOPRIGHT | Shape::TOPLEFT);
break;
case BOTTOMCENTER: // default is BOTTOMCENTER
default:
2002-12-03 17:02:53 +00:00
frame.x = head_x + (head_w - frame.width) / 2;
frame.y = head_y + head_h - frame.height - border_width*2;
frame.x_hidden = frame.x;
frame.y_hidden = head_y + head_h - bevel_width - border_width;
2003-07-10 11:48:14 +00:00
if (m_shape.get())
m_shape->setPlaces(Shape::TOPRIGHT | Shape::TOPLEFT);
break;
2002-12-03 17:02:53 +00:00
case LEFTCENTER:
2002-12-04 17:58:01 +00:00
frame.x = head_x;
2002-12-03 17:02:53 +00:00
frame.y = head_y + (head_h - frame.height)/2;
frame.x_hidden = frame.x - frame.width + bevel_width + border_width;
2002-12-04 17:58:01 +00:00
frame.y_hidden = frame.y;
2003-07-10 11:48:14 +00:00
if (m_shape.get())
m_shape->setPlaces(Shape::TOPRIGHT | Shape::BOTTOMRIGHT);
2002-12-04 17:58:01 +00:00
break;
case LEFTTOP:
frame.x = head_x;
frame.y = head_y;
frame.x_hidden = frame.x - frame.width + bevel_width + border_width;
2002-12-04 17:58:01 +00:00
frame.y_hidden = frame.y;
2003-07-10 11:48:14 +00:00
if (m_shape.get())
m_shape->setPlaces(Shape::TOPRIGHT | Shape::BOTTOMRIGHT);
2002-12-04 17:58:01 +00:00
break;
case LEFTBOTTOM:
frame.x = head_x;
frame.y = head_y + head_h - frame.height - border_width*2;
frame.x_hidden = frame.x - frame.width + bevel_width + border_width;
2002-12-04 17:58:01 +00:00
frame.y_hidden = frame.y;
2003-07-10 11:48:14 +00:00
if (m_shape.get())
m_shape->setPlaces(Shape::TOPRIGHT | Shape::BOTTOMRIGHT);
2002-12-04 17:58:01 +00:00
break;
case RIGHTCENTER:
frame.x = head_x + head_w - frame.width - border_width*2;
2002-12-04 17:58:01 +00:00
frame.y = head_y + (head_h - frame.height)/2;
frame.x_hidden = frame.x + frame.width - bevel_width - border_width;
2002-12-04 17:58:01 +00:00
frame.y_hidden = frame.y;
2003-07-10 11:48:14 +00:00
if (m_shape.get())
m_shape->setPlaces(Shape::TOPLEFT | Shape::BOTTOMLEFT);
2002-12-04 17:58:01 +00:00
break;
case RIGHTTOP:
frame.x = head_x + head_w - frame.width - border_width*2;
2002-12-04 17:58:01 +00:00
frame.y = head_y;
frame.x_hidden = frame.x + frame.width - bevel_width - border_width;
2002-12-04 17:58:01 +00:00
frame.y_hidden = frame.y;
2003-07-10 11:48:14 +00:00
if (m_shape.get())
m_shape->setPlaces(Shape::TOPLEFT | Shape::BOTTOMLEFT);
2002-12-04 17:58:01 +00:00
break;
case RIGHTBOTTOM:
frame.x = head_x + head_w - frame.width - border_width*2;
frame.y = head_y + head_h - frame.height - border_width*2;
frame.x_hidden = frame.x + frame.width - bevel_width - border_width;
2002-12-03 17:02:53 +00:00
frame.y_hidden = frame.y;
2003-07-10 11:48:14 +00:00
if (m_shape.get())
m_shape->setPlaces(Shape::TOPLEFT | Shape::BOTTOMLEFT);
2002-12-03 17:02:53 +00:00
break;
}
}
2002-12-03 17:02:53 +00:00
2003-08-11 15:56:10 +00:00
void Toolbar::toggleHidden() {
m_hide_timer.fireOnce(true);
2002-12-01 13:42:15 +00:00
// toggle hidden
2003-08-11 15:56:10 +00:00
m_hidden = ! m_hidden;
if (isHidden())
frame.window.move(frame.x_hidden, frame.y_hidden);
else
frame.window.move(frame.x, frame.y);
2001-12-11 20:47:02 +00:00
}
void Toolbar::moveToLayer(int layernum) {
m_layeritem.moveToLayer(layernum);
*m_rc_layernum = layernum;
}
void Toolbar::setupMenus() {
Toolbar &tbar = *this;
I18n *i18n = I18n::instance();
using namespace FBNLS;
using namespace FbTk;
FbTk::Menu &menu = tbar.menu();
2003-08-11 20:22:38 +00:00
//!! TODO: this should be inserted by the workspace tool
2003-08-11 20:22:38 +00:00
RefCount<Command> start_edit(new FbCommands::SetWorkspaceNameCmd());
menu.insert(i18n->getMessage(FBNLS::ToolbarSet, FBNLS::ToolbarEditWkspcName,
"Edit current workspace name"),
start_edit);
menu.setLabel(i18n->getMessage(FBNLS::ToolbarSet, FBNLS::ToolbarToolbarTitle,
"Toolbar"));
FbTk::MenuItem *toolbar_menuitem = new IntResMenuItem("Toolbar width percent",
m_rc_width_percent,
0, 100); // min/max value
FbTk::RefCount<FbTk::Command> reconfig_toolbar(new FbTk::
SimpleCommand<Toolbar>
(tbar, &Toolbar::reconfigure));
FbTk::RefCount<FbTk::Command> save_resources(new FbCommands::SaveResources());
FbTk::MacroCommand *toolbar_menuitem_macro = new FbTk::MacroCommand();
toolbar_menuitem_macro->add(reconfig_toolbar);
toolbar_menuitem_macro->add(save_resources);
FbTk::RefCount<FbTk::Command> reconfig_toolbar_and_save_resource(toolbar_menuitem_macro);
toolbar_menuitem->setCommand(reconfig_toolbar_and_save_resource);
menu.insert(toolbar_menuitem);
menu.insert(new BoolMenuItem(i18n->getMessage(FBNLS::CommonSet, FBNLS::CommonAutoHide,
"Auto hide"),
*m_rc_auto_hide,
reconfig_toolbar_and_save_resource));
menu.insert(new BoolMenuItem("Maximize Over", *m_rc_maximize_over,
reconfig_toolbar_and_save_resource));
menu.insert("Layer...", &tbar.layermenu());
if (tbar.screen().hasXinerama()) {
// TODO: nls (main label plus menu heading
menu.insert("On Head...", new XineramaHeadMenu<Toolbar>(
2003-08-11 20:22:38 +00:00
*tbar.screen().menuTheme(),
tbar.screen(),
tbar.screen().imageControl(),
*tbar.screen().layerManager().getLayer(Fluxbox::instance()->getMenuLayer()),
tbar,
"Toolbar on Head"
));
}
// setup items in placement menu
struct {
int set;
int base;
const char *default_str;
Toolbar::Placement placement;
} place_menu[] = {
{0, 0, "Top Left", Toolbar::TOPLEFT},
2003-08-15 15:29:10 +00:00
{0, 0, "Left Top", Toolbar::LEFTTOP},
{0, 0, "Left Center", Toolbar::LEFTCENTER},
{0, 0, "Left Bottom", Toolbar::LEFTBOTTOM},
2003-08-15 15:29:10 +00:00
{0, 0, "Bottom Left", Toolbar::BOTTOMLEFT},
{0, 0, "Top Center", Toolbar::TOPCENTER},
{0, 0, 0, Toolbar::TOPCENTER},
{0, 0, 0, Toolbar::BOTTOMCENTER},
{0, 0, 0, Toolbar::BOTTOMCENTER},
{0, 0, "Bottom Center", Toolbar::BOTTOMCENTER},
{0, 0, "Top Right", Toolbar::TOPRIGHT},
2003-08-15 15:29:10 +00:00
{0, 0, "Right Top", Toolbar::RIGHTTOP},
{0, 0, "Right Center", Toolbar::RIGHTCENTER},
{0, 0, "Right Bottom", Toolbar::RIGHTBOTTOM},
2003-08-15 15:29:10 +00:00
{0, 0, "Bottom Right", Toolbar::BOTTOMRIGHT}
};
tbar.placementMenu().setMinimumSublevels(3);
// create items in sub menu
for (size_t i=0; i<15; ++i) {
if (place_menu[i].default_str == 0) {
tbar.placementMenu().insert("");
} else {
const char *i18n_str = i18n->getMessage(place_menu[i].set,
place_menu[i].base,
place_menu[i].default_str);
RefCount<FbTk::Command> setplace(new SetToolbarPlacementCmd(tbar, place_menu[i].placement));
tbar.placementMenu().insert(i18n_str, setplace);
}
}
menu.insert("Placement", &tbar.placementMenu());
tbar.placementMenu().update();
menu.update();
}
void Toolbar::saveOnHead(int head) {
m_rc_on_head = head;
reconfigure();
}
void Toolbar::rearrangeItems() {
2003-08-28 13:58:18 +00:00
if (m_resize_lock || screen().isShuttingdown() ||
m_item_list.size() == 0)
return;
// lock this
m_resize_lock = true;
// calculate size for fixed items
ItemList::iterator item_it = m_item_list.begin();
ItemList::iterator item_it_end = m_item_list.end();
int fixed_width = 0; // combined size of all fixed items
int fixed_items = 0; // number of fixed items
for (; item_it != item_it_end; ++item_it) {
if ((*item_it)->type() == ToolbarItem::FIXED) {
fixed_width += (*item_it)->width() + (*item_it)->borderWidth()*2;
fixed_items++;
}
}
// calculate what's going to be left over to the relative sized items
int relative_width = 0;
if (fixed_items == 0) // no fixed items, then the rest is the entire width
relative_width = width();
else {
const int relative_items = m_item_list.size() - fixed_items;
if (relative_items == 0)
relative_width = 0;
else // size left after fixed items / number of relative items
relative_width = (width() - fixed_width)/relative_items;
}
// now move and resize the items
int next_x = m_item_list.front()->borderWidth();
for (item_it = m_item_list.begin(); item_it != item_it_end; ++item_it) {
if ((*item_it)->type() == ToolbarItem::RELATIVE) {
(*item_it)->moveResize(next_x, 0, relative_width, height());
} else { // fixed size
(*item_it)->moveResize(next_x, 0,
(*item_it)->width(), height());
}
next_x += (*item_it)->width() + (*item_it)->borderWidth()*2;
}
// unlock
m_resize_lock = false;
}
2003-08-28 13:58:18 +00:00
void Toolbar::deleteItems() {
while (!m_item_list.empty()) {
delete m_item_list.back();
m_item_list.pop_back();
}
m_tools.clear();
}