xref: /haiku/src/servers/bluetooth/DeskbarReplicant.cpp (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
1 /*
2  * Copyright 2009-2021, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Weirauch, dev@m-phasis.de
7  */
8 
9 
10 #include "DeskbarReplicant.h"
11 
12 #include <Alert.h>
13 #include <Application.h>
14 #include <Bitmap.h>
15 #include <Catalog.h>
16 #include <Deskbar.h>
17 #include <IconUtils.h>
18 #include <MenuItem.h>
19 #include <Message.h>
20 #include <PopUpMenu.h>
21 #include <Resources.h>
22 #include <Roster.h>
23 #include <String.h>
24 
25 #include <bluetoothserver_p.h>
26 
27 
28 extern "C" _EXPORT BView *instantiate_deskbar_item(float maxWidth, float maxHeight);
29 status_t our_image(image_info& image);
30 
31 const uint32 kMsgOpenBluetoothPreferences = 'obtp';
32 const uint32 kMsgQuitBluetoothServer = 'qbts';
33 
34 const char* kDeskbarItemName = "BluetoothServerReplicant";
35 const char* kClassName = "DeskbarReplicant";
36 
37 
38 #undef B_TRANSLATION_CONTEXT
39 #define B_TRANSLATION_CONTEXT "BluetoothReplicant"
40 
41 
42 //	#pragma mark -
43 
44 
45 DeskbarReplicant::DeskbarReplicant(BRect frame, int32 resizingMode)
46 	: BView(frame, kDeskbarItemName, resizingMode,
47 		B_WILL_DRAW | B_TRANSPARENT_BACKGROUND | B_FRAME_EVENTS)
48 {
49 	_Init();
50 }
51 
52 
53 DeskbarReplicant::DeskbarReplicant(BMessage* archive)
54 	: BView(archive)
55 {
56 	_Init();
57 }
58 
59 
60 DeskbarReplicant::~DeskbarReplicant()
61 {
62 }
63 
64 
65 void
66 DeskbarReplicant::_Init()
67 {
68 	fIcon = NULL;
69 
70 	image_info info;
71 	if (our_image(info) != B_OK)
72 		return;
73 
74 	BFile file(info.name, B_READ_ONLY);
75 	if (file.InitCheck() < B_OK)
76 		return;
77 
78 	BResources resources(&file);
79 	if (resources.InitCheck() < B_OK)
80 		return;
81 
82 	size_t size;
83 	const void* data = resources.LoadResource(B_VECTOR_ICON_TYPE,
84 		"tray_icon", &size);
85 	if (data != NULL) {
86 		BBitmap* icon = new BBitmap(Bounds(), B_RGBA32);
87 		if (icon->InitCheck() == B_OK
88 			&& BIconUtils::GetVectorIcon((const uint8 *)data,
89 				size, icon) == B_OK) {
90 			fIcon = icon;
91 		} else
92 			delete icon;
93 	}
94 }
95 
96 
97 DeskbarReplicant *
98 DeskbarReplicant::Instantiate(BMessage* archive)
99 {
100 	if (!validate_instantiation(archive, kClassName))
101 		return NULL;
102 
103 	return new DeskbarReplicant(archive);
104 }
105 
106 
107 status_t
108 DeskbarReplicant::Archive(BMessage* archive, bool deep) const
109 {
110 	status_t status = BView::Archive(archive, deep);
111 	if (status == B_OK)
112 		status = archive->AddString("add_on", BLUETOOTH_SIGNATURE);
113 	if (status == B_OK)
114 		status = archive->AddString("class", kClassName);
115 
116 	return status;
117 }
118 
119 
120 void
121 DeskbarReplicant::AttachedToWindow()
122 {
123 	BView::AttachedToWindow();
124 	AdoptParentColors();
125 
126 	if (ViewUIColor() == B_NO_COLOR)
127 		SetLowColor(ViewColor());
128 	else
129 		SetLowUIColor(ViewUIColor());
130 }
131 
132 
133 void
134 DeskbarReplicant::Draw(BRect updateRect)
135 {
136 	if (!fIcon) {
137 		/* At least display something... */
138 		rgb_color lowColor = LowColor();
139 		SetLowColor(0, 113, 187, 255);
140 		FillRoundRect(Bounds().InsetBySelf(3.f, 0.f), 5.f, 7.f, B_SOLID_LOW);
141 		SetLowColor(lowColor);
142 	} else {
143 		SetDrawingMode(B_OP_ALPHA);
144 		DrawBitmap(fIcon);
145 		SetDrawingMode(B_OP_COPY);
146 	}
147 }
148 
149 
150 void
151 DeskbarReplicant::MessageReceived(BMessage* msg)
152 {
153 	switch (msg->what) {
154 		case kMsgOpenBluetoothPreferences:
155 			be_roster->Launch(BLUETOOTH_APP_SIGNATURE);
156 			break;
157 
158 		case kMsgQuitBluetoothServer:
159 			_QuitBluetoothServer();
160 			break;
161 
162 		default:
163 			BView::MessageReceived(msg);
164 	}
165 }
166 
167 
168 void
169 DeskbarReplicant::MouseDown(BPoint where)
170 {
171 	BPoint point;
172 	uint32 buttons;
173 	GetMouse(&point, &buttons);
174 	if (!(buttons & B_SECONDARY_MOUSE_BUTTON)) {
175 		return;
176 	}
177 
178 	BPopUpMenu* menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
179 
180 	menu->AddItem(new BMenuItem(B_TRANSLATE("Settings" B_UTF8_ELLIPSIS),
181 		new BMessage(kMsgOpenBluetoothPreferences)));
182 
183 	// TODO show list of known/paired devices
184 
185 	menu->AddItem(new BMenuItem(B_TRANSLATE("Quit"),
186 		new BMessage(kMsgQuitBluetoothServer)));
187 
188 	menu->SetTargetForItems(this);
189 	ConvertToScreen(&point);
190 	menu->Go(point, true, true, true);
191 
192 	delete menu;
193 }
194 
195 
196 void
197 DeskbarReplicant::_QuitBluetoothServer()
198 {
199 	if (!be_roster->IsRunning(BLUETOOTH_SIGNATURE)) {
200 		// The server isn't running, so remove ourself
201 		BDeskbar deskbar;
202 		deskbar.RemoveItem(kDeskbarItemName);
203 
204 		return;
205 	}
206 	status_t status = BMessenger(BLUETOOTH_SIGNATURE).SendMessage(
207 		B_QUIT_REQUESTED);
208 	if (status < B_OK) {
209 		_ShowErrorAlert(B_TRANSLATE("Stopping the Bluetooth server failed."),
210 			status);
211 	}
212 }
213 
214 
215 void
216 DeskbarReplicant::_ShowErrorAlert(BString msg, status_t status)
217 {
218 	BString error = B_TRANSLATE("Error: %status%");
219 	error.ReplaceFirst("%status%", strerror(status));
220 	msg << "\n\n" << error;
221 	BAlert* alert = new BAlert(B_TRANSLATE("Bluetooth error"), msg.String(),
222 		B_TRANSLATE("OK"));
223 	alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
224 	alert->Go(NULL);
225 }
226 
227 
228 //	#pragma mark -
229 
230 
231 extern "C" _EXPORT BView *
232 instantiate_deskbar_item(float maxWidth, float maxHeight)
233 {
234 	return new DeskbarReplicant(BRect(0, 0, maxHeight - 1, maxHeight - 1),
235 		B_FOLLOW_NONE);
236 }
237 
238 
239 //	#pragma mark -
240 
241 
242 status_t
243 our_image(image_info& image)
244 {
245 	int32 cookie = 0;
246 	while (get_next_image_info(B_CURRENT_TEAM, &cookie, &image) == B_OK) {
247 		if ((char *)our_image >= (char *)image.text
248 			&& (char *)our_image <= (char *)image.text + image.text_size)
249 			return B_OK;
250 	}
251 
252 	return B_ERROR;
253 }
254