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