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(const char* mouse_name, int32 *type) 509 { 510 BMessage command(IS_GET_MOUSE_TYPE); 511 BMessage reply; 512 command.AddString("mouse_name", mouse_name); 513 514 status_t err = _control_input_server_(&command, &reply); 515 if (err != B_OK) 516 return err; 517 518 return reply.FindInt32("mouse_type", type); 519 } 520 521 522 status_t 523 set_mouse_type(const char* mouse_name, int32 type) 524 { 525 BMessage command(IS_SET_MOUSE_TYPE); 526 BMessage reply; 527 528 status_t err_mouse_name = command.AddString("mouse_name", mouse_name); 529 if (err_mouse_name != B_OK) 530 return err_mouse_name; 531 532 status_t err = command.AddInt32("mouse_type", type); 533 if (err != B_OK) 534 return err; 535 return _control_input_server_(&command, &reply); 536 } 537 538 539 status_t 540 get_mouse_map(mouse_map *map) 541 { 542 BMessage command(IS_GET_MOUSE_MAP); 543 BMessage reply; 544 const void *data = 0; 545 ssize_t count; 546 547 status_t err = _control_input_server_(&command, &reply); 548 if (err == B_OK) 549 err = reply.FindData("mousemap", B_RAW_TYPE, &data, &count); 550 if (err != B_OK) 551 return err; 552 553 memcpy(map, data, count); 554 555 return B_OK; 556 } 557 558 559 status_t 560 set_mouse_map(mouse_map *map) 561 { 562 BMessage command(IS_SET_MOUSE_MAP); 563 BMessage reply; 564 565 status_t err = command.AddData("mousemap", B_RAW_TYPE, map, 566 sizeof(mouse_map)); 567 if (err != B_OK) 568 return err; 569 return _control_input_server_(&command, &reply); 570 } 571 572 573 status_t 574 get_click_speed(bigtime_t *speed) 575 { 576 BMessage command(IS_GET_CLICK_SPEED); 577 BMessage reply; 578 579 status_t err = _control_input_server_(&command, &reply); 580 if (err != B_OK) 581 return err; 582 583 if (reply.FindInt64("speed", speed) != B_OK) 584 *speed = 500000; 585 586 return B_OK; 587 } 588 589 590 status_t 591 set_click_speed(bigtime_t speed) 592 { 593 BMessage command(IS_SET_CLICK_SPEED); 594 BMessage reply; 595 command.AddInt64("speed", speed); 596 return _control_input_server_(&command, &reply); 597 } 598 599 600 status_t 601 get_mouse_speed(int32 *speed) 602 { 603 BMessage command(IS_GET_MOUSE_SPEED); 604 BMessage reply; 605 606 status_t err = _control_input_server_(&command, &reply); 607 if (err != B_OK) 608 return err; 609 610 if (reply.FindInt32("speed", speed) != B_OK) 611 *speed = 65536; 612 613 return B_OK; 614 } 615 616 617 status_t 618 set_mouse_speed(int32 speed) 619 { 620 BMessage command(IS_SET_MOUSE_SPEED); 621 BMessage reply; 622 command.AddInt32("speed", speed); 623 return _control_input_server_(&command, &reply); 624 } 625 626 627 status_t 628 get_mouse_speed(const char* mouse_name, int32 *speed) 629 { 630 BMessage command(IS_GET_MOUSE_SPEED); 631 BMessage reply; 632 command.AddString("mouse_name", mouse_name); 633 634 status_t err = _control_input_server_(&command, &reply); 635 if (err != B_OK) 636 return err; 637 638 err = reply.FindInt32("speed", speed); 639 if (err != B_OK) 640 return err; 641 642 return B_OK; 643 } 644 645 646 status_t 647 set_mouse_speed(const char* mouse_name, int32 speed) 648 { 649 BMessage command(IS_SET_MOUSE_SPEED); 650 BMessage reply; 651 command.AddString("mouse_name", mouse_name); 652 653 command.AddInt32("speed", speed); 654 655 return _control_input_server_(&command, &reply); 656 } 657 658 659 status_t 660 get_mouse_acceleration(int32 *speed) 661 { 662 BMessage command(IS_GET_MOUSE_ACCELERATION); 663 BMessage reply; 664 665 _control_input_server_(&command, &reply); 666 667 if (reply.FindInt32("speed", speed) != B_OK) 668 *speed = 65536; 669 670 return B_OK; 671 } 672 673 674 status_t 675 set_mouse_acceleration(int32 speed) 676 { 677 BMessage command(IS_SET_MOUSE_ACCELERATION); 678 BMessage reply; 679 command.AddInt32("speed", speed); 680 return _control_input_server_(&command, &reply); 681 } 682 683 684 status_t 685 get_mouse_acceleration(const char* mouse_name, int32 *speed) 686 { 687 BMessage command(IS_GET_MOUSE_ACCELERATION); 688 BMessage reply; 689 command.AddString("mouse_name", mouse_name); 690 691 _control_input_server_(&command, &reply); 692 693 if (reply.FindInt32("speed", speed) != B_OK) 694 *speed = 65536; 695 696 return B_OK; 697 } 698 699 700 status_t 701 set_mouse_acceleration(const char* mouse_name, int32 speed) 702 { 703 BMessage command(IS_SET_MOUSE_ACCELERATION); 704 BMessage reply; 705 command.AddString("mouse_name", mouse_name); 706 707 command.AddInt32("speed", speed); 708 709 return _control_input_server_(&command, &reply); 710 } 711 712 713 status_t 714 get_key_repeat_rate(int32 *rate) 715 { 716 BMessage command(IS_GET_KEY_REPEAT_RATE); 717 BMessage reply; 718 719 _control_input_server_(&command, &reply); 720 721 if (reply.FindInt32("rate", rate) != B_OK) 722 *rate = 250000; 723 724 return B_OK; 725 } 726 727 728 status_t 729 set_key_repeat_rate(int32 rate) 730 { 731 BMessage command(IS_SET_KEY_REPEAT_RATE); 732 BMessage reply; 733 command.AddInt32("rate", rate); 734 return _control_input_server_(&command, &reply); 735 } 736 737 738 status_t 739 get_key_repeat_delay(bigtime_t *delay) 740 { 741 BMessage command(IS_GET_KEY_REPEAT_DELAY); 742 BMessage reply; 743 744 _control_input_server_(&command, &reply); 745 746 if (reply.FindInt64("delay", delay) != B_OK) 747 *delay = 200; 748 749 return B_OK; 750 } 751 752 753 status_t 754 set_key_repeat_delay(bigtime_t delay) 755 { 756 BMessage command(IS_SET_KEY_REPEAT_DELAY); 757 BMessage reply; 758 command.AddInt64("delay", delay); 759 return _control_input_server_(&command, &reply); 760 } 761 762 763 uint32 764 modifiers() 765 { 766 BMessage command(IS_GET_MODIFIERS); 767 BMessage reply; 768 int32 err, modifier; 769 770 _control_input_server_(&command, &reply); 771 772 if (reply.FindInt32("status", &err) != B_OK) 773 return 0; 774 775 if (reply.FindInt32("modifiers", &modifier) != B_OK) 776 return 0; 777 778 return modifier; 779 } 780 781 782 status_t 783 get_key_info(key_info *info) 784 { 785 BMessage command(IS_GET_KEY_INFO); 786 BMessage reply; 787 const void *data = 0; 788 int32 err; 789 ssize_t count; 790 791 _control_input_server_(&command, &reply); 792 793 if (reply.FindInt32("status", &err) != B_OK) 794 return B_ERROR; 795 796 if (reply.FindData("key_info", B_ANY_TYPE, &data, &count) != B_OK) 797 return B_ERROR; 798 799 memcpy(info, data, count); 800 return B_OK; 801 } 802 803 804 void 805 get_key_map(key_map **map, char **key_buffer) 806 { 807 _get_key_map(map, key_buffer, NULL); 808 } 809 810 811 void 812 _get_key_map(key_map **map, char **key_buffer, ssize_t *key_buffer_size) 813 { 814 BMessage command(IS_GET_KEY_MAP); 815 BMessage reply; 816 ssize_t map_count, key_count; 817 const void *map_array = 0, *key_array = 0; 818 if (key_buffer_size == NULL) 819 key_buffer_size = &key_count; 820 821 _control_input_server_(&command, &reply); 822 823 if (reply.FindData("keymap", B_ANY_TYPE, &map_array, &map_count) != B_OK) { 824 *map = 0; *key_buffer = 0; 825 return; 826 } 827 828 if (reply.FindData("key_buffer", B_ANY_TYPE, &key_array, key_buffer_size) 829 != B_OK) { 830 *map = 0; *key_buffer = 0; 831 return; 832 } 833 834 *map = (key_map *)malloc(map_count); 835 memcpy(*map, map_array, map_count); 836 *key_buffer = (char *)malloc(*key_buffer_size); 837 memcpy(*key_buffer, key_array, *key_buffer_size); 838 } 839 840 841 status_t 842 get_keyboard_id(uint16 *id) 843 { 844 BMessage command(IS_GET_KEYBOARD_ID); 845 BMessage reply; 846 uint16 kid; 847 848 _control_input_server_(&command, &reply); 849 850 status_t err = reply.FindInt16("id", (int16 *)&kid); 851 if (err != B_OK) 852 return err; 853 *id = kid; 854 855 return B_OK; 856 } 857 858 859 status_t 860 get_modifier_key(uint32 modifier, uint32 *key) 861 { 862 BMessage command(IS_GET_MODIFIER_KEY); 863 BMessage reply; 864 uint32 rkey; 865 866 command.AddInt32("modifier", modifier); 867 _control_input_server_(&command, &reply); 868 869 status_t err = reply.FindInt32("key", (int32 *) &rkey); 870 if (err != B_OK) 871 return err; 872 *key = rkey; 873 874 return B_OK; 875 } 876 877 878 void 879 set_modifier_key(uint32 modifier, uint32 key) 880 { 881 BMessage command(IS_SET_MODIFIER_KEY); 882 BMessage reply; 883 884 command.AddInt32("modifier", modifier); 885 command.AddInt32("key", key); 886 _control_input_server_(&command, &reply); 887 } 888 889 890 void 891 set_keyboard_locks(uint32 modifiers) 892 { 893 BMessage command(IS_SET_KEYBOARD_LOCKS); 894 BMessage reply; 895 896 command.AddInt32("locks", modifiers); 897 _control_input_server_(&command, &reply); 898 } 899 900 901 status_t 902 _restore_key_map_() 903 { 904 BMessage message(IS_RESTORE_KEY_MAP); 905 BMessage reply; 906 907 return _control_input_server_(&message, &reply); 908 } 909 910 911 rgb_color 912 keyboard_navigation_color() 913 { 914 // Queries the app_server 915 return ui_color(B_KEYBOARD_NAVIGATION_COLOR); 916 } 917 918 919 int32 920 count_workspaces() 921 { 922 uint32 columns; 923 uint32 rows; 924 BPrivate::get_workspaces_layout(&columns, &rows); 925 926 return columns * rows; 927 } 928 929 930 void 931 set_workspace_count(int32 count) 932 { 933 int32 squareRoot = (int32)sqrt(count); 934 935 int32 rows = 1; 936 for (int32 i = 2; i <= squareRoot; i++) { 937 if (count % i == 0) 938 rows = i; 939 } 940 941 int32 columns = count / rows; 942 943 BPrivate::set_workspaces_layout(columns, rows); 944 } 945 946 947 int32 948 current_workspace() 949 { 950 int32 index = 0; 951 952 BPrivate::AppServerLink link; 953 link.StartMessage(AS_CURRENT_WORKSPACE); 954 955 int32 status; 956 if (link.FlushWithReply(status) == B_OK && status == B_OK) 957 link.Read<int32>(&index); 958 959 return index; 960 } 961 962 963 void 964 activate_workspace(int32 workspace) 965 { 966 BPrivate::AppServerLink link; 967 link.StartMessage(AS_ACTIVATE_WORKSPACE); 968 link.Attach<int32>(workspace); 969 link.Attach<bool>(false); 970 link.Flush(); 971 } 972 973 974 bigtime_t 975 idle_time() 976 { 977 bigtime_t idletime = 0; 978 979 BPrivate::AppServerLink link; 980 link.StartMessage(AS_IDLE_TIME); 981 982 int32 code; 983 if (link.FlushWithReply(code) == B_OK && code == B_OK) 984 link.Read<int64>(&idletime); 985 986 return idletime; 987 } 988 989 990 void 991 run_select_printer_panel() 992 { 993 if (be_roster == NULL) 994 return; 995 996 // Launches the Printer prefs app via the Roster 997 be_roster->Launch(PRNT_SIGNATURE_TYPE); 998 } 999 1000 1001 void 1002 run_add_printer_panel() 1003 { 1004 // Launches the Printer prefs app via the Roster and asks it to 1005 // add a printer 1006 run_select_printer_panel(); 1007 1008 BMessenger printerPanelMessenger(PRNT_SIGNATURE_TYPE); 1009 printerPanelMessenger.SendMessage(PRINTERS_ADD_PRINTER); 1010 } 1011 1012 1013 void 1014 run_be_about() 1015 { 1016 if (be_roster != NULL) 1017 be_roster->Launch("application/x-vnd.Haiku-About"); 1018 } 1019 1020 1021 void 1022 set_focus_follows_mouse(bool follow) 1023 { 1024 // obviously deprecated API 1025 set_mouse_mode(follow ? B_FOCUS_FOLLOWS_MOUSE : B_NORMAL_MOUSE); 1026 } 1027 1028 1029 bool 1030 focus_follows_mouse() 1031 { 1032 return mouse_mode() == B_FOCUS_FOLLOWS_MOUSE; 1033 } 1034 1035 1036 void 1037 set_mouse_mode(mode_mouse mode) 1038 { 1039 BPrivate::AppServerLink link; 1040 link.StartMessage(AS_SET_MOUSE_MODE); 1041 link.Attach<mode_mouse>(mode); 1042 link.Flush(); 1043 } 1044 1045 1046 mode_mouse 1047 mouse_mode() 1048 { 1049 // Gets the mouse focus style, such as activate to click, 1050 // focus to click, ... 1051 mode_mouse mode = B_NORMAL_MOUSE; 1052 1053 BPrivate::AppServerLink link; 1054 link.StartMessage(AS_GET_MOUSE_MODE); 1055 1056 int32 code; 1057 if (link.FlushWithReply(code) == B_OK && code == B_OK) 1058 link.Read<mode_mouse>(&mode); 1059 1060 return mode; 1061 } 1062 1063 1064 void 1065 set_focus_follows_mouse_mode(mode_focus_follows_mouse mode) 1066 { 1067 BPrivate::AppServerLink link; 1068 link.StartMessage(AS_SET_FOCUS_FOLLOWS_MOUSE_MODE); 1069 link.Attach<mode_focus_follows_mouse>(mode); 1070 link.Flush(); 1071 } 1072 1073 1074 mode_focus_follows_mouse 1075 focus_follows_mouse_mode() 1076 { 1077 mode_focus_follows_mouse mode = B_NORMAL_FOCUS_FOLLOWS_MOUSE; 1078 1079 BPrivate::AppServerLink link; 1080 link.StartMessage(AS_GET_FOCUS_FOLLOWS_MOUSE_MODE); 1081 1082 int32 code; 1083 if (link.FlushWithReply(code) == B_OK && code == B_OK) 1084 link.Read<mode_focus_follows_mouse>(&mode); 1085 1086 return mode; 1087 } 1088 1089 1090 status_t 1091 get_mouse(BPoint* screenWhere, uint32* buttons) 1092 { 1093 if (screenWhere == NULL && buttons == NULL) 1094 return B_BAD_VALUE; 1095 1096 BPrivate::AppServerLink link; 1097 link.StartMessage(AS_GET_CURSOR_POSITION); 1098 1099 int32 code; 1100 status_t ret = link.FlushWithReply(code); 1101 if (ret != B_OK) 1102 return ret; 1103 if (code != B_OK) 1104 return code; 1105 1106 if (screenWhere != NULL) 1107 ret = link.Read<BPoint>(screenWhere); 1108 else { 1109 BPoint dummy; 1110 ret = link.Read<BPoint>(&dummy); 1111 } 1112 if (ret != B_OK) 1113 return ret; 1114 1115 if (buttons != NULL) 1116 ret = link.Read<uint32>(buttons); 1117 else { 1118 uint32 dummy; 1119 ret = link.Read<uint32>(&dummy); 1120 } 1121 1122 return ret; 1123 } 1124 1125 1126 status_t 1127 get_mouse_bitmap(BBitmap** bitmap, BPoint* hotspot) 1128 { 1129 if (bitmap == NULL && hotspot == NULL) 1130 return B_BAD_VALUE; 1131 1132 BPrivate::AppServerLink link; 1133 link.StartMessage(AS_GET_CURSOR_BITMAP); 1134 1135 int32 code; 1136 status_t status = link.FlushWithReply(code); 1137 if (status != B_OK) 1138 return status; 1139 if (code != B_OK) 1140 return code; 1141 1142 uint32 size = 0; 1143 uint32 cursorWidth = 0; 1144 uint32 cursorHeight = 0; 1145 color_space colorspace = B_RGBA32; 1146 1147 // if link.Read() returns an error, the same error will be returned on 1148 // subsequent calls, so we'll check only the return value of the last call 1149 link.Read<uint32>(&size); 1150 link.Read<uint32>(&cursorWidth); 1151 link.Read<uint32>(&cursorHeight); 1152 link.Read<color_space>(&colorspace); 1153 if (hotspot == NULL) { 1154 BPoint dummy; 1155 link.Read<BPoint>(&dummy); 1156 } else 1157 link.Read<BPoint>(hotspot); 1158 1159 void* data = NULL; 1160 if (size > 0) 1161 data = malloc(size); 1162 if (data == NULL) 1163 return B_NO_MEMORY; 1164 1165 status = link.Read(data, size); 1166 if (status != B_OK) { 1167 free(data); 1168 return status; 1169 } 1170 1171 BBitmap* cursorBitmap = new (std::nothrow) BBitmap(BRect(0, 0, 1172 cursorWidth - 1, cursorHeight - 1), colorspace); 1173 1174 if (cursorBitmap == NULL) { 1175 free(data); 1176 return B_NO_MEMORY; 1177 } 1178 status = cursorBitmap->InitCheck(); 1179 if (status == B_OK) 1180 cursorBitmap->SetBits(data, size, 0, colorspace); 1181 1182 free(data); 1183 1184 if (status == B_OK && bitmap != NULL) 1185 *bitmap = cursorBitmap; 1186 else 1187 delete cursorBitmap; 1188 1189 return status; 1190 } 1191 1192 1193 void 1194 set_accept_first_click(bool acceptFirstClick) 1195 { 1196 BPrivate::AppServerLink link; 1197 link.StartMessage(AS_SET_ACCEPT_FIRST_CLICK); 1198 link.Attach<bool>(acceptFirstClick); 1199 link.Flush(); 1200 } 1201 1202 1203 bool 1204 accept_first_click() 1205 { 1206 // Gets the accept first click status 1207 bool acceptFirstClick = true; 1208 1209 BPrivate::AppServerLink link; 1210 link.StartMessage(AS_GET_ACCEPT_FIRST_CLICK); 1211 1212 int32 code; 1213 if (link.FlushWithReply(code) == B_OK && code == B_OK) 1214 link.Read<bool>(&acceptFirstClick); 1215 1216 return acceptFirstClick; 1217 } 1218 1219 1220 rgb_color 1221 ui_color(color_which which) 1222 { 1223 int32 index = color_which_to_index(which); 1224 if (index < 0 || index >= kColorWhichCount) { 1225 fprintf(stderr, "ui_color(): unknown color_which %d\n", which); 1226 return make_color(0, 0, 0); 1227 } 1228 1229 if (be_app != NULL) { 1230 server_read_only_memory* shared 1231 = BApplication::Private::ServerReadOnlyMemory(); 1232 if (shared != NULL) { 1233 // check for unset colors 1234 if (shared->colors[index] == B_TRANSPARENT_COLOR) 1235 shared->colors[index] = kDefaultColors[index]; 1236 1237 return shared->colors[index]; 1238 } 1239 } 1240 1241 return kDefaultColors[index]; 1242 } 1243 1244 1245 const char* 1246 ui_color_name(color_which which) 1247 { 1248 // Suppress warnings for B_NO_COLOR. 1249 if (which == B_NO_COLOR) 1250 return NULL; 1251 1252 int32 index = color_which_to_index(which); 1253 if (index < 0 || index >= kColorWhichCount) { 1254 fprintf(stderr, "ui_color_name(): unknown color_which %d\n", which); 1255 return NULL; 1256 } 1257 1258 return kColorNames[index]; 1259 } 1260 1261 1262 color_which 1263 which_ui_color(const char* name) 1264 { 1265 if (name == NULL) 1266 return B_NO_COLOR; 1267 1268 for (int32 index = 0; index < kColorWhichCount; ++index) { 1269 if (!strcmp(kColorNames[index], name)) 1270 return index_to_color_which(index); 1271 } 1272 1273 return B_NO_COLOR; 1274 } 1275 1276 1277 void 1278 set_ui_color(const color_which &which, const rgb_color &color) 1279 { 1280 int32 index = color_which_to_index(which); 1281 if (index < 0 || index >= kColorWhichCount) { 1282 fprintf(stderr, "set_ui_color(): unknown color_which %d\n", which); 1283 return; 1284 } 1285 1286 if (ui_color(which) == color) 1287 return; 1288 1289 BPrivate::DesktopLink link; 1290 link.StartMessage(AS_SET_UI_COLOR); 1291 link.Attach<color_which>(which); 1292 link.Attach<rgb_color>(color); 1293 link.Flush(); 1294 } 1295 1296 1297 void 1298 set_ui_colors(const BMessage* colors) 1299 { 1300 if (colors == NULL) 1301 return; 1302 1303 int32 count = 0; 1304 int32 index = 0; 1305 char* name = NULL; 1306 type_code type; 1307 rgb_color color; 1308 color_which which = B_NO_COLOR; 1309 1310 BPrivate::DesktopLink desktop; 1311 if (desktop.InitCheck() != B_OK) 1312 return; 1313 1314 desktop.StartMessage(AS_SET_UI_COLORS); 1315 desktop.Attach<bool>(false); 1316 1317 // Only colors with names that map to system colors will get through. 1318 while (colors->GetInfo(B_RGB_32_BIT_TYPE, index, &name, &type) == B_OK) { 1319 1320 which = which_ui_color(name); 1321 ++index; 1322 1323 if (which == B_NO_COLOR || colors->FindColor(name, &color) != B_OK) 1324 continue; 1325 1326 desktop.Attach<color_which>(which); 1327 desktop.Attach<rgb_color>(color); 1328 ++count; 1329 } 1330 1331 if (count == 0) 1332 return; 1333 1334 desktop.Attach<color_which>(B_NO_COLOR); 1335 desktop.Flush(); 1336 } 1337 1338 1339 rgb_color 1340 tint_color(rgb_color color, float tint) 1341 { 1342 rgb_color result; 1343 1344 #define LIGHTEN(x) ((uint8)(255.0f - (255.0f - x) * tint)) 1345 #define DARKEN(x) ((uint8)(x * (2 - tint))) 1346 1347 if (tint < 1.0f) { 1348 result.red = LIGHTEN(color.red); 1349 result.green = LIGHTEN(color.green); 1350 result.blue = LIGHTEN(color.blue); 1351 result.alpha = color.alpha; 1352 } else { 1353 result.red = DARKEN(color.red); 1354 result.green = DARKEN(color.green); 1355 result.blue = DARKEN(color.blue); 1356 result.alpha = color.alpha; 1357 } 1358 1359 #undef LIGHTEN 1360 #undef DARKEN 1361 1362 return result; 1363 } 1364 1365 1366 rgb_color shift_color(rgb_color color, float shift); 1367 1368 rgb_color 1369 shift_color(rgb_color color, float shift) 1370 { 1371 return tint_color(color, shift); 1372 } 1373 1374 1375 extern "C" status_t 1376 _init_interface_kit_() 1377 { 1378 status_t status = BPrivate::PaletteConverter::InitializeDefault(true); 1379 if (status < B_OK) 1380 return status; 1381 1382 // init global clipboard 1383 if (be_clipboard == NULL) 1384 be_clipboard = new BClipboard(NULL); 1385 1386 BString path; 1387 if (get_control_look(path) && path.Length() > 0) { 1388 BControlLook* (*instantiate)(image_id); 1389 1390 sControlLookAddon = load_add_on(path.String()); 1391 if (sControlLookAddon >= 0 1392 && get_image_symbol(sControlLookAddon, 1393 "instantiate_control_look", 1394 B_SYMBOL_TYPE_TEXT, (void **)&instantiate) == B_OK) { 1395 be_control_look = instantiate(sControlLookAddon); 1396 if (be_control_look == NULL) { 1397 unload_add_on(sControlLookAddon); 1398 sControlLookAddon = -1; 1399 } 1400 } 1401 } 1402 if (be_control_look == NULL) 1403 be_control_look = new HaikuControlLook(); 1404 1405 _init_global_fonts_(); 1406 1407 BPrivate::gWidthBuffer = new BPrivate::WidthBuffer; 1408 status = BPrivate::MenuPrivate::CreateBitmaps(); 1409 if (status != B_OK) 1410 return status; 1411 1412 _menu_info_ptr_ = &BMenu::sMenuInfo; 1413 1414 status = get_menu_info(&BMenu::sMenuInfo); 1415 if (status != B_OK) 1416 return status; 1417 1418 general_info.background_color = ui_color(B_PANEL_BACKGROUND_COLOR); 1419 general_info.mark_color = ui_color(B_CONTROL_MARK_COLOR); 1420 general_info.highlight_color = ui_color(B_CONTROL_HIGHLIGHT_COLOR); 1421 general_info.window_frame_color = ui_color(B_WINDOW_TAB_COLOR); 1422 general_info.color_frame = true; 1423 1424 // TODO: fill the other static members 1425 1426 return status; 1427 } 1428 1429 1430 extern "C" status_t 1431 _fini_interface_kit_() 1432 { 1433 BPrivate::MenuPrivate::DeleteBitmaps(); 1434 1435 delete BPrivate::gWidthBuffer; 1436 BPrivate::gWidthBuffer = NULL; 1437 1438 delete be_control_look; 1439 be_control_look = NULL; 1440 1441 // Note: if we ever want to support live switching, we cannot just unload 1442 // the old one since some thread might still be in a method of the object. 1443 // maybe locking/unlocking all loopers around would ensure proper exit. 1444 if (sControlLookAddon >= 0) 1445 unload_add_on(sControlLookAddon); 1446 sControlLookAddon = -1; 1447 1448 // TODO: Anything else? 1449 1450 return B_OK; 1451 } 1452 1453 1454 1455 namespace BPrivate { 1456 1457 1458 /*! \brief queries the server for the current decorator 1459 \param path BString into which to store current decorator's location 1460 \return boolean true/false 1461 */ 1462 bool 1463 get_decorator(BString& path) 1464 { 1465 BPrivate::AppServerLink link; 1466 link.StartMessage(AS_GET_DECORATOR); 1467 1468 int32 code; 1469 if (link.FlushWithReply(code) != B_OK || code != B_OK) 1470 return false; 1471 1472 return link.ReadString(path) == B_OK; 1473 } 1474 1475 1476 /*! \brief Private function which sets the window decorator for the system. 1477 \param path BString with the path to the decorator to set 1478 1479 Will return detailed error status via status_t 1480 */ 1481 status_t 1482 set_decorator(const BString& path) 1483 { 1484 BPrivate::AppServerLink link; 1485 1486 link.StartMessage(AS_SET_DECORATOR); 1487 1488 link.AttachString(path.String()); 1489 link.Flush(); 1490 1491 status_t error = B_OK; 1492 link.Read<status_t>(&error); 1493 1494 return error; 1495 } 1496 1497 1498 /*! \brief sets a window to preview a given decorator 1499 \param path path to any given decorator add-on 1500 \param window pointer to BWindow which will show decorator 1501 1502 Piggy-backs on BWindow::SetDecoratorSettings(...) 1503 */ 1504 status_t 1505 preview_decorator(const BString& path, BWindow* window) 1506 { 1507 if (window == NULL) 1508 return B_ERROR; 1509 1510 BMessage msg('prVu'); 1511 msg.AddString("preview", path.String()); 1512 1513 return window->SetDecoratorSettings(msg); 1514 } 1515 1516 1517 /*! \brief queries the server for the current ControlLook path 1518 \param path BString into which to store current ControlLook's add-on path 1519 \return boolean true/false 1520 */ 1521 bool 1522 get_control_look(BString& path) 1523 { 1524 BPrivate::AppServerLink link; 1525 link.StartMessage(AS_GET_CONTROL_LOOK); 1526 1527 int32 code; 1528 if (link.FlushWithReply(code) != B_OK || code != B_OK) 1529 return false; 1530 1531 return link.ReadString(path) == B_OK; 1532 } 1533 1534 1535 /*! \brief Private function which sets the ControlLook for the system. 1536 \param BString with the ControlLook add-on path to set 1537 1538 Will return detailed error status via status_t 1539 */ 1540 status_t 1541 set_control_look(const BString& path) 1542 { 1543 BPrivate::AppServerLink link; 1544 1545 link.StartMessage(AS_SET_CONTROL_LOOK); 1546 1547 link.AttachString(path.String()); 1548 1549 status_t error = B_OK; 1550 if (link.FlushWithReply(error) != B_OK) 1551 return B_ERROR; 1552 1553 return error; 1554 } 1555 1556 1557 status_t 1558 get_application_order(int32 workspace, team_id** _applications, 1559 int32* _count) 1560 { 1561 BPrivate::AppServerLink link; 1562 1563 link.StartMessage(AS_GET_APPLICATION_ORDER); 1564 link.Attach<int32>(workspace); 1565 1566 int32 code; 1567 status_t status = link.FlushWithReply(code); 1568 if (status != B_OK) 1569 return status; 1570 if (code != B_OK) 1571 return code; 1572 1573 int32 count; 1574 link.Read<int32>(&count); 1575 1576 *_applications = (team_id*)malloc(count * sizeof(team_id)); 1577 if (*_applications == NULL) 1578 return B_NO_MEMORY; 1579 1580 link.Read(*_applications, count * sizeof(team_id)); 1581 *_count = count; 1582 return B_OK; 1583 } 1584 1585 1586 status_t 1587 get_window_order(int32 workspace, int32** _tokens, int32* _count) 1588 { 1589 BPrivate::AppServerLink link; 1590 1591 link.StartMessage(AS_GET_WINDOW_ORDER); 1592 link.Attach<int32>(workspace); 1593 1594 int32 code; 1595 status_t status = link.FlushWithReply(code); 1596 if (status != B_OK) 1597 return status; 1598 if (code != B_OK) 1599 return code; 1600 1601 int32 count; 1602 link.Read<int32>(&count); 1603 1604 *_tokens = (int32*)malloc(count * sizeof(int32)); 1605 if (*_tokens == NULL) 1606 return B_NO_MEMORY; 1607 1608 link.Read(*_tokens, count * sizeof(int32)); 1609 *_count = count; 1610 return B_OK; 1611 } 1612 1613 1614 } // namespace BPrivate 1615 1616 // These methods were marked with "Danger, will Robinson!" in 1617 // the OpenTracker source, so we might not want to be compatible 1618 // here. 1619 // In any way, we would need to update Deskbar to use our 1620 // replacements, so we could as well just implement them... 1621 1622 void 1623 do_window_action(int32 windowToken, int32 action, BRect zoomRect, bool zoom) 1624 { 1625 BPrivate::AppServerLink link; 1626 1627 link.StartMessage(AS_WINDOW_ACTION); 1628 link.Attach<int32>(windowToken); 1629 link.Attach<int32>(action); 1630 // we don't have any zooming effect 1631 1632 link.Flush(); 1633 } 1634 1635 1636 client_window_info* 1637 get_window_info(int32 serverToken) 1638 { 1639 BPrivate::AppServerLink link; 1640 1641 link.StartMessage(AS_GET_WINDOW_INFO); 1642 link.Attach<int32>(serverToken); 1643 1644 int32 code; 1645 if (link.FlushWithReply(code) != B_OK || code != B_OK) 1646 return NULL; 1647 1648 int32 size; 1649 link.Read<int32>(&size); 1650 1651 client_window_info* info = (client_window_info*)malloc(size); 1652 if (info == NULL) 1653 return NULL; 1654 1655 link.Read(info, size); 1656 return info; 1657 } 1658 1659 1660 int32* 1661 get_token_list(team_id team, int32* _count) 1662 { 1663 BPrivate::AppServerLink link; 1664 1665 link.StartMessage(AS_GET_WINDOW_LIST); 1666 link.Attach<team_id>(team); 1667 1668 int32 code; 1669 if (link.FlushWithReply(code) != B_OK || code != B_OK) 1670 return NULL; 1671 1672 int32 count; 1673 link.Read<int32>(&count); 1674 1675 int32* tokens = (int32*)malloc(count * sizeof(int32)); 1676 if (tokens == NULL) 1677 return NULL; 1678 1679 link.Read(tokens, count * sizeof(int32)); 1680 *_count = count; 1681 return tokens; 1682 } 1683 1684 1685 void 1686 do_bring_to_front_team(BRect zoomRect, team_id team, bool zoom) 1687 { 1688 BPrivate::AppServerLink link; 1689 1690 link.StartMessage(AS_BRING_TEAM_TO_FRONT); 1691 link.Attach<team_id>(team); 1692 // we don't have any zooming effect 1693 1694 link.Flush(); 1695 } 1696 1697 1698 void 1699 do_minimize_team(BRect zoomRect, team_id team, bool zoom) 1700 { 1701 BPrivate::AppServerLink link; 1702 1703 link.StartMessage(AS_MINIMIZE_TEAM); 1704 link.Attach<team_id>(team); 1705 // we don't have any zooming effect 1706 1707 link.Flush(); 1708 } 1709 1710 1711 // #pragma mark - truncate string 1712 1713 1714 void 1715 truncate_string(BString& string, uint32 mode, float width, 1716 const float* escapementArray, float fontSize, float ellipsisWidth, 1717 int32 charCount) 1718 { 1719 // add a tiny amount to the width to make floating point inaccuracy 1720 // not drop chars that would actually fit exactly 1721 width += 1.f / 128; 1722 1723 switch (mode) { 1724 case B_TRUNCATE_BEGINNING: 1725 { 1726 float totalWidth = 0; 1727 for (int32 i = charCount - 1; i >= 0; i--) { 1728 float charWidth = escapementArray[i] * fontSize; 1729 if (totalWidth + charWidth > width) { 1730 // we need to truncate 1731 while (totalWidth + ellipsisWidth > width) { 1732 // remove chars until there's enough space for the 1733 // ellipsis 1734 if (++i == charCount) { 1735 // we've reached the end of the string and still 1736 // no space, so return an empty string 1737 string.Truncate(0); 1738 return; 1739 } 1740 1741 totalWidth -= escapementArray[i] * fontSize; 1742 } 1743 1744 string.RemoveChars(0, i + 1); 1745 string.PrependChars(B_UTF8_ELLIPSIS, 1); 1746 return; 1747 } 1748 1749 totalWidth += charWidth; 1750 } 1751 1752 break; 1753 } 1754 1755 case B_TRUNCATE_END: 1756 { 1757 float totalWidth = 0; 1758 for (int32 i = 0; i < charCount; i++) { 1759 float charWidth = escapementArray[i] * fontSize; 1760 if (totalWidth + charWidth > width) { 1761 // we need to truncate 1762 while (totalWidth + ellipsisWidth > width) { 1763 // remove chars until there's enough space for the 1764 // ellipsis 1765 if (i-- == 0) { 1766 // we've reached the start of the string and still 1767 // no space, so return an empty string 1768 string.Truncate(0); 1769 return; 1770 } 1771 1772 totalWidth -= escapementArray[i] * fontSize; 1773 } 1774 1775 string.RemoveChars(i, charCount - i); 1776 string.AppendChars(B_UTF8_ELLIPSIS, 1); 1777 return; 1778 } 1779 1780 totalWidth += charWidth; 1781 } 1782 1783 break; 1784 } 1785 1786 case B_TRUNCATE_MIDDLE: 1787 case B_TRUNCATE_SMART: 1788 { 1789 float leftWidth = 0; 1790 float rightWidth = 0; 1791 int32 leftIndex = 0; 1792 int32 rightIndex = charCount - 1; 1793 bool left = true; 1794 1795 for (int32 i = 0; i < charCount; i++) { 1796 float charWidth 1797 = escapementArray[left ? leftIndex : rightIndex] * fontSize; 1798 1799 if (leftWidth + rightWidth + charWidth > width) { 1800 // we need to truncate 1801 while (leftWidth + rightWidth + ellipsisWidth > width) { 1802 // remove chars until there's enough space for the 1803 // ellipsis 1804 if (leftIndex == 0 && rightIndex == charCount - 1) { 1805 // we've reached both ends of the string and still 1806 // no space, so return an empty string 1807 string.Truncate(0); 1808 return; 1809 } 1810 1811 if (leftIndex > 0 && (rightIndex == charCount - 1 1812 || leftWidth > rightWidth)) { 1813 // remove char on the left 1814 leftWidth -= escapementArray[--leftIndex] 1815 * fontSize; 1816 } else { 1817 // remove char on the right 1818 rightWidth -= escapementArray[++rightIndex] 1819 * fontSize; 1820 } 1821 } 1822 1823 string.RemoveChars(leftIndex, rightIndex + 1 - leftIndex); 1824 string.InsertChars(B_UTF8_ELLIPSIS, 1, leftIndex); 1825 return; 1826 } 1827 1828 if (left) { 1829 leftIndex++; 1830 leftWidth += charWidth; 1831 } else { 1832 rightIndex--; 1833 rightWidth += charWidth; 1834 } 1835 1836 left = rightWidth > leftWidth; 1837 } 1838 1839 break; 1840 } 1841 } 1842 1843 // we've run through without the need to truncate, leave the string as it is 1844 } 1845