xref: /haiku/src/apps/deskbar/WindowMenu.cpp (revision fce4895d1884da5ae6fb299d23c735c598e690b1)
1 /*
2 Open Tracker License
3 
4 Terms and Conditions
5 
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
14 
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
28 
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered
30 trademarks of Be Incorporated in the United States and other countries. Other
31 brand product names are registered trademarks or trademarks of their respective
32 holders.
33 All rights reserved.
34 */
35 
36 
37 #include "WindowMenu.h"
38 
39 #include <Catalog.h>
40 #include <Locale.h>
41 #include <Window.h>
42 
43 #include "BarApp.h"
44 #include "BarView.h"
45 #include "ShowHideMenuItem.h"
46 #include "TeamMenu.h"
47 #include "TeamMenuItem.h"
48 #include "tracker_private.h"
49 #include "WindowMenuItem.h"
50 
51 
52 const int32 kDesktopWindow = 1024;
53 const int32 kMenuWindow	= 1025;
54 const uint32 kWindowScreen = 1026;
55 const uint32 kNormalWindow = 0;
56 const int32 kTeamFloater = 4;
57 const int32 kListFloater = 5;
58 const int32 kSystemFloater = 6;
59 
60 
61 #undef B_TRANSLATION_CONTEXT
62 #define B_TRANSLATION_CONTEXT "WindowMenu"
63 
64 
65 //	#pragma mark - TWindowMenu
66 
67 
68 bool
69 TWindowMenu::WindowShouldBeListed(client_window_info* info)
70 {
71 	return ((info->feel == kNormalWindow || info->feel == kWindowScreen)
72 			// Window has the right feel
73 		&& info->show_hide_level <= 0);
74 			// Window is not hidden
75 }
76 
77 
78 TWindowMenu::TWindowMenu(const BList* team, const char* signature)
79 	:
80 	BMenu("Deskbar Team Menu"),
81 	fTeam(team),
82 	fApplicationSignature(signature),
83 	fExpanded(false),
84 	fExpandedIndex(0)
85 {
86 	SetItemMargins(0.0f, 0.0f, 0.0f, 0.0f);
87 }
88 
89 
90 void
91 TWindowMenu::AttachedToWindow()
92 {
93 	SetFont(be_plain_font);
94 	RemoveItems(0, CountItems(), true);
95 	int32 miniCount = 0;
96 
97 	bool dragging = false;
98 	TBarView* barview =(static_cast<TBarApp*>(be_app))->BarView();
99 	if (barview != NULL && barview->LockLooper()) {
100 		// 'dragging' mode set in BarView::CacheDragData
101 		// invoke in MouseEnter in ExpandoMenuBar
102 		dragging = barview->Dragging();
103 		if (dragging) {
104 			// We don't want to show the menu when dragging, but it's not
105 			// possible to remove a submenu once it exists, so we simply hide it
106 			// Don't call BMenu::Hide(), it causes the menu to pop up every now
107 			// and then.
108 			Window()->Hide();
109 			// if in expando (horizontal or vertical)
110 			if (barview->ExpandoState()) {
111 				SetTrackingHook(barview->MenuTrackingHook,
112 					barview->GetTrackingHookData());
113 			}
114 			barview->DragStart();
115 		}
116 		barview->UnlockLooper();
117 	}
118 
119 	int32 parentMenuItems = 0;
120 
121 	int32 teamCount = fTeam->CountItems();
122 	for (int32 i = 0; i < teamCount; i++) {
123 		team_id theTeam = (addr_t)fTeam->ItemAt(i);
124 		int32 tokenCount = 0;
125 		int32* tokens = get_token_list(theTeam, &tokenCount);
126 
127 		for (int32 j = 0; j < tokenCount; j++) {
128 			client_window_info* wInfo = get_window_info(tokens[j]);
129 			if (wInfo == NULL)
130 				continue;
131 
132 			if (WindowShouldBeListed(wInfo)) {
133 				// Don't add new items if we're expanded. We've already done
134 				// this, they've just been moved.
135 				int32 numItems = CountItems();
136 
137 				// Find first item that sorts alphabetically after this window,
138 				// so we know where to put it
139 				for (int32 addIndex = 0; addIndex < numItems; addIndex++) {
140 					TWindowMenuItem* item
141 						= static_cast<TWindowMenuItem*>(ItemAt(addIndex));
142 					if (item != NULL
143 						&& strcasecmp(item->Label(), wInfo->name) > 0) {
144 						break;
145 					}
146 				}
147 
148 				if (!fExpanded) {
149 					TWindowMenuItem* item = new TWindowMenuItem(wInfo->name,
150 						wInfo->server_token, wInfo->is_mini,
151 						((1 << current_workspace()) & wInfo->workspaces) != 0,
152 						dragging);
153 
154 					// disable app's window dropping for now
155 					if (dragging)
156 						item->SetEnabled(false);
157 
158 					AddItem(item,
159 						TWindowMenuItem::InsertIndexFor(this, 0, item));
160 				} else {
161 					TTeamMenuItem* parentItem
162 						= static_cast<TTeamMenuItem*>(Superitem());
163 					if (parentItem->ExpandedWindowItem(wInfo->server_token)) {
164 						TWindowMenuItem* item = parentItem->ExpandedWindowItem(
165 							wInfo->server_token);
166 						if (item == NULL)
167 							continue;
168 
169 						item->SetTo(wInfo->name, wInfo->server_token,
170 							wInfo->is_mini,
171 							((1 << current_workspace()) & wInfo->workspaces)
172 								!= 0, dragging);
173 						parentMenuItems++;
174 					}
175 				}
176 
177 				if (wInfo->is_mini)
178 					miniCount++;
179 			}
180 			free(wInfo);
181 		}
182 		free(tokens);
183 	}
184 
185 	int32 itemCount = CountItems() + parentMenuItems;
186 	if (itemCount < 1) {
187 		TWindowMenuItem* noWindowsItem
188 			= new TWindowMenuItem(B_TRANSLATE("No windows"), -1, false, false);
189 
190 		noWindowsItem->SetEnabled(false);
191 		AddItem(noWindowsItem);
192 
193 		// Add a 'Quit application' item if no windows are open
194 		// unless the application is Tracker
195 		if (fApplicationSignature.ICompare(kTrackerSignature) != 0) {
196 			AddSeparatorItem();
197 			AddItem(new TShowHideMenuItem(B_TRANSLATE("Quit application"),
198 				fTeam, B_QUIT_REQUESTED));
199 		}
200 	} else {
201 		// Only add the window controls to the menu if we are not in drag mode
202 		if (!dragging) {
203 			TShowHideMenuItem* hide
204 				= new TShowHideMenuItem(B_TRANSLATE("Hide all"), fTeam,
205 					B_MINIMIZE_WINDOW);
206 			TShowHideMenuItem* show
207 				= new TShowHideMenuItem(B_TRANSLATE("Show all"), fTeam,
208 					B_BRING_TO_FRONT);
209 			TShowHideMenuItem* close
210 				= new TShowHideMenuItem(B_TRANSLATE("Close all"), fTeam,
211 					B_QUIT_REQUESTED);
212 
213 			if (miniCount == itemCount)
214 				hide->SetEnabled(false);
215 			else if (miniCount == 0)
216 				show->SetEnabled(false);
217 
218 			if (!parentMenuItems)
219 				AddSeparatorItem();
220 
221 			AddItem(hide);
222 			AddItem(show);
223 			AddItem(close);
224 		}
225 	}
226 
227 	BMenu::AttachedToWindow();
228 }
229 
230 
231 void
232 TWindowMenu::DetachedFromWindow()
233 {
234 	// in expando mode the teammenu will not call DragStop, thus, it needs to
235 	// be called from here
236 	TBarView* barview = (dynamic_cast<TBarApp*>(be_app))->BarView();
237 	if (barview && barview->ExpandoState() && barview->Dragging()
238 		&& barview->LockLooper()) {
239 		// We changed the show level in AttachedToWindow(). Undo it.
240 		Window()->Show();
241 		barview->DragStop();
242 		barview->UnlockLooper();
243 	}
244 
245 	BMenu::DetachedFromWindow();
246 }
247 
248 
249 BPoint
250 TWindowMenu::ScreenLocation()
251 {
252 	return BMenu::ScreenLocation();
253 }
254 
255 
256 void
257 TWindowMenu::SetExpanded(bool status, int lastIndex)
258 {
259 	fExpanded = status;
260 	fExpandedIndex = lastIndex;
261 }
262