1 /* 2 * Copyright 2005-2008, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 * Axel Dörfler, axeld@pinc-software.de 8 * Andrej Spielmann, <andrej.spielmann@seh.ox.ac.uk> 9 */ 10 11 12 #include "DesktopSettings.h" 13 #include "DesktopSettingsPrivate.h" 14 #include "Desktop.h" 15 #include "FontCache.h" 16 #include "FontCacheEntry.h" 17 #include "FontManager.h" 18 #include "GlobalSubpixelSettings.h" 19 #include "ServerConfig.h" 20 21 #include <DefaultColors.h> 22 #include <ServerReadOnlyMemory.h> 23 24 #include <Directory.h> 25 #include <File.h> 26 #include <FindDirectory.h> 27 #include <Path.h> 28 29 30 DesktopSettingsPrivate::DesktopSettingsPrivate(server_read_only_memory* shared) 31 : 32 fShared(*shared) 33 { 34 // if the on-disk settings are not complete, the defaults will be kept 35 _SetDefaults(); 36 _Load(); 37 } 38 39 40 DesktopSettingsPrivate::~DesktopSettingsPrivate() 41 { 42 } 43 44 45 void 46 DesktopSettingsPrivate::_SetDefaults() 47 { 48 fPlainFont = *gFontManager->DefaultPlainFont(); 49 fBoldFont = *gFontManager->DefaultBoldFont(); 50 fFixedFont = *gFontManager->DefaultFixedFont(); 51 52 fMouseMode = B_NORMAL_MOUSE; 53 fShowAllDraggers = true; 54 55 // init scrollbar info 56 fScrollBarInfo.proportional = true; 57 fScrollBarInfo.double_arrows = false; 58 fScrollBarInfo.knob = 1; 59 // look of the knob (R5: (0, 1, 2), 1 = default) 60 fScrollBarInfo.min_knob_size = 15; 61 62 // init menu info 63 strlcpy(fMenuInfo.f_family, fPlainFont.Family(), B_FONT_FAMILY_LENGTH); 64 strlcpy(fMenuInfo.f_style, fPlainFont.Style(), B_FONT_STYLE_LENGTH); 65 fMenuInfo.font_size = fPlainFont.Size(); 66 fMenuInfo.background_color.set_to(216, 216, 216); 67 68 fMenuInfo.separator = 0; 69 // look of the separator (R5: (0, 1, 2), default 0) 70 fMenuInfo.click_to_open = true; // always true 71 fMenuInfo.triggers_always_shown = false; 72 73 fWorkspacesCount = 4; 74 75 memcpy(fShared.colors, BPrivate::kDefaultColors, sizeof(rgb_color) * kNumColors); 76 77 gSubpixelAntialiasing = false; 78 gDefaultHinting = true; 79 gSubpixelAverageWeight = 120; 80 gSubpixelOrderingRGB = true; 81 } 82 83 84 status_t 85 DesktopSettingsPrivate::_GetPath(BPath& path) 86 { 87 status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path); 88 if (status < B_OK) 89 return status; 90 91 status = path.Append("system/app_server"); 92 if (status < B_OK) 93 return status; 94 95 return create_directory(path.Path(), 0755); 96 } 97 98 99 status_t 100 DesktopSettingsPrivate::_Load() 101 { 102 // TODO: add support for old app_server_settings file as well 103 104 BPath basePath; 105 status_t status = _GetPath(basePath); 106 if (status < B_OK) 107 return status; 108 109 // read workspaces settings 110 111 BPath path(basePath); 112 path.Append("workspaces"); 113 114 BFile file; 115 status = file.SetTo(path.Path(), B_READ_ONLY); 116 if (status == B_OK) { 117 BMessage settings; 118 status = settings.Unflatten(&file); 119 if (status == B_OK) { 120 int32 count; 121 if (settings.FindInt32("count", &count) == B_OK) { 122 fWorkspacesCount = count; 123 if (fWorkspacesCount < 1 || fWorkspacesCount > 32) 124 fWorkspacesCount = 4; 125 } 126 127 int32 i = 0; 128 while (i < kMaxWorkspaces 129 && settings.FindMessage("workspace", i, &fWorkspaceMessages[i]) == B_OK) { 130 i++; 131 } 132 } 133 } 134 135 // read font settings 136 137 path = basePath; 138 path.Append("fonts"); 139 140 status = file.SetTo(path.Path(), B_READ_ONLY); 141 if (status == B_OK) { 142 BMessage settings; 143 status = settings.Unflatten(&file); 144 if (status == B_OK && gFontManager->Lock()) { 145 const char* family; 146 const char* style; 147 float size; 148 bool hinting; 149 if (settings.FindString("plain family", &family) == B_OK 150 && settings.FindString("plain style", &style) == B_OK 151 && settings.FindFloat("plain size", &size) == B_OK) { 152 FontStyle* fontStyle = gFontManager->GetStyle(family, style); 153 fPlainFont.SetStyle(fontStyle); 154 fPlainFont.SetSize(size); 155 } 156 if (settings.FindString("bold family", &family) == B_OK 157 && settings.FindString("bold style", &style) == B_OK 158 && settings.FindFloat("bold size", &size) == B_OK) { 159 FontStyle* fontStyle = gFontManager->GetStyle(family, style); 160 fBoldFont.SetStyle(fontStyle); 161 fBoldFont.SetSize(size); 162 } 163 if (settings.FindString("fixed family", &family) == B_OK 164 && settings.FindString("fixed style", &style) == B_OK 165 && settings.FindFloat("fixed size", &size) == B_OK) { 166 FontStyle* fontStyle = gFontManager->GetStyle(family, style); 167 if (fontStyle->IsFixedWidth()) 168 fFixedFont.SetStyle(fontStyle); 169 fFixedFont.SetSize(size); 170 } 171 if (settings.FindBool("hinting", &hinting) == B_OK) { 172 gDefaultHinting = hinting; 173 } 174 gFontManager->Unlock(); 175 } 176 } 177 178 // read mouse settings 179 180 path = basePath; 181 path.Append("mouse"); 182 183 status = file.SetTo(path.Path(), B_READ_ONLY); 184 if (status == B_OK) { 185 BMessage settings; 186 status = settings.Unflatten(&file); 187 if (status == B_OK) { 188 int32 mode; 189 if (settings.FindInt32("mode", &mode) == B_OK) { 190 fMouseMode = (mode_mouse)mode; 191 } 192 } 193 } 194 195 // read appearance settings 196 197 path = basePath; 198 path.Append("appearance"); 199 200 status = file.SetTo(path.Path(), B_READ_ONLY); 201 if (status == B_OK) { 202 BMessage settings; 203 status = settings.Unflatten(&file); 204 if (status == B_OK) { 205 float fontSize; 206 if (settings.FindFloat("font size", &fontSize) == B_OK) 207 fMenuInfo.font_size = fontSize; 208 209 const char* fontFamily; 210 if (settings.FindString("font family", &fontFamily) == B_OK) 211 strlcpy(fMenuInfo.f_family, fontFamily, B_FONT_FAMILY_LENGTH); 212 213 const char* fontStyle; 214 if (settings.FindString("font style", &fontStyle) == B_OK) 215 strlcpy(fMenuInfo.f_style, fontStyle, B_FONT_STYLE_LENGTH); 216 217 rgb_color bgColor; 218 if (settings.FindInt32("bg color", (int32*)&bgColor) == B_OK) 219 fMenuInfo.background_color = bgColor; 220 221 int32 separator; 222 if (settings.FindInt32("separator", &separator) == B_OK) 223 fMenuInfo.separator = separator; 224 225 bool clickToOpen; 226 if (settings.FindBool("click to open", &clickToOpen) == B_OK) 227 fMenuInfo.click_to_open = clickToOpen; 228 229 bool triggersAlwaysShown; 230 if (settings.FindBool("triggers always shown", &triggersAlwaysShown) 231 == B_OK) { 232 fMenuInfo.triggers_always_shown = triggersAlwaysShown; 233 } 234 235 bool subpix; 236 if (settings.FindBool("subpixel antialiasing", &subpix) == B_OK) 237 gSubpixelAntialiasing = subpix; 238 239 int8 averageWeight; 240 if (settings.FindInt8("subpixel average weight", &averageWeight) 241 == B_OK) { 242 gSubpixelAverageWeight = averageWeight; 243 } 244 245 bool subpixelOrdering; 246 if (settings.FindBool("subpixel ordering", &subpixelOrdering) 247 == B_OK) { 248 gSubpixelOrderingRGB = subpixelOrdering; 249 } 250 251 for (int32 i = 0; i < kNumColors; i++) { 252 char colorName[12]; 253 snprintf(colorName, sizeof(colorName), "color%ld", 254 (int32)index_to_color_which(i)); 255 256 settings.FindInt32(colorName, (int32*)&fShared.colors[i]); 257 } 258 } 259 } 260 261 return B_OK; 262 } 263 264 265 status_t 266 DesktopSettingsPrivate::Save(uint32 mask) 267 { 268 BPath basePath; 269 status_t status = _GetPath(basePath); 270 if (status < B_OK) 271 return status; 272 273 if (mask & kWorkspacesSettings) { 274 BPath path(basePath); 275 if (path.Append("workspaces") == B_OK) { 276 BMessage settings('asws'); 277 settings.AddInt32("count", fWorkspacesCount); 278 279 for (int32 i = 0; i < kMaxWorkspaces; i++) { 280 settings.AddMessage("workspace", &fWorkspaceMessages[i]); 281 } 282 283 BFile file; 284 status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE 285 | B_READ_WRITE); 286 if (status == B_OK) { 287 status = settings.Flatten(&file, NULL); 288 } 289 } 290 } 291 292 if (mask & kFontSettings) { 293 BPath path(basePath); 294 if (path.Append("fonts") == B_OK) { 295 BMessage settings('asfn'); 296 297 settings.AddString("plain family", fPlainFont.Family()); 298 settings.AddString("plain style", fPlainFont.Style()); 299 settings.AddFloat("plain size", fPlainFont.Size()); 300 301 settings.AddString("bold family", fBoldFont.Family()); 302 settings.AddString("bold style", fBoldFont.Style()); 303 settings.AddFloat("bold size", fBoldFont.Size()); 304 305 settings.AddString("fixed family", fFixedFont.Family()); 306 settings.AddString("fixed style", fFixedFont.Style()); 307 settings.AddFloat("fixed size", fFixedFont.Size()); 308 309 settings.AddBool("hinting", gDefaultHinting); 310 311 BFile file; 312 status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE 313 | B_READ_WRITE); 314 if (status == B_OK) { 315 status = settings.Flatten(&file, NULL); 316 } 317 } 318 } 319 320 if (mask & kMouseSettings) { 321 BPath path(basePath); 322 if (path.Append("mouse") == B_OK) { 323 BMessage settings('asms'); 324 settings.AddInt32("mode", (int32)fMouseMode); 325 326 BFile file; 327 status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE 328 | B_READ_WRITE); 329 if (status == B_OK) { 330 status = settings.Flatten(&file, NULL); 331 } 332 } 333 } 334 335 if (mask & kDraggerSettings) { 336 BPath path(basePath); 337 if (path.Append("dragger") == B_OK) { 338 BMessage settings('asdg'); 339 settings.AddBool("show", fShowAllDraggers); 340 341 BFile file; 342 status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE 343 | B_READ_WRITE); 344 if (status == B_OK) { 345 status = settings.Flatten(&file, NULL); 346 } 347 } 348 } 349 350 if (mask & kAppearanceSettings) { 351 BPath path(basePath); 352 if (path.Append("appearance") == B_OK) { 353 BMessage settings('aslk'); 354 settings.AddFloat("font size", fMenuInfo.font_size); 355 settings.AddString("font family", fMenuInfo.f_family); 356 settings.AddString("font style", fMenuInfo.f_style); 357 settings.AddInt32("bg color", 358 (const int32&)fMenuInfo.background_color); 359 settings.AddInt32("separator", fMenuInfo.separator); 360 settings.AddBool("click to open", fMenuInfo.click_to_open); 361 settings.AddBool("triggers always shown", 362 fMenuInfo.triggers_always_shown); 363 364 settings.AddBool("subpixel antialiasing", gSubpixelAntialiasing); 365 settings.AddInt8("subpixel average weight", gSubpixelAverageWeight); 366 settings.AddBool("subpixel ordering", gSubpixelOrderingRGB); 367 368 for (int32 i = 0; i < kNumColors; i++) { 369 char colorName[12]; 370 snprintf(colorName, sizeof(colorName), "color%ld", 371 (int32)index_to_color_which(i)); 372 settings.AddInt32(colorName, (const int32&)fShared.colors[i]); 373 } 374 375 BFile file; 376 status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE 377 | B_READ_WRITE); 378 if (status == B_OK) { 379 status = settings.Flatten(&file, NULL); 380 } 381 } 382 } 383 384 return status; 385 } 386 387 388 void 389 DesktopSettingsPrivate::SetDefaultPlainFont(const ServerFont &font) 390 { 391 fPlainFont = font; 392 Save(kFontSettings); 393 } 394 395 396 const ServerFont & 397 DesktopSettingsPrivate::DefaultPlainFont() const 398 { 399 return fPlainFont; 400 } 401 402 403 void 404 DesktopSettingsPrivate::SetDefaultBoldFont(const ServerFont &font) 405 { 406 fBoldFont = font; 407 Save(kFontSettings); 408 } 409 410 411 const ServerFont & 412 DesktopSettingsPrivate::DefaultBoldFont() const 413 { 414 return fBoldFont; 415 } 416 417 418 void 419 DesktopSettingsPrivate::SetDefaultFixedFont(const ServerFont &font) 420 { 421 fFixedFont = font; 422 Save(kFontSettings); 423 } 424 425 426 const ServerFont & 427 DesktopSettingsPrivate::DefaultFixedFont() const 428 { 429 return fFixedFont; 430 } 431 432 433 void 434 DesktopSettingsPrivate::SetScrollBarInfo(const scroll_bar_info& info) 435 { 436 fScrollBarInfo = info; 437 Save(kAppearanceSettings); 438 } 439 440 441 const scroll_bar_info& 442 DesktopSettingsPrivate::ScrollBarInfo() const 443 { 444 return fScrollBarInfo; 445 } 446 447 448 void 449 DesktopSettingsPrivate::SetMenuInfo(const menu_info& info) 450 { 451 fMenuInfo = info; 452 // Also update the ui_color 453 SetUIColor(B_MENU_BACKGROUND_COLOR, info.background_color); 454 // SetUIColor already saves the settings 455 } 456 457 458 const menu_info& 459 DesktopSettingsPrivate::MenuInfo() const 460 { 461 return fMenuInfo; 462 } 463 464 465 void 466 DesktopSettingsPrivate::SetMouseMode(const mode_mouse mode) 467 { 468 fMouseMode = mode; 469 Save(kMouseSettings); 470 } 471 472 473 mode_mouse 474 DesktopSettingsPrivate::MouseMode() const 475 { 476 return fMouseMode; 477 } 478 479 480 bool 481 DesktopSettingsPrivate::FocusFollowsMouse() const 482 { 483 return MouseMode() != B_NORMAL_MOUSE; 484 } 485 486 487 void 488 DesktopSettingsPrivate::SetShowAllDraggers(bool show) 489 { 490 fShowAllDraggers = show; 491 Save(kDraggerSettings); 492 } 493 494 495 bool 496 DesktopSettingsPrivate::ShowAllDraggers() const 497 { 498 return fShowAllDraggers; 499 } 500 501 502 void 503 DesktopSettingsPrivate::SetWorkspacesCount(int32 number) 504 { 505 if (number < 1) 506 number = 1; 507 else if (number > kMaxWorkspaces) 508 number = kMaxWorkspaces; 509 510 fWorkspacesCount = number; 511 Save(kWorkspacesSettings); 512 } 513 514 515 int32 516 DesktopSettingsPrivate::WorkspacesCount() const 517 { 518 return fWorkspacesCount; 519 } 520 521 522 void 523 DesktopSettingsPrivate::SetWorkspacesMessage(int32 index, BMessage& message) 524 { 525 if (index < 0 || index > kMaxWorkspaces) 526 return; 527 528 fWorkspaceMessages[index] = message; 529 } 530 531 532 const BMessage* 533 DesktopSettingsPrivate::WorkspacesMessage(int32 index) const 534 { 535 if (index < 0 || index > kMaxWorkspaces) 536 return NULL; 537 538 return &fWorkspaceMessages[index]; 539 } 540 541 542 void 543 DesktopSettingsPrivate::SetUIColor(color_which which, const rgb_color color) 544 { 545 // 546 int32 index = color_which_to_index(which); 547 if (index < 0 || index >= kNumColors) 548 return; 549 fShared.colors[index] = color; 550 // TODO: deprecate the background_color member of the menu_info struct, 551 // otherwise we have to keep this duplication... 552 if (which == B_MENU_BACKGROUND_COLOR) 553 fMenuInfo.background_color = color; 554 Save(kAppearanceSettings); 555 } 556 557 558 rgb_color 559 DesktopSettingsPrivate::UIColor(color_which which) const 560 { 561 static const rgb_color invalidColor = {0, 0, 0, 0}; 562 int32 index = color_which_to_index(which); 563 if (index < 0 || index >= kNumColors) 564 return invalidColor; 565 return fShared.colors[index]; 566 } 567 568 569 void 570 DesktopSettingsPrivate::SetSubpixelAntialiasing(bool subpix) 571 { 572 gSubpixelAntialiasing = subpix; 573 Save(kAppearanceSettings); 574 } 575 576 577 bool 578 DesktopSettingsPrivate::SubpixelAntialiasing() const 579 { 580 return gSubpixelAntialiasing; 581 } 582 583 584 void 585 DesktopSettingsPrivate::SetHinting(bool hinting) 586 { 587 gDefaultHinting = hinting; 588 Save(kFontSettings); 589 } 590 591 592 bool 593 DesktopSettingsPrivate::Hinting() const 594 { 595 return gDefaultHinting; 596 } 597 598 599 void 600 DesktopSettingsPrivate::SetSubpixelAverageWeight(uint8 averageWeight) 601 { 602 gSubpixelAverageWeight = averageWeight; 603 Save(kAppearanceSettings); 604 } 605 606 607 uint8 608 DesktopSettingsPrivate::SubpixelAverageWeight() const 609 { 610 return gSubpixelAverageWeight; 611 } 612 613 614 void 615 DesktopSettingsPrivate::SetSubpixelOrderingRegular(bool subpixelOrdering) 616 { 617 gSubpixelOrderingRGB = subpixelOrdering; 618 Save(kAppearanceSettings); 619 } 620 621 622 bool 623 DesktopSettingsPrivate::IsSubpixelOrderingRegular() const 624 { 625 return gSubpixelOrderingRGB; 626 } 627 628 // #pragma mark - read access 629 630 631 DesktopSettings::DesktopSettings(Desktop* desktop) 632 : 633 fSettings(desktop->fSettings) 634 { 635 #if DEBUG 636 if (!desktop->fWindowLock.IsWriteLocked() 637 && !desktop->fWindowLock.IsReadLocked()) 638 debugger("desktop not locked when trying to access settings"); 639 #endif 640 } 641 642 643 void 644 DesktopSettings::GetDefaultPlainFont(ServerFont &font) const 645 { 646 font = fSettings->DefaultPlainFont(); 647 } 648 649 650 void 651 DesktopSettings::GetDefaultBoldFont(ServerFont &font) const 652 { 653 font = fSettings->DefaultBoldFont(); 654 } 655 656 657 void 658 DesktopSettings::GetDefaultFixedFont(ServerFont &font) const 659 { 660 font = fSettings->DefaultFixedFont(); 661 } 662 663 664 void 665 DesktopSettings::GetScrollBarInfo(scroll_bar_info& info) const 666 { 667 info = fSettings->ScrollBarInfo(); 668 } 669 670 671 void 672 DesktopSettings::GetMenuInfo(menu_info& info) const 673 { 674 info = fSettings->MenuInfo(); 675 } 676 677 678 mode_mouse 679 DesktopSettings::MouseMode() const 680 { 681 return fSettings->MouseMode(); 682 } 683 684 685 bool 686 DesktopSettings::FocusFollowsMouse() const 687 { 688 return fSettings->FocusFollowsMouse(); 689 } 690 691 692 bool 693 DesktopSettings::ShowAllDraggers() const 694 { 695 return fSettings->ShowAllDraggers(); 696 } 697 698 699 int32 700 DesktopSettings::WorkspacesCount() const 701 { 702 return fSettings->WorkspacesCount(); 703 } 704 705 706 const BMessage* 707 DesktopSettings::WorkspacesMessage(int32 index) const 708 { 709 return fSettings->WorkspacesMessage(index); 710 } 711 712 713 rgb_color 714 DesktopSettings::UIColor(color_which which) const 715 { 716 return fSettings->UIColor(which); 717 } 718 719 720 bool 721 DesktopSettings::SubpixelAntialiasing() const 722 { 723 return fSettings->SubpixelAntialiasing(); 724 } 725 726 727 bool 728 DesktopSettings::Hinting() const 729 { 730 return fSettings->Hinting(); 731 } 732 733 734 uint8 735 DesktopSettings::SubpixelAverageWeight() const 736 { 737 return fSettings->SubpixelAverageWeight(); 738 } 739 740 741 bool 742 DesktopSettings::IsSubpixelOrderingRegular() const 743 { 744 // True corresponds to RGB, false means BGR 745 return fSettings->IsSubpixelOrderingRegular(); 746 } 747 748 // #pragma mark - write access 749 750 751 LockedDesktopSettings::LockedDesktopSettings(Desktop* desktop) 752 : DesktopSettings(desktop), 753 fDesktop(desktop) 754 { 755 #if DEBUG 756 if (desktop->fWindowLock.IsReadLocked()) 757 debugger("desktop read locked when trying to change settings"); 758 #endif 759 760 fDesktop->LockAllWindows(); 761 } 762 763 764 LockedDesktopSettings::~LockedDesktopSettings() 765 { 766 fDesktop->UnlockAllWindows(); 767 } 768 769 770 void 771 LockedDesktopSettings::SetDefaultPlainFont(const ServerFont &font) 772 { 773 fSettings->SetDefaultPlainFont(font); 774 } 775 776 777 void 778 LockedDesktopSettings::SetDefaultBoldFont(const ServerFont &font) 779 { 780 fSettings->SetDefaultBoldFont(font); 781 fDesktop->BroadcastToAllWindows(AS_SYSTEM_FONT_CHANGED); 782 } 783 784 785 void 786 LockedDesktopSettings::SetDefaultFixedFont(const ServerFont &font) 787 { 788 fSettings->SetDefaultFixedFont(font); 789 } 790 791 792 void 793 LockedDesktopSettings::SetScrollBarInfo(const scroll_bar_info& info) 794 { 795 fSettings->SetScrollBarInfo(info); 796 } 797 798 799 void 800 LockedDesktopSettings::SetMenuInfo(const menu_info& info) 801 { 802 fSettings->SetMenuInfo(info); 803 } 804 805 806 void 807 LockedDesktopSettings::SetMouseMode(const mode_mouse mode) 808 { 809 fSettings->SetMouseMode(mode); 810 } 811 812 813 void 814 LockedDesktopSettings::SetShowAllDraggers(bool show) 815 { 816 fSettings->SetShowAllDraggers(show); 817 } 818 819 820 void 821 LockedDesktopSettings::SetUIColor(color_which which, const rgb_color color) 822 { 823 fSettings->SetUIColor(which, color); 824 } 825 826 827 void 828 LockedDesktopSettings::SetSubpixelAntialiasing(bool subpix) 829 { 830 fSettings->SetSubpixelAntialiasing(subpix); 831 } 832 833 834 void 835 LockedDesktopSettings::SetHinting(bool hinting) 836 { 837 fSettings->SetHinting(hinting); 838 } 839 840 841 void 842 LockedDesktopSettings::SetSubpixelAverageWeight(uint8 averageWeight) 843 { 844 fSettings->SetSubpixelAverageWeight(averageWeight); 845 } 846 847 void 848 LockedDesktopSettings::SetSubpixelOrderingRegular(bool subpixelOrdering) 849 { 850 fSettings->SetSubpixelOrderingRegular(subpixelOrdering); 851 } 852 853