1 /* 2 * Copyright 2001-2010, 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) { 1080 server_read_only_memory* shared 1081 = BApplication::Private::ServerReadOnlyMemory(); 1082 return shared->colors[index]; 1083 } 1084 1085 return kDefaultColors[index]; 1086 } 1087 1088 1089 void 1090 set_ui_color(const color_which &which, const rgb_color &color) 1091 { 1092 int32 index = color_which_to_index(which); 1093 if (index < 0 || index >= kColorWhichCount) { 1094 fprintf(stderr, "set_ui_color(): unknown color_which %d\n", which); 1095 return; 1096 } 1097 1098 BPrivate::AppServerLink link; 1099 link.StartMessage(AS_SET_UI_COLOR); 1100 link.Attach<color_which>(which); 1101 link.Attach<rgb_color>(color); 1102 link.Flush(); 1103 } 1104 1105 1106 rgb_color 1107 tint_color(rgb_color color, float tint) 1108 { 1109 rgb_color result; 1110 1111 #define LIGHTEN(x) ((uint8)(255.0f - (255.0f - x) * tint)) 1112 #define DARKEN(x) ((uint8)(x * (2 - tint))) 1113 1114 if (tint < 1.0f) { 1115 result.red = LIGHTEN(color.red); 1116 result.green = LIGHTEN(color.green); 1117 result.blue = LIGHTEN(color.blue); 1118 result.alpha = color.alpha; 1119 } else { 1120 result.red = DARKEN(color.red); 1121 result.green = DARKEN(color.green); 1122 result.blue = DARKEN(color.blue); 1123 result.alpha = color.alpha; 1124 } 1125 1126 #undef LIGHTEN 1127 #undef DARKEN 1128 1129 return result; 1130 } 1131 1132 1133 rgb_color shift_color(rgb_color color, float shift); 1134 1135 rgb_color 1136 shift_color(rgb_color color, float shift) 1137 { 1138 return tint_color(color, shift); 1139 } 1140 1141 1142 extern "C" status_t 1143 _init_interface_kit_() 1144 { 1145 status_t status = BPrivate::PaletteConverter::InitializeDefault(true); 1146 if (status < B_OK) 1147 return status; 1148 1149 // init global clipboard 1150 if (be_clipboard == NULL) 1151 be_clipboard = new BClipboard(NULL); 1152 1153 // TODO: Could support different themes here in the future. 1154 be_control_look = new BControlLook(); 1155 1156 _init_global_fonts_(); 1157 1158 BPrivate::gWidthBuffer = new BPrivate::WidthBuffer; 1159 status = BPrivate::MenuPrivate::CreateBitmaps(); 1160 if (status != B_OK) 1161 return status; 1162 1163 _menu_info_ptr_ = &BMenu::sMenuInfo; 1164 1165 status = get_menu_info(&BMenu::sMenuInfo); 1166 if (status != B_OK) 1167 return status; 1168 1169 general_info.background_color = ui_color(B_PANEL_BACKGROUND_COLOR); 1170 general_info.mark_color = ui_color(B_CONTROL_MARK_COLOR); 1171 general_info.highlight_color = ui_color(B_CONTROL_HIGHLIGHT_COLOR); 1172 general_info.window_frame_color = ui_color(B_WINDOW_TAB_COLOR); 1173 general_info.color_frame = true; 1174 1175 // TODO: fill the other static members 1176 1177 return status; 1178 } 1179 1180 1181 extern "C" status_t 1182 _fini_interface_kit_() 1183 { 1184 BPrivate::MenuPrivate::DeleteBitmaps(); 1185 1186 delete BPrivate::gWidthBuffer; 1187 BPrivate::gWidthBuffer = NULL; 1188 1189 delete be_control_look; 1190 be_control_look = NULL; 1191 1192 // TODO: Anything else? 1193 1194 return B_OK; 1195 } 1196 1197 1198 1199 namespace BPrivate { 1200 1201 1202 /*! \brief queries the server for the current decorator 1203 \param ref entry_ref into which to store current decorator's location 1204 \return boolean true/false 1205 */ 1206 bool 1207 get_decorator(BString& path) 1208 { 1209 BPrivate::AppServerLink link; 1210 link.StartMessage(AS_GET_DECORATOR); 1211 1212 int32 code; 1213 if (link.FlushWithReply(code) != B_OK || code != B_OK) 1214 return false; 1215 1216 return link.ReadString(path) == B_OK; 1217 } 1218 1219 1220 /*! \brief Private function which sets the window decorator for the system. 1221 \param entry_ref to the decorator to set 1222 1223 Will return detailed error status via status_t 1224 */ 1225 status_t 1226 set_decorator(const BString& path) 1227 { 1228 BPrivate::AppServerLink link; 1229 1230 link.StartMessage(AS_SET_DECORATOR); 1231 1232 link.AttachString(path.String()); 1233 link.Flush(); 1234 1235 status_t error = B_OK; 1236 link.Read<status_t>(&error); 1237 1238 return error; 1239 } 1240 1241 1242 /*! \brief sets a window to preview a given decorator 1243 \param path path to any given decorator add-on 1244 \param window pointer to BWindow which will show decorator 1245 1246 Piggy-backs on BWindow::SetDecoratorSettings(...) 1247 */ 1248 status_t 1249 preview_decorator(const BString& path, BWindow* window) 1250 { 1251 if (window == NULL) 1252 return B_ERROR; 1253 1254 BMessage msg('prVu'); 1255 msg.AddString("preview", path.String()); 1256 1257 return window->SetDecoratorSettings(msg); 1258 } 1259 1260 1261 status_t 1262 get_application_order(int32 workspace, team_id** _applications, 1263 int32* _count) 1264 { 1265 BPrivate::AppServerLink link; 1266 1267 link.StartMessage(AS_GET_APPLICATION_ORDER); 1268 link.Attach<int32>(workspace); 1269 1270 int32 code; 1271 status_t status = link.FlushWithReply(code); 1272 if (status != B_OK) 1273 return status; 1274 if (code != B_OK) 1275 return code; 1276 1277 int32 count; 1278 link.Read<int32>(&count); 1279 1280 *_applications = (team_id*)malloc(count * sizeof(team_id)); 1281 if (*_applications == NULL) 1282 return B_NO_MEMORY; 1283 1284 link.Read(*_applications, count * sizeof(team_id)); 1285 *_count = count; 1286 return B_OK; 1287 } 1288 1289 1290 status_t 1291 get_window_order(int32 workspace, int32** _tokens, int32* _count) 1292 { 1293 BPrivate::AppServerLink link; 1294 1295 link.StartMessage(AS_GET_WINDOW_ORDER); 1296 link.Attach<int32>(workspace); 1297 1298 int32 code; 1299 status_t status = link.FlushWithReply(code); 1300 if (status != B_OK) 1301 return status; 1302 if (code != B_OK) 1303 return code; 1304 1305 int32 count; 1306 link.Read<int32>(&count); 1307 1308 *_tokens = (int32*)malloc(count * sizeof(int32)); 1309 if (*_tokens == NULL) 1310 return B_NO_MEMORY; 1311 1312 link.Read(*_tokens, count * sizeof(int32)); 1313 *_count = count; 1314 return B_OK; 1315 } 1316 1317 1318 } // namespace BPrivate 1319 1320 // These methods were marked with "Danger, will Robinson!" in 1321 // the OpenTracker source, so we might not want to be compatible 1322 // here. 1323 // In any way, we would need to update Deskbar to use our 1324 // replacements, so we could as well just implement them... 1325 1326 void 1327 do_window_action(int32 windowToken, int32 action, BRect zoomRect, bool zoom) 1328 { 1329 BPrivate::AppServerLink link; 1330 1331 link.StartMessage(AS_WINDOW_ACTION); 1332 link.Attach<int32>(windowToken); 1333 link.Attach<int32>(action); 1334 // we don't have any zooming effect 1335 1336 link.Flush(); 1337 } 1338 1339 1340 client_window_info* 1341 get_window_info(int32 serverToken) 1342 { 1343 BPrivate::AppServerLink link; 1344 1345 link.StartMessage(AS_GET_WINDOW_INFO); 1346 link.Attach<int32>(serverToken); 1347 1348 int32 code; 1349 if (link.FlushWithReply(code) != B_OK || code != B_OK) 1350 return NULL; 1351 1352 int32 size; 1353 link.Read<int32>(&size); 1354 1355 client_window_info* info = (client_window_info*)malloc(size); 1356 if (info == NULL) 1357 return NULL; 1358 1359 link.Read(info, size); 1360 return info; 1361 } 1362 1363 1364 int32* 1365 get_token_list(team_id team, int32* _count) 1366 { 1367 BPrivate::AppServerLink link; 1368 1369 link.StartMessage(AS_GET_WINDOW_LIST); 1370 link.Attach<team_id>(team); 1371 1372 int32 code; 1373 if (link.FlushWithReply(code) != B_OK || code != B_OK) 1374 return NULL; 1375 1376 int32 count; 1377 link.Read<int32>(&count); 1378 1379 int32* tokens = (int32*)malloc(count * sizeof(int32)); 1380 if (tokens == NULL) 1381 return NULL; 1382 1383 link.Read(tokens, count * sizeof(int32)); 1384 *_count = count; 1385 return tokens; 1386 } 1387 1388 1389 void 1390 do_bring_to_front_team(BRect zoomRect, team_id team, bool zoom) 1391 { 1392 BPrivate::AppServerLink link; 1393 1394 link.StartMessage(AS_BRING_TEAM_TO_FRONT); 1395 link.Attach<team_id>(team); 1396 // we don't have any zooming effect 1397 1398 link.Flush(); 1399 } 1400 1401 1402 void 1403 do_minimize_team(BRect zoomRect, team_id team, bool zoom) 1404 { 1405 BPrivate::AppServerLink link; 1406 1407 link.StartMessage(AS_MINIMIZE_TEAM); 1408 link.Attach<team_id>(team); 1409 // we don't have any zooming effect 1410 1411 link.Flush(); 1412 } 1413 1414 1415 // #pragma mark - truncate string 1416 1417 1418 void 1419 truncate_string(BString& string, uint32 mode, float width, 1420 const float* escapementArray, float fontSize, float ellipsisWidth, 1421 int32 charCount) 1422 { 1423 // add a tiny amount to the width to make floating point inaccuracy 1424 // not drop chars that would actually fit exactly 1425 width += 1.f / 128; 1426 1427 switch (mode) { 1428 case B_TRUNCATE_BEGINNING: 1429 { 1430 float totalWidth = 0; 1431 for (int32 i = charCount - 1; i >= 0; i--) { 1432 float charWidth = escapementArray[i] * fontSize; 1433 if (totalWidth + charWidth > width) { 1434 // we need to truncate 1435 while (totalWidth + ellipsisWidth > width) { 1436 // remove chars until there's enough space for the 1437 // ellipsis 1438 if (++i == charCount) { 1439 // we've reached the end of the string and still 1440 // no space, so return an empty string 1441 string.Truncate(0); 1442 return; 1443 } 1444 1445 totalWidth -= escapementArray[i] * fontSize; 1446 } 1447 1448 string.RemoveChars(0, i + 1); 1449 string.PrependChars(B_UTF8_ELLIPSIS, 1); 1450 return; 1451 } 1452 1453 totalWidth += charWidth; 1454 } 1455 1456 break; 1457 } 1458 1459 case B_TRUNCATE_END: 1460 { 1461 float totalWidth = 0; 1462 for (int32 i = 0; i < charCount; i++) { 1463 float charWidth = escapementArray[i] * fontSize; 1464 if (totalWidth + charWidth > width) { 1465 // we need to truncate 1466 while (totalWidth + ellipsisWidth > width) { 1467 // remove chars until there's enough space for the 1468 // ellipsis 1469 if (i-- == 0) { 1470 // we've reached the start of the string and still 1471 // no space, so return an empty string 1472 string.Truncate(0); 1473 return; 1474 } 1475 1476 totalWidth -= escapementArray[i] * fontSize; 1477 } 1478 1479 string.RemoveChars(i, charCount - i); 1480 string.AppendChars(B_UTF8_ELLIPSIS, 1); 1481 return; 1482 } 1483 1484 totalWidth += charWidth; 1485 } 1486 1487 break; 1488 } 1489 1490 case B_TRUNCATE_MIDDLE: 1491 case B_TRUNCATE_SMART: 1492 { 1493 float leftWidth = 0; 1494 float rightWidth = 0; 1495 int32 leftIndex = 0; 1496 int32 rightIndex = charCount - 1; 1497 bool left = true; 1498 1499 for (int32 i = 0; i < charCount; i++) { 1500 float charWidth 1501 = escapementArray[left ? leftIndex : rightIndex] * fontSize; 1502 1503 if (leftWidth + rightWidth + charWidth > width) { 1504 // we need to truncate 1505 while (leftWidth + rightWidth + ellipsisWidth > width) { 1506 // remove chars until there's enough space for the 1507 // ellipsis 1508 if (leftIndex == 0 && rightIndex == charCount - 1) { 1509 // we've reached both ends of the string and still 1510 // no space, so return an empty string 1511 string.Truncate(0); 1512 return; 1513 } 1514 1515 if (leftIndex > 0 && (rightIndex == charCount - 1 1516 || leftWidth > rightWidth)) { 1517 // remove char on the left 1518 leftWidth -= escapementArray[--leftIndex] 1519 * fontSize; 1520 } else { 1521 // remove char on the right 1522 rightWidth -= escapementArray[++rightIndex] 1523 * fontSize; 1524 } 1525 } 1526 1527 string.RemoveChars(leftIndex, rightIndex + 1 - leftIndex); 1528 string.InsertChars(B_UTF8_ELLIPSIS, 1, leftIndex); 1529 return; 1530 } 1531 1532 if (left) { 1533 leftIndex++; 1534 leftWidth += charWidth; 1535 } else { 1536 rightIndex--; 1537 rightWidth += charWidth; 1538 } 1539 1540 left = rightWidth > leftWidth; 1541 } 1542 1543 break; 1544 } 1545 } 1546 1547 // we've run through without the need to truncate, leave the string as it is 1548 } 1549