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