1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef GRAPHICS_CURSORMAN_H
24 #define GRAPHICS_CURSORMAN_H
25 
26 #include "common/scummsys.h"
27 #include "common/stack.h"
28 #include "common/singleton.h"
29 #include "graphics/cursor.h"
30 #include "graphics/pixelformat.h"
31 
32 namespace Graphics {
33 
34 class CursorManager : public Common::Singleton<CursorManager> {
35 public:
36 	/** Query whether the mouse cursor is visible. */
37 	bool isVisible();
38 
39 	/**
40 	 * Show or hide the mouse cursor.
41 	 *
42 	 * This function does not call OSystem::updateScreen, when visible is true.
43 	 * This fact might result in a non visible mouse cursor if the caller does
44 	 * not call OSystem::updateScreen itself after a showMouse(true) call.
45 	 *
46 	 * TODO: We might want to reconsider this behavior, it might be confusing
47 	 * for the user to call OSystem::updateScreen separately, on the other
48 	 * hand OSystem::updateScreen might as well display unwanted changes on
49 	 * the screen. Another alternative would be to let the backend worry
50 	 * about this on OSystem::showMouse call.
51 	 *
52 	 * @see OSystem::showMouse.
53 	 */
54 	bool showMouse(bool visible);
55 
56 	/**
57 	 * Push a new cursor onto the stack, and set it in the backend. A local
58 	 * copy will be made of the cursor data, so the original buffer can be
59 	 * safely freed afterwards.
60 	 *
61 	 * @param buf		the new cursor data
62 	 * @param w			the width
63 	 * @param h			the height
64 	 * @param hotspotX	the hotspot X coordinate
65 	 * @param hotspotY	the hotspot Y coordinate
66 	 * @param keycolor	the color value for the transparent color. This may not exceed
67 	 *                  the maximum color value as defined by format.
68 	 * @param dontScale	Whether the cursor should never be scaled. An exception are high ppi displays, where the cursor
69 	 *                  would be too small to notice otherwise, these are allowed to scale the cursor anyway.
70 	 * @param format	a pointer to the pixel format which the cursor graphic uses,
71 	 *					CLUT8 will be used if this is NULL or not specified.
72 	 * @note It is ok for the buffer to be a NULL pointer. It is sometimes
73 	 *       useful to push a "dummy" cursor and modify it later. The
74 	 *       cursor will be added to the stack, but not to the backend.
75 	 */
76 	void pushCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL);
77 
78 	/**
79 	 * Pop a cursor from the stack, and restore the previous one to the
80 	 * backend. If there is no previous cursor, the cursor is hidden.
81 	 */
82 	void popCursor();
83 
84 	/**
85 	 * Replace the current cursor on the stack. If the stack is empty, the
86 	 * cursor is pushed instead. It's a slightly more optimized way of
87 	 * popping the old cursor before pushing the new one.
88 	 *
89 	 * @param buf		the new cursor data
90 	 * @param w		the width
91 	 * @param h		the height
92 	 * @param hotspotX	the hotspot X coordinate
93 	 * @param hotspotY	the hotspot Y coordinate
94 	 * @param keycolor	the color value for the transparent color. This may not exceed
95 	 *                  the maximum color value as defined by format.
96 	 * @param dontScale	Whether the cursor should never be scaled. An exception are high ppi displays, where the cursor
97 	 *                  would be too small to notice otherwise, these are allowed to scale the cursor anyway.
98 	 * @param format	a pointer to the pixel format which the cursor graphic uses,
99 	 *					CLUT8 will be used if this is NULL or not specified.
100 	 */
101 	void replaceCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL);
102 
103 	/**
104 	 * Replace the current cursor on the stack. If the stack is empty, the
105 	 * cursor is pushed instead. It's a slightly more optimized way of
106 	 * popping the old cursor before pushing the new one.
107 	 *
108 	 * @param cursor	the new cursor
109 	 */
110 	void replaceCursor(const Graphics::Cursor *cursor);
111 
112 	/**
113 	 * Pop all of the cursors and cursor palettes from their respective stacks.
114 	 * The purpose is to ensure that all unecessary cursors are removed from the
115 	 * stack when returning to the launcher from an engine.
116 	 *
117 	 */
118 	void popAllCursors();
119 
120 	/**
121 	 * Test whether cursor palettes are supported.
122 	 *
123 	 * This is just an convenience wrapper for checking for
124 	 * OSystem::kFeatureCursorPalette to be supported by OSystem.
125 	 *
126 	 * @see OSystem::kFeatureCursorPalette
127 	 * @see OSystem::hasFeature
128 	 */
129 	bool supportsCursorPalettes();
130 
131 	/**
132 	 * Enable/Disable the current cursor palette.
133 	 *
134 	 * @param disable
135 	 */
136 	void disableCursorPalette(bool disable);
137 
138 	/**
139 	 * Push a new cursor palette onto the stack, and set it in the backend.
140 	 * The palette entries from 'start' till (start+num-1) will be replaced
141 	 * so a full palette updated is accomplished via start=0, num=256.
142 	 *
143 	 * The palette data is specified in the same interleaved RGB format as
144 	 * used by all backends.
145 	 *
146 	 * @param colors	the new palette data, in interleaved RGB format
147 	 * @param start		the first palette entry to be updated
148 	 * @param num		the number of palette entries to be updated
149 	 *
150 	 * @note If num is zero, the cursor palette is disabled.
151 	 */
152 	void pushCursorPalette(const byte *colors, uint start, uint num);
153 
154 	/**
155 	 * Pop a cursor palette from the stack, and restore the previous one to
156 	 * the backend. If there is no previous palette, the cursor palette is
157 	 * disabled instead.
158 	 */
159 	void popCursorPalette();
160 
161 	/**
162 	 * Replace the current cursor palette on the stack. If the stack is
163 	 * empty, the palette is pushed instead. It's a slightly more optimized
164 	 * way of popping the old palette before pushing the new one.
165 	 *
166 	 * @param colors	the new palette data, in interleaved RGB format
167 	 * @param start		the first palette entry to be updated
168 	 * @param num		the number of palette entries to be updated
169 	 *
170 	 * @note If num is zero, the cursor palette is disabled.
171 	 */
172 	void replaceCursorPalette(const byte *colors, uint start, uint num);
173 
174 	void lock(bool locked);
175 private:
176 	friend class Common::Singleton<SingletonBaseType>;
177 	// Even though this is basically the default constructor we implement it
178 	// ourselves, so it is private and thus there is no way to create this class
179 	// except from the Singleton code.
CursorManager()180 	CursorManager() {
181 		_locked = false;
182 	}
183 	~CursorManager();
184 
185 	struct Cursor {
186 		byte *_data;
187 		bool _visible;
188 		uint _width;
189 		uint _height;
190 		int _hotspotX;
191 		int _hotspotY;
192 		uint32 _keycolor;
193 		Graphics::PixelFormat _format;
194 		bool _dontScale;
195 
196 		uint _size;
197 
198 		Cursor(const void *data, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL);
199 		~Cursor();
200 	};
201 
202 	struct Palette {
203 		byte *_data;
204 		uint _start;
205 		uint _num;
206 		uint _size;
207 
208 		bool _disabled;
209 
210 		Palette(const byte *colors, uint start, uint num);
211 		~Palette();
212 	};
213 	Common::Stack<Cursor *> _cursorStack;
214 	Common::Stack<Palette *> _cursorPaletteStack;
215 	bool _locked;
216 };
217 
218 } // End of namespace Graphics
219 
220 #define CursorMan	(::Graphics::CursorManager::instance())
221 
222 #endif
223