mirror of
https://github.com/glfw/glfw.git
synced 2026-09-21 16:44:11 +00:00
Added a conservative set of key modifiers.
This commit is contained in:
+51
-9
@@ -201,6 +201,22 @@ static void centerCursor(_GLFWwindow *window)
|
||||
|
||||
@end
|
||||
|
||||
// Converts Mac OS X key modifiers into GLFW ones
|
||||
//
|
||||
static int convertKeyMods(NSUInteger flags)
|
||||
{
|
||||
int mods = 0;
|
||||
|
||||
if (flags & NSShiftKeyMask)
|
||||
mods |= GLFW_MOD_SHIFT;
|
||||
if (flags & NSControlKeyMask)
|
||||
mods |= GLFW_MOD_CTRL;
|
||||
if (flags & NSAlternateKeyMask)
|
||||
mods |= GLFW_MOD_ALT;
|
||||
|
||||
return mods;
|
||||
}
|
||||
|
||||
// Converts a Mac OS X keycode to a GLFW keycode
|
||||
//
|
||||
static int convertMacKeyCode(unsigned int macKeyCode)
|
||||
@@ -413,7 +429,10 @@ static int convertMacKeyCode(unsigned int macKeyCode)
|
||||
|
||||
- (void)mouseDown:(NSEvent *)event
|
||||
{
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS);
|
||||
_glfwInputMouseClick(window,
|
||||
GLFW_MOUSE_BUTTON_LEFT,
|
||||
GLFW_PRESS,
|
||||
convertKeyMods([event modifierFlags]));
|
||||
}
|
||||
|
||||
- (void)mouseDragged:(NSEvent *)event
|
||||
@@ -423,7 +442,10 @@ static int convertMacKeyCode(unsigned int macKeyCode)
|
||||
|
||||
- (void)mouseUp:(NSEvent *)event
|
||||
{
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE);
|
||||
_glfwInputMouseClick(window,
|
||||
GLFW_MOUSE_BUTTON_LEFT,
|
||||
GLFW_RELEASE,
|
||||
convertKeyMods([event modifierFlags]));
|
||||
}
|
||||
|
||||
- (void)mouseMoved:(NSEvent *)event
|
||||
@@ -442,7 +464,10 @@ static int convertMacKeyCode(unsigned int macKeyCode)
|
||||
|
||||
- (void)rightMouseDown:(NSEvent *)event
|
||||
{
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS);
|
||||
_glfwInputMouseClick(window,
|
||||
GLFW_MOUSE_BUTTON_RIGHT,
|
||||
GLFW_PRESS,
|
||||
convertKeyMods([event modifierFlags]));
|
||||
}
|
||||
|
||||
- (void)rightMouseDragged:(NSEvent *)event
|
||||
@@ -452,12 +477,18 @@ static int convertMacKeyCode(unsigned int macKeyCode)
|
||||
|
||||
- (void)rightMouseUp:(NSEvent *)event
|
||||
{
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE);
|
||||
_glfwInputMouseClick(window,
|
||||
GLFW_MOUSE_BUTTON_RIGHT,
|
||||
GLFW_RELEASE,
|
||||
convertKeyMods([event modifierFlags]));
|
||||
}
|
||||
|
||||
- (void)otherMouseDown:(NSEvent *)event
|
||||
{
|
||||
_glfwInputMouseClick(window, [event buttonNumber], GLFW_PRESS);
|
||||
_glfwInputMouseClick(window,
|
||||
[event buttonNumber],
|
||||
GLFW_PRESS,
|
||||
convertKeyMods([event modifierFlags]));
|
||||
}
|
||||
|
||||
- (void)otherMouseDragged:(NSEvent *)event
|
||||
@@ -467,7 +498,10 @@ static int convertMacKeyCode(unsigned int macKeyCode)
|
||||
|
||||
- (void)otherMouseUp:(NSEvent *)event
|
||||
{
|
||||
_glfwInputMouseClick(window, [event buttonNumber], GLFW_RELEASE);
|
||||
_glfwInputMouseClick(window,
|
||||
[event buttonNumber],
|
||||
GLFW_RELEASE,
|
||||
convertKeyMods([event modifierFlags]));
|
||||
}
|
||||
|
||||
- (void)mouseExited:(NSEvent *)event
|
||||
@@ -503,7 +537,12 @@ static int convertMacKeyCode(unsigned int macKeyCode)
|
||||
|
||||
- (void)keyDown:(NSEvent *)event
|
||||
{
|
||||
_glfwInputKey(window, convertMacKeyCode([event keyCode]), GLFW_PRESS);
|
||||
const NSUInteger mods = [event modifierFlags];
|
||||
|
||||
_glfwInputKey(window,
|
||||
convertMacKeyCode([event keyCode]),
|
||||
GLFW_PRESS,
|
||||
convertKeyMods(mods));
|
||||
|
||||
if ([event modifierFlags] & NSCommandKeyMask)
|
||||
return;
|
||||
@@ -530,12 +569,15 @@ static int convertMacKeyCode(unsigned int macKeyCode)
|
||||
|
||||
key = convertMacKeyCode([event keyCode]);
|
||||
if (key != -1)
|
||||
_glfwInputKey(window, key, action);
|
||||
_glfwInputKey(window, key, action, convertKeyMods([event modifierFlags]));
|
||||
}
|
||||
|
||||
- (void)keyUp:(NSEvent *)event
|
||||
{
|
||||
_glfwInputKey(window, convertMacKeyCode([event keyCode]), GLFW_RELEASE);
|
||||
_glfwInputKey(window,
|
||||
convertMacKeyCode([event keyCode]),
|
||||
GLFW_RELEASE,
|
||||
convertKeyMods([event modifierFlags]));
|
||||
}
|
||||
|
||||
- (void)scrollWheel:(NSEvent *)event
|
||||
|
||||
+4
-4
@@ -122,7 +122,7 @@ static void setStickyMouseButtons(_GLFWwindow* window, int enabled)
|
||||
////// GLFW event API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwInputKey(_GLFWwindow* window, int key, int action)
|
||||
void _glfwInputKey(_GLFWwindow* window, int key, int action, int mods)
|
||||
{
|
||||
GLboolean repeated = GL_FALSE;
|
||||
|
||||
@@ -141,7 +141,7 @@ void _glfwInputKey(_GLFWwindow* window, int key, int action)
|
||||
action = GLFW_REPEAT;
|
||||
|
||||
if (window->callbacks.key)
|
||||
window->callbacks.key((GLFWwindow*) window, key, action);
|
||||
window->callbacks.key((GLFWwindow*) window, key, action, mods);
|
||||
}
|
||||
|
||||
void _glfwInputChar(_GLFWwindow* window, unsigned int character)
|
||||
@@ -162,7 +162,7 @@ void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
|
||||
window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
|
||||
}
|
||||
|
||||
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action)
|
||||
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
|
||||
{
|
||||
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
|
||||
return;
|
||||
@@ -174,7 +174,7 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action)
|
||||
window->mouseButton[button] = (char) action;
|
||||
|
||||
if (window->callbacks.mouseButton)
|
||||
window->callbacks.mouseButton((GLFWwindow*) window, button, action);
|
||||
window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods);
|
||||
}
|
||||
|
||||
void _glfwInputCursorMotion(_GLFWwindow* window, double x, double y)
|
||||
|
||||
+3
-2
@@ -591,9 +591,10 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window);
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] key The key that was pressed or released.
|
||||
* @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE.
|
||||
* @param[in] mods The modifiers pressed when the event was generated.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputKey(_GLFWwindow* window, int key, int action);
|
||||
void _glfwInputKey(_GLFWwindow* window, int key, int action, int mods);
|
||||
|
||||
/*! @brief Notifies shared code of a Unicode character input event.
|
||||
* @param[in] window The window that received the event.
|
||||
@@ -616,7 +617,7 @@ void _glfwInputScroll(_GLFWwindow* window, double x, double y);
|
||||
* @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action);
|
||||
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
||||
|
||||
/*! @brief Notifies shared code of a cursor motion event.
|
||||
* @param[in] window The window that received the event.
|
||||
|
||||
+59
-21
@@ -104,6 +104,38 @@ static void showCursor(_GLFWwindow* window)
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieves and translates modifier keys
|
||||
//
|
||||
static int getKeyMods(void)
|
||||
{
|
||||
int mods = 0;
|
||||
|
||||
if (GetKeyState(VK_SHIFT) & (1 << 31))
|
||||
mods |= GLFW_MOD_SHIFT;
|
||||
if (GetKeyState(VK_CONTROL) & (1 << 31))
|
||||
mods |= GLFW_MOD_CTRL;
|
||||
if (GetKeyState(VK_MENU) & (1 << 31))
|
||||
mods |= GLFW_MOD_ALT;
|
||||
|
||||
return mods;
|
||||
}
|
||||
|
||||
// Retrieves and translates modifier keys
|
||||
//
|
||||
static int getAsyncKeyMods(void)
|
||||
{
|
||||
int mods = 0;
|
||||
|
||||
if (GetAsyncKeyState(VK_SHIFT) & (1 << 31))
|
||||
mods |= GLFW_MOD_SHIFT;
|
||||
if (GetAsyncKeyState(VK_CONTROL) & (1 << 31))
|
||||
mods |= GLFW_MOD_CTRL;
|
||||
if (GetAsyncKeyState(VK_MENU) & (1 << 31))
|
||||
mods |= GLFW_MOD_ALT;
|
||||
|
||||
return mods;
|
||||
}
|
||||
|
||||
// Translates a Windows key to the corresponding GLFW key
|
||||
//
|
||||
static int translateKey(WPARAM wParam, LPARAM lParam)
|
||||
@@ -433,7 +465,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
{
|
||||
_glfwInputKey(window, translateKey(wParam, lParam), GLFW_PRESS);
|
||||
_glfwInputKey(window, translateKey(wParam, lParam), GLFW_PRESS, getKeyMods());
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -461,20 +493,22 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
{
|
||||
const int mods = getKeyMods();
|
||||
|
||||
if (wParam == VK_SHIFT)
|
||||
{
|
||||
// Special trick: release both shift keys on SHIFT up event
|
||||
_glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, GLFW_RELEASE);
|
||||
_glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, GLFW_RELEASE);
|
||||
_glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, GLFW_RELEASE, mods);
|
||||
_glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, GLFW_RELEASE, mods);
|
||||
}
|
||||
else if (wParam == VK_SNAPSHOT)
|
||||
{
|
||||
// Key down is not reported for the print screen key
|
||||
_glfwInputKey(window, GLFW_KEY_PRINT_SCREEN, GLFW_PRESS);
|
||||
_glfwInputKey(window, GLFW_KEY_PRINT_SCREEN, GLFW_RELEASE);
|
||||
_glfwInputKey(window, GLFW_KEY_PRINT_SCREEN, GLFW_PRESS, mods);
|
||||
_glfwInputKey(window, GLFW_KEY_PRINT_SCREEN, GLFW_RELEASE, mods);
|
||||
}
|
||||
else
|
||||
_glfwInputKey(window, translateKey(wParam, lParam), GLFW_RELEASE);
|
||||
_glfwInputKey(window, translateKey(wParam, lParam), GLFW_RELEASE, getKeyMods());
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -484,20 +518,22 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_XBUTTONDOWN:
|
||||
{
|
||||
const int mods = getKeyMods();
|
||||
|
||||
SetCapture(hWnd);
|
||||
|
||||
if (uMsg == WM_LBUTTONDOWN)
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS);
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods);
|
||||
else if (uMsg == WM_RBUTTONDOWN)
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS);
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, mods);
|
||||
else if (uMsg == WM_MBUTTONDOWN)
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS);
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, mods);
|
||||
else
|
||||
{
|
||||
if (HIWORD(wParam) == XBUTTON1)
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_4, GLFW_PRESS);
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_4, GLFW_PRESS, mods);
|
||||
else if (HIWORD(wParam) == XBUTTON2)
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_PRESS);
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_PRESS, mods);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -510,20 +546,22 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
case WM_MBUTTONUP:
|
||||
case WM_XBUTTONUP:
|
||||
{
|
||||
const int mods = getKeyMods();
|
||||
|
||||
ReleaseCapture();
|
||||
|
||||
if (uMsg == WM_LBUTTONUP)
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE);
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE, mods);
|
||||
else if (uMsg == WM_RBUTTONUP)
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE);
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE, mods);
|
||||
else if (uMsg == WM_MBUTTONUP)
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_RELEASE);
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_RELEASE, mods);
|
||||
else
|
||||
{
|
||||
if (HIWORD(wParam) == XBUTTON1)
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_4, GLFW_RELEASE);
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_4, GLFW_RELEASE, mods);
|
||||
else if (HIWORD(wParam) == XBUTTON2)
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_RELEASE);
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_RELEASE, mods);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1017,19 +1055,19 @@ void _glfwPlatformPollEvents(void)
|
||||
// This is the only async event handling in GLFW, but it solves some
|
||||
// nasty problems
|
||||
{
|
||||
int lshiftDown, rshiftDown;
|
||||
const int mods = getAsyncKeyMods();
|
||||
|
||||
// Get current state of left and right shift keys
|
||||
lshiftDown = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1;
|
||||
rshiftDown = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1;
|
||||
const int lshiftDown = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1;
|
||||
const int rshiftDown = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1;
|
||||
|
||||
// See if this differs from our belief of what has happened
|
||||
// (we only have to check for lost key up events)
|
||||
if (!lshiftDown && window->key[GLFW_KEY_LEFT_SHIFT] == 1)
|
||||
_glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, GLFW_RELEASE);
|
||||
_glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, GLFW_RELEASE, mods);
|
||||
|
||||
if (!rshiftDown && window->key[GLFW_KEY_RIGHT_SHIFT] == 1)
|
||||
_glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, GLFW_RELEASE);
|
||||
_glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, GLFW_RELEASE, mods);
|
||||
}
|
||||
|
||||
// Did the cursor move in an focused window that has captured the cursor
|
||||
|
||||
+2
-2
@@ -77,14 +77,14 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLboolean focused)
|
||||
for (i = 0; i <= GLFW_KEY_LAST; i++)
|
||||
{
|
||||
if (window->key[i] == GLFW_PRESS)
|
||||
_glfwInputKey(window, i, GLFW_RELEASE);
|
||||
_glfwInputKey(window, i, GLFW_RELEASE, 0);
|
||||
}
|
||||
|
||||
// Release all pressed mouse buttons
|
||||
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
|
||||
{
|
||||
if (window->mouseButton[i] == GLFW_PRESS)
|
||||
_glfwInputMouseClick(window, i, GLFW_RELEASE);
|
||||
_glfwInputMouseClick(window, i, GLFW_RELEASE, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+39
-13
@@ -58,6 +58,22 @@ typedef struct
|
||||
#define MWM_HINTS_DECORATIONS (1L << 1)
|
||||
|
||||
|
||||
// Translates an X event modifier state mask
|
||||
//
|
||||
int translateState(int state)
|
||||
{
|
||||
int mods = 0;
|
||||
|
||||
if (state & ShiftMask)
|
||||
mods |= GLFW_MOD_SHIFT;
|
||||
if (state & ControlMask)
|
||||
mods |= GLFW_MOD_CTRL;
|
||||
if (state & Mod1Mask)
|
||||
mods |= GLFW_MOD_ALT;
|
||||
|
||||
return mods;
|
||||
}
|
||||
|
||||
// Translates an X Window key to internal coding
|
||||
//
|
||||
static int translateKey(int keycode)
|
||||
@@ -511,31 +527,36 @@ static void processEvent(XEvent *event)
|
||||
{
|
||||
case KeyPress:
|
||||
{
|
||||
_glfwInputKey(window, translateKey(event->xkey.keycode), GLFW_PRESS);
|
||||
const int key = translateKey(event->xkey.keycode);
|
||||
const int mods = translateState(event->xkey.state);
|
||||
|
||||
if (!(event->xkey.state & ControlMask) &&
|
||||
!(event->xkey.state & Mod1Mask /*Alt*/))
|
||||
{
|
||||
_glfwInputChar(window, translateChar(&event->xkey));
|
||||
}
|
||||
_glfwInputKey(window, key, GLFW_PRESS, mods);
|
||||
|
||||
if (!(mods & GLFW_MOD_CTRL) && !(mods & GLFW_MOD_ALT))
|
||||
_glfwInputChar(window, translateChar(&event->xkey));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case KeyRelease:
|
||||
{
|
||||
_glfwInputKey(window, translateKey(event->xkey.keycode), GLFW_RELEASE);
|
||||
const int key = translateKey(event->xkey.keycode);
|
||||
const int mods = translateState(event->xkey.state);
|
||||
|
||||
_glfwInputKey(window, key, GLFW_RELEASE, mods);
|
||||
break;
|
||||
}
|
||||
|
||||
case ButtonPress:
|
||||
{
|
||||
const int mods = translateState(event->xbutton.state);
|
||||
|
||||
if (event->xbutton.button == Button1)
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS);
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods);
|
||||
else if (event->xbutton.button == Button2)
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS);
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, mods);
|
||||
else if (event->xbutton.button == Button3)
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS);
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, mods);
|
||||
|
||||
// Modern X provides scroll events as mouse button presses
|
||||
else if (event->xbutton.button == Button4)
|
||||
@@ -552,23 +573,28 @@ static void processEvent(XEvent *event)
|
||||
|
||||
case ButtonRelease:
|
||||
{
|
||||
const int mods = translateState(event->xbutton.state);
|
||||
|
||||
if (event->xbutton.button == Button1)
|
||||
{
|
||||
_glfwInputMouseClick(window,
|
||||
GLFW_MOUSE_BUTTON_LEFT,
|
||||
GLFW_RELEASE);
|
||||
GLFW_RELEASE,
|
||||
mods);
|
||||
}
|
||||
else if (event->xbutton.button == Button2)
|
||||
{
|
||||
_glfwInputMouseClick(window,
|
||||
GLFW_MOUSE_BUTTON_MIDDLE,
|
||||
GLFW_RELEASE);
|
||||
GLFW_RELEASE,
|
||||
mods);
|
||||
}
|
||||
else if (event->xbutton.button == Button3)
|
||||
{
|
||||
_glfwInputMouseClick(window,
|
||||
GLFW_MOUSE_BUTTON_RIGHT,
|
||||
GLFW_RELEASE);
|
||||
GLFW_RELEASE,
|
||||
mods);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user