xref: /haiku/src/servers/app/DesktopSettings.cpp (revision 89755088d790ff4fe36f8aa77dacb2bd15507108)
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  */
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 			for (int32 i = 0; i < kNumColors; i++) {
221 				char colorName[12];
222 				snprintf(colorName, sizeof(colorName), "color%ld",
223 					(int32)index_to_color_which(i));
224 
225 				settings.FindInt32(colorName, (int32*)&fShared.colors[i]);
226 			}
227 		}
228 	}
229 
230 	return B_OK;
231 }
232 
233 
234 status_t
235 DesktopSettingsPrivate::Save(uint32 mask)
236 {
237 	BPath basePath;
238 	status_t status = _GetPath(basePath);
239 	if (status < B_OK)
240 		return status;
241 
242 	if (mask & kWorkspacesSettings) {
243 		BPath path(basePath);
244 		if (path.Append("workspaces") == B_OK) {
245 			BMessage settings('asws');
246 			settings.AddInt32("count", fWorkspacesCount);
247 
248 			for (int32 i = 0; i < kMaxWorkspaces; i++) {
249 				settings.AddMessage("workspace", &fWorkspaceMessages[i]);
250 			}
251 
252 			BFile file;
253 			status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_READ_WRITE);
254 			if (status == B_OK) {
255 				status = settings.Flatten(&file, NULL);
256 			}
257 		}
258 	}
259 
260 	if (mask & kFontSettings) {
261 		BPath path(basePath);
262 		if (path.Append("fonts") == B_OK) {
263 			BMessage settings('asfn');
264 
265 			settings.AddString("plain family", fPlainFont.Family());
266 			settings.AddString("plain style", fPlainFont.Style());
267 			settings.AddFloat("plain size", fPlainFont.Size());
268 
269 			settings.AddString("bold family", fBoldFont.Family());
270 			settings.AddString("bold style", fBoldFont.Style());
271 			settings.AddFloat("bold size", fBoldFont.Size());
272 
273 			settings.AddString("fixed family", fFixedFont.Family());
274 			settings.AddString("fixed style", fFixedFont.Style());
275 			settings.AddFloat("fixed size", fFixedFont.Size());
276 
277 			BFile file;
278 			status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_READ_WRITE);
279 			if (status == B_OK) {
280 				status = settings.Flatten(&file, NULL);
281 			}
282 		}
283 	}
284 
285 	if (mask & kMouseSettings) {
286 		BPath path(basePath);
287 		if (path.Append("mouse") == B_OK) {
288 			BMessage settings('asms');
289 			settings.AddInt32("mode", (int32)fMouseMode);
290 
291 			BFile file;
292 			status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_READ_WRITE);
293 			if (status == B_OK) {
294 				status = settings.Flatten(&file, NULL);
295 			}
296 		}
297 	}
298 
299 	if (mask & kDraggerSettings) {
300 		BPath path(basePath);
301 		if (path.Append("dragger") == B_OK) {
302 			BMessage settings('asdg');
303 			settings.AddBool("show", fShowAllDraggers);
304 
305 			BFile file;
306 			status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_READ_WRITE);
307 			if (status == B_OK) {
308 				status = settings.Flatten(&file, NULL);
309 			}
310 		}
311 	}
312 
313 	if (mask & kAppearanceSettings) {
314 		BPath path(basePath);
315 		if (path.Append("appearance") == B_OK) {
316 			BMessage settings('aslk');
317 			settings.AddFloat("font size", fMenuInfo.font_size);
318 			settings.AddString("font family", fMenuInfo.f_family);
319 			settings.AddString("font style", fMenuInfo.f_style);
320 			settings.AddInt32("bg color", (const int32&)fMenuInfo.background_color);
321 			settings.AddInt32("separator", fMenuInfo.separator);
322 			settings.AddBool("click to open", fMenuInfo.click_to_open);
323 			settings.AddBool("triggers always shown", fMenuInfo.triggers_always_shown);
324 
325 			for (int32 i = 0; i < kNumColors; i++) {
326 				char colorName[12];
327 				snprintf(colorName, sizeof(colorName), "color%ld",
328 					(int32)index_to_color_which(i));
329 				settings.AddInt32(colorName, (const int32&)fShared.colors[i]);
330 			}
331 
332 			BFile file;
333 			status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_READ_WRITE);
334 			if (status == B_OK) {
335 				status = settings.Flatten(&file, NULL);
336 			}
337 		}
338 	}
339 
340 	return status;
341 }
342 
343 
344 void
345 DesktopSettingsPrivate::SetDefaultPlainFont(const ServerFont &font)
346 {
347 	fPlainFont = font;
348 	Save(kFontSettings);
349 }
350 
351 
352 const ServerFont &
353 DesktopSettingsPrivate::DefaultPlainFont() const
354 {
355 	return fPlainFont;
356 }
357 
358 
359 void
360 DesktopSettingsPrivate::SetDefaultBoldFont(const ServerFont &font)
361 {
362 	fBoldFont = font;
363 	Save(kFontSettings);
364 }
365 
366 
367 const ServerFont &
368 DesktopSettingsPrivate::DefaultBoldFont() const
369 {
370 	return fBoldFont;
371 }
372 
373 
374 void
375 DesktopSettingsPrivate::SetDefaultFixedFont(const ServerFont &font)
376 {
377 	fFixedFont = font;
378 	Save(kFontSettings);
379 }
380 
381 
382 const ServerFont &
383 DesktopSettingsPrivate::DefaultFixedFont() const
384 {
385 	return fFixedFont;
386 }
387 
388 
389 void
390 DesktopSettingsPrivate::SetScrollBarInfo(const scroll_bar_info& info)
391 {
392 	fScrollBarInfo = info;
393 	Save(kAppearanceSettings);
394 }
395 
396 
397 const scroll_bar_info&
398 DesktopSettingsPrivate::ScrollBarInfo() const
399 {
400 	return fScrollBarInfo;
401 }
402 
403 
404 void
405 DesktopSettingsPrivate::SetMenuInfo(const menu_info& info)
406 {
407 	fMenuInfo = info;
408 	// Also update the ui_color
409 	SetUIColor(B_MENU_BACKGROUND_COLOR, info.background_color);
410 		// SetUIColor already saves the settings
411 }
412 
413 
414 const menu_info&
415 DesktopSettingsPrivate::MenuInfo() const
416 {
417 	return fMenuInfo;
418 }
419 
420 
421 void
422 DesktopSettingsPrivate::SetMouseMode(const mode_mouse mode)
423 {
424 	fMouseMode = mode;
425 	Save(kMouseSettings);
426 }
427 
428 
429 mode_mouse
430 DesktopSettingsPrivate::MouseMode() const
431 {
432 	return fMouseMode;
433 }
434 
435 
436 bool
437 DesktopSettingsPrivate::FocusFollowsMouse() const
438 {
439 	return MouseMode() != B_NORMAL_MOUSE;
440 }
441 
442 
443 void
444 DesktopSettingsPrivate::SetShowAllDraggers(bool show)
445 {
446 	fShowAllDraggers = show;
447 	Save(kDraggerSettings);
448 }
449 
450 
451 bool
452 DesktopSettingsPrivate::ShowAllDraggers() const
453 {
454 	return fShowAllDraggers;
455 }
456 
457 
458 void
459 DesktopSettingsPrivate::SetWorkspacesCount(int32 number)
460 {
461 	if (number < 1)
462 		number = 1;
463 	else if (number > kMaxWorkspaces)
464 		number = kMaxWorkspaces;
465 
466 	fWorkspacesCount = number;
467 }
468 
469 
470 int32
471 DesktopSettingsPrivate::WorkspacesCount() const
472 {
473 	return fWorkspacesCount;
474 }
475 
476 
477 void
478 DesktopSettingsPrivate::SetWorkspacesMessage(int32 index, BMessage& message)
479 {
480 	if (index < 0 || index > kMaxWorkspaces)
481 		return;
482 
483 	fWorkspaceMessages[index] = message;
484 }
485 
486 
487 const BMessage*
488 DesktopSettingsPrivate::WorkspacesMessage(int32 index) const
489 {
490 	if (index < 0 || index > kMaxWorkspaces)
491 		return NULL;
492 
493 	return &fWorkspaceMessages[index];
494 }
495 
496 
497 void
498 DesktopSettingsPrivate::SetUIColor(color_which which, const rgb_color color)
499 {
500 	//
501 	int32 index = color_which_to_index(which);
502 	if (index < 0 || index >= kNumColors)
503 		return;
504 	fShared.colors[index] = color;
505 	// TODO: deprecate the background_color member of the menu_info struct,
506 	// otherwise we have to keep this duplication...
507 	if (which == B_MENU_BACKGROUND_COLOR)
508 		fMenuInfo.background_color = color;
509 	Save(kAppearanceSettings);
510 }
511 
512 
513 rgb_color
514 DesktopSettingsPrivate::UIColor(color_which which) const
515 {
516 	static const rgb_color invalidColor = {0, 0, 0, 0};
517 	int32 index = color_which_to_index(which);
518 	if (index < 0 || index >= kNumColors)
519 		return invalidColor;
520 	return fShared.colors[index];
521 }
522 
523 
524 //	#pragma mark - read access
525 
526 
527 DesktopSettings::DesktopSettings(Desktop* desktop)
528 	:
529 	fSettings(desktop->fSettings)
530 {
531 #if DEBUG
532 	if (!desktop->fWindowLock.IsWriteLocked()
533 		&& !desktop->fWindowLock.IsReadLocked())
534 		debugger("desktop not locked when trying to access settings");
535 #endif
536 }
537 
538 
539 void
540 DesktopSettings::GetDefaultPlainFont(ServerFont &font) const
541 {
542 	font = fSettings->DefaultPlainFont();
543 }
544 
545 
546 void
547 DesktopSettings::GetDefaultBoldFont(ServerFont &font) const
548 {
549 	font = fSettings->DefaultBoldFont();
550 }
551 
552 
553 void
554 DesktopSettings::GetDefaultFixedFont(ServerFont &font) const
555 {
556 	font = fSettings->DefaultFixedFont();
557 }
558 
559 
560 void
561 DesktopSettings::GetScrollBarInfo(scroll_bar_info& info) const
562 {
563 	info = fSettings->ScrollBarInfo();
564 }
565 
566 
567 void
568 DesktopSettings::GetMenuInfo(menu_info& info) const
569 {
570 	info = fSettings->MenuInfo();
571 }
572 
573 
574 mode_mouse
575 DesktopSettings::MouseMode() const
576 {
577 	return fSettings->MouseMode();
578 }
579 
580 
581 bool
582 DesktopSettings::FocusFollowsMouse() const
583 {
584 	return fSettings->FocusFollowsMouse();
585 }
586 
587 
588 bool
589 DesktopSettings::ShowAllDraggers() const
590 {
591 	return fSettings->ShowAllDraggers();
592 }
593 
594 
595 int32
596 DesktopSettings::WorkspacesCount() const
597 {
598 	return fSettings->WorkspacesCount();
599 }
600 
601 
602 const BMessage*
603 DesktopSettings::WorkspacesMessage(int32 index) const
604 {
605 	return fSettings->WorkspacesMessage(index);
606 }
607 
608 
609 rgb_color
610 DesktopSettings::UIColor(color_which which) const
611 {
612 	return fSettings->UIColor(which);
613 }
614 
615 
616 //	#pragma mark - write access
617 
618 
619 LockedDesktopSettings::LockedDesktopSettings(Desktop* desktop)
620 	: DesktopSettings(desktop),
621 	fDesktop(desktop)
622 {
623 #if DEBUG
624 	if (desktop->fWindowLock.IsReadLocked())
625 		debugger("desktop read locked when trying to change settings");
626 #endif
627 
628 	fDesktop->LockAllWindows();
629 }
630 
631 
632 LockedDesktopSettings::~LockedDesktopSettings()
633 {
634 	fDesktop->UnlockAllWindows();
635 }
636 
637 
638 void
639 LockedDesktopSettings::SetDefaultPlainFont(const ServerFont &font)
640 {
641 	fSettings->SetDefaultPlainFont(font);
642 }
643 
644 
645 void
646 LockedDesktopSettings::SetDefaultBoldFont(const ServerFont &font)
647 {
648 	fSettings->SetDefaultBoldFont(font);
649 }
650 
651 
652 void
653 LockedDesktopSettings::SetDefaultFixedFont(const ServerFont &font)
654 {
655 	fSettings->SetDefaultFixedFont(font);
656 }
657 
658 
659 void
660 LockedDesktopSettings::SetScrollBarInfo(const scroll_bar_info& info)
661 {
662 	fSettings->SetScrollBarInfo(info);
663 }
664 
665 
666 void
667 LockedDesktopSettings::SetMenuInfo(const menu_info& info)
668 {
669 	fSettings->SetMenuInfo(info);
670 }
671 
672 
673 void
674 LockedDesktopSettings::SetMouseMode(const mode_mouse mode)
675 {
676 	fSettings->SetMouseMode(mode);
677 }
678 
679 
680 void
681 LockedDesktopSettings::SetShowAllDraggers(bool show)
682 {
683 	fSettings->SetShowAllDraggers(show);
684 }
685 
686 
687 void
688 LockedDesktopSettings::SetUIColor(color_which which, const rgb_color color)
689 {
690 	fSettings->SetUIColor(which, color);
691 }
692 
693 
694