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