/usr/share/psychtoolbox-3/PsychBasic/RemapMouse.m is in psychtoolbox-3-common 3.0.11.20131230.dfsg1-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | function [xo, yo] = RemapMouse(win, viewId, xm, ym)
% [xo, yo] = RemapMouse(win, viewId, xm, ym); -- Map mouse position to stimulus position.
%
% Certain operations, e.g., PsychImaging('AddTask', ..., 'GeometryCorrection', ...);
% to perform geometric display correction, will break the 1:1
% correspondence between stimulus pixel locations (xo,yo) and the mouse
% cursor position, ie. a mouse cursor positioned at display position
% (xm,ym) will be no longer pointing to stimulus pixel (xm,ym). If you
% want to know which pixel in your original stimulus image corresponds to
% a specific physical display pixel (or mouse cursor position), use this
% function to perform the neccessary coordinate transformation.
%
% 'win' is the window handle of the onscreen window to remap.
%
% 'viewId' is the view id to remap, the same name you specified in
% PsychImaging() to setup a geometry correction, e.g., 'AllViews'.
%
% (xm,ym) is the 2D position in display device space, e.g., as returned
% from GetMouse() for a mouse cursor position query. Please make sure
% that you pass in the 'win'dow handle to GetMouse as well, ie.
% GetMouse(win), so GetMouse() can correct its returned mouse position
% for your specific display arrangement and onscreen window placement.
% This function only corrects for distortions inside the onscreen window
% 'win', ie. relative to its origin.
%
% The returned values (xo, yo) are the remapped stimulus pixel locations,
% over which a mouse cursor at location (xm,ym) is currently hovering.
%
% If you pass in a (xm,ym) position for which there doesn't exist any
% corresponding stimulus pixel position, the values (0,0) will be
% returned.
%
% If you call this function on a window or view without active geometry
% manipulations, it will do nothing and simply return the passed in (xm,
% ym) position, ie. it is safe to use this function all the time.
%
% Limitations: The function currently only corrects for distortions
% introduced by the tasks implemented in the Psychtoolbox image
% processing pipeline via some of the functions available via
% PsychImaging() function. It does not take other transformations into
% account, e.g., mirroring, arranging displays of a multi-display setup
% in an unusual way etc. You may need to add your own code to take such
% transformations into account.
%
% History:
% 26.12.2011 mk Written.
% 12.01.2013 mk Added panelfitter support.
% This global array is setup by PsychImaging() when setting up geometric
% display correction:
global ptb_geometry_inverseWarpMap;
if nargin < 4
error('At least one of the required parameters is missing!');
end
if ~isnumeric(win) || ~isscalar(win) || (Screen('WindowKind', win) ~= 1)
error('Window handle invalid. Does not correspond to an onscreen window!');
end
if ~ischar(viewId)
error('viewId parameter is not a name string, as required!');
end
if isempty(ptb_geometry_inverseWarpMap) || isempty(ptb_geometry_inverseWarpMap{win})
% Window does not use geometry correction. Just pass-through our input values:
xo = xm;
yo = ym;
else
% Apply gains and modulo transform to input (xm,ym):
xm = mod(xm * ptb_geometry_inverseWarpMap{win}.gx, ptb_geometry_inverseWarpMap{win}.mx);
ym = mod(ym * ptb_geometry_inverseWarpMap{win}.gy, ptb_geometry_inverseWarpMap{win}.my);
if ~isfield(ptb_geometry_inverseWarpMap{win}, viewId)
% No inverse map, we're almost done:
xo = xm;
yo = ym;
else
% Retrieve proper inverse mapping matrix for given viewId:
map = ptb_geometry_inverseWarpMap{win}.(viewId);
% Round and map (xm,ym) input mouse position to indices in inverse map:
xm = min(max(round(xm) + 1, 1), size(map, 2));
ym = min(max(round(ym) + 1, 1), size(map, 1));
% Lookup corresponding unmapped position from matrix:
xo = double(map(ym, xm, 1));
yo = double(map(ym, xm, 2));
end
end
% At this point (xo, yo) contain mouse position relative to the imaging
% pipelines image buffer for the requested viewId. If remapping wrt. some
% internal buffer or final buffer was requested, we're done. For the most
% common case of remapping to the stimulus input buffer, we need one more
% step:
if strcmpi(viewId, 'AllViews') || strcmpi(viewId, 'LeftView') || strcmpi(viewId, 'RightView')
% Want mouse position mapped to original stimulus image. The current
% (xo, yo) contains mouse position wrt. inputBufferFBO for viewId. If
% our gpu panel scaler is active then we need to undo the rescaling
% done by the scaler to get the position in the drawBufferFBO which
% corresponds to our effective stimulus position. Query panel fitter
% parameters into p:
p = Screen('PanelFitter', win);
% Panelfitter active aka p non-zero?
if any(p)
% Remap:
xo = ((xo - p(5)) / (p(7) - p(5)) * (p(3) - p(1))) + p(1);
yo = ((yo - p(6)) / (p(8) - p(6)) * (p(4) - p(2))) + p(2);
end
end
return;
|