xref: /haiku/src/kits/interface/InterfaceDefs.cpp (revision caed67a8cba83913b9c21ac2b06ebc6bd1cb3111)
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
get_mode_parameter(uint32 mode,int32 & width,int32 & height,uint32 & colorSpace)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
get_workspaces_layout(uint32 * _columns,uint32 * _rows)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
set_workspaces_layout(uint32 columns,uint32 rows)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
set_subpixel_antialiasing(bool subpix)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
get_subpixel_antialiasing(bool * subpix)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
set_hinting_mode(uint8 hinting)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
get_hinting_mode(uint8 * hinting)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
set_average_weight(uint8 averageWeight)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
get_average_weight(uint8 * averageWeight)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
set_is_subpixel_ordering_regular(bool subpixelOrdering)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
get_is_subpixel_ordering_regular(bool * subpixelOrdering)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 *
system_colors()453 system_colors()
454 {
455 	return BScreen(B_MAIN_SCREEN_ID).ColorMap();
456 }
457 
458 
459 status_t
set_screen_space(int32 index,uint32 space,bool stick)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
get_scroll_bar_info(scroll_bar_info * info)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
set_scroll_bar_info(scroll_bar_info * info)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
get_mouse_type(int32 * type)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
set_mouse_type(int32 type)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
get_mouse_type(const char * mouse_name,int32 * type)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
set_mouse_type(const char * mouse_name,int32 type)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
get_mouse_map(mouse_map * map)585 get_mouse_map(mouse_map* map)
586 {
587 	return get_mouse_map("", map);
588 }
589 
590 
591 status_t
set_mouse_map(mouse_map * map)592 set_mouse_map(mouse_map* map)
593 {
594 	return set_mouse_map("", map);
595 }
596 
597 
598 status_t
get_mouse_map(const char * mouse_name,mouse_map * map)599 get_mouse_map(const char* mouse_name, mouse_map* map)
600 {
601 	BMessage command(IS_GET_MOUSE_MAP);
602 	BMessage reply;
603 	const void *data = 0;
604 	ssize_t count;
605 
606 	status_t err = command.AddString("mouse_name", mouse_name);
607 	if (err == B_OK)
608 		err = _control_input_server_(&command, &reply);
609 	if (err == B_OK)
610 		err = reply.FindData("mousemap", B_RAW_TYPE, &data, &count);
611 	if (err == B_OK)
612 		memcpy(map, data, count);
613 
614 	return err;
615 }
616 
617 
618 status_t
set_mouse_map(const char * mouse_name,mouse_map * map)619 set_mouse_map(const char* mouse_name, mouse_map* map)
620 {
621 	BMessage command(IS_SET_MOUSE_MAP);
622 	BMessage reply;
623 
624 	status_t err = command.AddString("mouse_name", mouse_name);
625 	if (err == B_OK)
626 		err = command.AddData("mousemap", B_RAW_TYPE, map, sizeof(mouse_map));
627 	if (err != B_OK)
628 		return err;
629 	return _control_input_server_(&command, &reply);
630 }
631 
632 
633 status_t
get_click_speed(bigtime_t * speed)634 get_click_speed(bigtime_t* speed)
635 {
636 	return get_click_speed("", speed);
637 }
638 
639 
640 status_t
set_click_speed(bigtime_t speed)641 set_click_speed(bigtime_t speed)
642 {
643 	return set_click_speed("", speed);
644 }
645 
646 
647 status_t
get_click_speed(const char * mouse_name,bigtime_t * speed)648 get_click_speed(const char* mouse_name, bigtime_t* speed)
649 {
650 	BMessage command(IS_GET_CLICK_SPEED);
651 	BMessage reply;
652 
653 	status_t err = command.AddString("mouse_name", mouse_name);
654 	if (err == B_OK)
655 		err = _control_input_server_(&command, &reply);
656 	if (err != B_OK)
657 		return err;
658 
659 	if (reply.FindInt64("speed", speed) != B_OK)
660 		*speed = 500000;
661 
662 	return B_OK;
663 }
664 
665 
666 status_t
set_click_speed(const char * mouse_name,bigtime_t speed)667 set_click_speed(const char* mouse_name, bigtime_t speed)
668 {
669 	BMessage command(IS_SET_CLICK_SPEED);
670 	BMessage reply;
671 
672 	status_t err = command.AddString("mouse_name", mouse_name);
673 	if (err == B_OK)
674 		err = command.AddInt64("speed", speed);
675 	if (err != B_OK)
676 		return err;
677 	return _control_input_server_(&command, &reply);
678 }
679 
680 
681 status_t
get_mouse_speed(int32 * speed)682 get_mouse_speed(int32 *speed)
683 {
684 	BMessage command(IS_GET_MOUSE_SPEED);
685 	BMessage reply;
686 
687 	status_t err = _control_input_server_(&command, &reply);
688 	if (err != B_OK)
689 		return err;
690 
691 	if (reply.FindInt32("speed", speed) != B_OK)
692 		*speed = 65536;
693 
694 	return B_OK;
695 }
696 
697 
698 status_t
set_mouse_speed(int32 speed)699 set_mouse_speed(int32 speed)
700 {
701 	BMessage command(IS_SET_MOUSE_SPEED);
702 	BMessage reply;
703 	command.AddInt32("speed", speed);
704 	return _control_input_server_(&command, &reply);
705 }
706 
707 
708 status_t
get_mouse_speed(const char * mouse_name,int32 * speed)709 get_mouse_speed(const char* mouse_name, int32 *speed)
710 {
711 	BMessage command(IS_GET_MOUSE_SPEED);
712 	BMessage reply;
713 	command.AddString("mouse_name", mouse_name);
714 
715 	status_t err = _control_input_server_(&command, &reply);
716 	if (err != B_OK)
717 		return err;
718 
719 	err = reply.FindInt32("speed", speed);
720 	if (err != B_OK)
721 		return err;
722 
723 	return B_OK;
724 }
725 
726 
727 status_t
set_mouse_speed(const char * mouse_name,int32 speed)728 set_mouse_speed(const char* mouse_name, int32 speed)
729 {
730 	BMessage command(IS_SET_MOUSE_SPEED);
731 	BMessage reply;
732 	command.AddString("mouse_name", mouse_name);
733 
734 	command.AddInt32("speed", speed);
735 
736 	return _control_input_server_(&command, &reply);
737 }
738 
739 
740 status_t
get_mouse_acceleration(int32 * speed)741 get_mouse_acceleration(int32 *speed)
742 {
743 	BMessage command(IS_GET_MOUSE_ACCELERATION);
744 	BMessage reply;
745 
746 	_control_input_server_(&command, &reply);
747 
748 	if (reply.FindInt32("speed", speed) != B_OK)
749 		*speed = 65536;
750 
751 	return B_OK;
752 }
753 
754 
755 status_t
set_mouse_acceleration(int32 speed)756 set_mouse_acceleration(int32 speed)
757 {
758 	BMessage command(IS_SET_MOUSE_ACCELERATION);
759 	BMessage reply;
760 	command.AddInt32("speed", speed);
761 	return _control_input_server_(&command, &reply);
762 }
763 
764 
765 status_t
get_mouse_acceleration(const char * mouse_name,int32 * speed)766 get_mouse_acceleration(const char* mouse_name, int32 *speed)
767 {
768 	BMessage command(IS_GET_MOUSE_ACCELERATION);
769 	BMessage reply;
770 	command.AddString("mouse_name", mouse_name);
771 
772 	_control_input_server_(&command, &reply);
773 
774 	if (reply.FindInt32("speed", speed) != B_OK)
775 		*speed = 65536;
776 
777 	return B_OK;
778 }
779 
780 
781 status_t
set_mouse_acceleration(const char * mouse_name,int32 speed)782 set_mouse_acceleration(const char* mouse_name, int32 speed)
783 {
784 	BMessage command(IS_SET_MOUSE_ACCELERATION);
785 	BMessage reply;
786 	command.AddString("mouse_name", mouse_name);
787 
788 	command.AddInt32("speed", speed);
789 
790 	return _control_input_server_(&command, &reply);
791 }
792 
793 
794 status_t
get_key_repeat_rate(int32 * rate)795 get_key_repeat_rate(int32 *rate)
796 {
797 	BMessage command(IS_GET_KEY_REPEAT_RATE);
798 	BMessage reply;
799 
800 	status_t err = _control_input_server_(&command, &reply);
801 
802 	if (err == B_OK)
803 		err = reply.FindInt32("rate", rate);
804 
805 	if (err != B_OK) {
806 		*rate = 250000;
807 		return err;
808 	}
809 
810 	return B_OK;
811 }
812 
813 
814 status_t
set_key_repeat_rate(int32 rate)815 set_key_repeat_rate(int32 rate)
816 {
817 	BMessage command(IS_SET_KEY_REPEAT_RATE);
818 	BMessage reply;
819 	command.AddInt32("rate", rate);
820 	return _control_input_server_(&command, &reply);
821 }
822 
823 
824 status_t
get_key_repeat_delay(bigtime_t * delay)825 get_key_repeat_delay(bigtime_t *delay)
826 {
827 	BMessage command(IS_GET_KEY_REPEAT_DELAY);
828 	BMessage reply;
829 
830 	status_t err = _control_input_server_(&command, &reply);
831 
832 	if (err == B_OK)
833 		err = reply.FindInt64("delay", delay);
834 
835 	if (err != B_OK) {
836 		*delay = 200;
837 		return err;
838 	}
839 
840 	return B_OK;
841 }
842 
843 
844 status_t
set_key_repeat_delay(bigtime_t delay)845 set_key_repeat_delay(bigtime_t  delay)
846 {
847 	BMessage command(IS_SET_KEY_REPEAT_DELAY);
848 	BMessage reply;
849 	command.AddInt64("delay", delay);
850 	return _control_input_server_(&command, &reply);
851 }
852 
853 
854 uint32
modifiers()855 modifiers()
856 {
857 	BMessage command(IS_GET_MODIFIERS);
858 	BMessage reply;
859 	int32 err, modifier;
860 
861 	_control_input_server_(&command, &reply);
862 
863 	if (reply.FindInt32("status", &err) != B_OK)
864 		return 0;
865 
866 	if (reply.FindInt32("modifiers", &modifier) != B_OK)
867 		return 0;
868 
869 	return modifier;
870 }
871 
872 
873 status_t
get_key_info(key_info * info)874 get_key_info(key_info *info)
875 {
876 	BMessage command(IS_GET_KEY_INFO);
877 	BMessage reply;
878 	const void *data = 0;
879 	int32 err;
880 	ssize_t count;
881 
882 	_control_input_server_(&command, &reply);
883 
884 	if (reply.FindInt32("status", &err) != B_OK)
885 		return B_ERROR;
886 
887 	if (reply.FindData("key_info", B_ANY_TYPE, &data, &count) != B_OK)
888 		return B_ERROR;
889 
890 	memcpy(info, data, count);
891 	return B_OK;
892 }
893 
894 
895 void
get_key_map(key_map ** map,char ** key_buffer)896 get_key_map(key_map **map, char **key_buffer)
897 {
898 	_get_key_map(map, key_buffer, NULL);
899 }
900 
901 
902 void
_get_key_map(key_map ** map,char ** key_buffer,ssize_t * key_buffer_size)903 _get_key_map(key_map **map, char **key_buffer, ssize_t *key_buffer_size)
904 {
905 	BMessage command(IS_GET_KEY_MAP);
906 	BMessage reply;
907 	ssize_t map_count, key_count;
908 	const void *map_array = 0, *key_array = 0;
909 	if (key_buffer_size == NULL)
910 		key_buffer_size = &key_count;
911 
912 	_control_input_server_(&command, &reply);
913 
914 	if (reply.FindData("keymap", B_ANY_TYPE, &map_array, &map_count) != B_OK) {
915 		*map = 0; *key_buffer = 0;
916 		return;
917 	}
918 
919 	if (reply.FindData("key_buffer", B_ANY_TYPE, &key_array, key_buffer_size)
920 			!= B_OK) {
921 		*map = 0; *key_buffer = 0;
922 		return;
923 	}
924 
925 	*map = (key_map *)malloc(map_count);
926 	memcpy(*map, map_array, map_count);
927 	*key_buffer = (char *)malloc(*key_buffer_size);
928 	memcpy(*key_buffer, key_array, *key_buffer_size);
929 }
930 
931 
932 status_t
get_keyboard_id(uint16 * id)933 get_keyboard_id(uint16 *id)
934 {
935 	BMessage command(IS_GET_KEYBOARD_ID);
936 	BMessage reply;
937 	uint16 kid;
938 
939 	_control_input_server_(&command, &reply);
940 
941 	status_t err = reply.FindInt16("id", (int16 *)&kid);
942 	if (err != B_OK)
943 		return err;
944 	*id = kid;
945 
946 	return B_OK;
947 }
948 
949 
950 status_t
get_modifier_key(uint32 modifier,uint32 * key)951 get_modifier_key(uint32 modifier, uint32 *key)
952 {
953 	BMessage command(IS_GET_MODIFIER_KEY);
954 	BMessage reply;
955 	uint32 rkey;
956 
957 	command.AddInt32("modifier", modifier);
958 	_control_input_server_(&command, &reply);
959 
960 	status_t err = reply.FindInt32("key", (int32 *) &rkey);
961 	if (err != B_OK)
962 		return err;
963 	*key = rkey;
964 
965 	return B_OK;
966 }
967 
968 
969 void
set_modifier_key(uint32 modifier,uint32 key)970 set_modifier_key(uint32 modifier, uint32 key)
971 {
972 	BMessage command(IS_SET_MODIFIER_KEY);
973 	BMessage reply;
974 
975 	command.AddInt32("modifier", modifier);
976 	command.AddInt32("key", key);
977 	_control_input_server_(&command, &reply);
978 }
979 
980 
981 void
set_keyboard_locks(uint32 modifiers)982 set_keyboard_locks(uint32 modifiers)
983 {
984 	BMessage command(IS_SET_KEYBOARD_LOCKS);
985 	BMessage reply;
986 
987 	command.AddInt32("locks", modifiers);
988 	_control_input_server_(&command, &reply);
989 }
990 
991 
992 status_t
_restore_key_map_()993 _restore_key_map_()
994 {
995 	BMessage message(IS_RESTORE_KEY_MAP);
996 	BMessage reply;
997 
998 	return _control_input_server_(&message, &reply);
999 }
1000 
1001 
1002 rgb_color
keyboard_navigation_color()1003 keyboard_navigation_color()
1004 {
1005 	// Queries the app_server
1006 	return ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1007 }
1008 
1009 
1010 int32
count_workspaces()1011 count_workspaces()
1012 {
1013 	uint32 columns;
1014 	uint32 rows;
1015 	BPrivate::get_workspaces_layout(&columns, &rows);
1016 
1017 	return columns * rows;
1018 }
1019 
1020 
1021 void
set_workspace_count(int32 count)1022 set_workspace_count(int32 count)
1023 {
1024 	int32 squareRoot = (int32)sqrt(count);
1025 
1026 	int32 rows = 1;
1027 	for (int32 i = 2; i <= squareRoot; i++) {
1028 		if (count % i == 0)
1029 			rows = i;
1030 	}
1031 
1032 	int32 columns = count / rows;
1033 
1034 	BPrivate::set_workspaces_layout(columns, rows);
1035 }
1036 
1037 
1038 int32
current_workspace()1039 current_workspace()
1040 {
1041 	int32 index = 0;
1042 
1043 	BPrivate::AppServerLink link;
1044 	link.StartMessage(AS_CURRENT_WORKSPACE);
1045 
1046 	int32 status;
1047 	if (link.FlushWithReply(status) == B_OK && status == B_OK)
1048 		link.Read<int32>(&index);
1049 
1050 	return index;
1051 }
1052 
1053 
1054 void
activate_workspace(int32 workspace)1055 activate_workspace(int32 workspace)
1056 {
1057 	BPrivate::AppServerLink link;
1058 	link.StartMessage(AS_ACTIVATE_WORKSPACE);
1059 	link.Attach<int32>(workspace);
1060 	link.Attach<bool>(false);
1061 	link.Flush();
1062 }
1063 
1064 
1065 bigtime_t
idle_time()1066 idle_time()
1067 {
1068 	bigtime_t idletime = 0;
1069 
1070 	BPrivate::AppServerLink link;
1071 	link.StartMessage(AS_IDLE_TIME);
1072 
1073 	int32 code;
1074 	if (link.FlushWithReply(code) == B_OK && code == B_OK)
1075 		link.Read<int64>(&idletime);
1076 
1077 	return idletime;
1078 }
1079 
1080 
1081 void
run_select_printer_panel()1082 run_select_printer_panel()
1083 {
1084 	if (be_roster == NULL)
1085 		return;
1086 
1087 	// Launches the Printer prefs app via the Roster
1088 	be_roster->Launch(PRNT_SIGNATURE_TYPE);
1089 }
1090 
1091 
1092 void
run_add_printer_panel()1093 run_add_printer_panel()
1094 {
1095 	// Launches the Printer prefs app via the Roster and asks it to
1096 	// add a printer
1097 	run_select_printer_panel();
1098 
1099 	BMessenger printerPanelMessenger(PRNT_SIGNATURE_TYPE);
1100 	printerPanelMessenger.SendMessage(PRINTERS_ADD_PRINTER);
1101 }
1102 
1103 
1104 void
run_be_about()1105 run_be_about()
1106 {
1107 	if (be_roster != NULL)
1108 		be_roster->Launch("application/x-vnd.Haiku-About");
1109 }
1110 
1111 
1112 void
set_focus_follows_mouse(bool follow)1113 set_focus_follows_mouse(bool follow)
1114 {
1115 	// obviously deprecated API
1116 	set_mouse_mode(follow ? B_FOCUS_FOLLOWS_MOUSE : B_NORMAL_MOUSE);
1117 }
1118 
1119 
1120 bool
focus_follows_mouse()1121 focus_follows_mouse()
1122 {
1123 	return mouse_mode() == B_FOCUS_FOLLOWS_MOUSE;
1124 }
1125 
1126 
1127 void
set_mouse_mode(mode_mouse mode)1128 set_mouse_mode(mode_mouse mode)
1129 {
1130 	BPrivate::AppServerLink link;
1131 	link.StartMessage(AS_SET_MOUSE_MODE);
1132 	link.Attach<mode_mouse>(mode);
1133 	link.Flush();
1134 }
1135 
1136 
1137 mode_mouse
mouse_mode()1138 mouse_mode()
1139 {
1140 	// Gets the mouse focus style, such as activate to click,
1141 	// focus to click, ...
1142 	mode_mouse mode = B_NORMAL_MOUSE;
1143 
1144 	BPrivate::AppServerLink link;
1145 	link.StartMessage(AS_GET_MOUSE_MODE);
1146 
1147 	int32 code;
1148 	if (link.FlushWithReply(code) == B_OK && code == B_OK)
1149 		link.Read<mode_mouse>(&mode);
1150 
1151 	return mode;
1152 }
1153 
1154 
1155 void
set_focus_follows_mouse_mode(mode_focus_follows_mouse mode)1156 set_focus_follows_mouse_mode(mode_focus_follows_mouse mode)
1157 {
1158 	BPrivate::AppServerLink link;
1159 	link.StartMessage(AS_SET_FOCUS_FOLLOWS_MOUSE_MODE);
1160 	link.Attach<mode_focus_follows_mouse>(mode);
1161 	link.Flush();
1162 }
1163 
1164 
1165 mode_focus_follows_mouse
focus_follows_mouse_mode()1166 focus_follows_mouse_mode()
1167 {
1168 	mode_focus_follows_mouse mode = B_NORMAL_FOCUS_FOLLOWS_MOUSE;
1169 
1170 	BPrivate::AppServerLink link;
1171 	link.StartMessage(AS_GET_FOCUS_FOLLOWS_MOUSE_MODE);
1172 
1173 	int32 code;
1174 	if (link.FlushWithReply(code) == B_OK && code == B_OK)
1175 		link.Read<mode_focus_follows_mouse>(&mode);
1176 
1177 	return mode;
1178 }
1179 
1180 
1181 status_t
get_mouse(BPoint * screenWhere,uint32 * buttons)1182 get_mouse(BPoint* screenWhere, uint32* buttons)
1183 {
1184 	if (screenWhere == NULL && buttons == NULL)
1185 		return B_BAD_VALUE;
1186 
1187 	BPrivate::AppServerLink link;
1188 	link.StartMessage(AS_GET_CURSOR_POSITION);
1189 
1190 	int32 code;
1191 	status_t ret = link.FlushWithReply(code);
1192 	if (ret != B_OK)
1193 		return ret;
1194 	if (code != B_OK)
1195 		return code;
1196 
1197 	if (screenWhere != NULL)
1198 		ret = link.Read<BPoint>(screenWhere);
1199 	else {
1200 		BPoint dummy;
1201 		ret = link.Read<BPoint>(&dummy);
1202 	}
1203 	if (ret != B_OK)
1204 		return ret;
1205 
1206 	if (buttons != NULL)
1207 		ret = link.Read<uint32>(buttons);
1208 	else {
1209 		uint32 dummy;
1210 		ret = link.Read<uint32>(&dummy);
1211 	}
1212 
1213 	return ret;
1214 }
1215 
1216 
1217 status_t
get_mouse_bitmap(BBitmap ** bitmap,BPoint * hotspot)1218 get_mouse_bitmap(BBitmap** bitmap, BPoint* hotspot)
1219 {
1220 	if (bitmap == NULL && hotspot == NULL)
1221 		return B_BAD_VALUE;
1222 
1223 	BPrivate::AppServerLink link;
1224 	link.StartMessage(AS_GET_CURSOR_BITMAP);
1225 
1226 	int32 code;
1227 	status_t status = link.FlushWithReply(code);
1228 	if (status != B_OK)
1229 		return status;
1230 	if (code != B_OK)
1231 		return code;
1232 
1233 	uint32 size = 0;
1234 	uint32 cursorWidth = 0;
1235 	uint32 cursorHeight = 0;
1236 	color_space colorspace = B_RGBA32;
1237 
1238 	// if link.Read() returns an error, the same error will be returned on
1239 	// subsequent calls, so we'll check only the return value of the last call
1240 	link.Read<uint32>(&size);
1241 	link.Read<uint32>(&cursorWidth);
1242 	link.Read<uint32>(&cursorHeight);
1243 	link.Read<color_space>(&colorspace);
1244 	if (hotspot == NULL) {
1245 		BPoint dummy;
1246 		link.Read<BPoint>(&dummy);
1247 	} else
1248 		link.Read<BPoint>(hotspot);
1249 
1250 	void* data = NULL;
1251 	if (size > 0)
1252 		data = malloc(size);
1253 	if (data == NULL)
1254 		return B_NO_MEMORY;
1255 
1256 	status = link.Read(data, size);
1257 	if (status != B_OK) {
1258 		free(data);
1259 		return status;
1260 	}
1261 
1262 	BBitmap* cursorBitmap = new (std::nothrow) BBitmap(BRect(0, 0,
1263 		cursorWidth - 1, cursorHeight - 1), colorspace);
1264 
1265 	if (cursorBitmap == NULL) {
1266 		free(data);
1267 		return B_NO_MEMORY;
1268 	}
1269 	status = cursorBitmap->InitCheck();
1270 	if (status == B_OK)
1271 		cursorBitmap->SetBits(data, size, 0, colorspace);
1272 
1273 	free(data);
1274 
1275 	if (status == B_OK && bitmap != NULL)
1276 		*bitmap = cursorBitmap;
1277 	else
1278 		delete cursorBitmap;
1279 
1280 	return status;
1281 }
1282 
1283 
1284 void
set_accept_first_click(bool acceptFirstClick)1285 set_accept_first_click(bool acceptFirstClick)
1286 {
1287 	BPrivate::AppServerLink link;
1288 	link.StartMessage(AS_SET_ACCEPT_FIRST_CLICK);
1289 	link.Attach<bool>(acceptFirstClick);
1290 	link.Flush();
1291 }
1292 
1293 
1294 bool
accept_first_click()1295 accept_first_click()
1296 {
1297 	// Gets the accept first click status
1298 	bool acceptFirstClick = true;
1299 
1300 	BPrivate::AppServerLink link;
1301 	link.StartMessage(AS_GET_ACCEPT_FIRST_CLICK);
1302 
1303 	int32 code;
1304 	if (link.FlushWithReply(code) == B_OK && code == B_OK)
1305 		link.Read<bool>(&acceptFirstClick);
1306 
1307 	return acceptFirstClick;
1308 }
1309 
1310 
1311 rgb_color
ui_color(color_which which)1312 ui_color(color_which which)
1313 {
1314 	int32 index = color_which_to_index(which);
1315 	if (index < 0 || index >= kColorWhichCount) {
1316 		fprintf(stderr, "ui_color(): unknown color_which %d\n", which);
1317 		return make_color(0, 0, 0);
1318 	}
1319 
1320 	if (be_app != NULL) {
1321 		server_read_only_memory* shared
1322 			= BApplication::Private::ServerReadOnlyMemory();
1323 		if (shared != NULL) {
1324 			// check for unset colors
1325 			if (shared->colors[index] == B_TRANSPARENT_COLOR)
1326 				shared->colors[index] = _kDefaultColors[index];
1327 
1328 			return shared->colors[index];
1329 		}
1330 	}
1331 
1332 	return _kDefaultColors[index];
1333 }
1334 
1335 
1336 rgb_color
GetSystemColor(color_which colorConstant,bool darkVariant)1337 BPrivate::GetSystemColor(color_which colorConstant, bool darkVariant) {
1338 	if (darkVariant) {
1339 		return _kDefaultColorsDark[color_which_to_index(colorConstant)];
1340 	} else {
1341 		return _kDefaultColors[color_which_to_index(colorConstant)];
1342 	}
1343 }
1344 
1345 
1346 const char*
ui_color_name(color_which which)1347 ui_color_name(color_which which)
1348 {
1349 	// Suppress warnings for B_NO_COLOR.
1350 	if (which == B_NO_COLOR)
1351 		return NULL;
1352 
1353 	int32 index = color_which_to_index(which);
1354 	if (index < 0 || index >= kColorWhichCount) {
1355 		fprintf(stderr, "ui_color_name(): unknown color_which %d\n", which);
1356 		return NULL;
1357 	}
1358 
1359 	return kColorNames[index];
1360 }
1361 
1362 
1363 color_which
which_ui_color(const char * name)1364 which_ui_color(const char* name)
1365 {
1366 	if (name == NULL)
1367 		return B_NO_COLOR;
1368 
1369 	for (int32 index = 0; index < kColorWhichCount; ++index) {
1370 		if (!strcmp(kColorNames[index], name))
1371 			return index_to_color_which(index);
1372 	}
1373 
1374 	return B_NO_COLOR;
1375 }
1376 
1377 
1378 void
set_ui_color(const color_which & which,const rgb_color & color)1379 set_ui_color(const color_which &which, const rgb_color &color)
1380 {
1381 	int32 index = color_which_to_index(which);
1382 	if (index < 0 || index >= kColorWhichCount) {
1383 		fprintf(stderr, "set_ui_color(): unknown color_which %d\n", which);
1384 		return;
1385 	}
1386 
1387 	if (ui_color(which) == color)
1388 		return;
1389 
1390 	BPrivate::DesktopLink link;
1391 	link.StartMessage(AS_SET_UI_COLOR);
1392 	link.Attach<color_which>(which);
1393 	link.Attach<rgb_color>(color);
1394 	link.Flush();
1395 }
1396 
1397 
1398 void
set_ui_colors(const BMessage * colors)1399 set_ui_colors(const BMessage* colors)
1400 {
1401 	if (colors == NULL)
1402 		return;
1403 
1404 	int32 count = 0;
1405 	int32 index = 0;
1406 	char* name = NULL;
1407 	type_code type;
1408 	rgb_color color;
1409 	color_which which = B_NO_COLOR;
1410 
1411 	BPrivate::DesktopLink desktop;
1412 	if (desktop.InitCheck() != B_OK)
1413 		return;
1414 
1415 	desktop.StartMessage(AS_SET_UI_COLORS);
1416 	desktop.Attach<bool>(false);
1417 
1418 	// Only colors with names that map to system colors will get through.
1419 	while (colors->GetInfo(B_RGB_32_BIT_TYPE, index, &name, &type) == B_OK) {
1420 
1421 		which = which_ui_color(name);
1422 		++index;
1423 
1424 		if (which == B_NO_COLOR || colors->FindColor(name, &color) != B_OK)
1425 			continue;
1426 
1427 		desktop.Attach<color_which>(which);
1428 		desktop.Attach<rgb_color>(color);
1429 		++count;
1430 	}
1431 
1432 	if (count == 0)
1433 		return;
1434 
1435 	desktop.Attach<color_which>(B_NO_COLOR);
1436 	desktop.Flush();
1437 }
1438 
1439 
1440 rgb_color
tint_color(rgb_color color,float tint)1441 tint_color(rgb_color color, float tint)
1442 {
1443 	rgb_color result;
1444 
1445 	#define LIGHTEN(x) ((uint8)(255.0f - (255.0f - x) * tint))
1446 	#define DARKEN(x)  ((uint8)(x * (2 - tint)))
1447 
1448 	if (tint < 1.0f) {
1449 		result.red   = LIGHTEN(color.red);
1450 		result.green = LIGHTEN(color.green);
1451 		result.blue  = LIGHTEN(color.blue);
1452 		result.alpha = color.alpha;
1453 	} else {
1454 		result.red   = DARKEN(color.red);
1455 		result.green = DARKEN(color.green);
1456 		result.blue  = DARKEN(color.blue);
1457 		result.alpha = color.alpha;
1458 	}
1459 
1460 	#undef LIGHTEN
1461 	#undef DARKEN
1462 
1463 	return result;
1464 }
1465 
1466 
1467 rgb_color shift_color(rgb_color color, float shift);
1468 
1469 rgb_color
shift_color(rgb_color color,float shift)1470 shift_color(rgb_color color, float shift)
1471 {
1472 	return tint_color(color, shift);
1473 }
1474 
1475 
1476 extern "C" status_t
_init_interface_kit_()1477 _init_interface_kit_()
1478 {
1479 	status_t status = BPrivate::PaletteConverter::InitializeDefault(true);
1480 	if (status < B_OK)
1481 		return status;
1482 
1483 	// init global clipboard
1484 	if (be_clipboard == NULL)
1485 		be_clipboard = new BClipboard(NULL);
1486 
1487 	BString path;
1488 	if (get_control_look(path) && path.Length() > 0) {
1489 		BControlLook* (*instantiate)(image_id);
1490 
1491 		sControlLookAddon = load_add_on(path.String());
1492 		if (sControlLookAddon >= 0
1493 			&& get_image_symbol(sControlLookAddon,
1494 				"instantiate_control_look",
1495 				B_SYMBOL_TYPE_TEXT, (void **)&instantiate) == B_OK) {
1496 			be_control_look = instantiate(sControlLookAddon);
1497 			if (be_control_look == NULL) {
1498 				unload_add_on(sControlLookAddon);
1499 				sControlLookAddon = -1;
1500 			}
1501 		}
1502 	}
1503 	if (be_control_look == NULL)
1504 		be_control_look = new HaikuControlLook();
1505 
1506 	_init_global_fonts_();
1507 
1508 	BPrivate::gWidthBuffer = new BPrivate::WidthBuffer;
1509 	status = BPrivate::MenuPrivate::CreateBitmaps();
1510 	if (status != B_OK)
1511 		return status;
1512 
1513 	_menu_info_ptr_ = &BMenu::sMenuInfo;
1514 
1515 	status = get_menu_info(&BMenu::sMenuInfo);
1516 	if (status != B_OK)
1517 		return status;
1518 
1519 	general_info.background_color = ui_color(B_PANEL_BACKGROUND_COLOR);
1520 	general_info.mark_color = ui_color(B_CONTROL_MARK_COLOR);
1521 	general_info.highlight_color = ui_color(B_CONTROL_HIGHLIGHT_COLOR);
1522 	general_info.window_frame_color = ui_color(B_WINDOW_TAB_COLOR);
1523 	general_info.color_frame = true;
1524 
1525 	// TODO: fill the other static members
1526 
1527 	return status;
1528 }
1529 
1530 
1531 extern "C" status_t
_fini_interface_kit_()1532 _fini_interface_kit_()
1533 {
1534 	BPrivate::MenuPrivate::DeleteBitmaps();
1535 
1536 	delete BPrivate::gWidthBuffer;
1537 	BPrivate::gWidthBuffer = NULL;
1538 
1539 	delete be_control_look;
1540 	be_control_look = NULL;
1541 
1542 	// Note: if we ever want to support live switching, we cannot just unload
1543 	// the old one since some thread might still be in a method of the object.
1544 	// maybe locking/unlocking all loopers around would ensure proper exit.
1545 	if (sControlLookAddon >= 0)
1546 		unload_add_on(sControlLookAddon);
1547 	sControlLookAddon = -1;
1548 
1549 	// TODO: Anything else?
1550 
1551 	return B_OK;
1552 }
1553 
1554 
1555 
1556 namespace BPrivate {
1557 
1558 
1559 /*!	\brief queries the server for the current decorator
1560 	\param path BString into which to store current decorator's location
1561 	\return boolean true/false
1562 */
1563 bool
get_decorator(BString & path)1564 get_decorator(BString& path)
1565 {
1566 	BPrivate::AppServerLink link;
1567 	link.StartMessage(AS_GET_DECORATOR);
1568 
1569 	int32 code;
1570 	if (link.FlushWithReply(code) != B_OK || code != B_OK)
1571 		return false;
1572 
1573 	return link.ReadString(path) == B_OK;
1574 }
1575 
1576 
1577 /*!	\brief Private function which sets the window decorator for the system.
1578 	\param path BString with the path to the decorator to set
1579 
1580 	Will return detailed error status via status_t
1581 */
1582 status_t
set_decorator(const BString & path)1583 set_decorator(const BString& path)
1584 {
1585 	BPrivate::AppServerLink link;
1586 
1587 	link.StartMessage(AS_SET_DECORATOR);
1588 
1589 	link.AttachString(path.String());
1590 	link.Flush();
1591 
1592 	status_t error = B_OK;
1593 	link.Read<status_t>(&error);
1594 
1595 	return error;
1596 }
1597 
1598 
1599 /*! \brief sets a window to preview a given decorator
1600 	\param path path to any given decorator add-on
1601 	\param window pointer to BWindow which will show decorator
1602 
1603 	Piggy-backs on BWindow::SetDecoratorSettings(...)
1604 */
1605 status_t
preview_decorator(const BString & path,BWindow * window)1606 preview_decorator(const BString& path, BWindow* window)
1607 {
1608 	if (window == NULL)
1609 		return B_ERROR;
1610 
1611 	BMessage msg('prVu');
1612 	msg.AddString("preview", path.String());
1613 
1614 	return window->SetDecoratorSettings(msg);
1615 }
1616 
1617 
1618 /*!	\brief queries the server for the current ControlLook path
1619 	\param path BString into which to store current ControlLook's add-on path
1620 	\return boolean true/false
1621 */
1622 bool
get_control_look(BString & path)1623 get_control_look(BString& path)
1624 {
1625 	BPrivate::AppServerLink link;
1626 	link.StartMessage(AS_GET_CONTROL_LOOK);
1627 
1628 	int32 code;
1629 	if (link.FlushWithReply(code) != B_OK || code != B_OK)
1630 		return false;
1631 
1632 	return link.ReadString(path) == B_OK;
1633 }
1634 
1635 
1636 /*!	\brief Private function which sets the ControlLook for the system.
1637 	\param BString with the ControlLook add-on path to set
1638 
1639 	Will return detailed error status via status_t
1640 */
1641 status_t
set_control_look(const BString & path)1642 set_control_look(const BString& path)
1643 {
1644 	BPrivate::AppServerLink link;
1645 
1646 	link.StartMessage(AS_SET_CONTROL_LOOK);
1647 
1648 	link.AttachString(path.String());
1649 
1650 	status_t error = B_OK;
1651 	if (link.FlushWithReply(error) != B_OK)
1652 		return B_ERROR;
1653 
1654 	return error;
1655 }
1656 
1657 
1658 status_t
get_application_order(int32 workspace,team_id ** _applications,int32 * _count)1659 get_application_order(int32 workspace, team_id** _applications,
1660 	int32* _count)
1661 {
1662 	BPrivate::AppServerLink link;
1663 
1664 	link.StartMessage(AS_GET_APPLICATION_ORDER);
1665 	link.Attach<int32>(workspace);
1666 
1667 	int32 code;
1668 	status_t status = link.FlushWithReply(code);
1669 	if (status != B_OK)
1670 		return status;
1671 	if (code != B_OK)
1672 		return code;
1673 
1674 	int32 count;
1675 	link.Read<int32>(&count);
1676 
1677 	*_applications = (team_id*)malloc(count * sizeof(team_id));
1678 	if (*_applications == NULL)
1679 		return B_NO_MEMORY;
1680 
1681 	link.Read(*_applications, count * sizeof(team_id));
1682 	*_count = count;
1683 	return B_OK;
1684 }
1685 
1686 
1687 status_t
get_window_order(int32 workspace,int32 ** _tokens,int32 * _count)1688 get_window_order(int32 workspace, int32** _tokens, int32* _count)
1689 {
1690 	BPrivate::AppServerLink link;
1691 
1692 	link.StartMessage(AS_GET_WINDOW_ORDER);
1693 	link.Attach<int32>(workspace);
1694 
1695 	int32 code;
1696 	status_t status = link.FlushWithReply(code);
1697 	if (status != B_OK)
1698 		return status;
1699 	if (code != B_OK)
1700 		return code;
1701 
1702 	int32 count;
1703 	link.Read<int32>(&count);
1704 
1705 	*_tokens = (int32*)malloc(count * sizeof(int32));
1706 	if (*_tokens == NULL)
1707 		return B_NO_MEMORY;
1708 
1709 	link.Read(*_tokens, count * sizeof(int32));
1710 	*_count = count;
1711 	return B_OK;
1712 }
1713 
1714 
1715 }	// namespace BPrivate
1716 
1717 // These methods were marked with "Danger, will Robinson!" in
1718 // the OpenTracker source, so we might not want to be compatible
1719 // here.
1720 // In any way, we would need to update Deskbar to use our
1721 // replacements, so we could as well just implement them...
1722 
1723 void
do_window_action(int32 windowToken,int32 action,BRect zoomRect,bool zoom)1724 do_window_action(int32 windowToken, int32 action, BRect zoomRect, bool zoom)
1725 {
1726 	BPrivate::AppServerLink link;
1727 
1728 	link.StartMessage(AS_WINDOW_ACTION);
1729 	link.Attach<int32>(windowToken);
1730 	link.Attach<int32>(action);
1731 		// we don't have any zooming effect
1732 
1733 	link.Flush();
1734 }
1735 
1736 
1737 client_window_info*
get_window_info(int32 serverToken)1738 get_window_info(int32 serverToken)
1739 {
1740 	BPrivate::AppServerLink link;
1741 
1742 	link.StartMessage(AS_GET_WINDOW_INFO);
1743 	link.Attach<int32>(serverToken);
1744 
1745 	int32 code;
1746 	if (link.FlushWithReply(code) != B_OK || code != B_OK)
1747 		return NULL;
1748 
1749 	int32 size;
1750 	link.Read<int32>(&size);
1751 
1752 	client_window_info* info = (client_window_info*)malloc(size);
1753 	if (info == NULL)
1754 		return NULL;
1755 
1756 	link.Read(info, size);
1757 	return info;
1758 }
1759 
1760 
1761 int32*
get_token_list(team_id team,int32 * _count)1762 get_token_list(team_id team, int32* _count)
1763 {
1764 	BPrivate::AppServerLink link;
1765 
1766 	link.StartMessage(AS_GET_WINDOW_LIST);
1767 	link.Attach<team_id>(team);
1768 
1769 	int32 code;
1770 	if (link.FlushWithReply(code) != B_OK || code != B_OK)
1771 		return NULL;
1772 
1773 	int32 count;
1774 	link.Read<int32>(&count);
1775 
1776 	int32* tokens = (int32*)malloc(count * sizeof(int32));
1777 	if (tokens == NULL)
1778 		return NULL;
1779 
1780 	link.Read(tokens, count * sizeof(int32));
1781 	*_count = count;
1782 	return tokens;
1783 }
1784 
1785 
1786 void
do_bring_to_front_team(BRect zoomRect,team_id team,bool zoom)1787 do_bring_to_front_team(BRect zoomRect, team_id team, bool zoom)
1788 {
1789 	BPrivate::AppServerLink link;
1790 
1791 	link.StartMessage(AS_BRING_TEAM_TO_FRONT);
1792 	link.Attach<team_id>(team);
1793 		// we don't have any zooming effect
1794 
1795 	link.Flush();
1796 }
1797 
1798 
1799 void
do_minimize_team(BRect zoomRect,team_id team,bool zoom)1800 do_minimize_team(BRect zoomRect, team_id team, bool zoom)
1801 {
1802 	BPrivate::AppServerLink link;
1803 
1804 	link.StartMessage(AS_MINIMIZE_TEAM);
1805 	link.Attach<team_id>(team);
1806 		// we don't have any zooming effect
1807 
1808 	link.Flush();
1809 }
1810 
1811 
1812 //	#pragma mark - truncate string
1813 
1814 
1815 void
truncate_string(BString & string,uint32 mode,float width,const float * escapementArray,float fontSize,float ellipsisWidth,int32 charCount)1816 truncate_string(BString& string, uint32 mode, float width,
1817 	const float* escapementArray, float fontSize, float ellipsisWidth,
1818 	int32 charCount)
1819 {
1820 	// add a tiny amount to the width to make floating point inaccuracy
1821 	// not drop chars that would actually fit exactly
1822 	width += 1.f / 128;
1823 
1824 	switch (mode) {
1825 		case B_TRUNCATE_BEGINNING:
1826 		{
1827 			float totalWidth = 0;
1828 			for (int32 i = charCount - 1; i >= 0; i--) {
1829 				float charWidth = escapementArray[i] * fontSize;
1830 				if (totalWidth + charWidth > width) {
1831 					// we need to truncate
1832 					while (totalWidth + ellipsisWidth > width) {
1833 						// remove chars until there's enough space for the
1834 						// ellipsis
1835 						if (++i == charCount) {
1836 							// we've reached the end of the string and still
1837 							// no space, so return an empty string
1838 							string.Truncate(0);
1839 							return;
1840 						}
1841 
1842 						totalWidth -= escapementArray[i] * fontSize;
1843 					}
1844 
1845 					string.RemoveChars(0, i + 1);
1846 					string.PrependChars(B_UTF8_ELLIPSIS, 1);
1847 					return;
1848 				}
1849 
1850 				totalWidth += charWidth;
1851 			}
1852 
1853 			break;
1854 		}
1855 
1856 		case B_TRUNCATE_END:
1857 		{
1858 			float totalWidth = 0;
1859 			for (int32 i = 0; i < charCount; i++) {
1860 				float charWidth = escapementArray[i] * fontSize;
1861 				if (totalWidth + charWidth > width) {
1862 					// we need to truncate
1863 					while (totalWidth + ellipsisWidth > width) {
1864 						// remove chars until there's enough space for the
1865 						// ellipsis
1866 						if (i-- == 0) {
1867 							// we've reached the start of the string and still
1868 							// no space, so return an empty string
1869 							string.Truncate(0);
1870 							return;
1871 						}
1872 
1873 						totalWidth -= escapementArray[i] * fontSize;
1874 					}
1875 
1876 					string.RemoveChars(i, charCount - i);
1877 					string.AppendChars(B_UTF8_ELLIPSIS, 1);
1878 					return;
1879 				}
1880 
1881 				totalWidth += charWidth;
1882 			}
1883 
1884 			break;
1885 		}
1886 
1887 		case B_TRUNCATE_MIDDLE:
1888 		case B_TRUNCATE_SMART:
1889 		{
1890 			float leftWidth = 0;
1891 			float rightWidth = 0;
1892 			int32 leftIndex = 0;
1893 			int32 rightIndex = charCount - 1;
1894 			bool left = true;
1895 
1896 			for (int32 i = 0; i < charCount; i++) {
1897 				float charWidth
1898 					= escapementArray[left ? leftIndex : rightIndex] * fontSize;
1899 
1900 				if (leftWidth + rightWidth + charWidth > width) {
1901 					// we need to truncate
1902 					while (leftWidth + rightWidth + ellipsisWidth > width) {
1903 						// remove chars until there's enough space for the
1904 						// ellipsis
1905 						if (leftIndex == 0 && rightIndex == charCount - 1) {
1906 							// we've reached both ends of the string and still
1907 							// no space, so return an empty string
1908 							string.Truncate(0);
1909 							return;
1910 						}
1911 
1912 						if (leftIndex > 0 && (rightIndex == charCount - 1
1913 								|| leftWidth > rightWidth)) {
1914 							// remove char on the left
1915 							leftWidth -= escapementArray[--leftIndex]
1916 								* fontSize;
1917 						} else {
1918 							// remove char on the right
1919 							rightWidth -= escapementArray[++rightIndex]
1920 								* fontSize;
1921 						}
1922 					}
1923 
1924 					string.RemoveChars(leftIndex, rightIndex + 1 - leftIndex);
1925 					string.InsertChars(B_UTF8_ELLIPSIS, 1, leftIndex);
1926 					return;
1927 				}
1928 
1929 				if (left) {
1930 					leftIndex++;
1931 					leftWidth += charWidth;
1932 				} else {
1933 					rightIndex--;
1934 					rightWidth += charWidth;
1935 				}
1936 
1937 				left = rightWidth > leftWidth;
1938 			}
1939 
1940 			break;
1941 		}
1942 	}
1943 
1944 	// we've run through without the need to truncate, leave the string as it is
1945 }
1946