Find nouse position out of bounds

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
yellowtide
Prole
Posts: 2
Joined: Thu Jan 25, 2018 2:08 am

Find nouse position out of bounds

Post by yellowtide » Sun May 06, 2018 3:58 pm

I've been drawing a fake cursor that I color key and overlay on OBS to get a custom stream cursor, but I've been having issues grabbing the cursor coordinates while it's out of the window bounds. I know that LOVE doesn't actually support this, though is there a hacky way I could do it?

if this isn't a do-able thing I'll have to switch engines :c

grump
Party member
Posts: 440
Joined: Sat Jul 22, 2017 7:43 pm

Re: Find nouse position out of bounds

Post by grump » Mon May 07, 2018 4:09 am

Use ffi to query the mouse position from the OS.

User avatar
zorg
Party member
Posts: 2425
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Find nouse position out of bounds

Post by zorg » Mon May 07, 2018 5:36 am

To expand on that, SDL2 has a function for that, and iirc i tested it and it works: https://wiki.libsdl.org/SDL_GetGlobalMouseState
(For reference, my use-case was dragging and/or resizing borderless windows without that process stopping when i hit an edge from the inside)
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.

yellowtide
Prole
Posts: 2
Joined: Thu Jan 25, 2018 2:08 am

Re: Find nouse position out of bounds

Post by yellowtide » Mon May 07, 2018 1:49 pm

zorg wrote:
Mon May 07, 2018 5:36 am
To expand on that, SDL2 has a function for that, and iirc i tested it and it works: https://wiki.libsdl.org/SDL_GetGlobalMouseState
(For reference, my use-case was dragging and/or resizing borderless windows without that process stopping when i hit an edge from the inside)
ended up prototyping it using C++/SDL2, going to attempt @grumps' suggestion here in a sec
Thanks for the quick help guys :)

grump
Party member
Posts: 440
Joined: Sat Jul 22, 2017 7:43 pm

Re: Find nouse position out of bounds

Post by grump » Mon May 07, 2018 6:29 pm

yellowtide wrote:
Mon May 07, 2018 1:49 pm
ended up prototyping it using C++/SDL2, going to attempt @grumps' suggestion here in a sec
zorg's suggestion makes more sense, since it will instantly work on all platforms LÖVE runs on.

User avatar
zorg
Party member
Posts: 2425
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Find nouse position out of bounds

Post by zorg » Mon May 07, 2018 6:37 pm

To spare you the implementation horrors, here's my implementation; it may also contain more than what you needed, specifically. Do note that it's somewhat old, so minor cosmetic surgery may be needed to get it working with the latest löve version. :3

Code: Select all

-- desktop coordinate related functions
-- by zorg @ 2015-2016
-- license: ISC

