Skip to content

Commit 26831d6

Browse files
committed
Merge branch 'huge-cursor'
2 parents dd95ee8 + fbf580a commit 26831d6

File tree

4 files changed

+146
-11
lines changed

4 files changed

+146
-11
lines changed

Corona/main.lua

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,21 @@ local cursor = require('plugin.hwcursor')
44
local hidden = false
55
cursor.initPlugin()
66

7+
-- New in this version
8+
9+
-- Call cursor.loadCursor the first time with the path to the cursor
10+
-- and store the return value, which is a pointer to the cursor resource (preload step)
11+
12+
-- Call cursor.loadCursor the second time with the previously returned pointer
13+
-- to actually set the cursor (usage step)
14+
15+
-- Cursors must be preloaded before being used
16+
local cursors = {
17+
cursor1 = cursor.loadCursor(system.pathForFile('cursor1.cur')), -- Bigger than normal
18+
cursor2 = cursor.loadCursor(system.pathForFile('cursor2.ani')), -- Regular size
19+
cursor3 = cursor.loadCursor(system.pathForFile('cursor3.ani')) -- Huge (256x256)
20+
}
21+
722
display.newText(
823
{
924
x = display.contentCenterX,
@@ -37,7 +52,8 @@ widget.newButton(
3752
x = display.contentCenterX,
3853
y = display.contentCenterY - 50,
3954
label = 'Custom cursor 1',
40-
onRelease = function() cursor.loadCursor(system.pathForFile('cursor1.cur')) end,
55+
-- Set cursor using stored pointer
56+
onRelease = function() cursor.loadCursor(cursors.cursor1) end,
4157
labelColor = { default = { 1, 1, 1 }, over = { 0, 0, 0, 0.5 } },
4258
fillColor = { default = { 1, 0.2, 0.5, 0.7 }, over = { 1, 0.2, 0.5, 1 } }
4359
}
@@ -51,7 +67,8 @@ widget.newButton(
5167
x = display.contentCenterX,
5268
y = display.contentCenterY,
5369
label = 'Custom cursor 2',
54-
onRelease = function() cursor.loadCursor(system.pathForFile('cursor2.ani')) end,
70+
-- Set cursor using stored pointer
71+
onRelease = function() cursor.loadCursor(cursors.cursor2) end,
5572
labelColor = { default = { 1, 1, 1 }, over = { 0, 0, 0, 0.5 } },
5673
fillColor = { default = { 1, 0.2, 0.5, 0.7 }, over = { 1, 0.2, 0.5, 1 } }
5774
}
@@ -65,7 +82,8 @@ widget.newButton(
6582
x = display.contentCenterX,
6683
y = display.contentCenterY + 50,
6784
label = 'Custom cursor 3',
68-
onRelease = function() cursor.loadCursor(system.pathForFile('cursor3.ani')) end,
85+
-- Set cursor using stored pointer
86+
onRelease = function() cursor.loadCursor(cursors.cursor3) end,
6987
labelColor = { default = { 1, 1, 1 }, over = { 0, 0, 0, 0.5 } },
7088
fillColor = { default = { 1, 0.2, 0.5, 0.7 }, over = { 1, 0.2, 0.5, 1 } }
7189
}
@@ -101,7 +119,11 @@ widget.newButton(
101119
y = display.contentCenterY + 150,
102120
label = 'Exit application',
103121
onRelease = function()
104-
cursor.resetCursor()
122+
-- Destroy all cursors before exiting
123+
for k, v in pairs(cursors) do
124+
cursor.destroyCursor(v)
125+
cursors[k] = nil
126+
end
105127
cursor.freePlugin()
106128
native.requestExit()
107129
end,
@@ -110,6 +132,59 @@ widget.newButton(
110132
}
111133
)
112134

135+
--[[
136+
widget.newButton(
137+
{
138+
width = 200,
139+
height = 30,
140+
shape = 'roundedRect',
141+
x = display.contentCenterX,
142+
y = display.contentCenterY + 200,
143+
label = 'Destroy cursor 1',
144+
onRelease = function()
145+
cursor.destroyCursor(cursors.cursor1)
146+
cursors.cursor1 = nil
147+
end,
148+
labelColor = { default = { 1, 1, 1 }, over = { 0, 0, 0, 0.5 } },
149+
fillColor = { default = { 1, 0.2, 0.5, 0.7 }, over = { 1, 0.2, 0.5, 1 } }
150+
}
151+
)
152+
153+
widget.newButton(
154+
{
155+
width = 200,
156+
height = 30,
157+
shape = 'roundedRect',
158+
x = display.contentCenterX,
159+
y = display.contentCenterY + 250,
160+
label = 'Destroy cursor 2',
161+
onRelease = function()
162+
cursor.destroyCursor(cursors.cursor2)
163+
cursors.cursor2 = nil
164+
end,
165+
labelColor = { default = { 1, 1, 1 }, over = { 0, 0, 0, 0.5 } },
166+
fillColor = { default = { 1, 0.2, 0.5, 0.7 }, over = { 1, 0.2, 0.5, 1 } }
167+
}
168+
)
169+
170+
widget.newButton(
171+
{
172+
width = 200,
173+
height = 30,
174+
shape = 'roundedRect',
175+
x = display.contentCenterX,
176+
y = display.contentCenterY + 300,
177+
label = 'Destroy cursor 3',
178+
onRelease = function()
179+
cursor.destroyCursor(cursors.cursor3)
180+
cursors.cursor3 = nil
181+
end,
182+
labelColor = { default = { 1, 1, 1 }, over = { 0, 0, 0, 0.5 } },
183+
fillColor = { default = { 1, 0.2, 0.5, 0.7 }, over = { 1, 0.2, 0.5, 1 } }
184+
}
185+
)
186+
]]--
187+
113188
Runtime:addEventListener('key',
114189
function(event)
115190
if event.phase == 'up' then

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Refer to example project in ```Corona/``` directory
1212
- ```showCursor``` - shows the cursor if it was hidden
1313
- ```hideCursor``` - hides the cursor if it was visible
1414
- ```resetCursor``` - resets the cursor to the default arrow cursor
15+
- ```destroyCursor``` - destroys a cursor handle and frees its memory
1516
- ```loadWinCursor``` - loads the specified windows-provided cursor
1617

1718
# Valid arguments to loadWinCursor()
@@ -37,4 +38,5 @@ Refer to example project in ```Corona/``` directory
3738

3839
# Caveats
3940
- Only supports windows for now
41+
- Destroy preloaded cursors before exiting the application programmatically. Call ```plugin.destroyCursor(cursor)```.
4042
- You must call ```plugin.freePlugin()``` while exiting the application programmatically. An example of how this should be done is provided.

shared/PluginHwCursor.cpp

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ int luaopen_plugin_hwcursor(lua_State *L) {
2929
{"showCursor", showCursor},
3030
{"hideCursor", hideCursor},
3131
{"resetCursor", resetCursor},
32+
{"destroyCursor", destroyCursor},
3233
{"loadWinCursor", loadWinCursor},
3334
{"regExitCallback", regExitCallback},
3435
{NULL, NULL}
@@ -63,12 +64,12 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
6364
if(exitCallback != 0) {
6465
lua_rawgeti(state, LUA_REGISTRYINDEX, exitCallback);
6566
if(lua_pcall(state, 0, 0, 0) != 0) {
66-
CoronaLuaLog(state, "[hwcursor] the error below occurred while calling the callback function");
67-
CoronaLuaLog(state, lua_tostring(state, -1));
67+
CoronaLuaError(state, "[hwcursor] The error below occurred while calling the callback function");
68+
CoronaLuaError(state, lua_tostring(state, -1));
6869
}
6970
}
7071
else {
71-
CoronaLuaLog(state, "[hwcursor] no exit callback was found");
72+
CoronaLuaError(state, "[hwcursor] No exit callback was found");
7273
}
7374

7475
return false;
@@ -96,11 +97,22 @@ static int freePlugin(lua_State *L) {
9697

9798
// ----------------------------------------------------------------------------
9899

100+
// Requires 2 calls to actually set the cursor
101+
// 1st is to preload and second to actually set the cursor using pointer to preloaded resource
99102
static int loadCursor(lua_State *L) {
100-
std::string cursorLoc = lua_tostring(L, 1);
101-
currentCursor = LoadCursorFromFile(s2ws(cursorLoc).c_str());
102-
SetCursor(currentCursor);
103-
return 0;
103+
if(lua_islightuserdata(L, 1)) {
104+
currentCursor = (HCURSOR)lua_touserdata(L, 1);
105+
SetCursor(currentCursor);
106+
return 0;
107+
}
108+
else {
109+
std::string cursorLoc = lua_tostring(L, 1);
110+
// Allows for actual cursor size to be used with no constraints, i.e: even 256x256 size cursors will display at this
111+
// size with no downsizing being performed as happens with LoadCursorFromFile
112+
HCURSOR cursor = (HCURSOR)LoadImage(NULL, s2ws(cursorLoc).c_str(), IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
113+
lua_pushlightuserdata(L, cursor);
114+
return 1;
115+
}
104116
}
105117

106118
// ----------------------------------------------------------------------------
@@ -127,6 +139,25 @@ static int hideCursor(lua_State *L) {
127139

128140
static int resetCursor(lua_State *L) {
129141
currentCursor = NULL;
142+
SetCursor(currentCursor);
143+
return 0;
144+
}
145+
146+
// ----------------------------------------------------------------------------
147+
148+
static int destroyCursor(lua_State *L) {
149+
HCURSOR cursor = (HCURSOR)lua_touserdata(L, 1);
150+
if(cursor == currentCursor) {
151+
currentCursor = NULL;
152+
SetCursor(currentCursor);
153+
}
154+
DestroyCursor(cursor);
155+
/*
156+
if(!DestroyCursor(cursor)) {
157+
CoronaLuaError(L, "[hwcursor] The error below occurred while destroying the cursor");
158+
CoronaLuaError(L, GetLastErrorAsString().c_str());
159+
}
160+
*/
130161
return 0;
131162
}
132163

shared/PluginHwCursor.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ static int loadCursor(lua_State *L);
3131
static int showCursor(lua_State *L);
3232
static int hideCursor(lua_State *L);
3333
static int resetCursor(lua_State *L);
34+
static int destroyCursor(lua_State *L);
3435
static int loadWinCursor(lua_State *L);
3536
static int regExitCallback(lua_State *L);
3637

@@ -45,3 +46,29 @@ std::wstring s2ws(const std::string &s) {
4546
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, const_cast<wchar_t*>(buf.c_str()), len);
4647
return buf;
4748
}
49+
50+
// ----------------------------------------------------------------------------
51+
// https://stackoverflow.com/a/17387176
52+
/*
53+
std::string GetLastErrorAsString() {
54+
//Get the error message ID, if any.
55+
DWORD errorMessageID = GetLastError();
56+
if(errorMessageID == 0) {
57+
return std::string(); //No error message has been recorded
58+
}
59+
60+
LPSTR messageBuffer = nullptr;
61+
62+
//Ask Win32 to give us the string version of that message ID.
63+
//The parameters we pass in, tell Win32 to create the buffer that holds the message for us (because we don't yet know how long the message string will be).
64+
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
65+
66+
//Copy the error message into a std::string.
67+
std::string message(messageBuffer, size);
68+
69+
//Free the Win32's string's buffer.
70+
LocalFree(messageBuffer);
71+
72+
return message;
73+
}
74+
*/

0 commit comments

Comments
 (0)