xref: /haiku/src/servers/app/DesktopSettings.cpp (revision 676308a602849ad12219344e5a3fcdc86ce26c34)
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