1/**
2 * Copyright (c) 2006-2023 LOVE Development Team
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty. In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 *
8 * Permission is granted to anyone to use this software for any purpose,
9 * including commercial applications, and to alter it and redistribute it
10 * freely, subject to the following restrictions:
11 *
12 * 1. The origin of this software must not be misrepresented; you must not
13 * claim that you wrote the original software. If you use this software
14 * in a product, an acknowledgment in the product documentation would be
15 * appreciated but is not required.
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 * 3. This notice may not be removed or altered from any source distribution.
19 **/
20
21// LOVE
22#include "wrap_Mouse.h"
23#include "wrap_Cursor.h"
24#include "common/config.h"
25
26#include "sdl/Mouse.h"
27#include "filesystem/File.h"
28
29namespace love
30{
31namespace mouse
32{
33
34#define instance() (Module::getInstance<Mouse>(Module::M_MOUSE))
35
36int w_newCursor(lua_State *L)
37{
38 Cursor *cursor = nullptr;
39
40 if (lua_isstring(L, 1) || luax_istype(L, 1, love::filesystem::File::type) || luax_istype(L, 1, love::filesystem::FileData::type))
41 luax_convobj(L, 1, "image", "newImageData");
42
43 love::image::ImageData *data = luax_checktype<love::image::ImageData>(L, 1);
44 int hotx = (int) luaL_optinteger(L, 2, 0);
45 int hoty = (int) luaL_optinteger(L, 3, 0);
46
47 luax_catchexcept(L, [&](){ cursor = instance()->newCursor(data, hotx, hoty); });
48
49 luax_pushtype(L, cursor);
50 cursor->release();
51 return 1;
52}
53
54int w_getSystemCursor(lua_State *L)
55{
56 const char *str = luaL_checkstring(L, 1);
57 Cursor::SystemCursor systemCursor;
58
59 if (!Cursor::getConstant(str, systemCursor))
60 return luax_enumerror(L, "system cursor type", str);
61
62 Cursor *cursor = 0;
63 luax_catchexcept(L, [&](){ cursor = instance()->getSystemCursor(systemCursor); });
64
65 luax_pushtype(L, cursor);
66 return 1;
67}
68
69int w_setCursor(lua_State *L)
70{
71 // Revert to the default system cursor if no argument is given.
72 if (lua_isnoneornil(L, 1))
73 {
74 instance()->setCursor();
75 return 0;
76 }
77
78 Cursor *cursor = luax_checkcursor(L, 1);
79 instance()->setCursor(cursor);
80 return 0;
81}
82
83int w_getCursor(lua_State *L)
84{
85 Cursor *cursor = instance()->getCursor();
86
87 if (cursor)
88 luax_pushtype(L, cursor);
89 else
90 lua_pushnil(L);
91
92 return 1;
93}
94
95int w_isCursorSupported(lua_State *L)
96{
97 luax_pushboolean(L, instance()->isCursorSupported());
98 return 1;
99}
100
101int w_getX(lua_State *L)
102{
103 lua_pushnumber(L, instance()->getX());
104 return 1;
105}
106
107int w_getY(lua_State *L)
108{
109 lua_pushnumber(L, instance()->getY());
110 return 1;
111}
112
113int w_getPosition(lua_State *L)
114{
115 double x, y;
116 instance()->getPosition(x, y);
117 lua_pushnumber(L, x);
118 lua_pushnumber(L, y);
119 return 2;
120}
121
122int w_setX(lua_State *L)
123{
124 double x = luaL_checknumber(L, 1);
125 instance()->setX(x);
126 return 0;
127}
128
129int w_setY(lua_State *L)
130{
131 double y = luaL_checknumber(L, 1);
132 instance()->setY(y);
133 return 0;
134}
135
136int w_setPosition(lua_State *L)
137{
138 double x = luaL_checknumber(L, 1);
139 double y = luaL_checknumber(L, 2);
140 instance()->setPosition(x, y);
141 return 0;
142}
143
144int w_isDown(lua_State *L)
145{
146 bool istable = lua_istable(L, 1);
147 int num = istable ? (int) luax_objlen(L, 1) : lua_gettop(L);
148
149 std::vector<int> buttons;
150 buttons.reserve(num);
151
152 if (istable)
153 {
154 for (int i = 0; i < num; i++)
155 {
156 lua_rawgeti(L, 1, i + 1);
157 buttons.push_back((int) luaL_checkinteger(L, -1));
158 lua_pop(L, 1);
159 }
160 }
161 else
162 {
163 for (int i = 0; i < num; i++)
164 buttons.push_back((int) luaL_checkinteger(L, i + 1));
165 }
166
167 luax_pushboolean(L, instance()->isDown(buttons));
168 return 1;
169}
170
171int w_setVisible(lua_State *L)
172{
173 bool b = luax_checkboolean(L, 1);
174 instance()->setVisible(b);
175 return 0;
176}
177
178int w_isVisible(lua_State *L)
179{
180 luax_pushboolean(L, instance()->isVisible());
181 return 1;
182}
183
184int w_setGrabbed(lua_State *L)
185{
186 bool b = luax_checkboolean(L, 1);
187 instance()->setGrabbed(b);
188 return 0;
189}
190
191int w_isGrabbed(lua_State *L)
192{
193 luax_pushboolean(L, instance()->isGrabbed());
194 return 1;
195}
196
197int w_setRelativeMode(lua_State *L)
198{
199 bool relative = luax_checkboolean(L, 1);
200 luax_pushboolean(L, instance()->setRelativeMode(relative));
201 return 1;
202}
203
204int w_getRelativeMode(lua_State *L)
205{
206 luax_pushboolean(L, instance()->getRelativeMode());
207 return 1;
208}
209
210// List of functions to wrap.
211static const luaL_Reg functions[] =
212{
213 { "newCursor", w_newCursor },
214 { "getSystemCursor", w_getSystemCursor },
215 { "setCursor", w_setCursor },
216 { "getCursor", w_getCursor },
217 { "isCursorSupported", w_isCursorSupported },
218 { "getX", w_getX },
219 { "getY", w_getY },
220 { "setX", w_setX },
221 { "setY", w_setY },
222 { "setPosition", w_setPosition },
223 { "isDown", w_isDown },
224 { "setVisible", w_setVisible },
225 { "isVisible", w_isVisible },
226 { "getPosition", w_getPosition },
227 { "setGrabbed", w_setGrabbed },
228 { "isGrabbed", w_isGrabbed },
229 { "setRelativeMode", w_setRelativeMode },
230 { "getRelativeMode", w_getRelativeMode },
231 { 0, 0 }
232};
233
234// Types for this module.
235static const lua_CFunction types[] =
236{
237 luaopen_cursor,
238 0,
239};
240
241extern "C" int luaopen_love_mouse(lua_State *L)
242{
243 Mouse *instance = instance();
244 if (instance == nullptr)
245 {
246 luax_catchexcept(L, [&](){ instance = new love::mouse::sdl::Mouse(); });
247 }
248 else
249 instance->retain();
250
251 WrappedModule w;
252 w.module = instance;
253 w.name = "mouse";
254 w.type = &Module::type;
255 w.functions = functions;
256 w.types = types;
257
258 return luax_register_module(L, w);
259}
260
261} // mouse
262} // love
263