#include "glutint.h"
#include <sys/timeb.h>
#ifdef __MINGW32__
#include <ctype.h>
#endif
#if defined(_WIN32) && !defined(__CYGWIN32__)
#include <mmsystem.h>
#endif
extern unsigned __glutMenuButton;
extern GLUTidleCB __glutIdleFunc;
extern GLUTtimer *__glutTimerList;
extern GLUTmenuItem *__glutGetUniqueMenuItem(GLUTmenu * menu, int unique);
static HMENU __glutHMenu;
void
updateWindowState(GLUTwindow *window, int visState)
{
GLUTwindow* child;
window->shownState = visState;
if (visState != window->visState) {
if (window->windowStatus) {
window->visState = visState;
__glutSetWindow(window);
window->windowStatus(visState);
}
}
child = window->children;
while (child) {
updateWindowState(child, visState);
child = child->siblings;
}
}
LONG WINAPI
__glutWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
POINT point;
PAINTSTRUCT ps;
LPMINMAXINFO minmax;
GLUTwindow* window;
GLUTmenu* menu;
int x, y, width, height, key;
int button = -1;
switch(msg) {
case WM_CREATE:
return 0;
case WM_CLOSE:
if (__glutExitFunc) {
__glutExitFunc(0);
}
exit(0);
break;
#if 0
case WM_DESTROY:
window = __glutGetWindow(hwnd);
if (window) {
if (window->ctx) {
wglMakeCurrent(NULL, NULL);
wglDeleteContext(window->ctx);
}
}
return 0;
#endif
case WM_PAINT:
window = __glutGetWindow(hwnd);
if (window) {
BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
if (window->win == hwnd) {
__glutPostRedisplay(window, GLUT_REPAIR_WORK);
} else if (window->overlay && window->overlay->win == hwnd) {
__glutPostRedisplay(window, GLUT_OVERLAY_REPAIR_WORK);
}
}
return 0;
case WM_SYSKEYUP:
case WM_KEYUP:
window = __glutGetWindow(hwnd);
if (!window) {
break;
}
if (window->parent) {
GetCursorPos(&point);
ScreenToClient(hwnd, &point);
hwnd = ChildWindowFromPoint(hwnd, point);
window = __glutGetWindow(hwnd);
}
if (window->specialUp || window->keyboardUp) {
GetCursorPos(&point);
ScreenToClient(window->win, &point);
__glutSetWindow(window);
__glutModifierMask = 0;
if (GetKeyState(VK_SHIFT) < 0)
__glutModifierMask |= ShiftMask;
if (GetKeyState(VK_SHIFT) < 0)
__glutModifierMask |= ControlMask;
if (GetKeyState(VK_MENU) < 0)
__glutModifierMask |= Mod1Mask;
switch (wParam) {
case VK_F1: key = GLUT_KEY_F1; break;
case VK_F2: key = GLUT_KEY_F2; break;
case VK_F3: key = GLUT_KEY_F3; break;
case VK_F4: key = GLUT_KEY_F4; break;
case VK_F5: key = GLUT_KEY_F5; break;
case VK_F6: key = GLUT_KEY_F6; break;
case VK_F7: key = GLUT_KEY_F7; break;
case VK_F8: key = GLUT_KEY_F8; break;
case VK_F9: key = GLUT_KEY_F9; break;
case VK_F10: key = GLUT_KEY_F10; break;
case VK_F11: key = GLUT_KEY_F11; break;
case VK_F12: key = GLUT_KEY_F12; break;
case VK_LEFT: key = GLUT_KEY_LEFT; break;
case VK_UP: key = GLUT_KEY_UP; break;
case VK_RIGHT: key = GLUT_KEY_RIGHT; break;
case VK_DOWN: key = GLUT_KEY_DOWN; break;
case VK_PRIOR: key = GLUT_KEY_PAGE_UP; break;
case VK_NEXT: key = GLUT_KEY_PAGE_DOWN; break;
case VK_HOME: key = GLUT_KEY_HOME; break;
case VK_END: key = GLUT_KEY_END; break;
case VK_INSERT: key = GLUT_KEY_INSERT; break;
case VK_DELETE:
if (window->keyboardUp) {
window->keyboardUp((unsigned char) 127, point.x, point.y);
}
return 0;
default:
if (window->keyboardUp) {
key = MapVirtualKey(wParam, 2);
if (isascii(key) && (key != 0)) {
if (!(__glutModifierMask & ShiftMask))
key = tolower(key);
window->keyboardUp((unsigned char) key, point.x, point.y);
}
}
__glutModifierMask = (unsigned int) ~0;
return 0;
}
if (window->specialUp) {
window->specialUp(key, point.x, point.y);
}
__glutModifierMask = (unsigned int) ~0;
}
return 0;
case WM_SYSCHAR:
case WM_CHAR:
window = __glutGetWindow(hwnd);
if (!window) {
break;
}
if (window->ignoreKeyRepeat && (lParam & (1 << 30)) ) {
break;
}
if (window->parent) {
GetCursorPos(&point);
ScreenToClient(hwnd, &point);
hwnd = ChildWindowFromPoint(hwnd, point);
window = __glutGetWindow(hwnd);
}
if (window->keyboard) {
GetCursorPos(&point);
ScreenToClient(window->win, &point);
__glutSetWindow(window);
__glutModifierMask = 0;
if (GetKeyState(VK_SHIFT) < 0)
__glutModifierMask |= ShiftMask;
if (GetKeyState(VK_CONTROL) < 0)
__glutModifierMask |= ControlMask;
if (GetKeyState(VK_MENU) < 0)
__glutModifierMask |= Mod1Mask;
window->keyboard((unsigned char)wParam, point.x, point.y);
__glutModifierMask = (unsigned int) ~0;
}
return 0;
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
window = __glutGetWindow(hwnd);
if (!window) {
break;
}
if (window->ignoreKeyRepeat && (lParam & (1 << 30)) ) {
break;
}
if (window->parent) {
GetCursorPos(&point);
ScreenToClient(hwnd, &point);
hwnd = ChildWindowFromPoint(hwnd, point);
window = __glutGetWindow(hwnd);
}
if (window->special) {
switch (wParam) {
case VK_F1: key = GLUT_KEY_F1; break;
case VK_F2: key = GLUT_KEY_F2; break;
case VK_F3: key = GLUT_KEY_F3; break;
case VK_F4: key = GLUT_KEY_F4; break;
case VK_F5: key = GLUT_KEY_F5; break;
case VK_F6: key = GLUT_KEY_F6; break;
case VK_F7: key = GLUT_KEY_F7; break;
case VK_F8: key = GLUT_KEY_F8; break;
case VK_F9: key = GLUT_KEY_F9; break;
case VK_F10: key = GLUT_KEY_F10; break;
case VK_F11: key = GLUT_KEY_F11; break;
case VK_F12: key = GLUT_KEY_F12; break;
case VK_LEFT: key = GLUT_KEY_LEFT; break;
case VK_UP: key = GLUT_KEY_UP; break;
case VK_RIGHT: key = GLUT_KEY_RIGHT; break;
case VK_DOWN: key = GLUT_KEY_DOWN; break;
case VK_PRIOR:
key = GLUT_KEY_PAGE_UP;
break;
case VK_NEXT:
key = GLUT_KEY_PAGE_DOWN;
break;
case VK_HOME:
key = GLUT_KEY_HOME;
break;
case VK_END:
key = GLUT_KEY_END;
break;
case VK_INSERT:
key = GLUT_KEY_INSERT;
break;
case VK_DELETE:
goto handleDelete;
default:
goto defproc;
}
GetCursorPos(&point);
ScreenToClient(window->win, &point);
__glutSetWindow(window);
__glutModifierMask = 0;
if (GetKeyState(VK_SHIFT) < 0)
__glutModifierMask |= ShiftMask;
if (GetKeyState(VK_CONTROL) < 0)
__glutModifierMask |= ControlMask;
if (GetKeyState(VK_MENU) < 0)
__glutModifierMask |= Mod1Mask;
window->special(key, point.x, point.y);
__glutModifierMask = (unsigned int) ~0;
} else if (window->keyboard) {
switch (wParam) {
case VK_DELETE:
handleDelete:
GetCursorPos(&point);
ScreenToClient(window->win, &point);
__glutSetWindow(window);
__glutModifierMask = 0;
if (GetKeyState(VK_SHIFT) < 0)
__glutModifierMask |= ShiftMask;
if (GetKeyState(VK_CONTROL) < 0)
__glutModifierMask |= ControlMask;
if (GetKeyState(VK_MENU) < 0)
__glutModifierMask |= Mod1Mask;
window->keyboard((unsigned char) 127, point.x, point.y);
__glutModifierMask = (unsigned int) ~0;
return 0;
default:
break;
}
}
return 0;
case WM_LBUTTONDOWN:
button = GLUT_LEFT_BUTTON;
case WM_MBUTTONDOWN:
if (button < 0)
button = GLUT_MIDDLE_BUTTON;
case WM_RBUTTONDOWN:
if (button < 0)
button = GLUT_RIGHT_BUTTON;
if (__glutMappedMenu) {
if (button == GLUT_MIDDLE_BUTTON)
return 0;
GetCursorPos(&point);
ScreenToClient(hwnd, &point);
__glutItemSelected = NULL;
__glutFinishMenu(hwnd, point.x, point.y);
return 0;
}
SetCapture(hwnd);
x = LOWORD(lParam);
y = HIWORD(lParam);
if(x & 1 << 15) x -= (1 << 16);
if(y & 1 << 15) y -= (1 << 16);
window = __glutGetWindow(hwnd);
if (window) {
menu = __glutGetMenuByNum(window->menu[button]);
if (menu) {
point.x = LOWORD(lParam); point.y = HIWORD(lParam);
ClientToScreen(window->win, &point);
__glutMenuButton = button == GLUT_RIGHT_BUTTON ? TPM_RIGHTBUTTON :
button == GLUT_LEFT_BUTTON ? TPM_LEFTBUTTON :
0x0001;
__glutStartMenu(menu, window, point.x, point.y, x, y);
} else if (window->mouse) {
__glutSetWindow(window);
__glutModifierMask = 0;
if (GetKeyState(VK_SHIFT) < 0)
__glutModifierMask |= ShiftMask;
if (GetKeyState(VK_CONTROL) < 0)
__glutModifierMask |= ControlMask;
if (GetKeyState(VK_MENU) < 0)
__glutModifierMask |= Mod1Mask;
window->mouse(button, GLUT_DOWN, x, y);
__glutModifierMask = (unsigned int)~0;
} else {
}
}
return 0;
case WM_LBUTTONUP:
button = GLUT_LEFT_BUTTON;
case WM_MBUTTONUP:
if (button < 0)
button = GLUT_MIDDLE_BUTTON;
case WM_RBUTTONUP:
if (button < 0)
button = GLUT_RIGHT_BUTTON;
if (__glutMappedMenu) {
GetCursorPos(&point);
ScreenToClient(hwnd, &point);
if (button == GLUT_MIDDLE_BUTTON) {
return 0;
#if 0
int item = MenuItemFromPoint(hwnd, __glutHMenu, point);
if (item != -1)
__glutItemSelected = (GLUTmenuItem*)GetMenuItemID(__glutHMenu, item);
else
__glutItemSelected = NULL;
__glutFinishMenu(hwnd, point.x, point.y);
#endif
} else {
__glutItemSelected = NULL;
__glutFinishMenu(hwnd, point.x, point.y);
}
return 0;
}
ReleaseCapture();
window = __glutGetWindow(hwnd);
if (window && window->mouse) {
x = LOWORD(lParam);
y = HIWORD(lParam);
if(x & 1 << 15) x -= (1 << 16);
if(y & 1 << 15) y -= (1 << 16);
__glutSetWindow(window);
__glutModifierMask = 0;
if (GetKeyState(VK_SHIFT) < 0)
__glutModifierMask |= ShiftMask;
if (GetKeyState(VK_CONTROL) < 0)
__glutModifierMask |= ControlMask;
if (GetKeyState(VK_MENU) < 0)
__glutModifierMask |= Mod1Mask;
window->mouse(button, GLUT_UP, x, y);
__glutModifierMask = (unsigned int)~0;
} else {
}
return 0;
case WM_ENTERMENULOOP:
SetTimer(hwnd, 1, 1, NULL);
return 0;
case WM_TIMER:
#if 0
if (wParam == 2)
return 0;
#endif
#if 0
if (__glutIdleFunc)
__glutIdleFunc();
#endif
if (__glutTimerList)
handleTimeouts();
return 0;
case WM_EXITMENULOOP:
KillTimer(hwnd, 1);
return 0;
case WM_MENUSELECT:
if (lParam != 0)
__glutHMenu = (HMENU)lParam;
return 0;
case WM_COMMAND:
if (__glutMappedMenu) {
if (GetSubMenu(__glutHMenu, LOWORD(wParam)))
__glutItemSelected = NULL;
else
__glutItemSelected =
__glutGetUniqueMenuItem(__glutMappedMenu, LOWORD(wParam));
GetCursorPos(&point);
ScreenToClient(hwnd, &point);
__glutFinishMenu(hwnd, point.x, point.y);
}
return 0;
case WM_MOUSEMOVE:
if (!__glutMappedMenu) {
window = __glutGetWindow(hwnd);
if (window) {
x = LOWORD(lParam);
y = HIWORD(lParam);
if(x & 1 << 15) x -= (1 << 16);
if(y & 1 << 15) y -= (1 << 16);
if (window->motion && wParam &
(MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) {
__glutSetWindow(window);
window->motion(x, y);
}
else if (window->passive &&
((wParam &
(MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) ==
0)) {
__glutSetWindow(window);
window->passive(x, y);
}
}
} else {
}
return 0;
case WM_GETMINMAXINFO:
minmax = (LPMINMAXINFO)lParam;
minmax->ptMaxSize.x = __glutScreenWidth;
minmax->ptMaxSize.y = __glutScreenHeight;
minmax->ptMinTrackSize.x = 0;
minmax->ptMinTrackSize.y = 0;
minmax->ptMaxTrackSize.x = __glutScreenWidth +
GetSystemMetrics(SM_CXSIZE) * 2;
minmax->ptMaxTrackSize.y = __glutScreenHeight +
GetSystemMetrics(SM_CXSIZE) * 2 + GetSystemMetrics(SM_CYCAPTION);
return 0;
case WM_SIZE:
window = __glutGetWindow(hwnd);
if (window) {
width = LOWORD(lParam);
height = HIWORD(lParam);
if (width != window->width || height != window->height) {
#if 0
if (window->overlay) {
XResizeWindow(__glutDisplay, window->overlay->win, width, height);
}
#endif
window->width = width;
window->height = height;
__glutSetWindow(window);
GdiFlush();
window->reshape(width, height);
window->forceReshape = FALSE;
__glutPostRedisplay(window, GLUT_REPAIR_WORK);
}
}
return 0;
case WM_SETCURSOR:
if(LOWORD(lParam) != HTCLIENT) {
goto defproc;
}
window = __glutGetWindow(hwnd);
if (window) {
__glutSetCursor(window);
}
return 1;
case WM_SETFOCUS:
window = __glutGetWindow(hwnd);
if (window) {
window->entryState = WM_SETFOCUS;
if (window->entry) {
__glutSetWindow(window);
window->entry(GLUT_ENTERED);
}
if (window->joystick && __glutCurrentWindow) {
if (__glutCurrentWindow->joyPollInterval > 0) {
MMRESULT result;
result = joySetCapture(__glutCurrentWindow->win,
JOYSTICKID1, 0, TRUE);
if (result != JOYERR_NOERROR) {
return 0;
}
(void) joySetThreshold(JOYSTICKID1,
__glutCurrentWindow->joyPollInterval);
}
}
}
return 0;
case WM_KILLFOCUS:
window = __glutGetWindow(hwnd);
if (window) {
window->entryState = WM_KILLFOCUS;
if (window->entry) {
__glutSetWindow(window);
window->entry(GLUT_LEFT);
}
if (window->joystick && __glutCurrentWindow) {
if (__glutCurrentWindow->joyPollInterval > 0) {
(void) joyReleaseCapture(JOYSTICKID1);
}
}
}
return 0;
case WM_ACTIVATE:
window = __glutGetWindow(hwnd);
if (LOWORD(wParam)) {
PostMessage(hwnd, WM_PALETTECHANGED, 0, 0);
}
if (window) {
int visState;
visState = !HIWORD(wParam);
updateWindowState(window, visState);
}
return 0;
case WM_PALETTECHANGED:
if (hwnd == (HWND)wParam) {
break;
}
case WM_QUERYNEWPALETTE:
window = __glutGetWindow(hwnd);
if (window && window->colormap) {
UnrealizeObject(window->colormap->cmap);
SelectPalette(window->hdc, window->colormap->cmap, FALSE);
RealizePalette(window->hdc);
return TRUE;
}
return FALSE;
case MM_JOY1MOVE:
case MM_JOY1ZMOVE:
window = __glutGetWindow(hwnd);
if (window->joystick) {
JOYINFOEX jix;
int x, y, z;
jix.dwSize = sizeof(jix);
jix.dwFlags = JOY_RETURNALL;
joyGetPosEx(JOYSTICKID1,&jix);
#define SCALE(v) ((int) ((v - 32767)/32.768))
x = jix.dwXpos;
y = jix.dwYpos;
z = jix.dwZpos;
window->joystick(jix.dwButtons, SCALE(x), SCALE(y), SCALE(z));
return TRUE;
}
return FALSE;
case MM_JOY1BUTTONDOWN:
case MM_JOY1BUTTONUP:
window = __glutGetWindow(hwnd);
if (window->joystick) {
JOYINFOEX jix;
jix.dwSize = sizeof(jix);
jix.dwFlags = JOY_RETURNALL;
joyGetPosEx(JOYSTICKID1,&jix);
return TRUE;
}
return FALSE;
#if 0
case WM_DISPLAYCHANGE:
break;
case WM_NCHITTEST:
goto defproc;
case WM_NCMOUSEMOVE:
goto defproc;
case WM_NCACTIVATE:
goto defproc;
case WM_NCPAINT:
goto defproc;
case WM_NCCALCSIZE:
goto defproc;
case WM_NCCREATE:
goto defproc;
case WM_NCDESTROY:
goto defproc;
case WM_NCLBUTTONDOWN:
goto defproc;
case WM_SETTEXT:
goto defproc;
case WM_GETTEXT:
goto defproc;
case WM_ACTIVATEAPP:
goto defproc;
case WM_GETICON:
goto defproc;
case WM_ERASEBKGND:
goto defproc;
case WM_WINDOWPOSCHANGING:
goto defproc;
case WM_WINDOWPOSCHANGED:
goto defproc;
case WM_MOUSEACTIVATE:
goto defproc;
case WM_SHOWWINDOW:
goto defproc;
case WM_MOVING:
goto defproc;
case WM_MOVE:
goto defproc;
case WM_KEYUP:
goto defproc;
case WM_CAPTURECHANGED:
goto defproc;
case WM_SYSCOMMAND:
goto defproc;
case WM_ENTERSIZEMOVE:
goto defproc;
case WM_ENTERIDLE:
goto defproc;
#endif
default:
goto defproc;
}
defproc:
return DefWindowProc(hwnd, msg, wParam, lParam);
}