xref: /haiku/src/servers/app/ScreenConfigurations.cpp (revision 9760dcae2038d47442f4658c2575844c6cf92c40)
1 /*
2  * Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
3  * This file may be used under the terms of the MIT License.
4  */
5 
6 
7 #include "ScreenConfigurations.h"
8 
9 #include <new>
10 #include <string.h>
11 
12 #include <Message.h>
13 
14 
15 ScreenConfigurations::ScreenConfigurations()
16 	:
17 	fConfigurations(10, true)
18 {
19 }
20 
21 
22 ScreenConfigurations::~ScreenConfigurations()
23 {
24 }
25 
26 
27 screen_configuration*
28 ScreenConfigurations::CurrentByID(int32 id) const
29 {
30 	for (int32 i = fConfigurations.CountItems(); i-- > 0;) {
31 		screen_configuration* configuration = fConfigurations.ItemAt(i);
32 
33 		if (configuration->id == id && configuration->is_current)
34 			return configuration;
35 	}
36 
37 	return NULL;
38 }
39 
40 
41 screen_configuration*
42 ScreenConfigurations::BestFit(int32 id, const monitor_info* info,
43 	bool* _exactMatch) const
44 {
45 	if (info == NULL) {
46 		// Only look for a matching ID - this is all we have
47 		for (uint32 pass = 0; pass < 2; pass++) {
48 			for (int32 i = fConfigurations.CountItems(); i-- > 0;) {
49 				screen_configuration* configuration = fConfigurations.ItemAt(i);
50 
51 				if ((pass != 0 || !configuration->has_info)
52 					&& id == configuration->id)
53 					return configuration;
54 			}
55 		}
56 
57 		return NULL;
58 	}
59 
60 	// Look for a configuration that matches the monitor
61 
62 	bool exactMatch = false;
63 	int32 bestScore = 0;
64 	int32 bestIndex = -1;
65 	BMessage stored;
66 
67 	for (int32 i = fConfigurations.CountItems(); i-- > 0;) {
68 		screen_configuration* configuration = fConfigurations.ItemAt(i);
69 		if (!configuration->has_info)
70 			continue;
71 
72 		int32 score = 0;
73 
74 		if (!strcasecmp(configuration->info.vendor, info->vendor)
75 			&& !strcasecmp(configuration->info.name, info->name)
76 			&& configuration->info.product_id == info->product_id) {
77 			score += 2;
78 			if (info->serial_number[0] != '\0'
79 				&& !strcmp(configuration->info.serial_number,
80 						info->serial_number)) {
81 				exactMatch = true;
82 				score += 2;
83 			}
84 			if (configuration->info.produced.year == info->produced.year
85 				&& configuration->info.produced.week == info->produced.week)
86 				score++;
87 		}
88 
89 		if (score > bestScore) {
90 			bestScore = score;
91 			bestIndex = i;
92 		}
93 	}
94 
95 	if (bestIndex < 0)
96 		return NULL;
97 
98 	if (_exactMatch != NULL)
99 		*_exactMatch = exactMatch;
100 
101 	return fConfigurations.ItemAt(bestIndex);
102 }
103 
104 
105 status_t
106 ScreenConfigurations::Set(int32 id, const monitor_info* info,
107 	const BRect& frame, const display_mode& mode)
108 {
109 	// Find configuration that we can overwrite
110 
111 	bool exactMatch;
112 	screen_configuration* configuration = BestFit(id, info, &exactMatch);
113 
114 	if (configuration != NULL && configuration->has_info && !exactMatch) {
115 		// only overwrite exact or unspecified configurations
116 		configuration->is_current = false;
117 			// TODO: provide a more obvious current mechanism...
118 		configuration = NULL;
119 	}
120 
121 	if (configuration == NULL) {
122 		// we need a new configuration to store
123 		configuration = new (std::nothrow) screen_configuration;
124 		if (configuration == NULL)
125 			return B_NO_MEMORY;
126 
127 		fConfigurations.AddItem(configuration);
128 	}
129 
130 	configuration->id = id;
131 	configuration->frame = frame;
132 	configuration->is_current = true;
133 
134 	if (info != NULL) {
135 		memcpy(&configuration->info, info, sizeof(monitor_info));
136 		configuration->has_info = true;
137 	} else
138 		configuration->has_info = false;
139 
140 	memcpy(&configuration->mode, &mode, sizeof(display_mode));
141 
142 	return B_OK;
143 }
144 
145 
146 void
147 ScreenConfigurations::Remove(screen_configuration* configuration)
148 {
149 	if (configuration == NULL)
150 		return;
151 
152 	fConfigurations.RemoveItem(configuration);
153 		// this also deletes the configuration
154 }
155 
156 
157 /*!	Stores all configurations as separate BMessages into the provided
158 	\a settings container.
159 */
160 status_t
161 ScreenConfigurations::Store(BMessage& settings) const
162 {
163 	// Store the configuration of all current screens
164 
165 	for (int32 i = 0; i < fConfigurations.CountItems(); i++) {
166 		screen_configuration* configuration = fConfigurations.ItemAt(i);
167 
168 		BMessage screenSettings;
169 		screenSettings.AddInt32("id", configuration->id);
170 
171 		if (configuration->has_info) {
172 			screenSettings.AddString("vendor", configuration->info.vendor);
173 			screenSettings.AddString("name", configuration->info.name);
174 			screenSettings.AddInt32("product id",
175 				configuration->info.product_id);
176 			screenSettings.AddString("serial",
177 				configuration->info.serial_number);
178 			screenSettings.AddInt32("produced week",
179 				configuration->info.produced.week);
180 			screenSettings.AddInt32("produced year",
181 				configuration->info.produced.year);
182 		}
183 
184 		screenSettings.AddRect("frame", configuration->frame);
185 		screenSettings.AddData("mode", B_RAW_TYPE, &configuration->mode,
186 			sizeof(display_mode));
187 
188 		settings.AddMessage("screen", &screenSettings);
189 	}
190 
191 	return B_OK;
192 }
193 
194 
195 status_t
196 ScreenConfigurations::Restore(const BMessage& settings)
197 {
198 	fConfigurations.MakeEmpty();
199 
200 	BMessage stored;
201 	for (int32 i = 0; settings.FindMessage("screen", i, &stored) == B_OK; i++) {
202 		const display_mode* mode;
203 		ssize_t size;
204 		int32 id;
205 		if (stored.FindInt32("id", &id) != B_OK
206 			|| stored.FindData("mode", B_RAW_TYPE, (const void**)&mode,
207 					&size) != B_OK
208 			|| size != sizeof(display_mode))
209 			continue;
210 
211 		screen_configuration* configuration
212 			= new(std::nothrow) screen_configuration;
213 		if (configuration == NULL)
214 			return B_NO_MEMORY;
215 
216 		configuration->id = id;
217 		configuration->is_current = false;
218 
219 		const char* vendor;
220 		const char* name;
221 		uint32 productID;
222 		const char* serial;
223 		int32 week, year;
224 		if (stored.FindString("vendor", &vendor) == B_OK
225 			&& stored.FindString("name", &name) == B_OK
226 			&& stored.FindInt32("product id", (int32*)&productID) == B_OK
227 			&& stored.FindString("serial", &serial) == B_OK
228 			&& stored.FindInt32("produced week", &week) == B_OK
229 			&& stored.FindInt32("produced year", &year) == B_OK) {
230 			// create monitor info
231 			strlcpy(configuration->info.vendor, vendor,
232 				sizeof(configuration->info.vendor));
233 			strlcpy(configuration->info.name, name, sizeof(configuration->info.name));
234 			strlcpy(configuration->info.serial_number, serial,
235 				sizeof(configuration->info.serial_number));
236 			configuration->info.product_id = productID;
237 			configuration->info.produced.week = week;
238 			configuration->info.produced.year = year;
239 			configuration->has_info = true;
240 		} else
241 			configuration->has_info = false;
242 
243 		stored.FindRect("frame", &configuration->frame);
244 		memcpy(&configuration->mode, mode, sizeof(display_mode));
245 
246 		fConfigurations.AddItem(configuration);
247 	}
248 
249 	return B_OK;
250 }
251