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