xref: /haiku/src/apps/deskbar/WindowMenu.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
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 <malloc.h>
40 #include <stdio.h>
41 #include <string.h>
42 
43 #include <Catalog.h>
44 #include <Locale.h>
45 #include <Window.h>
46 
47 #include "BarApp.h"
48 #include "BarView.h"
49 #include "ExpandoMenuBar.h"
50 #include "ShowHideMenuItem.h"
51 #include "TeamMenu.h"
52 #include "TeamMenuItem.h"
53 #include "tracker_private.h"
54 #include "WindowMenuItem.h"
55 
56 
57 const int32 kDesktopWindow = 1024;
58 const int32 kMenuWindow	= 1025;
59 const uint32 kWindowScreen = 1026;
60 const uint32 kNormalWindow = 0;
61 const int32 kTeamFloater = 4;
62 const int32 kListFloater = 5;
63 const int32 kSystemFloater = 6;
64 
65 
66 #undef B_TRANSLATION_CONTEXT
67 #define B_TRANSLATION_CONTEXT "WindowMenu"
68 
69 bool
70 TWindowMenu::WindowShouldBeListed(client_window_info* info)
71 {
72 	return ((info->feel == kNormalWindow || info->feel == kWindowScreen)
73 			// Window has the right feel
74 		&& info->show_hide_level <= 0);
75 			// Window is not hidden
76 }
77 
78 
79 TWindowMenu::TWindowMenu(const BList* team, const char* signature)
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 && 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->FullTitle(), wInfo->name) > 0)
144 						break;
145 				}
146 
147 				if (!fExpanded) {
148 					TWindowMenuItem* item = new TWindowMenuItem(wInfo->name,
149 						wInfo->server_token, wInfo->is_mini,
150 						((1 << current_workspace()) & wInfo->workspaces) != 0,
151 						dragging);
152 
153 					// disable app's window dropping for now
154 					if (dragging)
155 						item->SetEnabled(false);
156 
157 					AddItem(item,
158 						TWindowMenuItem::InsertIndexFor(this, 0, item));
159 				} else {
160 					TTeamMenuItem* parentItem
161 						= static_cast<TTeamMenuItem*>(Superitem());
162 					if (parentItem->ExpandedWindowItem(wInfo->server_token)) {
163 						TWindowMenuItem* item = parentItem->ExpandedWindowItem(
164 							wInfo->server_token);
165 						if (item == NULL)
166 							continue;
167 
168 						item->SetTo(wInfo->name, wInfo->server_token,
169 							wInfo->is_mini,
170 							((1 << current_workspace()) & wInfo->workspaces)
171 								!= 0, dragging);
172 						parentMenuItems++;
173 					}
174 				}
175 
176 				if (wInfo->is_mini)
177 					miniCount++;
178 			}
179 			free(wInfo);
180 		}
181 		free(tokens);
182 	}
183 
184 	int32 itemCount = CountItems() + parentMenuItems;
185 	if (itemCount < 1) {
186 		TWindowMenuItem* noWindowsItem
187 			= new TWindowMenuItem(B_TRANSLATE("No windows"), -1, false, false);
188 
189 		noWindowsItem->SetEnabled(false);
190 		AddItem(noWindowsItem);
191 
192 		// Add a 'Quit application' item if no windows are open
193 		// unless the application is Tracker
194 		if (fApplicationSignature.ICompare(kTrackerSignature) != 0) {
195 			AddSeparatorItem();
196 			AddItem(new TShowHideMenuItem(B_TRANSLATE("Quit application"),
197 				fTeam, B_QUIT_REQUESTED));
198 		}
199 	} else {
200 		// Only add the window controls to the menu if we are not in drag mode
201 		if (!dragging) {
202 			TShowHideMenuItem* hide
203 				= new TShowHideMenuItem(B_TRANSLATE("Hide all"), fTeam,
204 					B_MINIMIZE_WINDOW);
205 			TShowHideMenuItem* show
206 				= new TShowHideMenuItem(B_TRANSLATE("Show all"), fTeam,
207 					B_BRING_TO_FRONT);
208 			TShowHideMenuItem* close
209 				= new TShowHideMenuItem(B_TRANSLATE("Close all"), fTeam,
210 					B_QUIT_REQUESTED);
211 
212 			if (miniCount == itemCount)
213 				hide->SetEnabled(false);
214 			else if (miniCount == 0)
215 				show->SetEnabled(false);
216 
217 			if (!parentMenuItems)
218 				AddSeparatorItem();
219 
220 			AddItem(hide);
221 			AddItem(show);
222 			AddItem(close);
223 		}
224 	}
225 
226 	BMenu::AttachedToWindow();
227 }
228 
229 
230 void
231 TWindowMenu::DetachedFromWindow()
232 {
233 	// in expando mode the teammenu will not call DragStop, thus, it needs to
234 	// be called from here
235 	TBarView* barview = (dynamic_cast<TBarApp*>(be_app))->BarView();
236 	if (barview && barview->ExpandoState() && barview->Dragging()
237 		&& barview->LockLooper()) {
238 		// We changed the show level in AttachedToWindow(). Undo it.
239 		Window()->Show();
240 		barview->DragStop();
241 		barview->UnlockLooper();
242 	}
243 
244 	BMenu::DetachedFromWindow();
245 }
246 
247 
248 BPoint
249 TWindowMenu::ScreenLocation()
250 {
251 	return BMenu::ScreenLocation();
252 }
253 
254 
255 void
256 TWindowMenu::SetExpanded(bool status, int lastIndex)
257 {
258 	fExpanded = status;
259 	fExpandedIndex = lastIndex;
260 }
261