1 module gfm.sdl2.mouse; 2 3 import bindbc.sdl; 4 import gfm.sdl2.sdl; 5 import gfm.sdl2.surface; 6 7 /// Holds SDL mouse state. 8 final class SDL2Mouse 9 { 10 public 11 { 12 /// Returns: true if a specific mouse button defined by mask is pressed 13 /// Example: 14 /// -------------------- 15 /// // Check if the left mouse button is pressed 16 /// if(_sdl2.mouse.isButtonPressed(SDL_BUTTON_LMASK)) 17 /// ... 18 /// -------------------- 19 bool isButtonPressed(int mask) pure const nothrow 20 { 21 return (_buttonState & mask) != 0; 22 } 23 24 /// Returns: X coordinate of mouse pointer. 25 int x() pure const nothrow 26 { 27 return _x; 28 } 29 30 /// Returns: Y coordinate of mouse pointer. 31 int y() pure const nothrow 32 { 33 return _y; 34 } 35 36 /// Returns: X relative movement on last motion event. 37 int lastDeltaX() pure const nothrow 38 { 39 return _lastDeltaX; 40 } 41 42 /// Returns: Y relative movement on last motion event. 43 int lastDeltaY() pure const nothrow 44 { 45 return _lastDeltaY; 46 } 47 48 /// Returns: Coordinates of mouse pointer. 49 SDL_Point position() pure const nothrow 50 { 51 return SDL_Point(_x, _y); 52 } 53 54 /// Returns: Previous coordinates of mouse pointer. Useful in onMouseMove event callback. 55 SDL_Point previousPosition() pure const nothrow 56 { 57 return SDL_Point(_x - _lastDeltaX, _y - _lastDeltaY); 58 } 59 60 /// Returns: How much was scrolled by X coordinate since the last call. 61 int wheelDeltaX() nothrow 62 { 63 int value = _wheelX; 64 _wheelX = 0; 65 return value; 66 } 67 68 /// Returns: How much was scrolled by Y coordinate since the last call. 69 int wheelDeltaY() nothrow 70 { 71 int value = _wheelY; 72 _wheelY = 0; 73 return value; 74 } 75 76 static if(sdlSupport >= SDLSupport.sdl204) 77 { 78 /// Use this function to capture the mouse and to track input outside an SDL window. 79 /// See_also: $(LINK https://wiki.libsdl.org/SDL_CaptureMouse) 80 /// Throws: $(D SDL2Exception) on error. 81 void startCapture() 82 { 83 if (SDL_CaptureMouse(SDL_TRUE) != 0) 84 _sdl2.throwSDL2Exception("SDL_CaptureMouse"); 85 } 86 87 /// Use this function to stop capturing the mouse. 88 /// See_also: $(LINK https://wiki.libsdl.org/SDL_CaptureMouse) 89 /// Throws: $(D SDL2Exception) on error. 90 void stopCapture() 91 { 92 if (SDL_CaptureMouse(SDL_FALSE) != 0) 93 _sdl2.throwSDL2Exception("SDL_CaptureMouse"); 94 } 95 } 96 } 97 98 package 99 { 100 this(SDL2 sdl2) 101 { 102 _sdl2 = sdl2; 103 } 104 105 void updateMotion(const(SDL_MouseMotionEvent)* event) 106 { 107 // Get mouse buttons state but ignore mouse coordinates 108 // because we get them from event data 109 _buttonState = SDL_GetMouseState(null, null); 110 _x = event.x; 111 _y = event.y; 112 _lastDeltaX = event.xrel; 113 _lastDeltaY = event.yrel; 114 } 115 116 void updateButtons(const(SDL_MouseButtonEvent)* event) 117 { 118 // get mouse buttons state but ignore mouse coordinates 119 // because we get them from event data 120 _buttonState = SDL_GetMouseState(null, null); 121 _x = event.x; 122 _y = event.y; 123 } 124 125 void updateWheel(const(SDL_MouseWheelEvent)* event) 126 { 127 _buttonState = SDL_GetMouseState(&_x, &_y); 128 _wheelX += event.x; 129 _wheelY += event.y; 130 } 131 } 132 133 private 134 { 135 SDL2 _sdl2; 136 137 // Last button state 138 int _buttonState; 139 140 // Last mouse coordinates 141 int _x = 0, 142 _y = 0; 143 144 // mouse wheel scrolled amounts 145 int _wheelX = 0, 146 _wheelY = 0; 147 148 int _lastDeltaX = 0, 149 _lastDeltaY = 0; 150 } 151 } 152 153 154 /// Mouse cursor, can be created from custom bitmap or from system defaults. 155 final class SDL2Cursor 156 { 157 public 158 { 159 /// Creates a cursor from a SDL surface. 160 /// The surface should outlive this cursor, its ownership will not be taken. 161 /// See_also: $(LINK http://wiki.libsdl.org/SDL_CreateColorCursor) 162 /// Throws: $(D SDL2Exception) on error. 163 this(SDL2 sdl2, SDL2Surface surface, int hotspotX, int hotspotY) 164 { 165 _sdl2 = sdl2; 166 _handle = SDL_CreateColorCursor(surface.handle(), hotspotX, hotspotY); 167 if(_handle is null) 168 _sdl2.throwSDL2Exception("SDL_CreateColorCursor"); 169 _owned = true; 170 } 171 172 /// Creates a system cursor. 173 /// See_also: $(LINK http://wiki.libsdl.org/SDL_CreateSystemCursor) 174 /// Throws: $(D SDL2Exception) on error. 175 this(SDL2 sdl2, SDL_SystemCursor id) 176 { 177 _sdl2 = sdl2; 178 _handle = SDL_CreateSystemCursor(id); 179 if(_handle is null) 180 _sdl2.throwSDL2Exception("SDL_CreateSystemCursor"); 181 _owned = true; 182 } 183 184 /// Returns: Default cursor. 185 /// See_also: $(LINK http://wiki.libsdl.org/SDL_GetDefaultCursor) 186 /// Throws: $(D SDL2Exception) on error. 187 static SDL2Cursor getDefault(SDL2 sdl2) 188 { 189 SDL_Cursor* handle = SDL_GetDefaultCursor(); 190 if(handle is null) 191 sdl2.throwSDL2Exception("SDL_GetDefaultCursor"); 192 193 return new SDL2Cursor(sdl2, handle); 194 195 } 196 197 /// Returns: Current cursor. 198 /// See_also: $(LINK http://wiki.libsdl.org/SDL_GetCursor) 199 /// Throws: $(D SDL2Exception) on error. 200 static SDL2Cursor getCurrent(SDL2 sdl2) 201 { 202 SDL_Cursor* handle = SDL_GetCursor(); 203 if(handle is null) 204 sdl2.throwSDL2Exception("SDL_GetCursor"); 205 206 return new SDL2Cursor(sdl2, handle); 207 } 208 209 ~this() 210 { 211 close(); 212 } 213 214 /// Returns: SDL handle. 215 SDL_Cursor* handle() 216 { 217 return _handle; 218 } 219 220 void close() 221 { 222 if (_owned && _handle !is null) 223 { 224 SDL_FreeCursor(_handle); 225 _handle = null; 226 } 227 } 228 229 void setCurrent() 230 { 231 SDL_SetCursor(_handle); 232 } 233 } 234 235 private 236 { 237 SDL2 _sdl2; 238 SDL_Cursor* _handle; 239 SDL2Surface _surface; 240 bool _owned; 241 242 // Create with specified handle. 243 this(SDL2 sdl2, SDL_Cursor* handle) 244 { 245 _sdl2 = sdl2; 246 _handle = handle; 247 _owned = false; 248 } 249 } 250 }