vfs: check userland buffers before reading them.
[haiku.git] / src / kits / interface / InterfaceDefs.cpp
blob4ad19fa81c75d6b08c4555da9114c838d0336f23
1 /*
2 * Copyright 2001-2015, Haiku, Inc.
3 * Distributed under the terms of the MIT License.
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>
15 /*! Global functions and variables for the Interface Kit */
18 #include <InterfaceDefs.h>
20 #include <new>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
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>
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>
58 using namespace BPrivate;
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;
69 struct general_ui_info general_info;
71 menu_info *_menu_info_ptr_;
73 extern "C" const char B_NOTIFICATION_SENDER[] = "be:sender";
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
118 const rgb_color* BPrivate::kDefaultColors = &_kDefaultColors[0];
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
166 namespace BPrivate {
169 /*! Fills the \a width, \a height, and \a colorSpace parameters according
170 to the window screen's mode.
171 Returns \c true if the mode is known.
173 bool
174 get_mode_parameter(uint32 mode, int32& width, int32& height,
175 uint32& colorSpace)
177 switch (mode) {
178 case B_8_BIT_640x480:
179 case B_8_BIT_800x600:
180 case B_8_BIT_1024x768:
181 case B_8_BIT_1152x900:
182 case B_8_BIT_1280x1024:
183 case B_8_BIT_1600x1200:
184 colorSpace = B_CMAP8;
185 break;
187 case B_15_BIT_640x480:
188 case B_15_BIT_800x600:
189 case B_15_BIT_1024x768:
190 case B_15_BIT_1152x900:
191 case B_15_BIT_1280x1024:
192 case B_15_BIT_1600x1200:
193 colorSpace = B_RGB15;
194 break;
196 case B_16_BIT_640x480:
197 case B_16_BIT_800x600:
198 case B_16_BIT_1024x768:
199 case B_16_BIT_1152x900:
200 case B_16_BIT_1280x1024:
201 case B_16_BIT_1600x1200:
202 colorSpace = B_RGB16;
203 break;
205 case B_32_BIT_640x480:
206 case B_32_BIT_800x600:
207 case B_32_BIT_1024x768:
208 case B_32_BIT_1152x900:
209 case B_32_BIT_1280x1024:
210 case B_32_BIT_1600x1200:
211 colorSpace = B_RGB32;
212 break;
214 default:
215 return false;
218 switch (mode) {
219 case B_8_BIT_640x480:
220 case B_15_BIT_640x480:
221 case B_16_BIT_640x480:
222 case B_32_BIT_640x480:
223 width = 640; height = 480;
224 break;
226 case B_8_BIT_800x600:
227 case B_15_BIT_800x600:
228 case B_16_BIT_800x600:
229 case B_32_BIT_800x600:
230 width = 800; height = 600;
231 break;
233 case B_8_BIT_1024x768:
234 case B_15_BIT_1024x768:
235 case B_16_BIT_1024x768:
236 case B_32_BIT_1024x768:
237 width = 1024; height = 768;
238 break;
240 case B_8_BIT_1152x900:
241 case B_15_BIT_1152x900:
242 case B_16_BIT_1152x900:
243 case B_32_BIT_1152x900:
244 width = 1152; height = 900;
245 break;
247 case B_8_BIT_1280x1024:
248 case B_15_BIT_1280x1024:
249 case B_16_BIT_1280x1024:
250 case B_32_BIT_1280x1024:
251 width = 1280; height = 1024;
252 break;
254 case B_8_BIT_1600x1200:
255 case B_15_BIT_1600x1200:
256 case B_16_BIT_1600x1200:
257 case B_32_BIT_1600x1200:
258 width = 1600; height = 1200;
259 break;
262 return true;
266 void
267 get_workspaces_layout(uint32* _columns, uint32* _rows)
269 int32 columns = 1;
270 int32 rows = 1;
272 BPrivate::AppServerLink link;
273 link.StartMessage(AS_GET_WORKSPACE_LAYOUT);
275 status_t status;
276 if (link.FlushWithReply(status) == B_OK && status == B_OK) {
277 link.Read<int32>(&columns);
278 link.Read<int32>(&rows);
281 if (_columns != NULL)
282 *_columns = columns;
283 if (_rows != NULL)
284 *_rows = rows;
288 void
289 set_workspaces_layout(uint32 columns, uint32 rows)
291 if (columns < 1 || rows < 1)
292 return;
294 BPrivate::AppServerLink link;
295 link.StartMessage(AS_SET_WORKSPACE_LAYOUT);
296 link.Attach<int32>(columns);
297 link.Attach<int32>(rows);
298 link.Flush();
302 } // namespace BPrivate
305 void
306 set_subpixel_antialiasing(bool subpix)
308 BPrivate::AppServerLink link;
310 link.StartMessage(AS_SET_SUBPIXEL_ANTIALIASING);
311 link.Attach<bool>(subpix);
312 link.Flush();
316 status_t
317 get_subpixel_antialiasing(bool* subpix)
319 BPrivate::AppServerLink link;
321 link.StartMessage(AS_GET_SUBPIXEL_ANTIALIASING);
322 int32 status = B_ERROR;
323 if (link.FlushWithReply(status) != B_OK || status < B_OK)
324 return status;
325 link.Read<bool>(subpix);
326 return B_OK;
330 void
331 set_hinting_mode(uint8 hinting)
333 BPrivate::AppServerLink link;
335 link.StartMessage(AS_SET_HINTING);
336 link.Attach<uint8>(hinting);
337 link.Flush();
341 status_t
342 get_hinting_mode(uint8* hinting)
344 BPrivate::AppServerLink link;
346 link.StartMessage(AS_GET_HINTING);
347 int32 status = B_ERROR;
348 if (link.FlushWithReply(status) != B_OK || status < B_OK)
349 return status;
350 link.Read<uint8>(hinting);
351 return B_OK;
355 void
356 set_average_weight(uint8 averageWeight)
358 BPrivate::AppServerLink link;
360 link.StartMessage(AS_SET_SUBPIXEL_AVERAGE_WEIGHT);
361 link.Attach<uint8>(averageWeight);
362 link.Flush();
366 status_t
367 get_average_weight(uint8* averageWeight)
369 BPrivate::AppServerLink link;
371 link.StartMessage(AS_GET_SUBPIXEL_AVERAGE_WEIGHT);
372 int32 status = B_ERROR;
373 if (link.FlushWithReply(status) != B_OK || status < B_OK)
374 return status;
375 link.Read<uint8>(averageWeight);
376 return B_OK;
380 void
381 set_is_subpixel_ordering_regular(bool subpixelOrdering)
383 BPrivate::AppServerLink link;
385 link.StartMessage(AS_SET_SUBPIXEL_ORDERING);
386 link.Attach<bool>(subpixelOrdering);
387 link.Flush();
391 status_t
392 get_is_subpixel_ordering_regular(bool* subpixelOrdering)
394 BPrivate::AppServerLink link;
396 link.StartMessage(AS_GET_SUBPIXEL_ORDERING);
397 int32 status = B_ERROR;
398 if (link.FlushWithReply(status) != B_OK || status < B_OK)
399 return status;
400 link.Read<bool>(subpixelOrdering);
401 return B_OK;
405 const color_map *
406 system_colors()
408 return BScreen(B_MAIN_SCREEN_ID).ColorMap();
412 status_t
413 set_screen_space(int32 index, uint32 space, bool stick)
415 int32 width;
416 int32 height;
417 uint32 depth;
418 if (!BPrivate::get_mode_parameter(space, width, height, depth))
419 return B_BAD_VALUE;
421 BScreen screen(B_MAIN_SCREEN_ID);
422 display_mode mode;
424 // TODO: What about refresh rate ?
425 // currently we get it from the current video mode, but
426 // this might be not so wise.
427 status_t status = screen.GetMode(index, &mode);
428 if (status < B_OK)
429 return status;
431 mode.virtual_width = width;
432 mode.virtual_height = height;
433 mode.space = depth;
435 return screen.SetMode(index, &mode, stick);
439 status_t
440 get_scroll_bar_info(scroll_bar_info *info)
442 if (info == NULL)
443 return B_BAD_VALUE;
445 BPrivate::AppServerLink link;
446 link.StartMessage(AS_GET_SCROLLBAR_INFO);
448 int32 code;
449 if (link.FlushWithReply(code) == B_OK
450 && code == B_OK) {
451 link.Read<scroll_bar_info>(info);
452 return B_OK;
455 return B_ERROR;
459 status_t
460 set_scroll_bar_info(scroll_bar_info *info)
462 if (info == NULL)
463 return B_BAD_VALUE;
465 BPrivate::AppServerLink link;
466 int32 code;
468 link.StartMessage(AS_SET_SCROLLBAR_INFO);
469 link.Attach<scroll_bar_info>(*info);
471 if (link.FlushWithReply(code) == B_OK
472 && code == B_OK)
473 return B_OK;
475 return B_ERROR;
479 status_t
480 get_mouse_type(int32 *type)
482 BMessage command(IS_GET_MOUSE_TYPE);
483 BMessage reply;
485 status_t err = _control_input_server_(&command, &reply);
486 if (err != B_OK)
487 return err;
488 return reply.FindInt32("mouse_type", type);
492 status_t
493 set_mouse_type(int32 type)
495 BMessage command(IS_SET_MOUSE_TYPE);
496 BMessage reply;
498 status_t err = command.AddInt32("mouse_type", type);
499 if (err != B_OK)
500 return err;
501 return _control_input_server_(&command, &reply);
505 status_t
506 get_mouse_map(mouse_map *map)
508 BMessage command(IS_GET_MOUSE_MAP);
509 BMessage reply;
510 const void *data = 0;
511 ssize_t count;
513 status_t err = _control_input_server_(&command, &reply);
514 if (err == B_OK)
515 err = reply.FindData("mousemap", B_RAW_TYPE, &data, &count);
516 if (err != B_OK)
517 return err;
519 memcpy(map, data, count);
521 return B_OK;
525 status_t
526 set_mouse_map(mouse_map *map)
528 BMessage command(IS_SET_MOUSE_MAP);
529 BMessage reply;
531 status_t err = command.AddData("mousemap", B_RAW_TYPE, map,
532 sizeof(mouse_map));
533 if (err != B_OK)
534 return err;
535 return _control_input_server_(&command, &reply);
539 status_t
540 get_click_speed(bigtime_t *speed)
542 BMessage command(IS_GET_CLICK_SPEED);
543 BMessage reply;
545 status_t err = _control_input_server_(&command, &reply);
546 if (err != B_OK)
547 return err;
549 if (reply.FindInt64("speed", speed) != B_OK)
550 *speed = 500000;
552 return B_OK;
556 status_t
557 set_click_speed(bigtime_t speed)
559 BMessage command(IS_SET_CLICK_SPEED);
560 BMessage reply;
561 command.AddInt64("speed", speed);
562 return _control_input_server_(&command, &reply);
566 status_t
567 get_mouse_speed(int32 *speed)
569 BMessage command(IS_GET_MOUSE_SPEED);
570 BMessage reply;
572 status_t err = _control_input_server_(&command, &reply);
573 if (err != B_OK)
574 return err;
576 if (reply.FindInt32("speed", speed) != B_OK)
577 *speed = 65536;
579 return B_OK;
583 status_t
584 set_mouse_speed(int32 speed)
586 BMessage command(IS_SET_MOUSE_SPEED);
587 BMessage reply;
588 command.AddInt32("speed", speed);
589 return _control_input_server_(&command, &reply);
593 status_t
594 get_mouse_acceleration(int32 *speed)
596 BMessage command(IS_GET_MOUSE_ACCELERATION);
597 BMessage reply;
599 _control_input_server_(&command, &reply);
601 if (reply.FindInt32("speed", speed) != B_OK)
602 *speed = 65536;
604 return B_OK;
608 status_t
609 set_mouse_acceleration(int32 speed)
611 BMessage command(IS_SET_MOUSE_ACCELERATION);
612 BMessage reply;
613 command.AddInt32("speed", speed);
614 return _control_input_server_(&command, &reply);
618 status_t
619 get_key_repeat_rate(int32 *rate)
621 BMessage command(IS_GET_KEY_REPEAT_RATE);
622 BMessage reply;
624 _control_input_server_(&command, &reply);
626 if (reply.FindInt32("rate", rate) != B_OK)
627 *rate = 250000;
629 return B_OK;
633 status_t
634 set_key_repeat_rate(int32 rate)
636 BMessage command(IS_SET_KEY_REPEAT_RATE);
637 BMessage reply;
638 command.AddInt32("rate", rate);
639 return _control_input_server_(&command, &reply);
643 status_t
644 get_key_repeat_delay(bigtime_t *delay)
646 BMessage command(IS_GET_KEY_REPEAT_DELAY);
647 BMessage reply;
649 _control_input_server_(&command, &reply);
651 if (reply.FindInt64("delay", delay) != B_OK)
652 *delay = 200;
654 return B_OK;
658 status_t
659 set_key_repeat_delay(bigtime_t delay)
661 BMessage command(IS_SET_KEY_REPEAT_DELAY);
662 BMessage reply;
663 command.AddInt64("delay", delay);
664 return _control_input_server_(&command, &reply);
668 uint32
669 modifiers()
671 BMessage command(IS_GET_MODIFIERS);
672 BMessage reply;
673 int32 err, modifier;
675 _control_input_server_(&command, &reply);
677 if (reply.FindInt32("status", &err) != B_OK)
678 return 0;
680 if (reply.FindInt32("modifiers", &modifier) != B_OK)
681 return 0;
683 return modifier;
687 status_t
688 get_key_info(key_info *info)
690 BMessage command(IS_GET_KEY_INFO);
691 BMessage reply;
692 const void *data = 0;
693 int32 err;
694 ssize_t count;
696 _control_input_server_(&command, &reply);
698 if (reply.FindInt32("status", &err) != B_OK)
699 return B_ERROR;
701 if (reply.FindData("key_info", B_ANY_TYPE, &data, &count) != B_OK)
702 return B_ERROR;
704 memcpy(info, data, count);
705 return B_OK;
709 void
710 get_key_map(key_map **map, char **key_buffer)
712 _get_key_map(map, key_buffer, NULL);
716 void
717 _get_key_map(key_map **map, char **key_buffer, ssize_t *key_buffer_size)
719 BMessage command(IS_GET_KEY_MAP);
720 BMessage reply;
721 ssize_t map_count, key_count;
722 const void *map_array = 0, *key_array = 0;
723 if (key_buffer_size == NULL)
724 key_buffer_size = &key_count;
726 _control_input_server_(&command, &reply);
728 if (reply.FindData("keymap", B_ANY_TYPE, &map_array, &map_count) != B_OK) {
729 *map = 0; *key_buffer = 0;
730 return;
733 if (reply.FindData("key_buffer", B_ANY_TYPE, &key_array, key_buffer_size)
734 != B_OK) {
735 *map = 0; *key_buffer = 0;
736 return;
739 *map = (key_map *)malloc(map_count);
740 memcpy(*map, map_array, map_count);
741 *key_buffer = (char *)malloc(*key_buffer_size);
742 memcpy(*key_buffer, key_array, *key_buffer_size);
746 status_t
747 get_keyboard_id(uint16 *id)
749 BMessage command(IS_GET_KEYBOARD_ID);
750 BMessage reply;
751 uint16 kid;
753 _control_input_server_(&command, &reply);
755 status_t err = reply.FindInt16("id", (int16 *)&kid);
756 if (err != B_OK)
757 return err;
758 *id = kid;
760 return B_OK;
764 status_t
765 get_modifier_key(uint32 modifier, uint32 *key)
767 BMessage command(IS_GET_MODIFIER_KEY);
768 BMessage reply;
769 uint32 rkey;
771 command.AddInt32("modifier", modifier);
772 _control_input_server_(&command, &reply);
774 status_t err = reply.FindInt32("key", (int32 *) &rkey);
775 if (err != B_OK)
776 return err;
777 *key = rkey;
779 return B_OK;
783 void
784 set_modifier_key(uint32 modifier, uint32 key)
786 BMessage command(IS_SET_MODIFIER_KEY);
787 BMessage reply;
789 command.AddInt32("modifier", modifier);
790 command.AddInt32("key", key);
791 _control_input_server_(&command, &reply);
795 void
796 set_keyboard_locks(uint32 modifiers)
798 BMessage command(IS_SET_KEYBOARD_LOCKS);
799 BMessage reply;
801 command.AddInt32("locks", modifiers);
802 _control_input_server_(&command, &reply);
806 status_t
807 _restore_key_map_()
809 BMessage message(IS_RESTORE_KEY_MAP);
810 BMessage reply;
812 return _control_input_server_(&message, &reply);
816 rgb_color
817 keyboard_navigation_color()
819 // Queries the app_server
820 return ui_color(B_KEYBOARD_NAVIGATION_COLOR);
824 int32
825 count_workspaces()
827 uint32 columns;
828 uint32 rows;
829 BPrivate::get_workspaces_layout(&columns, &rows);
831 return columns * rows;
835 void
836 set_workspace_count(int32 count)
838 int32 squareRoot = (int32)sqrt(count);
840 int32 rows = 1;
841 for (int32 i = 2; i <= squareRoot; i++) {
842 if (count % i == 0)
843 rows = i;
846 int32 columns = count / rows;
848 BPrivate::set_workspaces_layout(columns, rows);
852 int32
853 current_workspace()
855 int32 index = 0;
857 BPrivate::AppServerLink link;
858 link.StartMessage(AS_CURRENT_WORKSPACE);
860 int32 status;
861 if (link.FlushWithReply(status) == B_OK && status == B_OK)
862 link.Read<int32>(&index);
864 return index;
868 void
869 activate_workspace(int32 workspace)
871 BPrivate::AppServerLink link;
872 link.StartMessage(AS_ACTIVATE_WORKSPACE);
873 link.Attach<int32>(workspace);
874 link.Attach<bool>(false);
875 link.Flush();
879 bigtime_t
880 idle_time()
882 bigtime_t idletime = 0;
884 BPrivate::AppServerLink link;
885 link.StartMessage(AS_IDLE_TIME);
887 int32 code;
888 if (link.FlushWithReply(code) == B_OK && code == B_OK)
889 link.Read<int64>(&idletime);
891 return idletime;
895 void
896 run_select_printer_panel()
898 if (be_roster == NULL)
899 return;
901 // Launches the Printer prefs app via the Roster
902 be_roster->Launch(PRNT_SIGNATURE_TYPE);
906 void
907 run_add_printer_panel()
909 // Launches the Printer prefs app via the Roster and asks it to
910 // add a printer
911 run_select_printer_panel();
913 BMessenger printerPanelMessenger(PRNT_SIGNATURE_TYPE);
914 printerPanelMessenger.SendMessage(PRINTERS_ADD_PRINTER);
918 void
919 run_be_about()
921 if (be_roster != NULL)
922 be_roster->Launch("application/x-vnd.Haiku-About");
926 void
927 set_focus_follows_mouse(bool follow)
929 // obviously deprecated API
930 set_mouse_mode(B_FOCUS_FOLLOWS_MOUSE);
934 bool
935 focus_follows_mouse()
937 return mouse_mode() == B_FOCUS_FOLLOWS_MOUSE;
941 void
942 set_mouse_mode(mode_mouse mode)
944 BPrivate::AppServerLink link;
945 link.StartMessage(AS_SET_MOUSE_MODE);
946 link.Attach<mode_mouse>(mode);
947 link.Flush();
951 mode_mouse
952 mouse_mode()
954 // Gets the mouse focus style, such as activate to click,
955 // focus to click, ...
956 mode_mouse mode = B_NORMAL_MOUSE;
958 BPrivate::AppServerLink link;
959 link.StartMessage(AS_GET_MOUSE_MODE);
961 int32 code;
962 if (link.FlushWithReply(code) == B_OK && code == B_OK)
963 link.Read<mode_mouse>(&mode);
965 return mode;
969 void
970 set_focus_follows_mouse_mode(mode_focus_follows_mouse mode)
972 BPrivate::AppServerLink link;
973 link.StartMessage(AS_SET_FOCUS_FOLLOWS_MOUSE_MODE);
974 link.Attach<mode_focus_follows_mouse>(mode);
975 link.Flush();
979 mode_focus_follows_mouse
980 focus_follows_mouse_mode()
982 mode_focus_follows_mouse mode = B_NORMAL_FOCUS_FOLLOWS_MOUSE;
984 BPrivate::AppServerLink link;
985 link.StartMessage(AS_GET_FOCUS_FOLLOWS_MOUSE_MODE);
987 int32 code;
988 if (link.FlushWithReply(code) == B_OK && code == B_OK)
989 link.Read<mode_focus_follows_mouse>(&mode);
991 return mode;
995 status_t
996 get_mouse(BPoint* screenWhere, uint32* buttons)
998 if (screenWhere == NULL && buttons == NULL)
999 return B_BAD_VALUE;
1001 BPrivate::AppServerLink link;
1002 link.StartMessage(AS_GET_CURSOR_POSITION);
1004 int32 code;
1005 status_t ret = link.FlushWithReply(code);
1006 if (ret != B_OK)
1007 return ret;
1008 if (code != B_OK)
1009 return code;
1011 if (screenWhere != NULL)
1012 ret = link.Read<BPoint>(screenWhere);
1013 else {
1014 BPoint dummy;
1015 ret = link.Read<BPoint>(&dummy);
1017 if (ret != B_OK)
1018 return ret;
1020 if (buttons != NULL)
1021 ret = link.Read<uint32>(buttons);
1022 else {
1023 uint32 dummy;
1024 ret = link.Read<uint32>(&dummy);
1027 return ret;
1031 status_t
1032 get_mouse_bitmap(BBitmap** bitmap, BPoint* hotspot)
1034 if (bitmap == NULL && hotspot == NULL)
1035 return B_BAD_VALUE;
1037 BPrivate::AppServerLink link;
1038 link.StartMessage(AS_GET_CURSOR_BITMAP);
1040 int32 code;
1041 status_t status = link.FlushWithReply(code);
1042 if (status != B_OK)
1043 return status;
1044 if (code != B_OK)
1045 return code;
1047 uint32 size = 0;
1048 uint32 cursorWidth = 0;
1049 uint32 cursorHeight = 0;
1051 // if link.Read() returns an error, the same error will be returned on
1052 // subsequent calls, so we'll check only the return value of the last call
1053 link.Read<uint32>(&size);
1054 link.Read<uint32>(&cursorWidth);
1055 link.Read<uint32>(&cursorHeight);
1056 if (hotspot == NULL) {
1057 BPoint dummy;
1058 link.Read<BPoint>(&dummy);
1059 } else
1060 link.Read<BPoint>(hotspot);
1062 void* data = NULL;
1063 if (size > 0)
1064 data = malloc(size);
1065 if (data == NULL)
1066 return B_NO_MEMORY;
1068 status = link.Read(data, size);
1069 if (status != B_OK) {
1070 free(data);
1071 return status;
1074 BBitmap* cursorBitmap = new (std::nothrow) BBitmap(BRect(0, 0,
1075 cursorWidth - 1, cursorHeight - 1), B_RGBA32);
1077 if (cursorBitmap == NULL) {
1078 free(data);
1079 return B_NO_MEMORY;
1081 status = cursorBitmap->InitCheck();
1082 if (status == B_OK)
1083 cursorBitmap->SetBits(data, size, 0, B_RGBA32);
1085 free(data);
1087 if (status == B_OK && bitmap != NULL)
1088 *bitmap = cursorBitmap;
1089 else
1090 delete cursorBitmap;
1092 return status;
1096 void
1097 set_accept_first_click(bool acceptFirstClick)
1099 BPrivate::AppServerLink link;
1100 link.StartMessage(AS_SET_ACCEPT_FIRST_CLICK);
1101 link.Attach<bool>(acceptFirstClick);
1102 link.Flush();
1106 bool
1107 accept_first_click()
1109 // Gets the accept first click status
1110 bool acceptFirstClick = false;
1112 BPrivate::AppServerLink link;
1113 link.StartMessage(AS_GET_ACCEPT_FIRST_CLICK);
1115 int32 code;
1116 if (link.FlushWithReply(code) == B_OK && code == B_OK)
1117 link.Read<bool>(&acceptFirstClick);
1119 return acceptFirstClick;
1123 rgb_color
1124 ui_color(color_which which)
1126 int32 index = color_which_to_index(which);
1127 if (index < 0 || index >= kColorWhichCount) {
1128 fprintf(stderr, "ui_color(): unknown color_which %d\n", which);
1129 return make_color(0, 0, 0);
1132 if (be_app != NULL) {
1133 server_read_only_memory* shared
1134 = BApplication::Private::ServerReadOnlyMemory();
1135 if (shared != NULL) {
1136 // check for unset colors
1137 if (shared->colors[index] == B_TRANSPARENT_COLOR)
1138 shared->colors[index] = kDefaultColors[index];
1140 return shared->colors[index];
1144 return kDefaultColors[index];
1148 const char*
1149 ui_color_name(color_which which)
1151 // Suppress warnings for B_NO_COLOR.
1152 if (which == B_NO_COLOR)
1153 return NULL;
1155 int32 index = color_which_to_index(which);
1156 if (index < 0 || index >= kColorWhichCount) {
1157 fprintf(stderr, "ui_color_name(): unknown color_which %d\n", which);
1158 return NULL;
1161 return kColorNames[index];
1165 color_which
1166 which_ui_color(const char* name)
1168 if (name == NULL)
1169 return B_NO_COLOR;
1171 for (int32 index = 0; index < kColorWhichCount; ++index) {
1172 if (!strcmp(kColorNames[index], name))
1173 return index_to_color_which(index);
1176 return B_NO_COLOR;
1180 void
1181 set_ui_color(const color_which &which, const rgb_color &color)
1183 int32 index = color_which_to_index(which);
1184 if (index < 0 || index >= kColorWhichCount) {
1185 fprintf(stderr, "set_ui_color(): unknown color_which %d\n", which);
1186 return;
1189 if (ui_color(which) == color)
1190 return;
1192 BPrivate::DesktopLink link;
1193 link.StartMessage(AS_SET_UI_COLOR);
1194 link.Attach<color_which>(which);
1195 link.Attach<rgb_color>(color);
1196 link.Flush();
1200 void
1201 set_ui_colors(const BMessage* colors)
1203 if (colors == NULL)
1204 return;
1206 int32 count = 0;
1207 int32 index = 0;
1208 char* name = NULL;
1209 type_code type;
1210 rgb_color color;
1211 color_which which = B_NO_COLOR;
1213 BPrivate::DesktopLink desktop;
1214 if (desktop.InitCheck() != B_OK)
1215 return;
1217 desktop.StartMessage(AS_SET_UI_COLORS);
1218 desktop.Attach<bool>(false);
1220 // Only colors with names that map to system colors will get through.
1221 while (colors->GetInfo(B_RGB_32_BIT_TYPE, index, &name, &type) == B_OK) {
1223 which = which_ui_color(name);
1224 ++index;
1226 if (which == B_NO_COLOR || colors->FindColor(name, &color) != B_OK)
1227 continue;
1229 desktop.Attach<color_which>(which);
1230 desktop.Attach<rgb_color>(color);
1231 ++count;
1234 if (count == 0)
1235 return;
1237 desktop.Attach<color_which>(B_NO_COLOR);
1238 desktop.Flush();
1242 rgb_color
1243 tint_color(rgb_color color, float tint)
1245 rgb_color result;
1247 #define LIGHTEN(x) ((uint8)(255.0f - (255.0f - x) * tint))
1248 #define DARKEN(x) ((uint8)(x * (2 - tint)))
1250 if (tint < 1.0f) {
1251 result.red = LIGHTEN(color.red);
1252 result.green = LIGHTEN(color.green);
1253 result.blue = LIGHTEN(color.blue);
1254 result.alpha = color.alpha;
1255 } else {
1256 result.red = DARKEN(color.red);
1257 result.green = DARKEN(color.green);
1258 result.blue = DARKEN(color.blue);
1259 result.alpha = color.alpha;
1262 #undef LIGHTEN
1263 #undef DARKEN
1265 return result;
1269 rgb_color shift_color(rgb_color color, float shift);
1271 rgb_color
1272 shift_color(rgb_color color, float shift)
1274 return tint_color(color, shift);
1278 extern "C" status_t
1279 _init_interface_kit_()
1281 status_t status = BPrivate::PaletteConverter::InitializeDefault(true);
1282 if (status < B_OK)
1283 return status;
1285 // init global clipboard
1286 if (be_clipboard == NULL)
1287 be_clipboard = new BClipboard(NULL);
1289 // TODO: Could support different themes here in the future.
1290 be_control_look = new HaikuControlLook();
1292 _init_global_fonts_();
1294 BPrivate::gWidthBuffer = new BPrivate::WidthBuffer;
1295 status = BPrivate::MenuPrivate::CreateBitmaps();
1296 if (status != B_OK)
1297 return status;
1299 _menu_info_ptr_ = &BMenu::sMenuInfo;
1301 status = get_menu_info(&BMenu::sMenuInfo);
1302 if (status != B_OK)
1303 return status;
1305 general_info.background_color = ui_color(B_PANEL_BACKGROUND_COLOR);
1306 general_info.mark_color = ui_color(B_CONTROL_MARK_COLOR);
1307 general_info.highlight_color = ui_color(B_CONTROL_HIGHLIGHT_COLOR);
1308 general_info.window_frame_color = ui_color(B_WINDOW_TAB_COLOR);
1309 general_info.color_frame = true;
1311 // TODO: fill the other static members
1313 return status;
1317 extern "C" status_t
1318 _fini_interface_kit_()
1320 BPrivate::MenuPrivate::DeleteBitmaps();
1322 delete BPrivate::gWidthBuffer;
1323 BPrivate::gWidthBuffer = NULL;
1325 delete be_control_look;
1326 be_control_look = NULL;
1328 // TODO: Anything else?
1330 return B_OK;
1335 namespace BPrivate {
1338 /*! \brief queries the server for the current decorator
1339 \param ref entry_ref into which to store current decorator's location
1340 \return boolean true/false
1342 bool
1343 get_decorator(BString& path)
1345 BPrivate::AppServerLink link;
1346 link.StartMessage(AS_GET_DECORATOR);
1348 int32 code;
1349 if (link.FlushWithReply(code) != B_OK || code != B_OK)
1350 return false;
1352 return link.ReadString(path) == B_OK;
1356 /*! \brief Private function which sets the window decorator for the system.
1357 \param entry_ref to the decorator to set
1359 Will return detailed error status via status_t
1361 status_t
1362 set_decorator(const BString& path)
1364 BPrivate::AppServerLink link;
1366 link.StartMessage(AS_SET_DECORATOR);
1368 link.AttachString(path.String());
1369 link.Flush();
1371 status_t error = B_OK;
1372 link.Read<status_t>(&error);
1374 return error;
1378 /*! \brief sets a window to preview a given decorator
1379 \param path path to any given decorator add-on
1380 \param window pointer to BWindow which will show decorator
1382 Piggy-backs on BWindow::SetDecoratorSettings(...)
1384 status_t
1385 preview_decorator(const BString& path, BWindow* window)
1387 if (window == NULL)
1388 return B_ERROR;
1390 BMessage msg('prVu');
1391 msg.AddString("preview", path.String());
1393 return window->SetDecoratorSettings(msg);
1397 status_t
1398 get_application_order(int32 workspace, team_id** _applications,
1399 int32* _count)
1401 BPrivate::AppServerLink link;
1403 link.StartMessage(AS_GET_APPLICATION_ORDER);
1404 link.Attach<int32>(workspace);
1406 int32 code;
1407 status_t status = link.FlushWithReply(code);
1408 if (status != B_OK)
1409 return status;
1410 if (code != B_OK)
1411 return code;
1413 int32 count;
1414 link.Read<int32>(&count);
1416 *_applications = (team_id*)malloc(count * sizeof(team_id));
1417 if (*_applications == NULL)
1418 return B_NO_MEMORY;
1420 link.Read(*_applications, count * sizeof(team_id));
1421 *_count = count;
1422 return B_OK;
1426 status_t
1427 get_window_order(int32 workspace, int32** _tokens, int32* _count)
1429 BPrivate::AppServerLink link;
1431 link.StartMessage(AS_GET_WINDOW_ORDER);
1432 link.Attach<int32>(workspace);
1434 int32 code;
1435 status_t status = link.FlushWithReply(code);
1436 if (status != B_OK)
1437 return status;
1438 if (code != B_OK)
1439 return code;
1441 int32 count;
1442 link.Read<int32>(&count);
1444 *_tokens = (int32*)malloc(count * sizeof(int32));
1445 if (*_tokens == NULL)
1446 return B_NO_MEMORY;
1448 link.Read(*_tokens, count * sizeof(int32));
1449 *_count = count;
1450 return B_OK;
1454 } // namespace BPrivate
1456 // These methods were marked with "Danger, will Robinson!" in
1457 // the OpenTracker source, so we might not want to be compatible
1458 // here.
1459 // In any way, we would need to update Deskbar to use our
1460 // replacements, so we could as well just implement them...
1462 void
1463 do_window_action(int32 windowToken, int32 action, BRect zoomRect, bool zoom)
1465 BPrivate::AppServerLink link;
1467 link.StartMessage(AS_WINDOW_ACTION);
1468 link.Attach<int32>(windowToken);
1469 link.Attach<int32>(action);
1470 // we don't have any zooming effect
1472 link.Flush();
1476 client_window_info*
1477 get_window_info(int32 serverToken)
1479 BPrivate::AppServerLink link;
1481 link.StartMessage(AS_GET_WINDOW_INFO);
1482 link.Attach<int32>(serverToken);
1484 int32 code;
1485 if (link.FlushWithReply(code) != B_OK || code != B_OK)
1486 return NULL;
1488 int32 size;
1489 link.Read<int32>(&size);
1491 client_window_info* info = (client_window_info*)malloc(size);
1492 if (info == NULL)
1493 return NULL;
1495 link.Read(info, size);
1496 return info;
1500 int32*
1501 get_token_list(team_id team, int32* _count)
1503 BPrivate::AppServerLink link;
1505 link.StartMessage(AS_GET_WINDOW_LIST);
1506 link.Attach<team_id>(team);
1508 int32 code;
1509 if (link.FlushWithReply(code) != B_OK || code != B_OK)
1510 return NULL;
1512 int32 count;
1513 link.Read<int32>(&count);
1515 int32* tokens = (int32*)malloc(count * sizeof(int32));
1516 if (tokens == NULL)
1517 return NULL;
1519 link.Read(tokens, count * sizeof(int32));
1520 *_count = count;
1521 return tokens;
1525 void
1526 do_bring_to_front_team(BRect zoomRect, team_id team, bool zoom)
1528 BPrivate::AppServerLink link;
1530 link.StartMessage(AS_BRING_TEAM_TO_FRONT);
1531 link.Attach<team_id>(team);
1532 // we don't have any zooming effect
1534 link.Flush();
1538 void
1539 do_minimize_team(BRect zoomRect, team_id team, bool zoom)
1541 BPrivate::AppServerLink link;
1543 link.StartMessage(AS_MINIMIZE_TEAM);
1544 link.Attach<team_id>(team);
1545 // we don't have any zooming effect
1547 link.Flush();
1551 // #pragma mark - truncate string
1554 void
1555 truncate_string(BString& string, uint32 mode, float width,
1556 const float* escapementArray, float fontSize, float ellipsisWidth,
1557 int32 charCount)
1559 // add a tiny amount to the width to make floating point inaccuracy
1560 // not drop chars that would actually fit exactly
1561 width += 1.f / 128;
1563 switch (mode) {
1564 case B_TRUNCATE_BEGINNING:
1566 float totalWidth = 0;
1567 for (int32 i = charCount - 1; i >= 0; i--) {
1568 float charWidth = escapementArray[i] * fontSize;
1569 if (totalWidth + charWidth > width) {
1570 // we need to truncate
1571 while (totalWidth + ellipsisWidth > width) {
1572 // remove chars until there's enough space for the
1573 // ellipsis
1574 if (++i == charCount) {
1575 // we've reached the end of the string and still
1576 // no space, so return an empty string
1577 string.Truncate(0);
1578 return;
1581 totalWidth -= escapementArray[i] * fontSize;
1584 string.RemoveChars(0, i + 1);
1585 string.PrependChars(B_UTF8_ELLIPSIS, 1);
1586 return;
1589 totalWidth += charWidth;
1592 break;
1595 case B_TRUNCATE_END:
1597 float totalWidth = 0;
1598 for (int32 i = 0; i < charCount; i++) {
1599 float charWidth = escapementArray[i] * fontSize;
1600 if (totalWidth + charWidth > width) {
1601 // we need to truncate
1602 while (totalWidth + ellipsisWidth > width) {
1603 // remove chars until there's enough space for the
1604 // ellipsis
1605 if (i-- == 0) {
1606 // we've reached the start of the string and still
1607 // no space, so return an empty string
1608 string.Truncate(0);
1609 return;
1612 totalWidth -= escapementArray[i] * fontSize;
1615 string.RemoveChars(i, charCount - i);
1616 string.AppendChars(B_UTF8_ELLIPSIS, 1);
1617 return;
1620 totalWidth += charWidth;
1623 break;
1626 case B_TRUNCATE_MIDDLE:
1627 case B_TRUNCATE_SMART:
1629 float leftWidth = 0;
1630 float rightWidth = 0;
1631 int32 leftIndex = 0;
1632 int32 rightIndex = charCount - 1;
1633 bool left = true;
1635 for (int32 i = 0; i < charCount; i++) {
1636 float charWidth
1637 = escapementArray[left ? leftIndex : rightIndex] * fontSize;
1639 if (leftWidth + rightWidth + charWidth > width) {
1640 // we need to truncate
1641 while (leftWidth + rightWidth + ellipsisWidth > width) {
1642 // remove chars until there's enough space for the
1643 // ellipsis
1644 if (leftIndex == 0 && rightIndex == charCount - 1) {
1645 // we've reached both ends of the string and still
1646 // no space, so return an empty string
1647 string.Truncate(0);
1648 return;
1651 if (leftIndex > 0 && (rightIndex == charCount - 1
1652 || leftWidth > rightWidth)) {
1653 // remove char on the left
1654 leftWidth -= escapementArray[--leftIndex]
1655 * fontSize;
1656 } else {
1657 // remove char on the right
1658 rightWidth -= escapementArray[++rightIndex]
1659 * fontSize;
1663 string.RemoveChars(leftIndex, rightIndex + 1 - leftIndex);
1664 string.InsertChars(B_UTF8_ELLIPSIS, 1, leftIndex);
1665 return;
1668 if (left) {
1669 leftIndex++;
1670 leftWidth += charWidth;
1671 } else {
1672 rightIndex--;
1673 rightWidth += charWidth;
1676 left = rightWidth > leftWidth;
1679 break;
1683 // we've run through without the need to truncate, leave the string as it is