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