xref: /haiku/src/kits/interface/InterfaceDefs.cpp (revision 7b3e89c0944ae1efa9a8fc66c7303874b7a344b2)
1 /*
2  * Copyright 2001-2015, Haiku, Inc.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		DarkWyrm <bpmagic@columbus.rr.com>
7  *		Caz <turok2@currantbun.com>
8  *		Axel Dörfler, axeld@pinc-software.de
9  *		Michael Lotz <mmlr@mlotz.ch>
10  *		Wim van der Meer <WPJvanderMeer@gmail.com>
11  *		Joseph Groover <looncraz@looncraz.net>
12  */
13 
14 
15 /*!	Global functions and variables for the Interface Kit */
16 
17 
18 #include <InterfaceDefs.h>
19 
20 #include <new>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include <Bitmap.h>
26 #include <Clipboard.h>
27 #include <ControlLook.h>
28 #include <Font.h>
29 #include <Menu.h>
30 #include <Point.h>
31 #include <Roster.h>
32 #include <Screen.h>
33 #include <ScrollBar.h>
34 #include <String.h>
35 #include <TextView.h>
36 #include <Window.h>
37 
38 #include <ApplicationPrivate.h>
39 #include <AppServerLink.h>
40 #include <ColorConversion.h>
41 #include <DecorInfo.h>
42 #include <DefaultColors.h>
43 #include <DesktopLink.h>
44 #include <HaikuControlLook.h>
45 #include <InputServerTypes.h>
46 #include <input_globals.h>
47 #include <InterfacePrivate.h>
48 #include <MenuPrivate.h>
49 #include <pr_server.h>
50 #include <ServerProtocol.h>
51 #include <ServerReadOnlyMemory.h>
52 #include <truncate_string.h>
53 #include <utf8_functions.h>
54 #include <WidthBuffer.h>
55 #include <WindowInfo.h>
56 
57 
58 using namespace BPrivate;
59 
60 // some other weird struct exported by BeOS, it's not initialized, though
61 struct general_ui_info {
62 	rgb_color	background_color;
63 	rgb_color	mark_color;
64 	rgb_color	highlight_color;
65 	bool		color_frame;
66 	rgb_color	window_frame_color;
67 };
68 
69 struct general_ui_info general_info;
70 
71 menu_info *_menu_info_ptr_;
72 
73 extern "C" const char B_NOTIFICATION_SENDER[] = "be:sender";
74 
75 static const rgb_color _kDefaultColors[kColorWhichCount] = {
76 	{216, 216, 216, 255},	// B_PANEL_BACKGROUND_COLOR
77 	{216, 216, 216, 255},	// B_MENU_BACKGROUND_COLOR
78 	{255, 203, 0, 255},		// B_WINDOW_TAB_COLOR
79 	{0, 0, 229, 255},		// B_KEYBOARD_NAVIGATION_COLOR
80 	{51, 102, 152, 255},	// B_DESKTOP_COLOR
81 	{153, 153, 153, 255},	// B_MENU_SELECTED_BACKGROUND_COLOR
82 	{0, 0, 0, 255},			// B_MENU_ITEM_TEXT_COLOR
83 	{0, 0, 0, 255},			// B_MENU_SELECTED_ITEM_TEXT_COLOR
84 	{0, 0, 0, 255},			// B_MENU_SELECTED_BORDER_COLOR
85 	{0, 0, 0, 255},			// B_PANEL_TEXT_COLOR
86 	{255, 255, 255, 255},	// B_DOCUMENT_BACKGROUND_COLOR
87 	{0, 0, 0, 255},			// B_DOCUMENT_TEXT_COLOR
88 	{245, 245, 245, 255},	// B_CONTROL_BACKGROUND_COLOR
89 	{0, 0, 0, 255},			// B_CONTROL_TEXT_COLOR
90 	{172, 172, 172, 255},	// B_CONTROL_BORDER_COLOR
91 	{102, 152, 203, 255},	// B_CONTROL_HIGHLIGHT_COLOR
92 	{0, 0, 0, 255},			// B_NAVIGATION_PULSE_COLOR
93 	{255, 255, 255, 255},	// B_SHINE_COLOR
94 	{0, 0, 0, 255},			// B_SHADOW_COLOR
95 	{255, 255, 216, 255},	// B_TOOLTIP_BACKGROUND_COLOR
96 	{0, 0, 0, 255},			// B_TOOLTIP_TEXT_COLOR
97 	{0, 0, 0, 255},			// B_WINDOW_TEXT_COLOR
98 	{232, 232, 232, 255},	// B_WINDOW_INACTIVE_TAB_COLOR
99 	{80, 80, 80, 255},		// B_WINDOW_INACTIVE_TEXT_COLOR
100 	{224, 224, 224, 255},	// B_WINDOW_BORDER_COLOR
101 	{232, 232, 232, 255},	// B_WINDOW_INACTIVE_BORDER_COLOR
102 	{27, 82, 140, 255},     // B_CONTROL_MARK_COLOR
103 	{255, 255, 255, 255},	// B_LIST_BACKGROUND_COLOR
104 	{190, 190, 190, 255},	// B_LIST_SELECTED_BACKGROUND_COLOR
105 	{0, 0, 0, 255},			// B_LIST_ITEM_TEXT_COLOR
106 	{0, 0, 0, 255},			// B_LIST_SELECTED_ITEM_TEXT_COLOR
107 	{216, 216, 216, 255},	// B_SCROLL_BAR_THUMB_COLOR
108 	{51, 102, 187, 255},	// B_LINK_TEXT_COLOR
109 	{102, 152, 203, 255},	// B_LINK_HOVER_COLOR
110 	{145, 112, 155, 255},	// B_LINK_VISITED_COLOR
111 	{121, 142, 203, 255},	// B_LINK_ACTIVE_COLOR
112 	{50, 150, 255, 255},	// B_STATUS_BAR_COLOR
113 	// 100...
114 	{46, 204, 64, 255},		// B_SUCCESS_COLOR
115 	{255, 65, 54, 255},		// B_FAILURE_COLOR
116 	{}
117 };
118 const rgb_color* BPrivate::kDefaultColors = &_kDefaultColors[0];
119 
120 
121 static const rgb_color _kDefaultColorsDark[kColorWhichCount] = {
122 	{43, 43, 43, 255},		// B_PANEL_BACKGROUND_COLOR
123 	{28, 28, 28, 255},		// B_MENU_BACKGROUND_COLOR
124 	{227, 73, 17, 255},		// B_WINDOW_TAB_COLOR
125 	{0, 0, 229, 255},		// B_KEYBOARD_NAVIGATION_COLOR
126 	{51, 102, 152, 255},	// B_DESKTOP_COLOR
127 	{90, 90, 90, 255},		// B_MENU_SELECTED_BACKGROUND_COLOR
128 	{255, 255, 255, 255},	// B_MENU_ITEM_TEXT_COLOR
129 	{255, 255, 255, 255},	// B_MENU_SELECTED_ITEM_TEXT_COLOR
130 	{0, 0, 0, 255},			// B_MENU_SELECTED_BORDER_COLOR
131 	{253, 253, 253, 255},	// B_PANEL_TEXT_COLOR
132 	{0, 0, 0, 255},			// B_DOCUMENT_BACKGROUND_COLOR
133 	{234, 234, 234, 255},	// B_DOCUMENT_TEXT_COLOR
134 	{29, 29, 29, 255},		// B_CONTROL_BACKGROUND_COLOR
135 	{230, 230, 230, 255},	// B_CONTROL_TEXT_COLOR
136 	{195, 195, 195, 255},	// B_CONTROL_BORDER_COLOR
137 	{75, 124, 168, 255},	// B_CONTROL_HIGHLIGHT_COLOR
138 	{0, 0, 0, 255},			// B_NAVIGATION_PULSE_COLOR
139 	{255, 255, 255, 255},	// B_SHINE_COLOR
140 	{0, 0, 0, 255},			// B_SHADOW_COLOR
141 	{76, 68, 79, 255},		// B_TOOLTIP_BACKGROUND_COLOR
142 	{255, 255, 255, 255},	// B_TOOLTIP_TEXT_COLOR
143 	{255, 255, 255, 255},	// B_WINDOW_TEXT_COLOR
144 	{203, 32, 9, 255},		// B_WINDOW_INACTIVE_TAB_COLOR
145 	{255, 255, 255, 255},	// B_WINDOW_INACTIVE_TEXT_COLOR
146 	{227, 73, 17, 255},		// B_WINDOW_BORDER_COLOR
147 	{203, 32, 9, 255},		// B_WINDOW_INACTIVE_BORDER_COLOR
148 	{27, 82, 140, 255},     // B_CONTROL_MARK_COLOR
149 	{0, 0, 0, 255},			// B_LIST_BACKGROUND_COLOR
150 	{90, 90, 90, 255},		// B_LIST_SELECTED_BACKGROUND_COLOR
151 	{255, 255, 255, 255},	// B_LIST_ITEM_TEXT_COLOR
152 	{255, 255, 255, 255},	// B_LIST_SELECTED_ITEM_TEXT_COLOR
153 	{39, 39, 39, 255},		// B_SCROLL_BAR_THUMB_COLOR
154 	{106, 112, 212, 255},	// B_LINK_TEXT_COLOR
155 	{102, 152, 203, 255},	// B_LINK_HOVER_COLOR
156 	{145, 112, 155, 255},	// B_LINK_VISITED_COLOR
157 	{121, 142, 203, 255},	// B_LINK_ACTIVE_COLOR
158 	{50, 150, 255, 255},	// B_STATUS_BAR_COLOR
159 	// 100...
160 	{46, 204, 64, 255},		// B_SUCCESS_COLOR
161 	{255, 40, 54, 255},		// B_FAILURE_COLOR
162 	{}
163 };
164 
165 
166 static const char* kColorNames[kColorWhichCount] = {
167 	"B_PANEL_BACKGROUND_COLOR",
168 	"B_MENU_BACKGROUND_COLOR",
169 	"B_WINDOW_TAB_COLOR",
170 	"B_KEYBOARD_NAVIGATION_COLOR",
171 	"B_DESKTOP_COLOR",
172 	"B_MENU_SELECTED_BACKGROUND_COLOR",
173 	"B_MENU_ITEM_TEXT_COLOR",
174 	"B_MENU_SELECTED_ITEM_TEXT_COLOR",
175 	"B_MENU_SELECTED_BORDER_COLOR",
176 	"B_PANEL_TEXT_COLOR",
177 	"B_DOCUMENT_BACKGROUND_COLOR",
178 	"B_DOCUMENT_TEXT_COLOR",
179 	"B_CONTROL_BACKGROUND_COLOR",
180 	"B_CONTROL_TEXT_COLOR",
181 	"B_CONTROL_BORDER_COLOR",
182 	"B_CONTROL_HIGHLIGHT_COLOR",
183 	"B_NAVIGATION_PULSE_COLOR",
184 	"B_SHINE_COLOR",
185 	"B_SHADOW_COLOR",
186 	"B_TOOLTIP_BACKGROUND_COLOR",
187 	"B_TOOLTIP_TEXT_COLOR",
188 	"B_WINDOW_TEXT_COLOR",
189 	"B_WINDOW_INACTIVE_TAB_COLOR",
190 	"B_WINDOW_INACTIVE_TEXT_COLOR",
191 	"B_WINDOW_BORDER_COLOR",
192 	"B_WINDOW_INACTIVE_BORDER_COLOR",
193 	"B_CONTROL_MARK_COLOR",
194 	"B_LIST_BACKGROUND_COLOR",
195 	"B_LIST_SELECTED_BACKGROUND_COLOR",
196 	"B_LIST_ITEM_TEXT_COLOR",
197 	"B_LIST_SELECTED_ITEM_TEXT_COLOR",
198 	"B_SCROLL_BAR_THUMB_COLOR",
199 	"B_LINK_TEXT_COLOR",
200 	"B_LINK_HOVER_COLOR",
201 	"B_LINK_VISITED_COLOR",
202 	"B_LINK_ACTIVE_COLOR",
203 	"B_STATUS_BAR_COLOR",
204 	// 100...
205 	"B_SUCCESS_COLOR",
206 	"B_FAILURE_COLOR",
207 	NULL
208 };
209 
210 static image_id sControlLookAddon = -1;
211 
212 
213 namespace BPrivate {
214 
215 
216 /*!	Fills the \a width, \a height, and \a colorSpace parameters according
217 	to the window screen's mode.
218 	Returns \c true if the mode is known.
219 */
220 bool
221 get_mode_parameter(uint32 mode, int32& width, int32& height,
222 	uint32& colorSpace)
223 {
224 	switch (mode) {
225 		case B_8_BIT_640x480:
226 		case B_8_BIT_800x600:
227 		case B_8_BIT_1024x768:
228 		case B_8_BIT_1152x900:
229 		case B_8_BIT_1280x1024:
230 		case B_8_BIT_1600x1200:
231 			colorSpace = B_CMAP8;
232 			break;
233 
234 		case B_15_BIT_640x480:
235 		case B_15_BIT_800x600:
236 		case B_15_BIT_1024x768:
237 		case B_15_BIT_1152x900:
238 		case B_15_BIT_1280x1024:
239 		case B_15_BIT_1600x1200:
240 			colorSpace = B_RGB15;
241 			break;
242 
243 		case B_16_BIT_640x480:
244 		case B_16_BIT_800x600:
245 		case B_16_BIT_1024x768:
246 		case B_16_BIT_1152x900:
247 		case B_16_BIT_1280x1024:
248 		case B_16_BIT_1600x1200:
249 			colorSpace = B_RGB16;
250 			break;
251 
252 		case B_32_BIT_640x480:
253 		case B_32_BIT_800x600:
254 		case B_32_BIT_1024x768:
255 		case B_32_BIT_1152x900:
256 		case B_32_BIT_1280x1024:
257 		case B_32_BIT_1600x1200:
258 			colorSpace = B_RGB32;
259 			break;
260 
261 		default:
262 			return false;
263 	}
264 
265 	switch (mode) {
266 		case B_8_BIT_640x480:
267 		case B_15_BIT_640x480:
268 		case B_16_BIT_640x480:
269 		case B_32_BIT_640x480:
270 			width = 640; height = 480;
271 			break;
272 
273 		case B_8_BIT_800x600:
274 		case B_15_BIT_800x600:
275 		case B_16_BIT_800x600:
276 		case B_32_BIT_800x600:
277 			width = 800; height = 600;
278 			break;
279 
280 		case B_8_BIT_1024x768:
281 		case B_15_BIT_1024x768:
282 		case B_16_BIT_1024x768:
283 		case B_32_BIT_1024x768:
284 			width = 1024; height = 768;
285 			break;
286 
287 		case B_8_BIT_1152x900:
288 		case B_15_BIT_1152x900:
289 		case B_16_BIT_1152x900:
290 		case B_32_BIT_1152x900:
291 			width = 1152; height = 900;
292 			break;
293 
294 		case B_8_BIT_1280x1024:
295 		case B_15_BIT_1280x1024:
296 		case B_16_BIT_1280x1024:
297 		case B_32_BIT_1280x1024:
298 			width = 1280; height = 1024;
299 			break;
300 
301 		case B_8_BIT_1600x1200:
302 		case B_15_BIT_1600x1200:
303 		case B_16_BIT_1600x1200:
304 		case B_32_BIT_1600x1200:
305 			width = 1600; height = 1200;
306 			break;
307 	}
308 
309 	return true;
310 }
311 
312 
313 void
314 get_workspaces_layout(uint32* _columns, uint32* _rows)
315 {
316 	int32 columns = 1;
317 	int32 rows = 1;
318 
319 	BPrivate::AppServerLink link;
320 	link.StartMessage(AS_GET_WORKSPACE_LAYOUT);
321 
322 	status_t status;
323 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
324 		link.Read<int32>(&columns);
325 		link.Read<int32>(&rows);
326 	}
327 
328 	if (_columns != NULL)
329 		*_columns = columns;
330 	if (_rows != NULL)
331 		*_rows = rows;
332 }
333 
334 
335 void
336 set_workspaces_layout(uint32 columns, uint32 rows)
337 {
338 	if (columns < 1 || rows < 1)
339 		return;
340 
341 	BPrivate::AppServerLink link;
342 	link.StartMessage(AS_SET_WORKSPACE_LAYOUT);
343 	link.Attach<int32>(columns);
344 	link.Attach<int32>(rows);
345 	link.Flush();
346 }
347 
348 
349 }	// namespace BPrivate
350 
351 
352 void
353 set_subpixel_antialiasing(bool subpix)
354 {
355 	BPrivate::AppServerLink link;
356 
357 	link.StartMessage(AS_SET_SUBPIXEL_ANTIALIASING);
358 	link.Attach<bool>(subpix);
359 	link.Flush();
360 }
361 
362 
363 status_t
364 get_subpixel_antialiasing(bool* subpix)
365 {
366 	BPrivate::AppServerLink link;
367 
368 	link.StartMessage(AS_GET_SUBPIXEL_ANTIALIASING);
369 	int32 status = B_ERROR;
370 	if (link.FlushWithReply(status) != B_OK || status < B_OK)
371 		return status;
372 	link.Read<bool>(subpix);
373 	return B_OK;
374 }
375 
376 
377 void
378 set_hinting_mode(uint8 hinting)
379 {
380 	BPrivate::AppServerLink link;
381 
382 	link.StartMessage(AS_SET_HINTING);
383 	link.Attach<uint8>(hinting);
384 	link.Flush();
385 }
386 
387 
388 status_t
389 get_hinting_mode(uint8* hinting)
390 {
391 	BPrivate::AppServerLink link;
392 
393 	link.StartMessage(AS_GET_HINTING);
394 	int32 status = B_ERROR;
395 	if (link.FlushWithReply(status) != B_OK || status < B_OK)
396 		return status;
397 	link.Read<uint8>(hinting);
398 	return B_OK;
399 }
400 
401 
402 void
403 set_average_weight(uint8 averageWeight)
404 {
405 	BPrivate::AppServerLink link;
406 
407 	link.StartMessage(AS_SET_SUBPIXEL_AVERAGE_WEIGHT);
408 	link.Attach<uint8>(averageWeight);
409 	link.Flush();
410 }
411 
412 
413 status_t
414 get_average_weight(uint8* averageWeight)
415 {
416 	BPrivate::AppServerLink link;
417 
418 	link.StartMessage(AS_GET_SUBPIXEL_AVERAGE_WEIGHT);
419 	int32 status = B_ERROR;
420 	if (link.FlushWithReply(status) != B_OK || status < B_OK)
421 		return status;
422 	link.Read<uint8>(averageWeight);
423 	return B_OK;
424 }
425 
426 
427 void
428 set_is_subpixel_ordering_regular(bool subpixelOrdering)
429 {
430 	BPrivate::AppServerLink link;
431 
432 	link.StartMessage(AS_SET_SUBPIXEL_ORDERING);
433 	link.Attach<bool>(subpixelOrdering);
434 	link.Flush();
435 }
436 
437 
438 status_t
439 get_is_subpixel_ordering_regular(bool* subpixelOrdering)
440 {
441 	BPrivate::AppServerLink link;
442 
443 	link.StartMessage(AS_GET_SUBPIXEL_ORDERING);
444 	int32 status = B_ERROR;
445 	if (link.FlushWithReply(status) != B_OK || status < B_OK)
446 		return status;
447 	link.Read<bool>(subpixelOrdering);
448 	return B_OK;
449 }
450 
451 
452 const color_map *
453 system_colors()
454 {
455 	return BScreen(B_MAIN_SCREEN_ID).ColorMap();
456 }
457 
458 
459 status_t
460 set_screen_space(int32 index, uint32 space, bool stick)
461 {
462 	int32 width;
463 	int32 height;
464 	uint32 depth;
465 	if (!BPrivate::get_mode_parameter(space, width, height, depth))
466 		return B_BAD_VALUE;
467 
468 	BScreen screen(B_MAIN_SCREEN_ID);
469 	display_mode mode;
470 
471 	// TODO: What about refresh rate ?
472 	// currently we get it from the current video mode, but
473 	// this might be not so wise.
474 	status_t status = screen.GetMode(index, &mode);
475 	if (status < B_OK)
476 		return status;
477 
478 	mode.virtual_width = width;
479 	mode.virtual_height = height;
480 	mode.space = depth;
481 
482 	return screen.SetMode(index, &mode, stick);
483 }
484 
485 
486 status_t
487 get_scroll_bar_info(scroll_bar_info *info)
488 {
489 	if (info == NULL)
490 		return B_BAD_VALUE;
491 
492 	BPrivate::AppServerLink link;
493 	link.StartMessage(AS_GET_SCROLLBAR_INFO);
494 
495 	int32 code;
496 	if (link.FlushWithReply(code) == B_OK
497 		&& code == B_OK) {
498 		link.Read<scroll_bar_info>(info);
499 		return B_OK;
500 	}
501 
502 	return B_ERROR;
503 }
504 
505 
506 status_t
507 set_scroll_bar_info(scroll_bar_info *info)
508 {
509 	if (info == NULL)
510 		return B_BAD_VALUE;
511 
512 	BPrivate::AppServerLink link;
513 	int32 code;
514 
515 	link.StartMessage(AS_SET_SCROLLBAR_INFO);
516 	link.Attach<scroll_bar_info>(*info);
517 
518 	if (link.FlushWithReply(code) == B_OK
519 		&& code == B_OK)
520 		return B_OK;
521 
522 	return B_ERROR;
523 }
524 
525 
526 status_t
527 get_mouse_type(int32 *type)
528 {
529 	BMessage command(IS_GET_MOUSE_TYPE);
530 	BMessage reply;
531 
532 	status_t err = _control_input_server_(&command, &reply);
533 	if (err != B_OK)
534 		return err;
535 	return reply.FindInt32("mouse_type", type);
536 }
537 
538 
539 status_t
540 set_mouse_type(int32 type)
541 {
542 	BMessage command(IS_SET_MOUSE_TYPE);
543 	BMessage reply;
544 
545 	status_t err = command.AddInt32("mouse_type", type);
546 	if (err != B_OK)
547 		return err;
548 	return _control_input_server_(&command, &reply);
549 }
550 
551 
552 status_t
553 get_mouse_type(const char* mouse_name, int32 *type)
554 {
555 	BMessage command(IS_GET_MOUSE_TYPE);
556 	BMessage reply;
557 	command.AddString("mouse_name", mouse_name);
558 
559 	status_t err = _control_input_server_(&command, &reply);
560 	if (err != B_OK)
561 		return err;
562 
563 	return reply.FindInt32("mouse_type", type);
564 }
565 
566 
567 status_t
568 set_mouse_type(const char* mouse_name, int32 type)
569 {
570 	BMessage command(IS_SET_MOUSE_TYPE);
571 	BMessage reply;
572 
573 	status_t err_mouse_name = command.AddString("mouse_name", mouse_name);
574 	if (err_mouse_name != B_OK)
575 		return err_mouse_name;
576 
577 	status_t err = command.AddInt32("mouse_type", type);
578 	if (err != B_OK)
579 		return err;
580 	return _control_input_server_(&command, &reply);
581 }
582 
583 
584 status_t
585 get_mouse_map(mouse_map *map)
586 {
587 	BMessage command(IS_GET_MOUSE_MAP);
588 	BMessage reply;
589 	const void *data = 0;
590 	ssize_t count;
591 
592 	status_t err = _control_input_server_(&command, &reply);
593 	if (err == B_OK)
594 		err = reply.FindData("mousemap", B_RAW_TYPE, &data, &count);
595 	if (err != B_OK)
596 		return err;
597 
598 	memcpy(map, data, count);
599 
600 	return B_OK;
601 }
602 
603 
604 status_t
605 set_mouse_map(mouse_map *map)
606 {
607 	BMessage command(IS_SET_MOUSE_MAP);
608 	BMessage reply;
609 
610 	status_t err = command.AddData("mousemap", B_RAW_TYPE, map,
611 		sizeof(mouse_map));
612 	if (err != B_OK)
613 		return err;
614 	return _control_input_server_(&command, &reply);
615 }
616 
617 
618 status_t
619 get_click_speed(bigtime_t *speed)
620 {
621 	BMessage command(IS_GET_CLICK_SPEED);
622 	BMessage reply;
623 
624 	status_t err = _control_input_server_(&command, &reply);
625 	if (err != B_OK)
626 		return err;
627 
628 	if (reply.FindInt64("speed", speed) != B_OK)
629 		*speed = 500000;
630 
631 	return B_OK;
632 }
633 
634 
635 status_t
636 set_click_speed(bigtime_t speed)
637 {
638 	BMessage command(IS_SET_CLICK_SPEED);
639 	BMessage reply;
640 	command.AddInt64("speed", speed);
641 	return _control_input_server_(&command, &reply);
642 }
643 
644 
645 status_t
646 get_mouse_speed(int32 *speed)
647 {
648 	BMessage command(IS_GET_MOUSE_SPEED);
649 	BMessage reply;
650 
651 	status_t err = _control_input_server_(&command, &reply);
652 	if (err != B_OK)
653 		return err;
654 
655 	if (reply.FindInt32("speed", speed) != B_OK)
656 		*speed = 65536;
657 
658 	return B_OK;
659 }
660 
661 
662 status_t
663 set_mouse_speed(int32 speed)
664 {
665 	BMessage command(IS_SET_MOUSE_SPEED);
666 	BMessage reply;
667 	command.AddInt32("speed", speed);
668 	return _control_input_server_(&command, &reply);
669 }
670 
671 
672 status_t
673 get_mouse_speed(const char* mouse_name, int32 *speed)
674 {
675 	BMessage command(IS_GET_MOUSE_SPEED);
676 	BMessage reply;
677 	command.AddString("mouse_name", mouse_name);
678 
679 	status_t err = _control_input_server_(&command, &reply);
680 	if (err != B_OK)
681 		return err;
682 
683 	err = reply.FindInt32("speed", speed);
684 	if (err != B_OK)
685 		return err;
686 
687 	return B_OK;
688 }
689 
690 
691 status_t
692 set_mouse_speed(const char* mouse_name, int32 speed)
693 {
694 	BMessage command(IS_SET_MOUSE_SPEED);
695 	BMessage reply;
696 	command.AddString("mouse_name", mouse_name);
697 
698 	command.AddInt32("speed", speed);
699 
700 	return _control_input_server_(&command, &reply);
701 }
702 
703 
704 status_t
705 get_mouse_acceleration(int32 *speed)
706 {
707 	BMessage command(IS_GET_MOUSE_ACCELERATION);
708 	BMessage reply;
709 
710 	_control_input_server_(&command, &reply);
711 
712 	if (reply.FindInt32("speed", speed) != B_OK)
713 		*speed = 65536;
714 
715 	return B_OK;
716 }
717 
718 
719 status_t
720 set_mouse_acceleration(int32 speed)
721 {
722 	BMessage command(IS_SET_MOUSE_ACCELERATION);
723 	BMessage reply;
724 	command.AddInt32("speed", speed);
725 	return _control_input_server_(&command, &reply);
726 }
727 
728 
729 status_t
730 get_mouse_acceleration(const char* mouse_name, int32 *speed)
731 {
732 	BMessage command(IS_GET_MOUSE_ACCELERATION);
733 	BMessage reply;
734 	command.AddString("mouse_name", mouse_name);
735 
736 	_control_input_server_(&command, &reply);
737 
738 	if (reply.FindInt32("speed", speed) != B_OK)
739 		*speed = 65536;
740 
741 	return B_OK;
742 }
743 
744 
745 status_t
746 set_mouse_acceleration(const char* mouse_name, int32 speed)
747 {
748 	BMessage command(IS_SET_MOUSE_ACCELERATION);
749 	BMessage reply;
750 	command.AddString("mouse_name", mouse_name);
751 
752 	command.AddInt32("speed", speed);
753 
754 	return _control_input_server_(&command, &reply);
755 }
756 
757 
758 status_t
759 get_key_repeat_rate(int32 *rate)
760 {
761 	BMessage command(IS_GET_KEY_REPEAT_RATE);
762 	BMessage reply;
763 
764 	status_t err = _control_input_server_(&command, &reply);
765 
766 	if (err == B_OK)
767 		err = reply.FindInt32("rate", rate);
768 
769 	if (err != B_OK) {
770 		*rate = 250000;
771 		return err;
772 	}
773 
774 	return B_OK;
775 }
776 
777 
778 status_t
779 set_key_repeat_rate(int32 rate)
780 {
781 	BMessage command(IS_SET_KEY_REPEAT_RATE);
782 	BMessage reply;
783 	command.AddInt32("rate", rate);
784 	return _control_input_server_(&command, &reply);
785 }
786 
787 
788 status_t
789 get_key_repeat_delay(bigtime_t *delay)
790 {
791 	BMessage command(IS_GET_KEY_REPEAT_DELAY);
792 	BMessage reply;
793 
794 	status_t err = _control_input_server_(&command, &reply);
795 
796 	if (err == B_OK)
797 		err = reply.FindInt64("delay", delay);
798 
799 	if (err != B_OK) {
800 		*delay = 200;
801 		return err;
802 	}
803 
804 	return B_OK;
805 }
806 
807 
808 status_t
809 set_key_repeat_delay(bigtime_t  delay)
810 {
811 	BMessage command(IS_SET_KEY_REPEAT_DELAY);
812 	BMessage reply;
813 	command.AddInt64("delay", delay);
814 	return _control_input_server_(&command, &reply);
815 }
816 
817 
818 uint32
819 modifiers()
820 {
821 	BMessage command(IS_GET_MODIFIERS);
822 	BMessage reply;
823 	int32 err, modifier;
824 
825 	_control_input_server_(&command, &reply);
826 
827 	if (reply.FindInt32("status", &err) != B_OK)
828 		return 0;
829 
830 	if (reply.FindInt32("modifiers", &modifier) != B_OK)
831 		return 0;
832 
833 	return modifier;
834 }
835 
836 
837 status_t
838 get_key_info(key_info *info)
839 {
840 	BMessage command(IS_GET_KEY_INFO);
841 	BMessage reply;
842 	const void *data = 0;
843 	int32 err;
844 	ssize_t count;
845 
846 	_control_input_server_(&command, &reply);
847 
848 	if (reply.FindInt32("status", &err) != B_OK)
849 		return B_ERROR;
850 
851 	if (reply.FindData("key_info", B_ANY_TYPE, &data, &count) != B_OK)
852 		return B_ERROR;
853 
854 	memcpy(info, data, count);
855 	return B_OK;
856 }
857 
858 
859 void
860 get_key_map(key_map **map, char **key_buffer)
861 {
862 	_get_key_map(map, key_buffer, NULL);
863 }
864 
865 
866 void
867 _get_key_map(key_map **map, char **key_buffer, ssize_t *key_buffer_size)
868 {
869 	BMessage command(IS_GET_KEY_MAP);
870 	BMessage reply;
871 	ssize_t map_count, key_count;
872 	const void *map_array = 0, *key_array = 0;
873 	if (key_buffer_size == NULL)
874 		key_buffer_size = &key_count;
875 
876 	_control_input_server_(&command, &reply);
877 
878 	if (reply.FindData("keymap", B_ANY_TYPE, &map_array, &map_count) != B_OK) {
879 		*map = 0; *key_buffer = 0;
880 		return;
881 	}
882 
883 	if (reply.FindData("key_buffer", B_ANY_TYPE, &key_array, key_buffer_size)
884 			!= B_OK) {
885 		*map = 0; *key_buffer = 0;
886 		return;
887 	}
888 
889 	*map = (key_map *)malloc(map_count);
890 	memcpy(*map, map_array, map_count);
891 	*key_buffer = (char *)malloc(*key_buffer_size);
892 	memcpy(*key_buffer, key_array, *key_buffer_size);
893 }
894 
895 
896 status_t
897 get_keyboard_id(uint16 *id)
898 {
899 	BMessage command(IS_GET_KEYBOARD_ID);
900 	BMessage reply;
901 	uint16 kid;
902 
903 	_control_input_server_(&command, &reply);
904 
905 	status_t err = reply.FindInt16("id", (int16 *)&kid);
906 	if (err != B_OK)
907 		return err;
908 	*id = kid;
909 
910 	return B_OK;
911 }
912 
913 
914 status_t
915 get_modifier_key(uint32 modifier, uint32 *key)
916 {
917 	BMessage command(IS_GET_MODIFIER_KEY);
918 	BMessage reply;
919 	uint32 rkey;
920 
921 	command.AddInt32("modifier", modifier);
922 	_control_input_server_(&command, &reply);
923 
924 	status_t err = reply.FindInt32("key", (int32 *) &rkey);
925 	if (err != B_OK)
926 		return err;
927 	*key = rkey;
928 
929 	return B_OK;
930 }
931 
932 
933 void
934 set_modifier_key(uint32 modifier, uint32 key)
935 {
936 	BMessage command(IS_SET_MODIFIER_KEY);
937 	BMessage reply;
938 
939 	command.AddInt32("modifier", modifier);
940 	command.AddInt32("key", key);
941 	_control_input_server_(&command, &reply);
942 }
943 
944 
945 void
946 set_keyboard_locks(uint32 modifiers)
947 {
948 	BMessage command(IS_SET_KEYBOARD_LOCKS);
949 	BMessage reply;
950 
951 	command.AddInt32("locks", modifiers);
952 	_control_input_server_(&command, &reply);
953 }
954 
955 
956 status_t
957 _restore_key_map_()
958 {
959 	BMessage message(IS_RESTORE_KEY_MAP);
960 	BMessage reply;
961 
962 	return _control_input_server_(&message, &reply);
963 }
964 
965 
966 rgb_color
967 keyboard_navigation_color()
968 {
969 	// Queries the app_server
970 	return ui_color(B_KEYBOARD_NAVIGATION_COLOR);
971 }
972 
973 
974 int32
975 count_workspaces()
976 {
977 	uint32 columns;
978 	uint32 rows;
979 	BPrivate::get_workspaces_layout(&columns, &rows);
980 
981 	return columns * rows;
982 }
983 
984 
985 void
986 set_workspace_count(int32 count)
987 {
988 	int32 squareRoot = (int32)sqrt(count);
989 
990 	int32 rows = 1;
991 	for (int32 i = 2; i <= squareRoot; i++) {
992 		if (count % i == 0)
993 			rows = i;
994 	}
995 
996 	int32 columns = count / rows;
997 
998 	BPrivate::set_workspaces_layout(columns, rows);
999 }
1000 
1001 
1002 int32
1003 current_workspace()
1004 {
1005 	int32 index = 0;
1006 
1007 	BPrivate::AppServerLink link;
1008 	link.StartMessage(AS_CURRENT_WORKSPACE);
1009 
1010 	int32 status;
1011 	if (link.FlushWithReply(status) == B_OK && status == B_OK)
1012 		link.Read<int32>(&index);
1013 
1014 	return index;
1015 }
1016 
1017 
1018 void
1019 activate_workspace(int32 workspace)
1020 {
1021 	BPrivate::AppServerLink link;
1022 	link.StartMessage(AS_ACTIVATE_WORKSPACE);
1023 	link.Attach<int32>(workspace);
1024 	link.Attach<bool>(false);
1025 	link.Flush();
1026 }
1027 
1028 
1029 bigtime_t
1030 idle_time()
1031 {
1032 	bigtime_t idletime = 0;
1033 
1034 	BPrivate::AppServerLink link;
1035 	link.StartMessage(AS_IDLE_TIME);
1036 
1037 	int32 code;
1038 	if (link.FlushWithReply(code) == B_OK && code == B_OK)
1039 		link.Read<int64>(&idletime);
1040 
1041 	return idletime;
1042 }
1043 
1044 
1045 void
1046 run_select_printer_panel()
1047 {
1048 	if (be_roster == NULL)
1049 		return;
1050 
1051 	// Launches the Printer prefs app via the Roster
1052 	be_roster->Launch(PRNT_SIGNATURE_TYPE);
1053 }
1054 
1055 
1056 void
1057 run_add_printer_panel()
1058 {
1059 	// Launches the Printer prefs app via the Roster and asks it to
1060 	// add a printer
1061 	run_select_printer_panel();
1062 
1063 	BMessenger printerPanelMessenger(PRNT_SIGNATURE_TYPE);
1064 	printerPanelMessenger.SendMessage(PRINTERS_ADD_PRINTER);
1065 }
1066 
1067 
1068 void
1069 run_be_about()
1070 {
1071 	if (be_roster != NULL)
1072 		be_roster->Launch("application/x-vnd.Haiku-About");
1073 }
1074 
1075 
1076 void
1077 set_focus_follows_mouse(bool follow)
1078 {
1079 	// obviously deprecated API
1080 	set_mouse_mode(follow ? B_FOCUS_FOLLOWS_MOUSE : B_NORMAL_MOUSE);
1081 }
1082 
1083 
1084 bool
1085 focus_follows_mouse()
1086 {
1087 	return mouse_mode() == B_FOCUS_FOLLOWS_MOUSE;
1088 }
1089 
1090 
1091 void
1092 set_mouse_mode(mode_mouse mode)
1093 {
1094 	BPrivate::AppServerLink link;
1095 	link.StartMessage(AS_SET_MOUSE_MODE);
1096 	link.Attach<mode_mouse>(mode);
1097 	link.Flush();
1098 }
1099 
1100 
1101 mode_mouse
1102 mouse_mode()
1103 {
1104 	// Gets the mouse focus style, such as activate to click,
1105 	// focus to click, ...
1106 	mode_mouse mode = B_NORMAL_MOUSE;
1107 
1108 	BPrivate::AppServerLink link;
1109 	link.StartMessage(AS_GET_MOUSE_MODE);
1110 
1111 	int32 code;
1112 	if (link.FlushWithReply(code) == B_OK && code == B_OK)
1113 		link.Read<mode_mouse>(&mode);
1114 
1115 	return mode;
1116 }
1117 
1118 
1119 void
1120 set_focus_follows_mouse_mode(mode_focus_follows_mouse mode)
1121 {
1122 	BPrivate::AppServerLink link;
1123 	link.StartMessage(AS_SET_FOCUS_FOLLOWS_MOUSE_MODE);
1124 	link.Attach<mode_focus_follows_mouse>(mode);
1125 	link.Flush();
1126 }
1127 
1128 
1129 mode_focus_follows_mouse
1130 focus_follows_mouse_mode()
1131 {
1132 	mode_focus_follows_mouse mode = B_NORMAL_FOCUS_FOLLOWS_MOUSE;
1133 
1134 	BPrivate::AppServerLink link;
1135 	link.StartMessage(AS_GET_FOCUS_FOLLOWS_MOUSE_MODE);
1136 
1137 	int32 code;
1138 	if (link.FlushWithReply(code) == B_OK && code == B_OK)
1139 		link.Read<mode_focus_follows_mouse>(&mode);
1140 
1141 	return mode;
1142 }
1143 
1144 
1145 status_t
1146 get_mouse(BPoint* screenWhere, uint32* buttons)
1147 {
1148 	if (screenWhere == NULL && buttons == NULL)
1149 		return B_BAD_VALUE;
1150 
1151 	BPrivate::AppServerLink link;
1152 	link.StartMessage(AS_GET_CURSOR_POSITION);
1153 
1154 	int32 code;
1155 	status_t ret = link.FlushWithReply(code);
1156 	if (ret != B_OK)
1157 		return ret;
1158 	if (code != B_OK)
1159 		return code;
1160 
1161 	if (screenWhere != NULL)
1162 		ret = link.Read<BPoint>(screenWhere);
1163 	else {
1164 		BPoint dummy;
1165 		ret = link.Read<BPoint>(&dummy);
1166 	}
1167 	if (ret != B_OK)
1168 		return ret;
1169 
1170 	if (buttons != NULL)
1171 		ret = link.Read<uint32>(buttons);
1172 	else {
1173 		uint32 dummy;
1174 		ret = link.Read<uint32>(&dummy);
1175 	}
1176 
1177 	return ret;
1178 }
1179 
1180 
1181 status_t
1182 get_mouse_bitmap(BBitmap** bitmap, BPoint* hotspot)
1183 {
1184 	if (bitmap == NULL && hotspot == NULL)
1185 		return B_BAD_VALUE;
1186 
1187 	BPrivate::AppServerLink link;
1188 	link.StartMessage(AS_GET_CURSOR_BITMAP);
1189 
1190 	int32 code;
1191 	status_t status = link.FlushWithReply(code);
1192 	if (status != B_OK)
1193 		return status;
1194 	if (code != B_OK)
1195 		return code;
1196 
1197 	uint32 size = 0;
1198 	uint32 cursorWidth = 0;
1199 	uint32 cursorHeight = 0;
1200 	color_space colorspace = B_RGBA32;
1201 
1202 	// if link.Read() returns an error, the same error will be returned on
1203 	// subsequent calls, so we'll check only the return value of the last call
1204 	link.Read<uint32>(&size);
1205 	link.Read<uint32>(&cursorWidth);
1206 	link.Read<uint32>(&cursorHeight);
1207 	link.Read<color_space>(&colorspace);
1208 	if (hotspot == NULL) {
1209 		BPoint dummy;
1210 		link.Read<BPoint>(&dummy);
1211 	} else
1212 		link.Read<BPoint>(hotspot);
1213 
1214 	void* data = NULL;
1215 	if (size > 0)
1216 		data = malloc(size);
1217 	if (data == NULL)
1218 		return B_NO_MEMORY;
1219 
1220 	status = link.Read(data, size);
1221 	if (status != B_OK) {
1222 		free(data);
1223 		return status;
1224 	}
1225 
1226 	BBitmap* cursorBitmap = new (std::nothrow) BBitmap(BRect(0, 0,
1227 		cursorWidth - 1, cursorHeight - 1), colorspace);
1228 
1229 	if (cursorBitmap == NULL) {
1230 		free(data);
1231 		return B_NO_MEMORY;
1232 	}
1233 	status = cursorBitmap->InitCheck();
1234 	if (status == B_OK)
1235 		cursorBitmap->SetBits(data, size, 0, colorspace);
1236 
1237 	free(data);
1238 
1239 	if (status == B_OK && bitmap != NULL)
1240 		*bitmap = cursorBitmap;
1241 	else
1242 		delete cursorBitmap;
1243 
1244 	return status;
1245 }
1246 
1247 
1248 void
1249 set_accept_first_click(bool acceptFirstClick)
1250 {
1251 	BPrivate::AppServerLink link;
1252 	link.StartMessage(AS_SET_ACCEPT_FIRST_CLICK);
1253 	link.Attach<bool>(acceptFirstClick);
1254 	link.Flush();
1255 }
1256 
1257 
1258 bool
1259 accept_first_click()
1260 {
1261 	// Gets the accept first click status
1262 	bool acceptFirstClick = true;
1263 
1264 	BPrivate::AppServerLink link;
1265 	link.StartMessage(AS_GET_ACCEPT_FIRST_CLICK);
1266 
1267 	int32 code;
1268 	if (link.FlushWithReply(code) == B_OK && code == B_OK)
1269 		link.Read<bool>(&acceptFirstClick);
1270 
1271 	return acceptFirstClick;
1272 }
1273 
1274 
1275 rgb_color
1276 ui_color(color_which which)
1277 {
1278 	int32 index = color_which_to_index(which);
1279 	if (index < 0 || index >= kColorWhichCount) {
1280 		fprintf(stderr, "ui_color(): unknown color_which %d\n", which);
1281 		return make_color(0, 0, 0);
1282 	}
1283 
1284 	if (be_app != NULL) {
1285 		server_read_only_memory* shared
1286 			= BApplication::Private::ServerReadOnlyMemory();
1287 		if (shared != NULL) {
1288 			// check for unset colors
1289 			if (shared->colors[index] == B_TRANSPARENT_COLOR)
1290 				shared->colors[index] = _kDefaultColors[index];
1291 
1292 			return shared->colors[index];
1293 		}
1294 	}
1295 
1296 	return _kDefaultColors[index];
1297 }
1298 
1299 
1300 rgb_color
1301 BPrivate::GetSystemColor(color_which colorConstant, bool darkVariant) {
1302 	if (darkVariant) {
1303 		return _kDefaultColorsDark[color_which_to_index(colorConstant)];
1304 	} else {
1305 		return _kDefaultColors[color_which_to_index(colorConstant)];
1306 	}
1307 }
1308 
1309 
1310 const char*
1311 ui_color_name(color_which which)
1312 {
1313 	// Suppress warnings for B_NO_COLOR.
1314 	if (which == B_NO_COLOR)
1315 		return NULL;
1316 
1317 	int32 index = color_which_to_index(which);
1318 	if (index < 0 || index >= kColorWhichCount) {
1319 		fprintf(stderr, "ui_color_name(): unknown color_which %d\n", which);
1320 		return NULL;
1321 	}
1322 
1323 	return kColorNames[index];
1324 }
1325 
1326 
1327 color_which
1328 which_ui_color(const char* name)
1329 {
1330 	if (name == NULL)
1331 		return B_NO_COLOR;
1332 
1333 	for (int32 index = 0; index < kColorWhichCount; ++index) {
1334 		if (!strcmp(kColorNames[index], name))
1335 			return index_to_color_which(index);
1336 	}
1337 
1338 	return B_NO_COLOR;
1339 }
1340 
1341 
1342 void
1343 set_ui_color(const color_which &which, const rgb_color &color)
1344 {
1345 	int32 index = color_which_to_index(which);
1346 	if (index < 0 || index >= kColorWhichCount) {
1347 		fprintf(stderr, "set_ui_color(): unknown color_which %d\n", which);
1348 		return;
1349 	}
1350 
1351 	if (ui_color(which) == color)
1352 		return;
1353 
1354 	BPrivate::DesktopLink link;
1355 	link.StartMessage(AS_SET_UI_COLOR);
1356 	link.Attach<color_which>(which);
1357 	link.Attach<rgb_color>(color);
1358 	link.Flush();
1359 }
1360 
1361 
1362 void
1363 set_ui_colors(const BMessage* colors)
1364 {
1365 	if (colors == NULL)
1366 		return;
1367 
1368 	int32 count = 0;
1369 	int32 index = 0;
1370 	char* name = NULL;
1371 	type_code type;
1372 	rgb_color color;
1373 	color_which which = B_NO_COLOR;
1374 
1375 	BPrivate::DesktopLink desktop;
1376 	if (desktop.InitCheck() != B_OK)
1377 		return;
1378 
1379 	desktop.StartMessage(AS_SET_UI_COLORS);
1380 	desktop.Attach<bool>(false);
1381 
1382 	// Only colors with names that map to system colors will get through.
1383 	while (colors->GetInfo(B_RGB_32_BIT_TYPE, index, &name, &type) == B_OK) {
1384 
1385 		which = which_ui_color(name);
1386 		++index;
1387 
1388 		if (which == B_NO_COLOR || colors->FindColor(name, &color) != B_OK)
1389 			continue;
1390 
1391 		desktop.Attach<color_which>(which);
1392 		desktop.Attach<rgb_color>(color);
1393 		++count;
1394 	}
1395 
1396 	if (count == 0)
1397 		return;
1398 
1399 	desktop.Attach<color_which>(B_NO_COLOR);
1400 	desktop.Flush();
1401 }
1402 
1403 
1404 rgb_color
1405 tint_color(rgb_color color, float tint)
1406 {
1407 	rgb_color result;
1408 
1409 	#define LIGHTEN(x) ((uint8)(255.0f - (255.0f - x) * tint))
1410 	#define DARKEN(x)  ((uint8)(x * (2 - tint)))
1411 
1412 	if (tint < 1.0f) {
1413 		result.red   = LIGHTEN(color.red);
1414 		result.green = LIGHTEN(color.green);
1415 		result.blue  = LIGHTEN(color.blue);
1416 		result.alpha = color.alpha;
1417 	} else {
1418 		result.red   = DARKEN(color.red);
1419 		result.green = DARKEN(color.green);
1420 		result.blue  = DARKEN(color.blue);
1421 		result.alpha = color.alpha;
1422 	}
1423 
1424 	#undef LIGHTEN
1425 	#undef DARKEN
1426 
1427 	return result;
1428 }
1429 
1430 
1431 rgb_color shift_color(rgb_color color, float shift);
1432 
1433 rgb_color
1434 shift_color(rgb_color color, float shift)
1435 {
1436 	return tint_color(color, shift);
1437 }
1438 
1439 
1440 extern "C" status_t
1441 _init_interface_kit_()
1442 {
1443 	status_t status = BPrivate::PaletteConverter::InitializeDefault(true);
1444 	if (status < B_OK)
1445 		return status;
1446 
1447 	// init global clipboard
1448 	if (be_clipboard == NULL)
1449 		be_clipboard = new BClipboard(NULL);
1450 
1451 	BString path;
1452 	if (get_control_look(path) && path.Length() > 0) {
1453 		BControlLook* (*instantiate)(image_id);
1454 
1455 		sControlLookAddon = load_add_on(path.String());
1456 		if (sControlLookAddon >= 0
1457 			&& get_image_symbol(sControlLookAddon,
1458 				"instantiate_control_look",
1459 				B_SYMBOL_TYPE_TEXT, (void **)&instantiate) == B_OK) {
1460 			be_control_look = instantiate(sControlLookAddon);
1461 			if (be_control_look == NULL) {
1462 				unload_add_on(sControlLookAddon);
1463 				sControlLookAddon = -1;
1464 			}
1465 		}
1466 	}
1467 	if (be_control_look == NULL)
1468 		be_control_look = new HaikuControlLook();
1469 
1470 	_init_global_fonts_();
1471 
1472 	BPrivate::gWidthBuffer = new BPrivate::WidthBuffer;
1473 	status = BPrivate::MenuPrivate::CreateBitmaps();
1474 	if (status != B_OK)
1475 		return status;
1476 
1477 	_menu_info_ptr_ = &BMenu::sMenuInfo;
1478 
1479 	status = get_menu_info(&BMenu::sMenuInfo);
1480 	if (status != B_OK)
1481 		return status;
1482 
1483 	general_info.background_color = ui_color(B_PANEL_BACKGROUND_COLOR);
1484 	general_info.mark_color = ui_color(B_CONTROL_MARK_COLOR);
1485 	general_info.highlight_color = ui_color(B_CONTROL_HIGHLIGHT_COLOR);
1486 	general_info.window_frame_color = ui_color(B_WINDOW_TAB_COLOR);
1487 	general_info.color_frame = true;
1488 
1489 	// TODO: fill the other static members
1490 
1491 	return status;
1492 }
1493 
1494 
1495 extern "C" status_t
1496 _fini_interface_kit_()
1497 {
1498 	BPrivate::MenuPrivate::DeleteBitmaps();
1499 
1500 	delete BPrivate::gWidthBuffer;
1501 	BPrivate::gWidthBuffer = NULL;
1502 
1503 	delete be_control_look;
1504 	be_control_look = NULL;
1505 
1506 	// Note: if we ever want to support live switching, we cannot just unload
1507 	// the old one since some thread might still be in a method of the object.
1508 	// maybe locking/unlocking all loopers around would ensure proper exit.
1509 	if (sControlLookAddon >= 0)
1510 		unload_add_on(sControlLookAddon);
1511 	sControlLookAddon = -1;
1512 
1513 	// TODO: Anything else?
1514 
1515 	return B_OK;
1516 }
1517 
1518 
1519 
1520 namespace BPrivate {
1521 
1522 
1523 /*!	\brief queries the server for the current decorator
1524 	\param path BString into which to store current decorator's location
1525 	\return boolean true/false
1526 */
1527 bool
1528 get_decorator(BString& path)
1529 {
1530 	BPrivate::AppServerLink link;
1531 	link.StartMessage(AS_GET_DECORATOR);
1532 
1533 	int32 code;
1534 	if (link.FlushWithReply(code) != B_OK || code != B_OK)
1535 		return false;
1536 
1537 	return link.ReadString(path) == B_OK;
1538 }
1539 
1540 
1541 /*!	\brief Private function which sets the window decorator for the system.
1542 	\param path BString with the path to the decorator to set
1543 
1544 	Will return detailed error status via status_t
1545 */
1546 status_t
1547 set_decorator(const BString& path)
1548 {
1549 	BPrivate::AppServerLink link;
1550 
1551 	link.StartMessage(AS_SET_DECORATOR);
1552 
1553 	link.AttachString(path.String());
1554 	link.Flush();
1555 
1556 	status_t error = B_OK;
1557 	link.Read<status_t>(&error);
1558 
1559 	return error;
1560 }
1561 
1562 
1563 /*! \brief sets a window to preview a given decorator
1564 	\param path path to any given decorator add-on
1565 	\param window pointer to BWindow which will show decorator
1566 
1567 	Piggy-backs on BWindow::SetDecoratorSettings(...)
1568 */
1569 status_t
1570 preview_decorator(const BString& path, BWindow* window)
1571 {
1572 	if (window == NULL)
1573 		return B_ERROR;
1574 
1575 	BMessage msg('prVu');
1576 	msg.AddString("preview", path.String());
1577 
1578 	return window->SetDecoratorSettings(msg);
1579 }
1580 
1581 
1582 /*!	\brief queries the server for the current ControlLook path
1583 	\param path BString into which to store current ControlLook's add-on path
1584 	\return boolean true/false
1585 */
1586 bool
1587 get_control_look(BString& path)
1588 {
1589 	BPrivate::AppServerLink link;
1590 	link.StartMessage(AS_GET_CONTROL_LOOK);
1591 
1592 	int32 code;
1593 	if (link.FlushWithReply(code) != B_OK || code != B_OK)
1594 		return false;
1595 
1596 	return link.ReadString(path) == B_OK;
1597 }
1598 
1599 
1600 /*!	\brief Private function which sets the ControlLook for the system.
1601 	\param BString with the ControlLook add-on path to set
1602 
1603 	Will return detailed error status via status_t
1604 */
1605 status_t
1606 set_control_look(const BString& path)
1607 {
1608 	BPrivate::AppServerLink link;
1609 
1610 	link.StartMessage(AS_SET_CONTROL_LOOK);
1611 
1612 	link.AttachString(path.String());
1613 
1614 	status_t error = B_OK;
1615 	if (link.FlushWithReply(error) != B_OK)
1616 		return B_ERROR;
1617 
1618 	return error;
1619 }
1620 
1621 
1622 status_t
1623 get_application_order(int32 workspace, team_id** _applications,
1624 	int32* _count)
1625 {
1626 	BPrivate::AppServerLink link;
1627 
1628 	link.StartMessage(AS_GET_APPLICATION_ORDER);
1629 	link.Attach<int32>(workspace);
1630 
1631 	int32 code;
1632 	status_t status = link.FlushWithReply(code);
1633 	if (status != B_OK)
1634 		return status;
1635 	if (code != B_OK)
1636 		return code;
1637 
1638 	int32 count;
1639 	link.Read<int32>(&count);
1640 
1641 	*_applications = (team_id*)malloc(count * sizeof(team_id));
1642 	if (*_applications == NULL)
1643 		return B_NO_MEMORY;
1644 
1645 	link.Read(*_applications, count * sizeof(team_id));
1646 	*_count = count;
1647 	return B_OK;
1648 }
1649 
1650 
1651 status_t
1652 get_window_order(int32 workspace, int32** _tokens, int32* _count)
1653 {
1654 	BPrivate::AppServerLink link;
1655 
1656 	link.StartMessage(AS_GET_WINDOW_ORDER);
1657 	link.Attach<int32>(workspace);
1658 
1659 	int32 code;
1660 	status_t status = link.FlushWithReply(code);
1661 	if (status != B_OK)
1662 		return status;
1663 	if (code != B_OK)
1664 		return code;
1665 
1666 	int32 count;
1667 	link.Read<int32>(&count);
1668 
1669 	*_tokens = (int32*)malloc(count * sizeof(int32));
1670 	if (*_tokens == NULL)
1671 		return B_NO_MEMORY;
1672 
1673 	link.Read(*_tokens, count * sizeof(int32));
1674 	*_count = count;
1675 	return B_OK;
1676 }
1677 
1678 
1679 }	// namespace BPrivate
1680 
1681 // These methods were marked with "Danger, will Robinson!" in
1682 // the OpenTracker source, so we might not want to be compatible
1683 // here.
1684 // In any way, we would need to update Deskbar to use our
1685 // replacements, so we could as well just implement them...
1686 
1687 void
1688 do_window_action(int32 windowToken, int32 action, BRect zoomRect, bool zoom)
1689 {
1690 	BPrivate::AppServerLink link;
1691 
1692 	link.StartMessage(AS_WINDOW_ACTION);
1693 	link.Attach<int32>(windowToken);
1694 	link.Attach<int32>(action);
1695 		// we don't have any zooming effect
1696 
1697 	link.Flush();
1698 }
1699 
1700 
1701 client_window_info*
1702 get_window_info(int32 serverToken)
1703 {
1704 	BPrivate::AppServerLink link;
1705 
1706 	link.StartMessage(AS_GET_WINDOW_INFO);
1707 	link.Attach<int32>(serverToken);
1708 
1709 	int32 code;
1710 	if (link.FlushWithReply(code) != B_OK || code != B_OK)
1711 		return NULL;
1712 
1713 	int32 size;
1714 	link.Read<int32>(&size);
1715 
1716 	client_window_info* info = (client_window_info*)malloc(size);
1717 	if (info == NULL)
1718 		return NULL;
1719 
1720 	link.Read(info, size);
1721 	return info;
1722 }
1723 
1724 
1725 int32*
1726 get_token_list(team_id team, int32* _count)
1727 {
1728 	BPrivate::AppServerLink link;
1729 
1730 	link.StartMessage(AS_GET_WINDOW_LIST);
1731 	link.Attach<team_id>(team);
1732 
1733 	int32 code;
1734 	if (link.FlushWithReply(code) != B_OK || code != B_OK)
1735 		return NULL;
1736 
1737 	int32 count;
1738 	link.Read<int32>(&count);
1739 
1740 	int32* tokens = (int32*)malloc(count * sizeof(int32));
1741 	if (tokens == NULL)
1742 		return NULL;
1743 
1744 	link.Read(tokens, count * sizeof(int32));
1745 	*_count = count;
1746 	return tokens;
1747 }
1748 
1749 
1750 void
1751 do_bring_to_front_team(BRect zoomRect, team_id team, bool zoom)
1752 {
1753 	BPrivate::AppServerLink link;
1754 
1755 	link.StartMessage(AS_BRING_TEAM_TO_FRONT);
1756 	link.Attach<team_id>(team);
1757 		// we don't have any zooming effect
1758 
1759 	link.Flush();
1760 }
1761 
1762 
1763 void
1764 do_minimize_team(BRect zoomRect, team_id team, bool zoom)
1765 {
1766 	BPrivate::AppServerLink link;
1767 
1768 	link.StartMessage(AS_MINIMIZE_TEAM);
1769 	link.Attach<team_id>(team);
1770 		// we don't have any zooming effect
1771 
1772 	link.Flush();
1773 }
1774 
1775 
1776 //	#pragma mark - truncate string
1777 
1778 
1779 void
1780 truncate_string(BString& string, uint32 mode, float width,
1781 	const float* escapementArray, float fontSize, float ellipsisWidth,
1782 	int32 charCount)
1783 {
1784 	// add a tiny amount to the width to make floating point inaccuracy
1785 	// not drop chars that would actually fit exactly
1786 	width += 1.f / 128;
1787 
1788 	switch (mode) {
1789 		case B_TRUNCATE_BEGINNING:
1790 		{
1791 			float totalWidth = 0;
1792 			for (int32 i = charCount - 1; i >= 0; i--) {
1793 				float charWidth = escapementArray[i] * fontSize;
1794 				if (totalWidth + charWidth > width) {
1795 					// we need to truncate
1796 					while (totalWidth + ellipsisWidth > width) {
1797 						// remove chars until there's enough space for the
1798 						// ellipsis
1799 						if (++i == charCount) {
1800 							// we've reached the end of the string and still
1801 							// no space, so return an empty string
1802 							string.Truncate(0);
1803 							return;
1804 						}
1805 
1806 						totalWidth -= escapementArray[i] * fontSize;
1807 					}
1808 
1809 					string.RemoveChars(0, i + 1);
1810 					string.PrependChars(B_UTF8_ELLIPSIS, 1);
1811 					return;
1812 				}
1813 
1814 				totalWidth += charWidth;
1815 			}
1816 
1817 			break;
1818 		}
1819 
1820 		case B_TRUNCATE_END:
1821 		{
1822 			float totalWidth = 0;
1823 			for (int32 i = 0; i < charCount; i++) {
1824 				float charWidth = escapementArray[i] * fontSize;
1825 				if (totalWidth + charWidth > width) {
1826 					// we need to truncate
1827 					while (totalWidth + ellipsisWidth > width) {
1828 						// remove chars until there's enough space for the
1829 						// ellipsis
1830 						if (i-- == 0) {
1831 							// we've reached the start of the string and still
1832 							// no space, so return an empty string
1833 							string.Truncate(0);
1834 							return;
1835 						}
1836 
1837 						totalWidth -= escapementArray[i] * fontSize;
1838 					}
1839 
1840 					string.RemoveChars(i, charCount - i);
1841 					string.AppendChars(B_UTF8_ELLIPSIS, 1);
1842 					return;
1843 				}
1844 
1845 				totalWidth += charWidth;
1846 			}
1847 
1848 			break;
1849 		}
1850 
1851 		case B_TRUNCATE_MIDDLE:
1852 		case B_TRUNCATE_SMART:
1853 		{
1854 			float leftWidth = 0;
1855 			float rightWidth = 0;
1856 			int32 leftIndex = 0;
1857 			int32 rightIndex = charCount - 1;
1858 			bool left = true;
1859 
1860 			for (int32 i = 0; i < charCount; i++) {
1861 				float charWidth
1862 					= escapementArray[left ? leftIndex : rightIndex] * fontSize;
1863 
1864 				if (leftWidth + rightWidth + charWidth > width) {
1865 					// we need to truncate
1866 					while (leftWidth + rightWidth + ellipsisWidth > width) {
1867 						// remove chars until there's enough space for the
1868 						// ellipsis
1869 						if (leftIndex == 0 && rightIndex == charCount - 1) {
1870 							// we've reached both ends of the string and still
1871 							// no space, so return an empty string
1872 							string.Truncate(0);
1873 							return;
1874 						}
1875 
1876 						if (leftIndex > 0 && (rightIndex == charCount - 1
1877 								|| leftWidth > rightWidth)) {
1878 							// remove char on the left
1879 							leftWidth -= escapementArray[--leftIndex]
1880 								* fontSize;
1881 						} else {
1882 							// remove char on the right
1883 							rightWidth -= escapementArray[++rightIndex]
1884 								* fontSize;
1885 						}
1886 					}
1887 
1888 					string.RemoveChars(leftIndex, rightIndex + 1 - leftIndex);
1889 					string.InsertChars(B_UTF8_ELLIPSIS, 1, leftIndex);
1890 					return;
1891 				}
1892 
1893 				if (left) {
1894 					leftIndex++;
1895 					leftWidth += charWidth;
1896 				} else {
1897 					rightIndex--;
1898 					rightWidth += charWidth;
1899 				}
1900 
1901 				left = rightWidth > leftWidth;
1902 			}
1903 
1904 			break;
1905 		}
1906 	}
1907 
1908 	// we've run through without the need to truncate, leave the string as it is
1909 }
1910