1 module gfm.sdl2.mouse; 2 3 import derelict.sdl2.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 /// Use this function to capture the mouse and to track input outside an SDL window. 77 /// See_also: $(LINK https://wiki.libsdl.org/SDL_CaptureMouse) 78 /// Throws: $(D SDL2Exception) on error. 79 void startCapture() 80 { 81 if (SDL_CaptureMouse(SDL_TRUE) != 0) 82 _sdl2.throwSDL2Exception("SDL_CaptureMouse"); 83 } 84 85 /// Use this function to stop capturing the mouse. 86 /// See_also: $(LINK https://wiki.libsdl.org/SDL_CaptureMouse) 87 /// Throws: $(D SDL2Exception) on error. 88 void stopCapture() 89 { 90 if (SDL_CaptureMouse(SDL_FALSE) != 0) 91 _sdl2.throwSDL2Exception("SDL_CaptureMouse"); 92 } 93 } 94 95 package 96 { 97 this(SDL2 sdl2) 98 { 99 _sdl2 = sdl2; 100 } 101 102 void updateMotion(const(SDL_MouseMotionEvent)* event) 103 { 104 // Get mouse buttons state but ignore mouse coordinates 105 // because we get them from event data 106 _buttonState = SDL_GetMouseState(null, null); 107 _x = event.x; 108 _y = event.y; 109 _lastDeltaX = event.xrel; 110 _lastDeltaY = event.yrel; 111 } 112 113 void updateButtons(const(SDL_MouseButtonEvent)* event) 114 { 115 // get mouse buttons state but ignore mouse coordinates 116 // because we get them from event data 117 _buttonState = SDL_GetMouseState(null, null); 118 _x = event.x; 119 _y = event.y; 120 } 121 122 void updateWheel(const(SDL_MouseWheelEvent)* event) 123 { 124 _buttonState = SDL_GetMouseState(&_x, &_y); 125 _wheelX += event.x; 126 _wheelY += event.y; 127 } 128 } 129 130 private 131 { 132 SDL2 _sdl2; 133 134 // Last button state 135 int _buttonState; 136 137 // Last mouse coordinates 138 int _x = 0, 139 _y = 0; 140 141 // mouse wheel scrolled amounts 142 int _wheelX = 0, 143 _wheelY = 0; 144 145 int _lastDeltaX = 0, 146 _lastDeltaY = 0; 147 } 148 } 149 150 151 /// Mouse cursor, can be created from custom bitmap or from system defaults. 152 final class SDL2Cursor 153 { 154 public 155 { 156 /// Creates a cursor from a SDL surface. 157 /// The surface should outlive this cursor, its ownership will not be taken. 158 /// See_also: $(LINK http://wiki.libsdl.org/SDL_CreateColorCursor) 159 /// Throws: $(D SDL2Exception) on error. 160 this(SDL2 sdl2, SDL2Surface surface, int hotspotX, int hotspotY) 161 { 162 _sdl2 = sdl2; 163 _handle = SDL_CreateColorCursor(surface.handle(), hotspotX, hotspotY); 164 if(_handle is null) 165 _sdl2.throwSDL2Exception("SDL_CreateColorCursor"); 166 _owned = true; 167 } 168 169 /// Creates a system cursor. 170 /// See_also: $(LINK http://wiki.libsdl.org/SDL_CreateSystemCursor) 171 /// Throws: $(D SDL2Exception) on error. 172 this(SDL2 sdl2, SDL_SystemCursor id) 173 { 174 _sdl2 = sdl2; 175 _handle = SDL_CreateSystemCursor(id); 176 if(_handle is null) 177 _sdl2.throwSDL2Exception("SDL_CreateSystemCursor"); 178 _owned = true; 179 } 180 181 /// Returns: Default cursor. 182 /// See_also: $(LINK http://wiki.libsdl.org/SDL_GetDefaultCursor) 183 /// Throws: $(D SDL2Exception) on error. 184 static SDL2Cursor getDefault(SDL2 sdl2) 185 { 186 SDL_Cursor* handle = SDL_GetDefaultCursor(); 187 if(handle is null) 188 sdl2.throwSDL2Exception("SDL_GetDefaultCursor"); 189 190 return new SDL2Cursor(sdl2, handle); 191 192 } 193 194 /// Returns: Current cursor. 195 /// See_also: $(LINK http://wiki.libsdl.org/SDL_GetCursor) 196 /// Throws: $(D SDL2Exception) on error. 197 static SDL2Cursor getCurrent(SDL2 sdl2) 198 { 199 SDL_Cursor* handle = SDL_GetCursor(); 200 if(handle is null) 201 sdl2.throwSDL2Exception("SDL_GetCursor"); 202 203 return new SDL2Cursor(sdl2, handle); 204 } 205 206 ~this() 207 { 208 close(); 209 } 210 211 /// Returns: SDL handle. 212 SDL_Cursor* handle() 213 { 214 return _handle; 215 } 216 217 void close() 218 { 219 if (_owned && _handle !is null) 220 { 221 SDL_FreeCursor(_handle); 222 _handle = null; 223 } 224 } 225 226 void setCurrent() 227 { 228 SDL_SetCursor(_handle); 229 } 230 } 231 232 private 233 { 234 SDL2 _sdl2; 235 SDL_Cursor* _handle; 236 SDL2Surface _surface; 237 bool _owned; 238 239 // Create with specified handle. 240 this(SDL2 sdl2, SDL_Cursor* handle) 241 { 242 _sdl2 = sdl2; 243 _handle = handle; 244 _owned = false; 245 } 246 } 247 }