aboutsummaryrefslogtreecommitdiff
path: root/src/ClientMenu.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/ClientMenu.cc')
-rw-r--r--src/ClientMenu.cc146
1 files changed, 146 insertions, 0 deletions
diff --git a/src/ClientMenu.cc b/src/ClientMenu.cc
new file mode 100644
index 0000000..ae35aab
--- /dev/null
+++ b/src/ClientMenu.cc
@@ -0,0 +1,146 @@
1// ClientMenu.hh
2// Copyright (c) 2007 Fluxbox Team (fluxgen at fluxbox dot org)
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22// $Id$
23
24#include "ClientMenu.hh"
25
26#include "Layer.hh"
27#include "Screen.hh"
28#include "Window.hh"
29#include "WindowCmd.hh"
30
31#include "FbTk/MenuItem.hh"
32
33namespace { // anonymous
34
35class ClientMenuItem: public FbTk::MenuItem {
36public:
37 ClientMenuItem(Focusable &client, ClientMenu &menu):
38 FbTk::MenuItem(client.title().c_str(), menu),
39 m_client(client) {
40 client.titleSig().attach(&menu);
41 client.dieSig().attach(&menu);
42 }
43 ~ClientMenuItem() { m_client.titleSig().detach(menu()); }
44
45 void click(int button, int time) {
46 FluxboxWindow *fbwin = m_client.fbwindow();
47 if (fbwin == 0)
48 return;
49
50 // this MenuItem object can get destroyed as a result of focus(), so we
51 // must get a local copy of the parent menu
52 FbTk::Menu *parent = menu();
53
54 m_client.focus();
55 fbwin->raise();
56 parent->hide();
57 }
58
59 const std::string &label() const { return m_client.title(); }
60 const FbTk::PixmapWithMask *icon() const {
61 return m_client.screen().clientMenuUsePixmap() ? &m_client.icon() : 0;
62 }
63
64 bool isSelected() const {
65 if (m_client.fbwindow() == 0)
66 return false;
67 if (m_client.fbwindow()->isFocused() == false)
68 return false;
69 return (&(m_client.fbwindow()->winClient()) == &m_client);
70 }
71
72 // for updating menu when receiving a signal from client
73 Focusable *client() { return &m_client; }
74
75private:
76 Focusable &m_client;
77};
78
79}; // end anonymous namespace
80
81ClientMenu::ClientMenu(BScreen &screen, Focusables &clients,
82 FbTk::Subject *refresh):
83 FbMenu(screen.menuTheme(), screen.imageControl(),
84 *screen.layerManager().getLayer(Layer::MENU)),
85 m_list(clients),
86 m_refresh_sig(refresh) {
87
88 if (refresh)
89 refresh->attach(this);
90 refreshMenu();
91
92}
93
94void ClientMenu::refreshMenu() {
95 // remove all items and then add them again
96 removeAll();
97
98 // for each fluxboxwindow add every client in them to our clientlist
99 Focusables::iterator win_it = m_list.begin();
100 Focusables::iterator win_it_end = m_list.end();
101 for (; win_it != win_it_end; ++win_it) {
102 // add every client in this fluxboxwindow to menu
103 if (typeid(*win_it) == typeid(FluxboxWindow *)) {
104 FluxboxWindow *win = static_cast<FluxboxWindow *>(*win_it);
105 FluxboxWindow::ClientList::iterator client_it =
106 win->clientList().begin();
107 FluxboxWindow::ClientList::iterator client_it_end =
108 win->clientList().end();
109 for (; client_it != client_it_end; ++client_it)
110 insert(new ClientMenuItem(**client_it, *this));
111 } else
112 insert(new ClientMenuItem(**win_it, *this));
113 }
114
115 updateMenu();
116}
117
118void ClientMenu::update(FbTk::Subject *subj) {
119 if (subj == m_refresh_sig)
120 refreshMenu();
121 else if (subj && typeid(*subj) == typeid(Focusable::FocusSubject)) {
122
123 Focusable::FocusSubject *fsubj = static_cast<Focusable::FocusSubject *>(subj);
124 Focusable &win = fsubj->win();
125
126 // find the corresponding menuitem
127 ClientMenuItem *cl_item = 0;
128 for (size_t i = 0; i < numberOfItems(); i++) {
129 FbTk::MenuItem *item = find(i);
130 if (item && typeid(*item) == typeid(ClientMenuItem)) {
131 cl_item = static_cast<ClientMenuItem *>(item);
132 if (cl_item->client() == &win)
133 break;
134 }
135 }
136
137 // update accordingly
138 if (cl_item && fsubj == &win.dieSig())
139 remove(cl_item->getIndex());
140 else if (cl_item && fsubj == &win.titleSig())
141 // this could change the size of the menu, so do a full update
142 FbTk::Menu::update(subj);
143
144 } else
145 FbTk::Menu::update(subj);
146}