1
// Toolbar.cc for Fluxbox
2
// Copyright (c) 2002 - 2005 Henrik Kinnunen (fluxgen at fluxbox dot org)
4
// Toolbar.cc for Blackbox - an X11 Window manager
5
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
7
// Permission is hereby granted, free of charge, to any person obtaining a
8
// copy of this software and associated documentation files (the "Software"),
9
// to deal in the Software without restriction, including without limitation
10
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
// and/or sell copies of the Software, and to permit persons to whom the
12
// Software is furnished to do so, subject to the following conditions:
14
// The above copyright notice and this permission notice shall be included in
15
// all copies or substantial portions of the Software.
17
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
// DEALINGS IN THE SOFTWARE.
25
// $Id: Toolbar.cc 4068 2005-06-28 10:16:59Z mathias $
30
#include "ToolbarItem.hh"
33
#include "ToolbarTheme.hh"
35
#include "FbTk/I18n.hh"
38
#include "IntResMenuItem.hh"
39
#include "BoolMenuItem.hh"
40
#include "Xinerama.hh"
42
#include "CommandParser.hh"
44
#include "FbTk/ImageControl.hh"
45
#include "FbTk/MacroCommand.hh"
46
#include "FbTk/EventManager.hh"
47
#include "FbTk/SimpleCommand.hh"
48
#include "FbTk/StringUtil.hh"
49
#include "FbTk/Transparent.hh"
59
#endif // HAVE_CONFIG_H
63
#include <X11/Xutil.h>
64
#include <X11/keysym.h>
79
void FbTk::Resource<Toolbar::Placement>::
80
setFromString(const char *strval) {
81
if (strcasecmp(strval, "TopLeft")==0)
82
m_value = Toolbar::TOPLEFT;
83
else if (strcasecmp(strval, "BottomLeft")==0)
84
m_value = Toolbar::BOTTOMLEFT;
85
else if (strcasecmp(strval, "TopCenter")==0)
86
m_value = Toolbar::TOPCENTER;
87
else if (strcasecmp(strval, "BottomCenter")==0)
88
m_value = Toolbar::BOTTOMCENTER;
89
else if (strcasecmp(strval, "TopRight")==0)
90
m_value = Toolbar::TOPRIGHT;
91
else if (strcasecmp(strval, "BottomRight")==0)
92
m_value = Toolbar::BOTTOMRIGHT;
93
else if (strcasecmp(strval, "LeftTop") == 0)
94
m_value = Toolbar::LEFTTOP;
95
else if (strcasecmp(strval, "LeftCenter") == 0)
96
m_value = Toolbar::LEFTCENTER;
97
else if (strcasecmp(strval, "LeftBottom") == 0)
98
m_value = Toolbar::LEFTBOTTOM;
99
else if (strcasecmp(strval, "RightTop") == 0)
100
m_value = Toolbar::RIGHTTOP;
101
else if (strcasecmp(strval, "RightCenter") == 0)
102
m_value = Toolbar::RIGHTCENTER;
103
else if (strcasecmp(strval, "RightBottom") == 0)
104
m_value = Toolbar::RIGHTBOTTOM;
110
string FbTk::Resource<Toolbar::Placement>::
113
case Toolbar::TOPLEFT:
114
return string("TopLeft");
116
case Toolbar::BOTTOMLEFT:
117
return string("BottomLeft");
119
case Toolbar::TOPCENTER:
120
return string("TopCenter");
122
case Toolbar::BOTTOMCENTER:
123
return string("BottomCenter");
125
case Toolbar::TOPRIGHT:
126
return string("TopRight");
128
case Toolbar::BOTTOMRIGHT:
129
return string("BottomRight");
131
case Toolbar::LEFTTOP:
132
return string("LeftTop");
134
case Toolbar::LEFTCENTER:
135
return string("LeftCenter");
137
case Toolbar::LEFTBOTTOM:
138
return string("LeftBottom");
140
case Toolbar::RIGHTTOP:
141
return string("RightTop");
143
case Toolbar::RIGHTCENTER:
144
return string("RightCenter");
146
case Toolbar::RIGHTBOTTOM:
147
return string("RightBottom");
151
return string("BottomCenter");
157
class SetToolbarPlacementCmd: public FbTk::Command {
159
SetToolbarPlacementCmd(Toolbar &tbar, Toolbar::Placement place):m_tbar(tbar), m_place(place) { }
161
m_tbar.setPlacement(m_place);
162
m_tbar.reconfigure();
163
Fluxbox::instance()->save_rc();
167
Toolbar::Placement m_place;
173
Toolbar::Frame::Frame(FbTk::EventHandler &evh, int screen_num):
174
window(screen_num, // screen (parent)
178
ButtonPressMask | ButtonReleaseMask | ExposureMask |
179
EnterWindowMask | LeaveWindowMask | SubstructureNotifyMask,
181
true) // override redirect
184
FbTk::EventManager &evm = *FbTk::EventManager::instance();
185
// add windows to eventmanager
186
evm.add(evh, window);
190
Toolbar::Frame::~Frame() {
191
FbTk::EventManager &evm = *FbTk::EventManager::instance();
192
// remove windows from eventmanager
196
Toolbar::Toolbar(BScreen &scrn, FbTk::XLayer &layer, size_t width):
198
frame(*this, scrn.screenNumber()),
201
m_layeritem(frame.window, layer),
202
m_layermenu(scrn.menuTheme(),
204
*scrn.layerManager().getLayer(Fluxbox::instance()->getMenuLayer()),
207
m_placementmenu(scrn.menuTheme(),
209
*scrn.layerManager().getLayer(Fluxbox::instance()->getMenuLayer())),
210
m_toolbarmenu(scrn.menuTheme(),
212
*scrn.layerManager().getLayer(Fluxbox::instance()->getMenuLayer())),
213
m_theme(scrn.screenNumber()),
214
m_tool_factory(scrn),
216
// lock rcmanager here
217
m_rc_auto_hide(scrn.resourceManager().lock(), false,
218
scrn.name() + ".toolbar.autoHide", scrn.altName() + ".Toolbar.AutoHide"),
219
m_rc_maximize_over(scrn.resourceManager(), false,
220
scrn.name() + ".toolbar.maxOver", scrn.altName() + ".Toolbar.MaxOver"),
221
m_rc_visible(scrn.resourceManager(), true, scrn.name() + ".toolbar.visible", scrn.altName() + ".Toolbar.Visible"),
222
m_rc_width_percent(scrn.resourceManager(), 65,
223
scrn.name() + ".toolbar.widthPercent", scrn.altName() + ".Toolbar.WidthPercent"),
224
m_rc_alpha(scrn.resourceManager(), 255,
225
scrn.name() + ".toolbar.alpha", scrn.altName() + ".Toolbar.Alpha"),
226
m_rc_layernum(scrn.resourceManager(), Fluxbox::Layer(Fluxbox::instance()->getDesktopLayer()),
227
scrn.name() + ".toolbar.layer", scrn.altName() + ".Toolbar.Layer"),
228
m_rc_on_head(scrn.resourceManager(), 0,
229
scrn.name() + ".toolbar.onhead", scrn.altName() + ".Toolbar.onHead"),
230
m_rc_placement(scrn.resourceManager(), Toolbar::BOTTOMCENTER,
231
scrn.name() + ".toolbar.placement", scrn.altName() + ".Toolbar.Placement"),
232
m_rc_height(scrn.resourceManager(), 0, scrn.name() + ".toolbar.height", scrn.altName() + ".Toolbar.Height"),
233
m_rc_tools(scrn.resourceManager(), "workspacename, prevworkspace, nextworkspace, iconbar, systemtray, prevwindow, nextwindow, clock",
234
scrn.name() + ".toolbar.tools", scrn.altName() + ".Toolbar.Tools"),
235
m_shape(new Shape(frame.window, 0)),
236
m_resize_lock(false) {
238
// we need to get notified when the theme is reloaded
239
m_theme.reconfigSig().attach(this);
240
// listen to screen size changes
241
screen().resizeSig().attach(this);
242
screen().reconfigureSig().attach(this); // get this on antialias change
244
moveToLayer((*m_rc_layernum).getNum());
246
m_layermenu.setLabel(_FBTEXT(Toolbar, Layer, "Toolbar Layer", "Title of toolbar layer menu"));
247
m_placementmenu.setLabel(_FBTEXT(Toolbar, Placement, "Toolbar Placement", "Title of toolbar placement menu"));
249
m_layermenu.setInternalMenu();
250
m_placementmenu.setInternalMenu();
252
// add menu to screen
253
screen().addConfigMenu(_FBTEXT(Toolbar, Toolbar, "Toolbar", "title of toolbar menu item"), menu());
259
frame.grab_x = frame.grab_y = 0;
262
m_hide_timer.setTimeout(Fluxbox::instance()->getAutoRaiseDelay());
263
FbTk::RefCount<FbTk::Command> toggle_hidden(new FbTk::SimpleCommand<Toolbar>(*this, &Toolbar::toggleHidden));
264
m_hide_timer.setCommand(toggle_hidden);
265
m_hide_timer.fireOnce(true);
269
frame.window.showSubwindows();
270
// frame.window.show();
272
scrn.resourceManager().unlock();
273
// setup to listen to child events
274
FbTk::EventManager::instance()->addParent(*this, window());
275
// get everything together
277
// this gets done by the screen later as it loads
281
Toolbar::~Toolbar() {
282
FbTk::EventManager::instance()->remove(window());
283
// remove menu items before we delete tools so we dont end up
284
// with dangling pointers to old submenu items (internal menus)
292
screen().imageControl().removeImage(m_window_pm);
295
void Toolbar::clearStrut() {
297
screen().clearStrut(m_strut);
302
void Toolbar::updateStrut() {
304
bool had_strut = m_strut ? true : false;
306
// we should request space if we're in autohide mode or
307
// if the user dont want to request space for toolbar.
308
if (doAutoHide() || *m_rc_maximize_over || ! *m_rc_visible) {
310
screen().updateAvailableWorkspaceArea();
314
// request area on screen
315
int top = 0, bottom = 0, left = 0, right = 0;
316
switch (placement()) {
320
top = height() + 2 * theme().border().width();
325
bottom = height() + 2 * theme().border().width();
330
right = width() + 2 * theme().border().width();
335
left = width() + 2 * theme().border().width();
338
m_strut = screen().requestStrut(getOnHead(), left, right, top, bottom);
339
screen().updateAvailableWorkspaceArea();
342
bool Toolbar::isVertical() const {
343
return (placement() == RIGHTCENTER ||
344
placement() == RIGHTTOP ||
345
placement() == RIGHTBOTTOM ||
346
placement() == LEFTCENTER ||
347
placement() == LEFTTOP ||
348
placement() == LEFTBOTTOM);
352
void Toolbar::raise() {
356
void Toolbar::lower() {
360
void Toolbar::reconfigure() {
361
// updateVisibleState();
363
if (!doAutoHide() && isHidden())
366
m_tool_factory.updateThemes();
368
// parse resource tools and determine if we need to rebuild toolbar
370
bool need_update = false;
371
// parse and transform to lower case
372
std::list<std::string> tools;
373
FbTk::StringUtil::stringtok(tools, *m_rc_tools, ", ");
374
transform(tools.begin(),
377
FbTk::StringUtil::toLower);
379
if (!tools.empty() && tools.size() == m_tools.size()) {
380
StringList::const_iterator tool_it = tools.begin();
381
StringList::const_iterator current_tool_it = m_tools.begin();
382
StringList::const_iterator tool_it_end = tools.end();
383
for (; tool_it != tool_it_end; ++tool_it, ++current_tool_it) {
384
if (*current_tool_it != *tool_it)
387
// did we find anything that wasn't in the right place or new item?
388
if (tool_it != tool_it_end)
390
} else // sizes does not match so we update
395
// destroy tools and rebuild them
398
m_tools = tools; // copy values
400
if (m_tools.size()) {
402
transform(m_tools.begin(), m_tools.end(),
404
FbTk::StringUtil::toLower);
407
StringList::const_iterator item_it = m_tools.begin();
408
StringList::const_iterator item_it_end = m_tools.end();
409
for (; item_it != item_it_end; ++item_it) {
410
ToolbarItem *item = m_tool_factory.create(*item_it, frame.window, *this);
413
m_item_list.push_back(item);
414
item->resizeSig().attach(this);
418
frame.window.showSubwindows();
423
m_hide_timer.start();
425
frame.bevel_w = theme().bevelWidth();
426
// destroy shape if the theme wasn't specified with one,
428
if (theme().shape() == false && m_shape.get())
430
else if (theme().shape() && m_shape.get() == 0) {
431
m_shape.reset(new Shape(frame.window, 0));
435
setPlacement(placement());
438
frame.window.moveResize(frame.x_hidden, frame.y_hidden,
439
frame.width, frame.height);
441
frame.window.moveResize(frame.x, frame.y,
442
frame.width, frame.height);
445
// render frame window
446
Pixmap tmp = m_window_pm;
447
if (!theme().toolbar().usePixmap()) {
449
frame.window.setBackgroundColor(theme().toolbar().color());
451
m_window_pm = screen().imageControl().renderImage(frame.window.width(), frame.window.height(),
453
frame.window.setBackgroundPixmap(m_window_pm);
456
screen().imageControl().removeImage(tmp);
458
frame.window.setBorderColor(theme().border().color());
459
frame.window.setBorderWidth(theme().border().width());
461
bool have_composite = FbTk::Transparent::haveComposite();
462
if (have_composite) {
463
frame.window.setOpaque(alpha());
465
frame.window.setAlpha(alpha());
467
frame.window.clear();
469
if (theme().shape() && m_shape.get())
472
ItemList::iterator item_it = m_item_list.begin();
473
ItemList::iterator item_it_end = m_item_list.end();
474
for (; item_it != item_it_end; ++item_it) {
475
(*item_it)->updateSizing();
480
for (item_it = m_item_list.begin(); item_it != item_it_end; ++item_it) {
481
(*item_it)->renderTheme(alpha());
484
menu().reconfigure();
485
// we're done with all resizing and stuff now we can request a new
486
// area to be reserved on screen
493
void Toolbar::buttonPressEvent(XButtonEvent &be) {
497
screen().hideMenus();
499
if (! menu().isVisible()) {
501
int head = screen().getHead(be.x_root, be.y_root);
502
int borderw = menu().fbwindow().borderWidth();
503
pair<int, int> m = screen().clampToHead(head,
504
be.x_root - (menu().width() / 2),
505
be.y_root - (menu().titleWindow().height() / 2),
506
menu().width() + 2*borderw,
507
menu().height() + 2*borderw);
509
menu().setScreen(screen().getHeadX(head),
510
screen().getHeadY(head),
511
screen().getHeadWidth(head),
512
screen().getHeadHeight(head));
513
menu().move(m.first, m.second);
515
menu().grabInputFocus();
522
void Toolbar::buttonReleaseEvent(XButtonEvent &re) {
525
else if (re.button == 4) //mousewheel scroll up
526
screen().nextWorkspace(1);
527
else if (re.button == 5) //mousewheel scroll down
528
screen().prevWorkspace(1);
531
void Toolbar::enterNotifyEvent(XCrossingEvent ¬_used) {
532
if (! doAutoHide()) {
539
if (! m_hide_timer.isTiming())
540
m_hide_timer.start();
542
if (m_hide_timer.isTiming())
547
void Toolbar::leaveNotifyEvent(XCrossingEvent &event) {
551
if (event.x_root > x() && event.x_root <= (int)(x() + width()) &&
552
event.y_root > y() && event.y_root <= (int)(y() + height()))
556
if (m_hide_timer.isTiming())
558
} else if (! menu().isVisible() && ! m_hide_timer.isTiming())
559
m_hide_timer.start();
564
void Toolbar::exposeEvent(XExposeEvent &ee) {
565
if (ee.window == frame.window) {
566
frame.window.clearArea(ee.x, ee.y,
567
ee.width, ee.height);
572
void Toolbar::handleEvent(XEvent &event) {
573
/* Commented out by Simon 16jun04, since it causes LOTS of rearrangeItems
574
particularly on startup. This was needed to resize when tool changes its own
575
size, but it has too many side effects. Use the resizeSig in ToolbarItem instead.
577
if (event.type == ConfigureNotify &&
578
event.xconfigure.window != window().window()) {
584
void Toolbar::update(FbTk::Subject *subj) {
586
// either screen reconfigured, theme was reloaded
587
// or a tool resized itself
589
if (typeid(*subj) == typeid(ToolbarItem::ToolbarItemSubject))
596
void Toolbar::setPlacement(Toolbar::Placement where) {
597
// disable vertical toolbar
605
where = BOTTOMCENTER;
611
*m_rc_placement = where;
614
head_w = screen().width(),
615
head_h = screen().height();
617
if (screen().hasXinerama()) {
618
int head = *m_rc_on_head;
619
head_x = screen().getHeadX(head);
620
head_y = screen().getHeadY(head);
621
head_w = screen().getHeadWidth(head);
622
head_h = screen().getHeadHeight(head);
625
int bevel_width = theme().bevelWidth();
626
int border_width = theme().border().width();
628
frame.width = (head_w - 2*border_width) * (*m_rc_width_percent) / 100;
629
//!! TODO: change this
630
// max height of each toolbar items font...
631
unsigned int max_height = m_tool_factory.maxFontHeight();
633
if (theme().height() > 0)
634
max_height = theme().height();
636
if (*m_rc_height > 0 && *m_rc_height < 100)
637
max_height = *m_rc_height;
639
frame.height = max_height;
642
frame.height += (frame.bevel_w * 2);
644
// should we flipp sizes?
646
frame.width = frame.height;
647
frame.height = head_h * (*m_rc_width_percent) / 100;
649
} // else horizontal toolbar
652
// So we get at least one pixel visible in hidden mode
653
if (bevel_width <= border_width)
654
bevel_width = border_width + 1;
660
frame.x_hidden = head_x;
661
frame.y_hidden = head_y + bevel_width - border_width - frame.height;
663
m_shape->setPlaces(Shape::BOTTOMRIGHT | Shape::BOTTOMLEFT);
668
frame.y = head_y + head_h - frame.height - border_width*2;
669
frame.x_hidden = head_x;
670
frame.y_hidden = head_y + head_h - bevel_width - border_width;
672
m_shape->setPlaces(Shape::TOPRIGHT | Shape::TOPLEFT);
676
frame.x = head_x + (head_w - frame.width) / 2 - border_width;
678
frame.x_hidden = frame.x;
679
frame.y_hidden = head_y + bevel_width - border_width - frame.height;
681
m_shape->setPlaces(Shape::BOTTOMRIGHT | Shape::BOTTOMLEFT);
684
frame.x = head_x + head_w - frame.width - border_width*2;
686
frame.x_hidden = frame.x;
687
frame.y_hidden = head_y + bevel_width - border_width - frame.height;
689
m_shape->setPlaces(Shape::BOTTOMRIGHT | Shape::BOTTOMLEFT);
693
frame.x = head_x + head_w - frame.width - border_width*2;
694
frame.y = head_y + head_h - frame.height - border_width*2;
695
frame.x_hidden = frame.x;
696
frame.y_hidden = head_y + head_h - bevel_width - border_width;
698
m_shape->setPlaces(Shape::TOPRIGHT | Shape::TOPLEFT);
701
case BOTTOMCENTER: // default is BOTTOMCENTER
703
frame.x = head_x + (head_w - frame.width) / 2 - border_width;
704
frame.y = head_y + head_h - frame.height - border_width*2;
705
frame.x_hidden = frame.x;
706
frame.y_hidden = head_y + head_h - bevel_width - border_width;
708
m_shape->setPlaces(Shape::TOPRIGHT | Shape::TOPLEFT);
712
frame.y = head_y + (head_h - frame.height)/2 - border_width;
713
frame.x_hidden = frame.x - frame.width + bevel_width + border_width;
714
frame.y_hidden = frame.y;
716
m_shape->setPlaces(Shape::TOPRIGHT | Shape::BOTTOMRIGHT);
721
frame.x_hidden = frame.x - frame.width + bevel_width + border_width;
722
frame.y_hidden = frame.y;
724
m_shape->setPlaces(Shape::TOPRIGHT | Shape::BOTTOMRIGHT);
728
frame.y = head_y + head_h - frame.height - border_width*2;
729
frame.x_hidden = frame.x - frame.width + bevel_width + border_width;
730
frame.y_hidden = frame.y;
732
m_shape->setPlaces(Shape::TOPRIGHT | Shape::BOTTOMRIGHT);
735
frame.x = head_x + head_w - frame.width - border_width*2;
736
frame.y = head_y + (head_h - frame.height)/2 - border_width;
737
frame.x_hidden = frame.x + frame.width - bevel_width - border_width;
738
frame.y_hidden = frame.y;
740
m_shape->setPlaces(Shape::TOPLEFT | Shape::BOTTOMLEFT);
743
frame.x = head_x + head_w - frame.width - border_width*2;
745
frame.x_hidden = frame.x + frame.width - bevel_width - border_width;
746
frame.y_hidden = frame.y;
748
m_shape->setPlaces(Shape::TOPLEFT | Shape::BOTTOMLEFT);
751
frame.x = head_x + head_w - frame.width - border_width*2;
752
frame.y = head_y + head_h - frame.height - border_width*2;
753
frame.x_hidden = frame.x + frame.width - bevel_width - border_width;
754
frame.y_hidden = frame.y;
756
m_shape->setPlaces(Shape::TOPLEFT | Shape::BOTTOMLEFT);
761
void Toolbar::updateVisibleState() {
762
*m_rc_visible ? frame.window.show() : frame.window.hide();
765
void Toolbar::toggleHidden() {
769
m_hidden = ! m_hidden;
771
frame.window.move(frame.x_hidden, frame.y_hidden);
773
frame.window.move(frame.x, frame.y);
777
void Toolbar::moveToLayer(int layernum) {
778
m_layeritem.moveToLayer(layernum);
779
*m_rc_layernum = layernum;
782
void Toolbar::setupMenus() {
784
using namespace FbTk;
786
typedef RefCount<Command> RefCommand;
787
typedef SimpleCommand<Toolbar> ToolbarCommand;
789
menu().setLabel(_FBTEXT(Toolbar, Toolbar,
790
"Toolbar", "Title of Toolbar menu"));
792
RefCommand reconfig_toolbar(new ToolbarCommand(*this, &Toolbar::reconfigure));
793
RefCommand save_resources(CommandParser::instance().parseLine("saverc"));
794
MacroCommand *toolbar_menuitem_macro = new MacroCommand();
795
toolbar_menuitem_macro->add(reconfig_toolbar);
796
toolbar_menuitem_macro->add(save_resources);
797
RefCommand reconfig_toolbar_and_save_resource(toolbar_menuitem_macro);
799
MacroCommand *visible_macro = new MacroCommand();
800
RefCommand toggle_visible(new ToolbarCommand(*this, &Toolbar::updateVisibleState));
801
visible_macro->add(toggle_visible);
802
visible_macro->add(reconfig_toolbar);
803
visible_macro->add(save_resources);
804
RefCommand toggle_visible_cmd(visible_macro);
805
menu().insert(new BoolMenuItem(_FBTEXT(Common, Visible, "Visible", "Whether this item is visible"),
806
*m_rc_visible, toggle_visible_cmd));
808
menu().insert(new BoolMenuItem(_FBTEXT(Common, AutoHide,
809
"Auto hide", "Toggle auto hide of toolbar"),
811
reconfig_toolbar_and_save_resource));
813
MenuItem *toolbar_menuitem = new IntResMenuItem(_FBTEXT(Toolbar, WidthPercent, "Toolbar width percent", "Percentage of screen width taken by toolbar"),
815
0, 100, menu()); // min/max value
818
toolbar_menuitem->setCommand(reconfig_toolbar_and_save_resource);
819
menu().insert(toolbar_menuitem);
821
menu().insert(new BoolMenuItem(_FBTEXT(Common, MaximizeOver,"Maximize Over", "Maximize over this thing when maximizing"),
823
reconfig_toolbar_and_save_resource));
824
menu().insert(_FBTEXT(Menu, Layer, "Layer...", "Title of Layer menu"), &layerMenu());
826
if (screen().hasXinerama()) {
827
menu().insert(_FBTEXT(Menu, OnHead, "On Head...", "Title of On Head menu"),
828
new XineramaHeadMenu<Toolbar>(screen().menuTheme(),
830
screen().imageControl(),
831
*screen().layerManager().getLayer(Fluxbox::instance()->getMenuLayer()),
833
_FBTEXT(Toolbar, OnHead, "Toolbar on Head", "Title of toolbar on head menu")));
836
typedef pair<const char*, Toolbar::Placement> PlacementP;
837
typedef list<PlacementP> Placements;
838
Placements place_menu;
840
// menu is 3 wide, 5 down
841
place_menu.push_back(PlacementP(_FBTEXT(Align, TopLeft, "Top Left", "Top Left"), Toolbar::TOPLEFT));
842
place_menu.push_back(PlacementP(_FBTEXT(Align, LeftTop, "Left Top", "Left Top"), Toolbar::LEFTTOP));
843
place_menu.push_back(PlacementP(_FBTEXT(Align, LeftCenter, "Left Center", "Left Center"), Toolbar::LEFTCENTER));
844
place_menu.push_back(PlacementP(_FBTEXT(Align, LeftBottom, "Left Bottom", "Left Bottom"), Toolbar::LEFTBOTTOM));
845
place_menu.push_back(PlacementP(_FBTEXT(Align, BottomLeft, "Bottom Left", "Bottom Left"), Toolbar::BOTTOMLEFT));
846
place_menu.push_back(PlacementP(_FBTEXT(Align, TopCenter, "Top Center", "Top Center"), Toolbar::TOPCENTER));
847
place_menu.push_back(PlacementP((const char *)0, Toolbar::TOPLEFT));
848
place_menu.push_back(PlacementP((const char *)0, Toolbar::TOPLEFT));
849
place_menu.push_back(PlacementP((const char *)0, Toolbar::TOPLEFT));
850
place_menu.push_back(PlacementP(_FBTEXT(Align, BottomCenter, "Bottom Center", "Bottom Center"), Toolbar::BOTTOMCENTER));
851
place_menu.push_back(PlacementP(_FBTEXT(Align, TopRight, "Top Right", "Top Right"), Toolbar::TOPRIGHT));
852
place_menu.push_back(PlacementP(_FBTEXT(Align, RightTop, "Right Top", "Right Top"), Toolbar::RIGHTTOP));
853
place_menu.push_back(PlacementP(_FBTEXT(Align, RightCenter, "Right Center", "Right Center"), Toolbar::RIGHTCENTER));
854
place_menu.push_back(PlacementP(_FBTEXT(Align, RightBottom, "Right Bottom", "Right Bottom"), Toolbar::RIGHTBOTTOM));
855
place_menu.push_back(PlacementP(_FBTEXT(Align, BottomRight, "Bottom Right", "Bottom Right"), Toolbar::BOTTOMRIGHT));
858
placementMenu().setMinimumSublevels(3);
859
// create items in sub menu
860
for (size_t i=0; i<15; ++i) {
861
const char *str = place_menu.front().first;
862
Toolbar::Placement placement = place_menu.front().second;
865
placementMenu().insert("");
866
placementMenu().setItemEnabled(i, false);
868
RefCommand setplace(new SetToolbarPlacementCmd(*this, placement));
869
placementMenu().insert(str, setplace);
872
place_menu.pop_front();
874
menu().insert(_FBTEXT(Menu, Placement, "Placement", "Title of Placement menu"), &placementMenu());
875
placementMenu().updateMenu();
878
// this saves resources and clears the slit window to update alpha value
879
FbTk::MenuItem *alpha_menuitem =
880
new IntResMenuItem(_FBTEXT(Common, Alpha, "Alpha", "Transparency level"),
883
// setup command for alpha value
884
MacroCommand *alpha_macrocmd = new MacroCommand();
885
RefCount<Command> alpha_cmd(new SimpleCommand<Toolbar>(*this, &Toolbar::updateAlpha));
886
alpha_macrocmd->add(save_resources);
887
alpha_macrocmd->add(alpha_cmd);
888
RefCount<Command> set_alpha_cmd(alpha_macrocmd);
889
alpha_menuitem->setCommand(set_alpha_cmd);
891
menu().insert(alpha_menuitem);
895
void Toolbar::saveOnHead(int head) {
901
* Place items next to each other, with a bevel width between,
902
* above and below each item. BUT, if there is no bevel width, then
903
* borders should be merged for evenness.
906
void Toolbar::rearrangeItems() {
907
if (m_resize_lock || screen().isShuttingdown() ||
912
m_resize_lock = true;
913
// calculate size for fixed items
914
ItemList::iterator item_it = m_item_list.begin();
915
ItemList::iterator item_it_end = m_item_list.end();
916
int bevel_width = theme().bevelWidth();
917
int fixed_width = bevel_width; // combined size of all fixed items
918
int fixed_items = 0; // number of fixed items
919
int relative_items = 0;
920
int last_bw = 0; // we show the largest border of adjoining items
922
for (; item_it != item_it_end; ++item_it) {
923
if (!(*item_it)->active())
926
int borderW = (*item_it)->borderWidth();
928
if (bevel_width > 0) {
929
// the bevel and border are fixed whether relative or not
930
fixed_width += bevel_width + 2*borderW;
933
if (borderW > last_bw)
934
fixed_width += borderW;
936
fixed_width += last_bw;
944
if ((*item_it)->type() == ToolbarItem::FIXED) {
945
fixed_width += (*item_it)->width();
947
} else if ((*item_it)->type() == ToolbarItem::SQUARE) {
948
fixed_width += height() - 2*bevel_width;
949
if (bevel_width != 0) fixed_width -= 2*borderW;
956
// calculate what's going to be le ft over to the relative sized items
957
int relative_width = 0;
958
int rounding_error = 0;
959
if (fixed_items == 0) // no fixed items, then the rest is the entire width
960
relative_width = width();
962
if (relative_items == 0)
964
else { // size left after fixed items / number of relative items
965
relative_width = (width() - fixed_width)/relative_items;
966
rounding_error = width() - fixed_width - relative_items*(relative_width);
970
// now move and resize the items
971
// borderWidth added back on straight away
972
int next_x = -m_item_list.front()->borderWidth(); // list isn't empty
973
if (bevel_width != 0)
977
for (item_it = m_item_list.begin(); item_it != item_it_end; ++item_it) {
978
int borderW = (*item_it)->borderWidth();
979
if (!(*item_it)->active()) {
981
// make sure it still gets told the toolbar height
982
(*item_it)->resize(1, height()-2*(bevel_width+borderW)); // width of 0 changes to 1 anyway
985
int offset = bevel_width;
986
int size_offset = 2*(borderW + bevel_width);
988
if (bevel_width == 0) {
991
if (borderW > last_bw)
998
if ((*item_it)->type() == ToolbarItem::RELATIVE) {
1000
if (rounding_error != 0) { // distribute rounding error over all relatives
1004
(*item_it)->moveResize(next_x + offset, offset, extra + relative_width, height() - size_offset);
1005
} else if ((*item_it)->type() == ToolbarItem::SQUARE) {
1006
(*item_it)->moveResize(next_x + offset, offset,
1007
height() - size_offset, height() - size_offset);
1008
} else { // fixed size
1009
(*item_it)->moveResize(next_x + offset, offset,
1010
(*item_it)->width(), height() - size_offset);
1013
next_x += (*item_it)->width() + bevel_width;
1014
if (bevel_width != 0)
1015
next_x += 2*borderW;
1019
m_resize_lock = false;
1020
frame.window.clear();
1023
void Toolbar::deleteItems() {
1024
while (!m_item_list.empty()) {
1025
delete m_item_list.back();
1026
m_item_list.pop_back();
1031
void Toolbar::updateAlpha() {
1032
// called when the alpha resource is changed
1033
if (FbTk::Transparent::haveComposite()) {
1034
frame.window.setOpaque(*m_rc_alpha);
1036
frame.window.setAlpha(*m_rc_alpha);
1037
frame.window.clear();
1039
ItemList::iterator item_it = m_item_list.begin();
1040
ItemList::iterator item_it_end = m_item_list.end();
1041
for (item_it = m_item_list.begin(); item_it != item_it_end; ++item_it) {
1042
(*item_it)->renderTheme(alpha());