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