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