1 /* 2 * Copyright 2005-2006, 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 50 // init scrollbar info 51 fScrollBarInfo.proportional = true; 52 fScrollBarInfo.double_arrows = false; 53 // look of the knob (R5: (0, 1, 2), 1 = default) 54 fScrollBarInfo.knob = 1; 55 fScrollBarInfo.min_knob_size = 15; 56 57 // init menu info 58 strlcpy(fMenuInfo.f_family, fPlainFont.Family(), B_FONT_FAMILY_LENGTH); 59 strlcpy(fMenuInfo.f_style, fPlainFont.Style(), B_FONT_STYLE_LENGTH); 60 fMenuInfo.font_size = fPlainFont.Size(); 61 fMenuInfo.background_color.set_to(216, 216, 216); 62 63 // look of the separator (R5: (0, 1, 2), default 0) 64 // TODO: we could just choose a nice one and remove the others 65 fMenuInfo.separator = 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 } 221 222 return B_OK; 223 } 224 225 226 status_t 227 DesktopSettingsPrivate::Save(uint32 mask) 228 { 229 BPath basePath; 230 status_t status = _GetPath(basePath); 231 if (status < B_OK) 232 return status; 233 234 if (mask & kWorkspacesSettings) { 235 BPath path(basePath); 236 if (path.Append("workspaces") == B_OK) { 237 BMessage settings('asws'); 238 settings.AddInt32("count", fWorkspacesCount); 239 240 for (int32 i = 0; i < kMaxWorkspaces; i++) { 241 settings.AddMessage("workspace", &fWorkspaceMessages[i]); 242 } 243 244 BFile file; 245 status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_READ_WRITE); 246 if (status == B_OK) { 247 status = settings.Flatten(&file, NULL); 248 } 249 } 250 } 251 252 if (mask & kFontSettings) { 253 BPath path(basePath); 254 if (path.Append("fonts") == B_OK) { 255 BMessage settings('asfn'); 256 257 settings.AddString("plain family", fPlainFont.Family()); 258 settings.AddString("plain style", fPlainFont.Style()); 259 settings.AddFloat("plain size", fPlainFont.Size()); 260 261 settings.AddString("bold family", fBoldFont.Family()); 262 settings.AddString("bold style", fBoldFont.Style()); 263 settings.AddFloat("bold size", fBoldFont.Size()); 264 265 settings.AddString("fixed family", fFixedFont.Family()); 266 settings.AddString("fixed style", fFixedFont.Style()); 267 settings.AddFloat("fixed size", fFixedFont.Size()); 268 269 BFile file; 270 status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_READ_WRITE); 271 if (status == B_OK) { 272 status = settings.Flatten(&file, NULL); 273 } 274 } 275 } 276 277 if (mask & kMouseSettings) { 278 BPath path(basePath); 279 if (path.Append("mouse") == B_OK) { 280 BMessage settings('asms'); 281 settings.AddInt32("mode", (int32)fMouseMode); 282 283 BFile file; 284 status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_READ_WRITE); 285 if (status == B_OK) { 286 status = settings.Flatten(&file, NULL); 287 } 288 } 289 } 290 291 if (mask & kAppearanceSettings) { 292 BPath path(basePath); 293 if (path.Append("appearance") == B_OK) { 294 BMessage settings('aslk'); 295 settings.AddFloat("font size", fMenuInfo.font_size); 296 settings.AddString("font family", fMenuInfo.f_family); 297 settings.AddString("font style", fMenuInfo.f_style); 298 settings.AddInt32("bg color", (const int32&)fMenuInfo.background_color); 299 settings.AddInt32("separator", fMenuInfo.separator); 300 settings.AddBool("click to open", fMenuInfo.click_to_open); 301 settings.AddBool("triggers always shown", fMenuInfo.triggers_always_shown); 302 // TODO: more appearance settings 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 return status; 313 } 314 315 316 void 317 DesktopSettingsPrivate::SetDefaultPlainFont(const ServerFont &font) 318 { 319 fPlainFont = font; 320 Save(kFontSettings); 321 } 322 323 324 const ServerFont & 325 DesktopSettingsPrivate::DefaultPlainFont() const 326 { 327 return fPlainFont; 328 } 329 330 331 void 332 DesktopSettingsPrivate::SetDefaultBoldFont(const ServerFont &font) 333 { 334 fBoldFont = font; 335 Save(kFontSettings); 336 } 337 338 339 const ServerFont & 340 DesktopSettingsPrivate::DefaultBoldFont() const 341 { 342 return fBoldFont; 343 } 344 345 346 void 347 DesktopSettingsPrivate::SetDefaultFixedFont(const ServerFont &font) 348 { 349 fFixedFont = font; 350 Save(kFontSettings); 351 } 352 353 354 const ServerFont & 355 DesktopSettingsPrivate::DefaultFixedFont() const 356 { 357 return fFixedFont; 358 } 359 360 361 void 362 DesktopSettingsPrivate::SetScrollBarInfo(const scroll_bar_info& info) 363 { 364 fScrollBarInfo = info; 365 Save(kAppearanceSettings); 366 } 367 368 369 const scroll_bar_info& 370 DesktopSettingsPrivate::ScrollBarInfo() const 371 { 372 return fScrollBarInfo; 373 } 374 375 376 void 377 DesktopSettingsPrivate::SetMenuInfo(const menu_info& info) 378 { 379 fMenuInfo = info; 380 Save(kAppearanceSettings); 381 } 382 383 384 const menu_info& 385 DesktopSettingsPrivate::MenuInfo() const 386 { 387 return fMenuInfo; 388 } 389 390 391 void 392 DesktopSettingsPrivate::SetMouseMode(const mode_mouse mode) 393 { 394 fMouseMode = mode; 395 Save(kMouseSettings); 396 } 397 398 399 mode_mouse 400 DesktopSettingsPrivate::MouseMode() const 401 { 402 return fMouseMode; 403 } 404 405 406 bool 407 DesktopSettingsPrivate::FocusFollowsMouse() const 408 { 409 return MouseMode() != B_NORMAL_MOUSE; 410 } 411 412 413 void 414 DesktopSettingsPrivate::SetWorkspacesCount(int32 number) 415 { 416 if (number < 1) 417 number = 1; 418 else if (number > kMaxWorkspaces) 419 number = kMaxWorkspaces; 420 421 fWorkspacesCount = number; 422 } 423 424 425 int32 426 DesktopSettingsPrivate::WorkspacesCount() const 427 { 428 return fWorkspacesCount; 429 } 430 431 432 void 433 DesktopSettingsPrivate::SetWorkspacesMessage(int32 index, BMessage& message) 434 { 435 if (index < 0 || index > kMaxWorkspaces) 436 return; 437 438 fWorkspaceMessages[index] = message; 439 } 440 441 442 const BMessage* 443 DesktopSettingsPrivate::WorkspacesMessage(int32 index) const 444 { 445 if (index < 0 || index > kMaxWorkspaces) 446 return NULL; 447 448 return &fWorkspaceMessages[index]; 449 } 450 451 452 // #pragma mark - read access 453 454 455 DesktopSettings::DesktopSettings(Desktop* desktop) 456 : 457 fSettings(desktop->fSettings) 458 { 459 if (!desktop->fWindowLock.IsReadLocked() && !desktop->fWindowLock.IsWriteLocked()) 460 debugger("desktop not locked when trying to access settings"); 461 } 462 463 464 void 465 DesktopSettings::GetDefaultPlainFont(ServerFont &font) const 466 { 467 font = fSettings->DefaultPlainFont(); 468 } 469 470 471 void 472 DesktopSettings::GetDefaultBoldFont(ServerFont &font) const 473 { 474 font = fSettings->DefaultBoldFont(); 475 } 476 477 478 void 479 DesktopSettings::GetDefaultFixedFont(ServerFont &font) const 480 { 481 font = fSettings->DefaultFixedFont(); 482 } 483 484 485 void 486 DesktopSettings::GetScrollBarInfo(scroll_bar_info& info) const 487 { 488 info = fSettings->ScrollBarInfo(); 489 } 490 491 492 void 493 DesktopSettings::GetMenuInfo(menu_info& info) const 494 { 495 info = fSettings->MenuInfo(); 496 } 497 498 499 mode_mouse 500 DesktopSettings::MouseMode() const 501 { 502 return fSettings->MouseMode(); 503 } 504 505 506 bool 507 DesktopSettings::FocusFollowsMouse() const 508 { 509 return fSettings->FocusFollowsMouse(); 510 } 511 512 513 int32 514 DesktopSettings::WorkspacesCount() const 515 { 516 return fSettings->WorkspacesCount(); 517 } 518 519 520 const BMessage* 521 DesktopSettings::WorkspacesMessage(int32 index) const 522 { 523 return fSettings->WorkspacesMessage(index); 524 } 525 526 527 // #pragma mark - write access 528 529 530 LockedDesktopSettings::LockedDesktopSettings(Desktop* desktop) 531 : 532 fSettings(desktop->fSettings), 533 fDesktop(desktop) 534 { 535 // TODO: this only works in MultiLocker's DEBUG mode 536 #if 0 537 if (desktop->fWindowLock.IsReadLocked()) 538 debugger("desktop read locked when trying to change settings"); 539 #endif 540 541 fDesktop->LockAllWindows(); 542 } 543 544 545 LockedDesktopSettings::~LockedDesktopSettings() 546 { 547 fDesktop->UnlockAllWindows(); 548 } 549 550 551 void 552 LockedDesktopSettings::SetDefaultPlainFont(const ServerFont &font) 553 { 554 fSettings->SetDefaultPlainFont(font); 555 } 556 557 558 void 559 LockedDesktopSettings::SetDefaultBoldFont(const ServerFont &font) 560 { 561 fSettings->SetDefaultBoldFont(font); 562 } 563 564 565 void 566 LockedDesktopSettings::SetDefaultFixedFont(const ServerFont &font) 567 { 568 fSettings->SetDefaultFixedFont(font); 569 } 570 571 572 void 573 LockedDesktopSettings::SetScrollBarInfo(const scroll_bar_info& info) 574 { 575 fSettings->SetScrollBarInfo(info); 576 } 577 578 579 void 580 LockedDesktopSettings::SetMenuInfo(const menu_info& info) 581 { 582 fSettings->SetMenuInfo(info); 583 } 584 585 586 void 587 LockedDesktopSettings::SetMouseMode(const mode_mouse mode) 588 { 589 fSettings->SetMouseMode(mode); 590 } 591 592 593