1/*
2 * Copyright 2005-2015, 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 *		Andrej Spielmann, <andrej.spielmann@seh.ox.ac.uk>
9 *		Joseph Groover <looncraz@looncraz.net>
10 */
11
12
13#include "DesktopSettings.h"
14#include "DesktopSettingsPrivate.h"
15
16#include <Directory.h>
17#include <File.h>
18#include <FindDirectory.h>
19#include <Path.h>
20
21#include <DefaultColors.h>
22#include <InterfaceDefs.h>
23#include <ServerReadOnlyMemory.h>
24
25#include "Desktop.h"
26#include "FontCache.h"
27#include "FontCacheEntry.h"
28#include "GlobalFontManager.h"
29#include "GlobalSubpixelSettings.h"
30#include "ServerConfig.h"
31
32
33DesktopSettingsPrivate::DesktopSettingsPrivate(server_read_only_memory* shared)
34	:
35	fShared(*shared)
36{
37	// if the on-disk settings are not complete, the defaults will be kept
38	_SetDefaults();
39	_Load();
40}
41
42
43DesktopSettingsPrivate::~DesktopSettingsPrivate()
44{
45}
46
47
48void
49DesktopSettingsPrivate::_SetDefaults()
50{
51	fPlainFont = *gFontManager->DefaultPlainFont();
52	fBoldFont = *gFontManager->DefaultBoldFont();
53	fFixedFont = *gFontManager->DefaultFixedFont();
54
55	fMouseMode = B_NORMAL_MOUSE;
56	fFocusFollowsMouseMode = B_NORMAL_FOCUS_FOLLOWS_MOUSE;
57	fAcceptFirstClick = true;
58	fShowAllDraggers = true;
59
60	// init scrollbar info
61	fScrollBarInfo.proportional = true;
62	fScrollBarInfo.double_arrows = false;
63	fScrollBarInfo.knob = 0;
64		// look of the knob (R5: (0, 1, 2), 1 = default)
65		// change default = 0 (no knob) in Haiku
66	fScrollBarInfo.min_knob_size = 15;
67
68	// init menu info
69	strlcpy(fMenuInfo.f_family, fPlainFont.Family(), B_FONT_FAMILY_LENGTH);
70	strlcpy(fMenuInfo.f_style, fPlainFont.Style(), B_FONT_STYLE_LENGTH);
71	fMenuInfo.font_size = fPlainFont.Size();
72	fMenuInfo.background_color.set_to(216, 216, 216);
73
74	fMenuInfo.separator = 0;
75		// look of the separator (R5: (0, 1, 2), default 0)
76	fMenuInfo.click_to_open = true; // always true
77	fMenuInfo.triggers_always_shown = false;
78
79	fWorkspacesColumns = 2;
80	fWorkspacesRows = 2;
81
82	memcpy((void*)fShared.colors, BPrivate::kDefaultColors,
83		sizeof(rgb_color) * kColorWhichCount);
84
85	gSubpixelAntialiasing = true;
86	gDefaultHintingMode = HINTING_MODE_ON;
87	gSubpixelAverageWeight = 120;
88	gSubpixelOrderingRGB = true;
89}
90
91
92status_t
93DesktopSettingsPrivate::_GetPath(BPath& path)
94{
95	status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
96	if (status < B_OK)
97		return status;
98
99	status = path.Append("system/app_server");
100	if (status < B_OK)
101		return status;
102
103	return create_directory(path.Path(), 0755);
104}
105
106
107status_t
108DesktopSettingsPrivate::_Load()
109{
110	// TODO: add support for old app_server_settings file as well
111
112	BPath basePath;
113	status_t status = _GetPath(basePath);
114	if (status < B_OK)
115		return status;
116
117	// read workspaces settings
118
119	BPath path(basePath);
120	path.Append("workspaces");
121
122	BFile file;
123	status = file.SetTo(path.Path(), B_READ_ONLY);
124	if (status == B_OK) {
125		BMessage settings;
126		status = settings.Unflatten(&file);
127		if (status == B_OK) {
128			int32 columns;
129			int32 rows;
130			if (settings.FindInt32("columns", &columns) == B_OK
131				&& settings.FindInt32("rows", &rows) == B_OK) {
132				_ValidateWorkspacesLayout(columns, rows);
133				fWorkspacesColumns = columns;
134				fWorkspacesRows = rows;
135			}
136
137			int32 i = 0;
138			while (i < kMaxWorkspaces && settings.FindMessage("workspace",
139					i, &fWorkspaceMessages[i]) == B_OK) {
140				i++;
141			}
142		}
143	}
144
145	// read font settings
146
147	path = basePath;
148	path.Append("fonts");
149
150	status = file.SetTo(path.Path(), B_READ_ONLY);
151	if (status == B_OK) {
152		BMessage settings;
153		status = settings.Unflatten(&file);
154		if (status != B_OK) {
155			fFontSettingsLoadStatus = status;
156		} else if (gFontManager->Lock()) {
157			const char* family;
158			const char* style;
159			float size;
160
161			if (settings.FindString("plain family", &family) == B_OK
162				&& settings.FindString("plain style", &style) == B_OK
163				&& settings.FindFloat("plain size", &size) == B_OK) {
164				FontStyle* fontStyle = gFontManager->GetStyle(family, style);
165				fPlainFont.SetStyle(fontStyle);
166				fPlainFont.SetSize(size);
167			}
168
169			if (settings.FindString("bold family", &family) == B_OK
170				&& settings.FindString("bold style", &style) == B_OK
171				&& settings.FindFloat("bold size", &size) == B_OK) {
172				FontStyle* fontStyle = gFontManager->GetStyle(family, style);
173				fBoldFont.SetStyle(fontStyle);
174				fBoldFont.SetSize(size);
175			}
176
177			if (settings.FindString("fixed family", &family) == B_OK
178				&& settings.FindString("fixed style", &style) == B_OK
179				&& settings.FindFloat("fixed size", &size) == B_OK) {
180				FontStyle* fontStyle = gFontManager->GetStyle(family, style);
181				if (fontStyle != NULL && (fontStyle->IsFixedWidth()
182						|| fontStyle->IsFullAndHalfFixed()))
183					fFixedFont.SetStyle(fontStyle);
184				fFixedFont.SetSize(size);
185			}
186
187			int32 hinting;
188			if (settings.FindInt32("hinting", &hinting) == B_OK)
189				gDefaultHintingMode = hinting;
190
191			gFontManager->Unlock();
192		} else
193			fFontSettingsLoadStatus = EWOULDBLOCK;
194	} else
195		fFontSettingsLoadStatus = status;
196
197	// read mouse settings
198
199	path = basePath;
200	path.Append("mouse");
201
202	status = file.SetTo(path.Path(), B_READ_ONLY);
203	if (status == B_OK) {
204		BMessage settings;
205		status = settings.Unflatten(&file);
206		if (status == B_OK) {
207			int32 mode;
208			if (settings.FindInt32("mode", &mode) == B_OK)
209				fMouseMode = (mode_mouse)mode;
210
211			int32 focusFollowsMouseMode;
212			if (settings.FindInt32("focus follows mouse mode",
213					&focusFollowsMouseMode) == B_OK) {
214				fFocusFollowsMouseMode
215					= (mode_focus_follows_mouse)focusFollowsMouseMode;
216			}
217
218			bool acceptFirstClick;
219			if (settings.FindBool("accept first click", &acceptFirstClick)
220					== B_OK) {
221				fAcceptFirstClick = acceptFirstClick;
222			}
223		}
224	}
225
226	// read appearance settings
227
228	path = basePath;
229	path.Append("appearance");
230
231	status = file.SetTo(path.Path(), B_READ_ONLY);
232	if (status == B_OK) {
233		BMessage settings;
234		status = settings.Unflatten(&file);
235		if (status == B_OK) {
236			// menus
237			float fontSize;
238			if (settings.FindFloat("font size", &fontSize) == B_OK)
239				fMenuInfo.font_size = fontSize;
240
241			const char* fontFamily;
242			if (settings.FindString("font family", &fontFamily) == B_OK)
243				strlcpy(fMenuInfo.f_family, fontFamily, B_FONT_FAMILY_LENGTH);
244
245			const char* fontStyle;
246			if (settings.FindString("font style", &fontStyle) == B_OK)
247				strlcpy(fMenuInfo.f_style, fontStyle, B_FONT_STYLE_LENGTH);
248
249			rgb_color bgColor;
250			if (settings.FindInt32("bg color", (int32*)&bgColor) == B_OK)
251				fMenuInfo.background_color = bgColor;
252
253			int32 separator;
254			if (settings.FindInt32("separator", &separator) == B_OK)
255				fMenuInfo.separator = separator;
256
257			bool clickToOpen;
258			if (settings.FindBool("click to open", &clickToOpen) == B_OK)
259				fMenuInfo.click_to_open = clickToOpen;
260
261			bool triggersAlwaysShown;
262			if (settings.FindBool("triggers always shown", &triggersAlwaysShown)
263					 == B_OK) {
264				fMenuInfo.triggers_always_shown = triggersAlwaysShown;
265			}
266
267			// scrollbars
268			bool proportional;
269			if (settings.FindBool("proportional", &proportional) == B_OK)
270				fScrollBarInfo.proportional = proportional;
271
272			bool doubleArrows;
273			if (settings.FindBool("double arrows", &doubleArrows) == B_OK)
274				fScrollBarInfo.double_arrows = doubleArrows;
275
276			int32 knob;
277			if (settings.FindInt32("knob", &knob) == B_OK)
278				fScrollBarInfo.knob = knob;
279
280			int32 minKnobSize;
281			if (settings.FindInt32("min knob size", &minKnobSize) == B_OK)
282				fScrollBarInfo.min_knob_size = minKnobSize;
283
284			// subpixel font rendering
285			bool subpix;
286			if (settings.FindBool("subpixel antialiasing", &subpix) == B_OK)
287				gSubpixelAntialiasing = subpix;
288
289			int8 averageWeight;
290			if (settings.FindInt8("subpixel average weight", &averageWeight)
291					== B_OK) {
292				gSubpixelAverageWeight = averageWeight;
293			}
294
295			bool subpixelOrdering;
296			if (settings.FindBool("subpixel ordering", &subpixelOrdering)
297					== B_OK) {
298				gSubpixelOrderingRGB = subpixelOrdering;
299			}
300
301			const char* controlLook;
302			if (settings.FindString("control look", &controlLook) == B_OK) {
303				fControlLook = controlLook;
304			}
305
306			// colors
307			for (int32 i = 0; i < kColorWhichCount; i++) {
308				char colorName[12];
309				snprintf(colorName, sizeof(colorName), "color%" B_PRId32,
310					(int32)index_to_color_which(i));
311
312				if (settings.FindInt32(colorName, (int32*)&fShared.colors[i]) != B_OK) {
313					// Set obviously bad value so the Appearance app can detect it
314					fShared.colors[i] = B_TRANSPARENT_COLOR;
315				}
316			}
317		}
318	}
319
320	// read dragger settings
321
322	path = basePath;
323	path.Append("dragger");
324
325	status = file.SetTo(path.Path(), B_READ_ONLY);
326	if (status == B_OK) {
327		BMessage settings;
328		status = settings.Unflatten(&file);
329		if (status == B_OK) {
330			if (settings.FindBool("show", &fShowAllDraggers) != B_OK)
331				fShowAllDraggers = true;
332		}
333	}
334
335	return B_OK;
336}
337
338
339status_t
340DesktopSettingsPrivate::Save(uint32 mask)
341{
342#if TEST_MODE
343	return B_OK;
344#endif
345
346	BPath basePath;
347	status_t status = _GetPath(basePath);
348	if (status != B_OK)
349		return status;
350
351	if (mask & kWorkspacesSettings) {
352		BPath path(basePath);
353		if (path.Append("workspaces") == B_OK) {
354			BMessage settings('asws');
355			settings.AddInt32("columns", fWorkspacesColumns);
356			settings.AddInt32("rows", fWorkspacesRows);
357
358			for (int32 i = 0; i < kMaxWorkspaces; i++) {
359				settings.AddMessage("workspace", &fWorkspaceMessages[i]);
360			}
361
362			BFile file;
363			status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE
364				| B_READ_WRITE);
365			if (status == B_OK) {
366				status = settings.Flatten(&file, NULL);
367			}
368		}
369	}
370
371	if (mask & kFontSettings) {
372		BPath path(basePath);
373		if (path.Append("fonts") == B_OK) {
374			BMessage settings('asfn');
375
376			settings.AddString("plain family", fPlainFont.Family());
377			settings.AddString("plain style", fPlainFont.Style());
378			settings.AddFloat("plain size", fPlainFont.Size());
379
380			settings.AddString("bold family", fBoldFont.Family());
381			settings.AddString("bold style", fBoldFont.Style());
382			settings.AddFloat("bold size", fBoldFont.Size());
383
384			settings.AddString("fixed family", fFixedFont.Family());
385			settings.AddString("fixed style", fFixedFont.Style());
386			settings.AddFloat("fixed size", fFixedFont.Size());
387
388			settings.AddInt32("hinting", gDefaultHintingMode);
389
390			BFile file;
391			status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE
392				| B_READ_WRITE);
393			if (status == B_OK) {
394				status = settings.Flatten(&file, NULL);
395			}
396		}
397	}
398
399	if (mask & kMouseSettings) {
400		BPath path(basePath);
401		if (path.Append("mouse") == B_OK) {
402			BMessage settings('asms');
403			settings.AddInt32("mode", (int32)fMouseMode);
404			settings.AddInt32("focus follows mouse mode",
405				(int32)fFocusFollowsMouseMode);
406			settings.AddBool("accept first click", fAcceptFirstClick);
407
408			BFile file;
409			status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE
410				| B_READ_WRITE);
411			if (status == B_OK) {
412				status = settings.Flatten(&file, NULL);
413			}
414		}
415	}
416
417	if (mask & kDraggerSettings) {
418		BPath path(basePath);
419		if (path.Append("dragger") == B_OK) {
420			BMessage settings('asdg');
421			settings.AddBool("show", fShowAllDraggers);
422
423			BFile file;
424			status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE
425				| B_READ_WRITE);
426			if (status == B_OK) {
427				status = settings.Flatten(&file, NULL);
428			}
429		}
430	}
431
432	if (mask & kAppearanceSettings) {
433		BPath path(basePath);
434		if (path.Append("appearance") == B_OK) {
435			BMessage settings('aslk');
436			settings.AddFloat("font size", fMenuInfo.font_size);
437			settings.AddString("font family", fMenuInfo.f_family);
438			settings.AddString("font style", fMenuInfo.f_style);
439			settings.AddInt32("bg color",
440				(const int32&)fMenuInfo.background_color);
441			settings.AddInt32("separator", fMenuInfo.separator);
442			settings.AddBool("click to open", fMenuInfo.click_to_open);
443			settings.AddBool("triggers always shown",
444				fMenuInfo.triggers_always_shown);
445
446			settings.AddBool("proportional", fScrollBarInfo.proportional);
447			settings.AddBool("double arrows", fScrollBarInfo.double_arrows);
448			settings.AddInt32("knob", fScrollBarInfo.knob);
449			settings.AddInt32("min knob size", fScrollBarInfo.min_knob_size);
450
451			settings.AddBool("subpixel antialiasing", gSubpixelAntialiasing);
452			settings.AddInt8("subpixel average weight", gSubpixelAverageWeight);
453			settings.AddBool("subpixel ordering", gSubpixelOrderingRGB);
454
455			settings.AddString("control look", fControlLook);
456
457			for (int32 i = 0; i < kColorWhichCount; i++) {
458				char colorName[12];
459				snprintf(colorName, sizeof(colorName), "color%" B_PRId32,
460					(int32)index_to_color_which(i));
461				settings.AddInt32(colorName, (const int32&)fShared.colors[i]);
462			}
463
464			BFile file;
465			status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE
466				| B_READ_WRITE);
467			if (status == B_OK) {
468				status = settings.Flatten(&file, NULL);
469			}
470		}
471	}
472
473	return status;
474}
475
476
477void
478DesktopSettingsPrivate::SetDefaultPlainFont(const ServerFont &font)
479{
480	fPlainFont = font;
481	Save(kFontSettings);
482}
483
484
485const ServerFont &
486DesktopSettingsPrivate::DefaultPlainFont() const
487{
488	return fPlainFont;
489}
490
491
492void
493DesktopSettingsPrivate::SetDefaultBoldFont(const ServerFont &font)
494{
495	fBoldFont = font;
496	Save(kFontSettings);
497}
498
499
500const ServerFont &
501DesktopSettingsPrivate::DefaultBoldFont() const
502{
503	return fBoldFont;
504}
505
506
507void
508DesktopSettingsPrivate::SetDefaultFixedFont(const ServerFont &font)
509{
510	fFixedFont = font;
511	Save(kFontSettings);
512}
513
514
515const ServerFont &
516DesktopSettingsPrivate::DefaultFixedFont() const
517{
518	return fFixedFont;
519}
520
521
522void
523DesktopSettingsPrivate::SetScrollBarInfo(const scroll_bar_info& info)
524{
525	fScrollBarInfo = info;
526	Save(kAppearanceSettings);
527}
528
529
530const scroll_bar_info&
531DesktopSettingsPrivate::ScrollBarInfo() const
532{
533	return fScrollBarInfo;
534}
535
536
537void
538DesktopSettingsPrivate::SetMenuInfo(const menu_info& info)
539{
540	fMenuInfo = info;
541	// Also update the ui_color
542	SetUIColor(B_MENU_BACKGROUND_COLOR, info.background_color);
543		// SetUIColor already saves the settings
544}
545
546
547const menu_info&
548DesktopSettingsPrivate::MenuInfo() const
549{
550	return fMenuInfo;
551}
552
553
554void
555DesktopSettingsPrivate::SetMouseMode(const mode_mouse mode)
556{
557	fMouseMode = mode;
558	Save(kMouseSettings);
559}
560
561
562void
563DesktopSettingsPrivate::SetFocusFollowsMouseMode(mode_focus_follows_mouse mode)
564{
565	fFocusFollowsMouseMode = mode;
566	Save(kMouseSettings);
567}
568
569
570mode_mouse
571DesktopSettingsPrivate::MouseMode() const
572{
573	return fMouseMode;
574}
575
576
577mode_focus_follows_mouse
578DesktopSettingsPrivate::FocusFollowsMouseMode() const
579{
580	return fFocusFollowsMouseMode;
581}
582
583
584void
585DesktopSettingsPrivate::SetAcceptFirstClick(const bool acceptFirstClick)
586{
587	fAcceptFirstClick = acceptFirstClick;
588	Save(kMouseSettings);
589}
590
591
592bool
593DesktopSettingsPrivate::AcceptFirstClick() const
594{
595	return fAcceptFirstClick;
596}
597
598
599void
600DesktopSettingsPrivate::SetShowAllDraggers(bool show)
601{
602	fShowAllDraggers = show;
603	Save(kDraggerSettings);
604}
605
606
607bool
608DesktopSettingsPrivate::ShowAllDraggers() const
609{
610	return fShowAllDraggers;
611}
612
613
614void
615DesktopSettingsPrivate::SetWorkspacesLayout(int32 columns, int32 rows)
616{
617	_ValidateWorkspacesLayout(columns, rows);
618	fWorkspacesColumns = columns;
619	fWorkspacesRows = rows;
620
621	Save(kWorkspacesSettings);
622}
623
624
625int32
626DesktopSettingsPrivate::WorkspacesCount() const
627{
628	return fWorkspacesColumns * fWorkspacesRows;
629}
630
631
632int32
633DesktopSettingsPrivate::WorkspacesColumns() const
634{
635	return fWorkspacesColumns;
636}
637
638
639int32
640DesktopSettingsPrivate::WorkspacesRows() const
641{
642	return fWorkspacesRows;
643}
644
645
646void
647DesktopSettingsPrivate::SetWorkspacesMessage(int32 index, BMessage& message)
648{
649	if (index < 0 || index >= kMaxWorkspaces)
650		return;
651
652	fWorkspaceMessages[index] = message;
653}
654
655
656const BMessage*
657DesktopSettingsPrivate::WorkspacesMessage(int32 index) const
658{
659	if (index < 0 || index >= kMaxWorkspaces)
660		return NULL;
661
662	return &fWorkspaceMessages[index];
663}
664
665
666void
667DesktopSettingsPrivate::SetUIColor(color_which which, const rgb_color color,
668									bool* changed)
669{
670	int32 index = color_which_to_index(which);
671	if (index < 0 || index >= kColorWhichCount)
672		return;
673
674	if (changed != NULL)
675		*changed = fShared.colors[index] != color;
676
677	fShared.colors[index] = color;
678	// TODO: deprecate the background_color member of the menu_info struct,
679	// otherwise we have to keep this duplication...
680	if (which == B_MENU_BACKGROUND_COLOR)
681		fMenuInfo.background_color = color;
682
683	Save(kAppearanceSettings);
684}
685
686
687void
688DesktopSettingsPrivate::SetUIColors(const BMessage& colors, bool* changed)
689{
690	int32 count = colors.CountNames(B_RGB_32_BIT_TYPE);
691	if (count <= 0)
692		return;
693
694	int32 index = 0;
695	int32 colorIndex = 0;
696	char* name = NULL;
697	type_code type;
698	rgb_color color;
699	color_which which = B_NO_COLOR;
700
701	while (colors.GetInfo(B_RGB_32_BIT_TYPE, index, &name, &type) == B_OK) {
702		which = which_ui_color(name);
703		colorIndex = color_which_to_index(which);
704		if (colorIndex < 0 || colorIndex >= kColorWhichCount
705			|| colors.FindColor(name, &color) != B_OK) {
706			if (changed != NULL)
707				changed[index] = false;
708
709			++index;
710			continue;
711		}
712
713		if (changed != NULL)
714			changed[index] = fShared.colors[colorIndex] != color;
715
716		fShared.colors[colorIndex] = color;
717
718		if (which == (int32)B_MENU_BACKGROUND_COLOR)
719			fMenuInfo.background_color = color;
720
721		++index;
722	}
723
724	Save(kAppearanceSettings);
725}
726
727
728rgb_color
729DesktopSettingsPrivate::UIColor(color_which which) const
730{
731	static const rgb_color invalidColor = {0, 0, 0, 0};
732	int32 index = color_which_to_index(which);
733	if (index < 0 || index >= kColorWhichCount)
734		return invalidColor;
735
736	return fShared.colors[index];
737}
738
739
740void
741DesktopSettingsPrivate::SetSubpixelAntialiasing(bool subpix)
742{
743	gSubpixelAntialiasing = subpix;
744	Save(kAppearanceSettings);
745}
746
747
748bool
749DesktopSettingsPrivate::SubpixelAntialiasing() const
750{
751	return gSubpixelAntialiasing;
752}
753
754
755void
756DesktopSettingsPrivate::SetHinting(uint8 hinting)
757{
758	gDefaultHintingMode = hinting;
759	Save(kFontSettings);
760}
761
762
763uint8
764DesktopSettingsPrivate::Hinting() const
765{
766	return gDefaultHintingMode;
767}
768
769
770void
771DesktopSettingsPrivate::SetSubpixelAverageWeight(uint8 averageWeight)
772{
773	gSubpixelAverageWeight = averageWeight;
774	Save(kAppearanceSettings);
775}
776
777
778uint8
779DesktopSettingsPrivate::SubpixelAverageWeight() const
780{
781	return gSubpixelAverageWeight;
782}
783
784
785void
786DesktopSettingsPrivate::SetSubpixelOrderingRegular(bool subpixelOrdering)
787{
788	gSubpixelOrderingRGB = subpixelOrdering;
789	Save(kAppearanceSettings);
790}
791
792
793bool
794DesktopSettingsPrivate::IsSubpixelOrderingRegular() const
795{
796	return gSubpixelOrderingRGB;
797}
798
799
800status_t
801DesktopSettingsPrivate::SetControlLook(const char* path)
802{
803	fControlLook = path;
804	return Save(kAppearanceSettings);
805}
806
807
808const BString&
809DesktopSettingsPrivate::ControlLook() const
810{
811	return fControlLook;
812}
813
814
815void
816DesktopSettingsPrivate::_ValidateWorkspacesLayout(int32& columns,
817	int32& rows) const
818{
819	if (columns < 1)
820		columns = 1;
821	if (rows < 1)
822		rows = 1;
823
824	if (columns * rows > kMaxWorkspaces) {
825		// Revert to defaults in case of invalid settings
826		columns = 2;
827		rows = 2;
828	}
829}
830
831
832//	#pragma mark - read access
833
834
835DesktopSettings::DesktopSettings(Desktop* desktop)
836	:
837	fSettings(desktop->fSettings.Get())
838{
839
840}
841
842
843void
844DesktopSettings::GetDefaultPlainFont(ServerFont &font) const
845{
846	font = fSettings->DefaultPlainFont();
847}
848
849
850void
851DesktopSettings::GetDefaultBoldFont(ServerFont &font) const
852{
853	font = fSettings->DefaultBoldFont();
854}
855
856
857void
858DesktopSettings::GetDefaultFixedFont(ServerFont &font) const
859{
860	font = fSettings->DefaultFixedFont();
861}
862
863
864void
865DesktopSettings::GetScrollBarInfo(scroll_bar_info& info) const
866{
867	info = fSettings->ScrollBarInfo();
868}
869
870
871void
872DesktopSettings::GetMenuInfo(menu_info& info) const
873{
874	info = fSettings->MenuInfo();
875}
876
877
878mode_mouse
879DesktopSettings::MouseMode() const
880{
881	return fSettings->MouseMode();
882}
883
884
885mode_focus_follows_mouse
886DesktopSettings::FocusFollowsMouseMode() const
887{
888	return fSettings->FocusFollowsMouseMode();
889}
890
891
892bool
893DesktopSettings::AcceptFirstClick() const
894{
895	return fSettings->AcceptFirstClick();
896}
897
898
899bool
900DesktopSettings::ShowAllDraggers() const
901{
902	return fSettings->ShowAllDraggers();
903}
904
905
906int32
907DesktopSettings::WorkspacesCount() const
908{
909	return fSettings->WorkspacesCount();
910}
911
912
913int32
914DesktopSettings::WorkspacesColumns() const
915{
916	return fSettings->WorkspacesColumns();
917}
918
919
920int32
921DesktopSettings::WorkspacesRows() const
922{
923	return fSettings->WorkspacesRows();
924}
925
926
927const BMessage*
928DesktopSettings::WorkspacesMessage(int32 index) const
929{
930	return fSettings->WorkspacesMessage(index);
931}
932
933
934rgb_color
935DesktopSettings::UIColor(color_which which) const
936{
937	return fSettings->UIColor(which);
938}
939
940
941bool
942DesktopSettings::SubpixelAntialiasing() const
943{
944	return fSettings->SubpixelAntialiasing();
945}
946
947
948uint8
949DesktopSettings::Hinting() const
950{
951	return fSettings->Hinting();
952}
953
954
955uint8
956DesktopSettings::SubpixelAverageWeight() const
957{
958	return fSettings->SubpixelAverageWeight();
959}
960
961
962bool
963DesktopSettings::IsSubpixelOrderingRegular() const
964{
965	// True corresponds to RGB, false means BGR
966	return fSettings->IsSubpixelOrderingRegular();
967}
968
969
970const BString&
971DesktopSettings::ControlLook() const
972{
973	return fSettings->ControlLook();
974}
975
976//	#pragma mark - write access
977
978
979LockedDesktopSettings::LockedDesktopSettings(Desktop* desktop)
980	:
981	DesktopSettings(desktop),
982	fDesktop(desktop)
983{
984#if DEBUG
985	if (desktop->fWindowLock.IsReadLocked())
986		debugger("desktop read locked when trying to change settings");
987#endif
988
989	fDesktop->LockAllWindows();
990}
991
992
993LockedDesktopSettings::~LockedDesktopSettings()
994{
995	fDesktop->UnlockAllWindows();
996}
997
998
999void
1000LockedDesktopSettings::SetDefaultPlainFont(const ServerFont &font)
1001{
1002	fSettings->SetDefaultPlainFont(font);
1003}
1004
1005
1006void
1007LockedDesktopSettings::SetDefaultBoldFont(const ServerFont &font)
1008{
1009	fSettings->SetDefaultBoldFont(font);
1010	fDesktop->BroadcastToAllWindows(AS_SYSTEM_FONT_CHANGED);
1011}
1012
1013
1014void
1015LockedDesktopSettings::SetDefaultFixedFont(const ServerFont &font)
1016{
1017	fSettings->SetDefaultFixedFont(font);
1018}
1019
1020
1021void
1022LockedDesktopSettings::SetScrollBarInfo(const scroll_bar_info& info)
1023{
1024	fSettings->SetScrollBarInfo(info);
1025}
1026
1027
1028void
1029LockedDesktopSettings::SetMenuInfo(const menu_info& info)
1030{
1031	fSettings->SetMenuInfo(info);
1032}
1033
1034
1035void
1036LockedDesktopSettings::SetMouseMode(const mode_mouse mode)
1037{
1038	fSettings->SetMouseMode(mode);
1039}
1040
1041
1042void
1043LockedDesktopSettings::SetFocusFollowsMouseMode(mode_focus_follows_mouse mode)
1044{
1045	fSettings->SetFocusFollowsMouseMode(mode);
1046}
1047
1048
1049void
1050LockedDesktopSettings::SetAcceptFirstClick(const bool acceptFirstClick)
1051{
1052	fSettings->SetAcceptFirstClick(acceptFirstClick);
1053}
1054
1055
1056void
1057LockedDesktopSettings::SetShowAllDraggers(bool show)
1058{
1059	fSettings->SetShowAllDraggers(show);
1060}
1061
1062
1063void
1064LockedDesktopSettings::SetUIColors(const BMessage& colors, bool* changed)
1065{
1066	fSettings->SetUIColors(colors, &changed[0]);
1067}
1068
1069
1070void
1071LockedDesktopSettings::SetSubpixelAntialiasing(bool subpix)
1072{
1073	fSettings->SetSubpixelAntialiasing(subpix);
1074}
1075
1076
1077void
1078LockedDesktopSettings::SetHinting(uint8 hinting)
1079{
1080	fSettings->SetHinting(hinting);
1081}
1082
1083
1084void
1085LockedDesktopSettings::SetSubpixelAverageWeight(uint8 averageWeight)
1086{
1087	fSettings->SetSubpixelAverageWeight(averageWeight);
1088}
1089
1090void
1091LockedDesktopSettings::SetSubpixelOrderingRegular(bool subpixelOrdering)
1092{
1093	fSettings->SetSubpixelOrderingRegular(subpixelOrdering);
1094}
1095
1096
1097status_t
1098LockedDesktopSettings::SetControlLook(const char* path)
1099{
1100	return fSettings->SetControlLook(path);
1101}
1102
1103