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