-- This library implements a somewhat robust method of allowing the usage of desktop mouse coordinates in Löve.
-- Main usage would be the implementation of borderless dragging (in windows at least, where it's not possible otherwise)
-- This may not yet be perfect, since window dimensions and position and the inner canvas/frame/viewport dimensions and positioning
-- may be offset differently by different OS-es, so testing needed still. Also doesn't have that much use on android or ios.

-- Use LuaJIT FFI to load in SDL2.
local ffi = require("ffi")
local sdl = ffi.os == "Windows" and ffi.load("SDL2") or ffi.C

-- We need this for borderless dragging, in windows at least; still need to test on nix and osx.
-- Note that for this to work, the user needs to give screen position hints to the application.
ffi.cdef[[
	typedef uint32_t Uint32;

	typedef struct SDL_Rect
	{
    	int x, y;
    	int w, h;
	} SDL_Rect;

	Uint32 SDL_GetGlobalMouseState(int *x, int *y); /*needs SDL 2.0.4 or higher*/
	int SDL_GetNumVideoDisplays(void);
	int SDL_GetDisplayBounds(int displayIndex, SDL_Rect* rect);
]]

-- Function holder table
local t = {}

-- Given a display, and a coordinate inside that display, return a point in desktop-space.
t.toGlobalPosition = function(D,x,y,d) -- Displaylist, horizontal pos., vertical pos., display
	return D[d][1]+x, D[d][2]+y
end

-- Given a point in desktop-space, return display-local coordinates and the display's index.
t.toScreenPosition = function(D,x,y) -- Displaylist, horizontal pos., vertical pos.
	local X,Y,d = 0,0,0
	local minx, miny, maxx, maxy = 1/0,1/0,0,0

	-- Get width and height of the viewport, the area inside the window, because we will need it for the other bounds...
	-- TODO: Which to use...
	local w,h = love.graphics.getDimensions()
	--local w,h,_ = love.window.getMode()

	-- Check boundary conditions per-display.
	-- May not be perfectly sound, logically speaking (for non-convex arrangements)
	for i=1,#D do
		if minx > D[i][1] then minx = D[i][1] end
		if miny > D[i][2] then miny = D[i][2] end
		if maxx < D[i][1]+D[i][3] then maxx = D[i][1]+D[i][3] end
		if maxy < D[i][2]+D[i][4] then maxy = D[i][2]+D[i][4] end
	end

	-- If out of bounds, return false, and the bound we were near to.
	if x <  minx then
		return false, 'x', -1
	end
	if x+w > maxx then
		return false, 'x',  1
	end
	if y <  miny then
		return false, 'y', -1
	end
	if y+h > maxy then
		return false, 'y',  1
	end

	-- Check which display we're actually in, and return the coordinates as such.
	for i=1,#D do
		if x >= D[i][1] and x < D[i][1]+D[i][3] and y >= D[i][2] and y < D[i][2]+D[i][4] then
			return x-D[i][1], y-D[i][2], i
		end
	end

	-- Point doesn't exist on any screen; should not be possible to set to this anyway.
	return false, '0', 0
end

-- Return the mouse position on the desktop.
t.getGlobalMousePosition = function()
	local x, y = ffi.new("int[1]", 0), ffi.new("int[1]", 0)
	local err = sdl.SDL_GetGlobalMouseState(x,y)
	if err ~= 1 then return false end -- Not on the desktop.
	return x[0], y[0]
end

-- Metatable for the above functions.
local mt = {__index = t}

-- Constructor; we could have just went with an init function and made the module stateful, but this works just as well.
local new = function()

	-- The array of displays (xOffset, yOffset,width,height)
	local D = {}

	-- How many displays the computer has.
	local n = sdl.SDL_GetNumVideoDisplays()

	-- Get the position and size data from all displays.
	for i = 1, n do
		local rect = ffi.new("SDL_Rect[1]")

		sdl.SDL_GetDisplayBounds(i-1, rect)

		D[i]    = {}
		D[i][1] = rect[0].x
		D[i][2] = rect[0].y
		D[i][3] = rect[0].w
		D[i][4] = rect[0].h
	end

	-- Allows to use the above 3 functions with the D displaylist. (with the colon (:) syntax)
	return setmetatable(D, mt}

end

return new
(And yes, i'll release this thing, all fixed up, on github normally when i have time, as well)
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.

User avatar
ac3raven
Prole
Posts: 42
Joined: Tue May 19, 2009 1:14 am

Re: Find nouse position out of bounds

Post by ac3raven » Sat Jul 07, 2018 7:48 pm

This is a great little library and It'd be great if you could provide a small tutorial on how to use it. At least for me, it's not self-evident. Thanks!

User avatar
zorg
Party member
Posts: 2425
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Find nouse position out of bounds

Post by zorg » Sun Jul 08, 2018 4:28 pm

firstly, you require it into your own project like so: local whatever = require 'libname'
then calling it like local displays = whatever() will return a table containing all detected displays coordinates and dimensions (and it also has methods you can use)
A simpler way would be to just do local displays = require('libname')()


Now you can use the table and the given functions to transform coordinates between desktop (global) corodinates and display-local ones. (and also a function to get the global coordinates of the mouse pointer, which is also useful)
What you do with these though is up to you; my use case was dragging borderless windows on windows. (although maybe the relative mouse mode would have also worked, i haven't tested that :v)
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.

Post Reply

Who is online

Users browsing this forum: No registered users and 3 guests