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