1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20 */
21
22 #include "../../SDL_internal.h"
23
24 #if SDL_VIDEO_DRIVER_OS2
25
26 #include "SDL_video.h"
27 #include "SDL_mouse.h"
28 #include "../SDL_pixels_c.h"
29 #include "../SDL_shape_internals.h"
30 #include "../../events/SDL_events_c.h"
31 #include "SDL_os2video.h"
32 #include "SDL_syswm.h"
33 #include "SDL_os2util.h"
34
35 #define __MEERROR_H__
36 #define _MEERROR_H_
37 #include <mmioos2.h>
38 #include <fourcc.h>
39 #ifndef FOURCC_R666
40 #define FOURCC_R666 mmioFOURCC('R','6','6','6')
41 #endif
42
43 #define WIN_CLIENT_CLASS "SDL2"
44 #define OS2DRIVER_NAME_DIVE "DIVE"
45 #define OS2DRIVER_NAME_VMAN "VMAN"
46
47
48 static const SDL_Scancode aSDLScancode[] = {
49 /* 0 1 2 3 4 5 6 7 */
50 /* 8 9 A B C D E F */
51 SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_ESCAPE, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_3, SDL_SCANCODE_4, SDL_SCANCODE_5, SDL_SCANCODE_6, /* 0 */
52 SDL_SCANCODE_7, SDL_SCANCODE_8, SDL_SCANCODE_9, SDL_SCANCODE_0, SDL_SCANCODE_MINUS, SDL_SCANCODE_EQUALS, SDL_SCANCODE_BACKSPACE, SDL_SCANCODE_TAB, /* 0 */
53
54 SDL_SCANCODE_Q, SDL_SCANCODE_W, SDL_SCANCODE_E, SDL_SCANCODE_R, SDL_SCANCODE_T, SDL_SCANCODE_Y, SDL_SCANCODE_U, SDL_SCANCODE_I, /* 1 */
55 SDL_SCANCODE_O, SDL_SCANCODE_P, SDL_SCANCODE_LEFTBRACKET, SDL_SCANCODE_RIGHTBRACKET, SDL_SCANCODE_RETURN, SDL_SCANCODE_LCTRL, SDL_SCANCODE_A, SDL_SCANCODE_S, /* 1 */
56
57 SDL_SCANCODE_D, SDL_SCANCODE_F, SDL_SCANCODE_G, SDL_SCANCODE_H, SDL_SCANCODE_J, SDL_SCANCODE_K, SDL_SCANCODE_L, SDL_SCANCODE_SEMICOLON, /* 2 */
58 SDL_SCANCODE_APOSTROPHE, SDL_SCANCODE_GRAVE, SDL_SCANCODE_LSHIFT, SDL_SCANCODE_BACKSLASH, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_C, SDL_SCANCODE_V, /* 2 */
59
60 SDL_SCANCODE_B, SDL_SCANCODE_N, SDL_SCANCODE_M, SDL_SCANCODE_COMMA, SDL_SCANCODE_PERIOD, SDL_SCANCODE_SLASH, SDL_SCANCODE_RSHIFT, /*55*/SDL_SCANCODE_KP_MULTIPLY,/* 3 */
61 SDL_SCANCODE_LALT, SDL_SCANCODE_SPACE, SDL_SCANCODE_CAPSLOCK, SDL_SCANCODE_F1, SDL_SCANCODE_F2, SDL_SCANCODE_F3, SDL_SCANCODE_F4, SDL_SCANCODE_F5, /* 3 */
62
63 SDL_SCANCODE_F6, SDL_SCANCODE_F7, SDL_SCANCODE_F8, SDL_SCANCODE_F9, SDL_SCANCODE_F10, SDL_SCANCODE_NUMLOCKCLEAR, SDL_SCANCODE_SCROLLLOCK, SDL_SCANCODE_KP_7, /* 4 */
64 /*72*/ SDL_SCANCODE_KP_8, /*73*/SDL_SCANCODE_KP_9, SDL_SCANCODE_KP_MINUS,/*75*/SDL_SCANCODE_KP_4, /*76*/SDL_SCANCODE_KP_5, /*77*/SDL_SCANCODE_KP_6, /*78*/SDL_SCANCODE_KP_PLUS, /*79*/SDL_SCANCODE_KP_1, /* 4 */
65
66 /*80*/ SDL_SCANCODE_KP_2, /*81*/SDL_SCANCODE_KP_3, SDL_SCANCODE_KP_0, /*83*/SDL_SCANCODE_KP_PERIOD, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_NONUSBACKSLASH,SDL_SCANCODE_F11, /* 5 */
67 /*88*/ SDL_SCANCODE_F12, /*89*/SDL_SCANCODE_PAUSE, /*90*/SDL_SCANCODE_KP_ENTER,/*91*/SDL_SCANCODE_RCTRL, /*92*/SDL_SCANCODE_KP_DIVIDE, SDL_SCANCODE_APPLICATION, SDL_SCANCODE_RALT, /*95*/SDL_SCANCODE_UNKNOWN, /* 5 */
68
69 /*96*/ SDL_SCANCODE_HOME, /*97*/SDL_SCANCODE_UP, /*98*/SDL_SCANCODE_PAGEUP, SDL_SCANCODE_LEFT, /*100*/SDL_SCANCODE_RIGHT, SDL_SCANCODE_END, /*102*/SDL_SCANCODE_DOWN, /*103*/SDL_SCANCODE_PAGEDOWN, /* 6 */
70 /*104*/ SDL_SCANCODE_F17, /*105*/SDL_SCANCODE_DELETE, SDL_SCANCODE_F19, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,/*110*/SDL_SCANCODE_UNKNOWN,/*111*/SDL_SCANCODE_UNKNOWN, /* 6 */
71
72 /*112*/ SDL_SCANCODE_INTERNATIONAL2, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_INTERNATIONAL1,SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, /* 7 */
73 /*120*/ SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_INTERNATIONAL4,SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_INTERNATIONAL5,SDL_SCANCODE_APPLICATION,SDL_SCANCODE_INTERNATIONAL3,SDL_SCANCODE_LGUI, SDL_SCANCODE_RGUI /* 7 */
74 };
75
76 /* Utilites.
77 * ---------
78 */
_getSDLPixelFormatData(SDL_PixelFormat * pSDLPixelFormat,ULONG ulBPP,ULONG fccColorEncoding)79 static BOOL _getSDLPixelFormatData(SDL_PixelFormat *pSDLPixelFormat,
80 ULONG ulBPP, ULONG fccColorEncoding)
81 {
82 ULONG ulRshift, ulGshift, ulBshift;
83 ULONG ulRmask, ulGmask, ulBmask;
84 ULONG ulRloss, ulGloss, ulBloss;
85
86 pSDLPixelFormat->BitsPerPixel = ulBPP;
87 pSDLPixelFormat->BytesPerPixel = (pSDLPixelFormat->BitsPerPixel + 7) / 8;
88
89 switch (fccColorEncoding) {
90 case FOURCC_LUT8:
91 ulRshift = 0; ulGshift = 0; ulBshift = 0;
92 ulRmask = 0; ulGmask = 0; ulBmask = 0;
93 ulRloss = 8; ulGloss = 8; ulBloss = 8;
94 break;
95
96 case FOURCC_R555:
97 ulRshift = 10; ulGshift = 5; ulBshift = 0;
98 ulRmask = 0x7C00; ulGmask = 0x03E0; ulBmask = 0x001F;
99 ulRloss = 3; ulGloss = 3; ulBloss = 3;
100 break;
101
102 case FOURCC_R565:
103 ulRshift = 11; ulGshift = 5; ulBshift = 0;
104 ulRmask = 0xF800; ulGmask = 0x07E0; ulBmask = 0x001F;
105 ulRloss = 3; ulGloss = 2; ulBloss = 3;
106 break;
107
108 case FOURCC_R664:
109 ulRshift = 10; ulGshift = 4; ulBshift = 0;
110 ulRmask = 0xFC00; ulGmask = 0x03F0; ulBmask = 0x000F;
111 ulRloss = 2; ulGloss = 4; ulBloss = 3;
112 break;
113
114 case FOURCC_R666:
115 ulRshift = 12; ulGshift = 6; ulBshift = 0;
116 ulRmask = 0x03F000; ulGmask = 0x000FC0; ulBmask = 0x00003F;
117 ulRloss = 2; ulGloss = 2; ulBloss = 2;
118 break;
119
120 case FOURCC_RGB3:
121 case FOURCC_RGB4:
122 ulRshift = 0; ulGshift = 8; ulBshift = 16;
123 ulRmask = 0x0000FF; ulGmask = 0x00FF00; ulBmask = 0xFF0000;
124 ulRloss = 0x00; ulGloss = 0x00; ulBloss = 0x00;
125 break;
126
127 case FOURCC_BGR3:
128 case FOURCC_BGR4:
129 ulRshift = 16; ulGshift = 8; ulBshift = 0;
130 ulRmask = 0xFF0000; ulGmask = 0x00FF00; ulBmask = 0x0000FF;
131 ulRloss = 0; ulGloss = 0; ulBloss = 0;
132 break;
133
134 default:
135 /* printf("Unknown color encoding: %.4s\n", fccColorEncoding);*/
136 SDL_memset(pSDLPixelFormat, 0, sizeof(SDL_PixelFormat));
137 return FALSE;
138 }
139
140 pSDLPixelFormat->Rshift = ulRshift;
141 pSDLPixelFormat->Gshift = ulGshift;
142 pSDLPixelFormat->Bshift = ulBshift;
143 pSDLPixelFormat->Rmask = ulRmask;
144 pSDLPixelFormat->Gmask = ulGmask;
145 pSDLPixelFormat->Bmask = ulBmask;
146 pSDLPixelFormat->Rloss = ulRloss;
147 pSDLPixelFormat->Gloss = ulGloss;
148 pSDLPixelFormat->Bloss = ulBloss;
149
150 pSDLPixelFormat->Ashift = 0x00;
151 pSDLPixelFormat->Amask = 0x00;
152 pSDLPixelFormat->Aloss = 0x00;
153
154 return TRUE;
155 }
156
_getSDLPixelFormat(ULONG ulBPP,FOURCC fccColorEncoding)157 static Uint32 _getSDLPixelFormat(ULONG ulBPP, FOURCC fccColorEncoding)
158 {
159 SDL_PixelFormat stSDLPixelFormat;
160 Uint32 uiResult = SDL_PIXELFORMAT_UNKNOWN;
161
162 if (_getSDLPixelFormatData(&stSDLPixelFormat, ulBPP, fccColorEncoding))
163 uiResult = SDL_MasksToPixelFormatEnum(ulBPP, stSDLPixelFormat.Rmask,
164 stSDLPixelFormat.Gmask,
165 stSDLPixelFormat.Bmask, 0);
166
167 return uiResult;
168 }
169
_getDisplayModeForSDLWindow(SDL_Window * window)170 static SDL_DisplayMode *_getDisplayModeForSDLWindow(SDL_Window *window)
171 {
172 SDL_VideoDisplay *pSDLDisplay = SDL_GetDisplayForWindow(window);
173
174 if (pSDLDisplay == NULL) {
175 debug_os2("No display for the window");
176 return FALSE;
177 }
178
179 return &pSDLDisplay->current_mode;
180 }
181
_mouseCheck(WINDATA * pWinData)182 static VOID _mouseCheck(WINDATA *pWinData)
183 {
184 SDL_Mouse *pSDLMouse = SDL_GetMouse();
185
186 if ((pSDLMouse->relative_mode || (pWinData->window->flags & SDL_WINDOW_MOUSE_GRABBED) != 0) &&
187 ((pWinData->window->flags & SDL_WINDOW_INPUT_FOCUS) != 0)) {
188 /* We will make a real capture in _wmMouseButton() */
189 } else {
190 WinSetCapture(HWND_DESKTOP, NULLHANDLE);
191 }
192 }
193
194
195 /* PM window procedure.
196 * --------------------
197 */
198 static int OS2_ResizeWindowShape(SDL_Window *window);
199
_setVisibleRegion(WINDATA * pWinData,BOOL fVisible)200 static VOID _setVisibleRegion(WINDATA *pWinData, BOOL fVisible)
201 {
202 SDL_VideoDisplay *pSDLDisplay;
203
204 if (! pWinData->pVOData)
205 return;
206
207 pSDLDisplay = (fVisible)? SDL_GetDisplayForWindow(pWinData->window) : NULL;
208 pWinData->pOutput->SetVisibleRegion(pWinData->pVOData, pWinData->hwnd,
209 (pSDLDisplay == NULL) ?
210 NULL : &pSDLDisplay->current_mode,
211 pWinData->hrgnShape, fVisible);
212 }
213
_wmPaint(WINDATA * pWinData,HWND hwnd)214 static VOID _wmPaint(WINDATA *pWinData, HWND hwnd)
215 {
216 if (pWinData->pVOData == NULL ||
217 !pWinData->pOutput->Update(pWinData->pVOData, hwnd, NULL, 0)) {
218 RECTL rectl;
219 HPS hps;
220
221 hps = WinBeginPaint(hwnd, 0, &rectl);
222 WinFillRect(hps, &rectl, CLR_BLACK);
223 WinEndPaint(hps);
224 }
225 }
226
_wmMouseMove(WINDATA * pWinData,SHORT lX,SHORT lY)227 static VOID _wmMouseMove(WINDATA *pWinData, SHORT lX, SHORT lY)
228 {
229 SDL_Mouse *pSDLMouse = SDL_GetMouse();
230 POINTL pointl;
231 BOOL fWinActive = (pWinData->window->flags & SDL_WINDOW_INPUT_FOCUS) != 0;
232
233 if (!pSDLMouse->relative_mode || pSDLMouse->relative_mode_warp) {
234 if (!pSDLMouse->relative_mode && fWinActive &&
235 ((pWinData->window->flags & SDL_WINDOW_MOUSE_GRABBED) != 0) &&
236 (WinQueryCapture(HWND_DESKTOP) == pWinData->hwnd)) {
237
238 pointl.x = lX;
239 pointl.y = lY;
240
241 if (lX < 0)
242 lX = 0;
243 else if (lX >= pWinData->window->w)
244 lX = pWinData->window->w - 1;
245
246 if (lY < 0)
247 lY = 0;
248 else if (lY >= pWinData->window->h)
249 lY = pWinData->window->h - 1;
250
251 if (lX != pointl.x || lY != pointl.x) {
252 pointl.x = lX;
253 pointl.y = lY;
254 WinMapWindowPoints(pWinData->hwnd, HWND_DESKTOP, &pointl, 1);
255 pWinData->lSkipWMMouseMove++;
256 WinSetPointerPos(HWND_DESKTOP, pointl.x, pointl.y);
257 }
258 }
259
260 SDL_SendMouseMotion(pWinData->window, 0, 0, lX,
261 pWinData->window->h - lY - 1);
262 return;
263 }
264
265 if (fWinActive) {
266 pointl.x = pWinData->window->w / 2;
267 pointl.y = pWinData->window->h / 2;
268 WinMapWindowPoints(pWinData->hwnd, HWND_DESKTOP, &pointl, 1);
269
270 SDL_SendMouseMotion(pWinData->window, 0, 1,
271 lX - pointl.x, pointl.y - lY);
272
273 pWinData->lSkipWMMouseMove++;
274 WinSetPointerPos(HWND_DESKTOP, pointl.x, pointl.y);
275 }
276 }
277
_wmMouseButton(WINDATA * pWinData,ULONG ulButton,BOOL fDown)278 static VOID _wmMouseButton(WINDATA *pWinData, ULONG ulButton, BOOL fDown)
279 {
280 static ULONG aBtnGROP2SDL[3] = { SDL_BUTTON_LEFT, SDL_BUTTON_RIGHT,
281 SDL_BUTTON_MIDDLE };
282 SDL_Mouse *pSDLMouse = SDL_GetMouse();
283
284 if ((pSDLMouse->relative_mode || ((pWinData->window->flags & SDL_WINDOW_MOUSE_GRABBED) != 0)) &&
285 ((pWinData->window->flags & SDL_WINDOW_INPUT_FOCUS) != 0) &&
286 (WinQueryCapture(HWND_DESKTOP) != pWinData->hwnd)) {
287 /* Mouse should be captured. */
288 if (pSDLMouse->relative_mode && !pSDLMouse->relative_mode_warp) {
289 POINTL pointl;
290
291 pointl.x = pWinData->window->w / 2;
292 pointl.y = pWinData->window->h / 2;
293 WinMapWindowPoints(pWinData->hwnd, HWND_DESKTOP, &pointl, 1);
294 pWinData->lSkipWMMouseMove++;
295 WinSetPointerPos(HWND_DESKTOP, pointl.x, pointl.y);
296 }
297
298 WinSetCapture(HWND_DESKTOP, pWinData->hwnd);
299 }
300
301 SDL_SendMouseButton(pWinData->window, 0,
302 (fDown)? SDL_PRESSED : SDL_RELEASED,
303 aBtnGROP2SDL[ulButton]);
304 }
305
_wmChar(WINDATA * pWinData,MPARAM mp1,MPARAM mp2)306 static VOID _wmChar(WINDATA *pWinData, MPARAM mp1, MPARAM mp2)
307 {
308 ULONG ulFlags = SHORT1FROMMP(mp1); /* WM_CHAR flags */
309 ULONG ulVirtualKey = SHORT2FROMMP(mp2); /* Virtual key code VK_* */
310 ULONG ulCharCode = SHORT1FROMMP(mp2); /* Character code */
311 ULONG ulScanCode = CHAR4FROMMP(mp1); /* Scan code */
312
313 if (((ulFlags & (KC_VIRTUALKEY | KC_KEYUP | KC_ALT)) == (KC_VIRTUALKEY | KC_ALT)) &&
314 (ulVirtualKey == VK_F4)) {
315 SDL_SendWindowEvent(pWinData->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
316 }
317
318 if ((ulFlags & KC_SCANCODE) != 0) {
319 SDL_SendKeyboardKey(((ulFlags & KC_KEYUP) == 0)? SDL_PRESSED : SDL_RELEASED, aSDLScancode[ulScanCode]);
320 }
321
322 if ((ulFlags & KC_CHAR) != 0) {
323 CHAR acUTF8[4];
324 LONG lRC = StrUTF8(1, acUTF8, sizeof(acUTF8), (PSZ)&ulCharCode, 1);
325
326 SDL_SendKeyboardText((lRC > 0)? acUTF8 : (PSZ)&ulCharCode);
327 }
328 }
329
_wmMove(WINDATA * pWinData)330 static VOID _wmMove(WINDATA *pWinData)
331 {
332 SDL_DisplayMode *pSDLDisplayMode = _getDisplayModeForSDLWindow(pWinData->window);
333 POINTL pointl = { 0 };
334 RECTL rectl;
335
336 WinQueryWindowRect(pWinData->hwnd, &rectl);
337 WinMapWindowPoints(pWinData->hwnd, HWND_DESKTOP, (PPOINTL)&rectl, 2);
338
339 WinMapWindowPoints(pWinData->hwnd, HWND_DESKTOP, &pointl, 1);
340 SDL_SendWindowEvent(pWinData->window, SDL_WINDOWEVENT_MOVED, rectl.xLeft,
341 pSDLDisplayMode->h - rectl.yTop);
342 }
343
_wmDragOver(WINDATA * pWinData,PDRAGINFO pDragInfo)344 static MRESULT _wmDragOver(WINDATA *pWinData, PDRAGINFO pDragInfo)
345 {
346 ULONG ulIdx;
347 PDRAGITEM pDragItem;
348 USHORT usDrag = DOR_NEVERDROP;
349 USHORT usDragOp = DO_UNKNOWN;
350
351 if (!DrgAccessDraginfo(pDragInfo))
352 return MRFROM2SHORT(DOR_NEVERDROP, DO_UNKNOWN);
353
354 for (ulIdx = 0; ulIdx < pDragInfo->cditem; ulIdx++) {
355 pDragItem = DrgQueryDragitemPtr(pDragInfo, ulIdx);
356
357 /* We accept WPS files only. */
358 if (!DrgVerifyRMF(pDragItem, "DRM_OS2FILE", NULL)) {
359 usDrag = DOR_NEVERDROP;
360 usDragOp = DO_UNKNOWN;
361 break;
362 }
363
364 if (pDragInfo->usOperation == DO_DEFAULT &&
365 (pDragItem->fsSupportedOps & DO_COPYABLE) != 0) {
366 usDrag = DOR_DROP;
367 usDragOp = DO_COPY;
368 } else
369 if (pDragInfo->usOperation == DO_LINK &&
370 (pDragItem->fsSupportedOps & DO_LINKABLE) != 0) {
371 usDrag = DOR_DROP;
372 usDragOp = DO_LINK;
373 } else {
374 usDrag = DOR_NODROPOP;
375 usDragOp = DO_UNKNOWN;
376 break;
377 }
378 }
379
380 /* Update window (The DIVE surface spoiled while dragging) */
381 WinInvalidateRect(pWinData->hwnd, NULL, FALSE);
382 WinUpdateWindow(pWinData->hwnd);
383
384 DrgFreeDraginfo(pDragInfo);
385 return MPFROM2SHORT(usDrag, usDragOp);
386 }
387
_wmDrop(WINDATA * pWinData,PDRAGINFO pDragInfo)388 static MRESULT _wmDrop(WINDATA *pWinData, PDRAGINFO pDragInfo)
389 {
390 ULONG ulIdx;
391 PDRAGITEM pDragItem;
392 CHAR acFName[_MAX_PATH];
393 PCHAR pcFName;
394
395 if (!DrgAccessDraginfo(pDragInfo))
396 return MRFROM2SHORT(DOR_NEVERDROP, 0);
397
398 for (ulIdx = 0; ulIdx < pDragInfo->cditem; ulIdx++) {
399 pDragItem = DrgQueryDragitemPtr(pDragInfo, ulIdx);
400
401 if (DrgVerifyRMF(pDragItem, "DRM_OS2FILE", NULL) &&
402 pDragItem->hstrContainerName != NULLHANDLE &&
403 pDragItem->hstrSourceName != NULLHANDLE) {
404 /* Get file name from the item. */
405 DrgQueryStrName(pDragItem->hstrContainerName, sizeof(acFName), acFName);
406 pcFName = SDL_strchr(acFName, '\0');
407 DrgQueryStrName(pDragItem->hstrSourceName,
408 sizeof(acFName) - (pcFName - acFName), pcFName);
409
410 /* Send to SDL full file name converted to UTF-8. */
411 pcFName = OS2_SysToUTF8(acFName);
412 SDL_SendDropFile(pWinData->window, pcFName);
413 SDL_free(pcFName);
414
415 /* Notify a source that a drag operation is complete. */
416 if (pDragItem->hwndItem)
417 DrgSendTransferMsg(pDragItem->hwndItem, DM_ENDCONVERSATION,
418 (MPARAM)pDragItem->ulItemID,
419 (MPARAM)DMFL_TARGETSUCCESSFUL);
420 }
421 }
422
423 DrgDeleteDraginfoStrHandles(pDragInfo);
424 DrgFreeDraginfo(pDragInfo);
425
426 SDL_SendDropComplete(pWinData->window);
427
428 return (MRESULT)FALSE;
429 }
430
wndFrameProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)431 static MRESULT EXPENTRY wndFrameProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
432 {
433 HWND hwndClient = WinQueryWindow(hwnd, QW_BOTTOM);
434 WINDATA * pWinData = (WINDATA *)WinQueryWindowULong(hwndClient, 0);
435
436 if (pWinData == NULL)
437 return WinDefWindowProc(hwnd, msg, mp1, mp2);
438
439 /* Send a SDL_SYSWMEVENT if the application wants them */
440 if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
441 SDL_SysWMmsg wmmsg;
442
443 SDL_VERSION(&wmmsg.version);
444 wmmsg.subsystem = SDL_SYSWM_OS2;
445 wmmsg.msg.os2.fFrame = TRUE;
446 wmmsg.msg.os2.hwnd = hwnd;
447 wmmsg.msg.os2.msg = msg;
448 wmmsg.msg.os2.mp1 = mp1;
449 wmmsg.msg.os2.mp2 = mp2;
450 SDL_SendSysWMEvent(&wmmsg);
451 }
452
453 switch (msg) {
454 case WM_MINMAXFRAME:
455 if ((((PSWP)mp1)->fl & SWP_RESTORE) != 0) {
456 pWinData->lSkipWMMove += 2;
457 SDL_SendWindowEvent(pWinData->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
458 }
459 if ((((PSWP)mp1)->fl & SWP_MINIMIZE) != 0) {
460 pWinData->lSkipWMSize++;
461 pWinData->lSkipWMMove += 2;
462 SDL_SendWindowEvent(pWinData->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
463 }
464 if ((((PSWP)mp1)->fl & SWP_MAXIMIZE) != 0) {
465 SDL_SendWindowEvent(pWinData->window, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
466 }
467 break;
468
469 case WM_ADJUSTFRAMEPOS:
470 if (pWinData->lSkipWMAdjustFramePos > 0) {
471 pWinData->lSkipWMAdjustFramePos++;
472 break;
473 }
474 if ((pWinData->window->flags & SDL_WINDOW_FULLSCREEN) != 0 &&
475 (((PSWP)mp1)->fl & SWP_RESTORE) != 0) {
476 /* Keep fullscreen window size on restore. */
477 RECTL rectl;
478
479 rectl.xLeft = 0;
480 rectl.yBottom = 0;
481 rectl.xRight = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);
482 rectl.yTop = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
483 WinCalcFrameRect(hwnd, &rectl, FALSE);
484 ((PSWP)mp1)->x = rectl.xLeft;
485 ((PSWP)mp1)->y = rectl.yBottom;
486 ((PSWP)mp1)->cx = rectl.xRight - rectl.xLeft;
487 ((PSWP)mp1)->cy = rectl.yTop - rectl.yBottom;
488 }
489 if ((((PSWP)mp1)->fl & (SWP_SIZE | SWP_MINIMIZE)) == SWP_SIZE) {
490 if ((pWinData->window->flags & SDL_WINDOW_FULLSCREEN) != 0) {
491 /* SDL_WINDOW_FULLSCREEN_DESKTOP have flag SDL_WINDOW_FULLSCREEN... */
492 if (SDL_IsShapedWindow(pWinData->window))
493 OS2_ResizeWindowShape(pWinData->window);
494 break;
495 }
496 if ((SDL_GetWindowFlags(pWinData->window) & SDL_WINDOW_RESIZABLE) != 0) {
497 RECTL rectl;
498 int iMinW, iMinH, iMaxW, iMaxH;
499 int iWinW, iWinH;
500
501 rectl.xLeft = 0;
502 rectl.yBottom = 0;
503 SDL_GetWindowSize(pWinData->window,
504 (int *)&rectl.xRight, (int *)&rectl.yTop);
505 iWinW = rectl.xRight;
506 iWinH = rectl.yTop;
507
508 SDL_GetWindowMinimumSize(pWinData->window, &iMinW, &iMinH);
509 SDL_GetWindowMaximumSize(pWinData->window, &iMaxW, &iMaxH);
510
511 if (iWinW < iMinW)
512 rectl.xRight = iMinW;
513 else if (iMaxW != 0 && iWinW > iMaxW)
514 rectl.xRight = iMaxW;
515
516 if (iWinH < iMinH)
517 rectl.yTop = iMinW;
518 else if (iMaxH != 0 && iWinH > iMaxH)
519 rectl.yTop = iMaxH;
520
521 if (rectl.xRight == iWinW && rectl.yTop == iWinH) {
522 if (SDL_IsShapedWindow(pWinData->window))
523 OS2_ResizeWindowShape(pWinData->window);
524 break;
525 }
526
527 WinCalcFrameRect(hwnd, &rectl, FALSE);
528 ((PSWP)mp1)->cx = rectl.xRight - rectl.xLeft;
529 ((PSWP)mp1)->cy = rectl.yTop - rectl.yBottom;
530 }
531 }
532 break;
533 }
534
535 return pWinData->fnWndFrameProc(hwnd, msg, mp1, mp2);
536 }
537
wndProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)538 static MRESULT EXPENTRY wndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
539 {
540 WINDATA *pWinData = (WINDATA *)WinQueryWindowULong(hwnd, 0);
541
542 if (pWinData == NULL)
543 return WinDefWindowProc(hwnd, msg, mp1, mp2);
544
545 /* Send a SDL_SYSWMEVENT if the application wants them */
546 if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
547 SDL_SysWMmsg wmmsg;
548
549 SDL_VERSION(&wmmsg.version);
550 wmmsg.subsystem = SDL_SYSWM_OS2;
551 wmmsg.msg.os2.fFrame = FALSE;
552 wmmsg.msg.os2.hwnd = hwnd;
553 wmmsg.msg.os2.msg = msg;
554 wmmsg.msg.os2.mp1 = mp1;
555 wmmsg.msg.os2.mp2 = mp2;
556 SDL_SendSysWMEvent(&wmmsg);
557 }
558
559 switch (msg) {
560 case WM_CLOSE:
561 case WM_QUIT:
562 SDL_SendWindowEvent(pWinData->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
563 if (pWinData->fnUserWndProc == NULL)
564 return (MRESULT)FALSE;
565 break;
566
567 case WM_PAINT:
568 _wmPaint(pWinData, hwnd);
569 break;
570
571 case WM_SHOW:
572 SDL_SendWindowEvent(pWinData->window, (SHORT1FROMMP(mp1) == 0)?
573 SDL_WINDOWEVENT_HIDDEN :
574 SDL_WINDOWEVENT_SHOWN ,
575 0, 0);
576 break;
577
578 case WM_UPDATEFRAME:
579 /* Return TRUE - no further action for the frame control window procedure */
580 return (MRESULT)TRUE;
581
582 case WM_ACTIVATE:
583 if ((BOOL)mp1) {
584 POINTL pointl;
585
586 if (SDL_GetKeyboardFocus() != pWinData->window)
587 SDL_SetKeyboardFocus(pWinData->window);
588
589 WinQueryPointerPos(HWND_DESKTOP, &pointl);
590 WinMapWindowPoints(HWND_DESKTOP, pWinData->hwnd, &pointl, 1);
591 SDL_SendMouseMotion(pWinData->window, 0, 0,
592 pointl.x, pWinData->window->h - pointl.y - 1);
593 } else {
594 if (SDL_GetKeyboardFocus() == pWinData->window)
595 SDL_SetKeyboardFocus(NULL);
596
597 WinSetCapture(HWND_DESKTOP, NULLHANDLE);
598 }
599 break;
600
601 case WM_MOUSEMOVE:
602 WinSetPointer(HWND_DESKTOP, hptrCursor);
603
604 if (pWinData->lSkipWMMouseMove > 0)
605 pWinData->lSkipWMMouseMove--;
606 else {
607 _wmMouseMove(pWinData, SHORT1FROMMP(mp1), SHORT2FROMMP(mp1));
608 }
609 return (MRESULT)FALSE;
610
611 case WM_BUTTON1DOWN:
612 case WM_BUTTON1DBLCLK:
613 _wmMouseButton(pWinData, 0, TRUE);
614 break;
615
616 case WM_BUTTON1UP:
617 _wmMouseButton(pWinData, 0, FALSE);
618 break;
619
620 case WM_BUTTON2DOWN:
621 case WM_BUTTON2DBLCLK:
622 _wmMouseButton(pWinData, 1, TRUE);
623 break;
624
625 case WM_BUTTON2UP:
626 _wmMouseButton(pWinData, 1, FALSE);
627 break;
628
629 case WM_BUTTON3DOWN:
630 case WM_BUTTON3DBLCLK:
631 _wmMouseButton(pWinData, 2, TRUE);
632 break;
633
634 case WM_BUTTON3UP:
635 _wmMouseButton(pWinData, 2, FALSE);
636 break;
637
638 case WM_TRANSLATEACCEL:
639 /* ALT and acceleration keys not allowed (must be processed in WM_CHAR) */
640 if (mp1 == NULL || ((PQMSG)mp1)->msg != WM_CHAR)
641 break;
642 return (MRESULT)FALSE;
643
644 case WM_CHAR:
645 _wmChar(pWinData, mp1, mp2);
646 break;
647
648 case WM_SIZE:
649 if (pWinData->lSkipWMSize > 0)
650 pWinData->lSkipWMSize--;
651 else {
652 if ((pWinData->window->flags & SDL_WINDOW_FULLSCREEN) == 0) {
653 SDL_SendWindowEvent(pWinData->window, SDL_WINDOWEVENT_RESIZED,
654 SHORT1FROMMP(mp2), SHORT2FROMMP(mp2));
655 } else {
656 pWinData->lSkipWMVRNEnabled++;
657 }
658 }
659 break;
660
661 case WM_MOVE:
662 if (pWinData->lSkipWMMove > 0)
663 pWinData->lSkipWMMove--;
664 else if ((pWinData->window->flags & SDL_WINDOW_FULLSCREEN) == 0) {
665 _wmMove(pWinData);
666 }
667 break;
668
669 case WM_VRNENABLED:
670 if (pWinData->lSkipWMVRNEnabled > 0)
671 pWinData->lSkipWMVRNEnabled--;
672 else {
673 _setVisibleRegion(pWinData, TRUE);
674 }
675 return (MRESULT)TRUE;
676
677 case WM_VRNDISABLED:
678 _setVisibleRegion(pWinData, FALSE);
679 return (MRESULT)TRUE;
680
681 case DM_DRAGOVER:
682 return _wmDragOver(pWinData, (PDRAGINFO)PVOIDFROMMP(mp1));
683
684 case DM_DROP:
685 return _wmDrop(pWinData, (PDRAGINFO)PVOIDFROMMP(mp1));
686 }
687
688 return (pWinData->fnUserWndProc != NULL)?
689 pWinData->fnUserWndProc(hwnd, msg, mp1, mp2) :
690 WinDefWindowProc(hwnd, msg, mp1, mp2);
691 }
692
693
694 /* SDL routines.
695 * ------------
696 */
697
OS2_PumpEvents(_THIS)698 static void OS2_PumpEvents(_THIS)
699 {
700 SDL_VideoData *pVData = (SDL_VideoData *)_this->driverdata;
701 QMSG qmsg;
702
703 if (WinPeekMsg(pVData->hab, &qmsg, NULLHANDLE, 0, 0, PM_REMOVE))
704 WinDispatchMsg(pVData->hab, &qmsg);
705 }
706
_setupWindow(_THIS,SDL_Window * window,HWND hwndFrame,HWND hwnd)707 static WINDATA *_setupWindow(_THIS, SDL_Window *window, HWND hwndFrame,
708 HWND hwnd)
709 {
710 SDL_VideoData *pVData = (SDL_VideoData *)_this->driverdata;
711 WINDATA *pWinData = SDL_calloc(1, sizeof(WINDATA));
712
713 if (pWinData == NULL) {
714 SDL_OutOfMemory();
715 return NULL;
716 }
717 pWinData->hwnd = hwnd;
718 pWinData->hwndFrame = hwndFrame;
719 pWinData->window = window;
720 window->driverdata = pWinData;
721
722 WinSetWindowULong(hwnd, 0, (ULONG)pWinData);
723 pWinData->fnWndFrameProc = WinSubclassWindow(hwndFrame, wndFrameProc);
724
725 pWinData->pOutput = pVData->pOutput;
726 pWinData->pVOData = pVData->pOutput->Open();
727
728 WinSetVisibleRegionNotify(hwnd, TRUE);
729
730 return pWinData;
731 }
732
OS2_CreateWindow(_THIS,SDL_Window * window)733 static int OS2_CreateWindow(_THIS, SDL_Window *window)
734 {
735 RECTL rectl;
736 HWND hwndFrame, hwnd;
737 SDL_DisplayMode *pSDLDisplayMode = _getDisplayModeForSDLWindow(window);
738 ULONG ulFrameFlags = FCF_TASKLIST | FCF_TITLEBAR | FCF_SYSMENU |
739 FCF_MINBUTTON | FCF_SHELLPOSITION;
740 ULONG ulSWPFlags = SWP_SIZE | SWP_SHOW | SWP_ZORDER | SWP_ACTIVATE;
741 WINDATA *pWinData;
742
743 if (pSDLDisplayMode == NULL)
744 return -1;
745
746 /* Create a PM window */
747 if ((window->flags & SDL_WINDOW_RESIZABLE) != 0)
748 ulFrameFlags |= FCF_SIZEBORDER | FCF_DLGBORDER | FCF_MAXBUTTON;
749 else if ((window->flags & SDL_WINDOW_BORDERLESS) == 0)
750 ulFrameFlags |= FCF_DLGBORDER;
751
752 if ((window->flags & SDL_WINDOW_MAXIMIZED) != 0)
753 ulSWPFlags |= SWP_MAXIMIZE;
754 else if ((window->flags & SDL_WINDOW_MINIMIZED) != 0)
755 ulSWPFlags |= SWP_MINIMIZE;
756
757 hwndFrame = WinCreateStdWindow(HWND_DESKTOP, 0, &ulFrameFlags,
758 WIN_CLIENT_CLASS, "SDL2", 0, 0, 0, &hwnd);
759 if (hwndFrame == NULLHANDLE)
760 return SDL_SetError("Couldn't create window");
761
762 /* Setup window data and frame window procedure */
763 pWinData = _setupWindow(_this, window, hwndFrame, hwnd);
764 if (pWinData == NULL) {
765 WinDestroyWindow(hwndFrame);
766 return -1;
767 }
768
769 /* Show window */
770 rectl.xLeft = 0;
771 rectl.yBottom = 0;
772 rectl.xRight = window->w;
773 rectl.yTop = window->h;
774 WinCalcFrameRect(hwndFrame, &rectl, FALSE);
775 pWinData->lSkipWMSize++;
776 pWinData->lSkipWMMove++;
777 WinSetWindowPos(hwndFrame, HWND_TOP, rectl.xLeft, rectl.yBottom,
778 rectl.xRight - rectl.xLeft, rectl.yTop - rectl.yBottom,
779 ulSWPFlags);
780
781 rectl.xLeft = 0;
782 rectl.yBottom = 0;
783 WinMapWindowPoints(hwnd, HWND_DESKTOP, (PPOINTL)&rectl, 1);
784 window->x = rectl.xLeft;
785 window->y = pSDLDisplayMode->h - (rectl.yBottom + window->h);
786
787 window->flags |= SDL_WINDOW_SHOWN;
788
789 return 0;
790 }
791
OS2_CreateWindowFrom(_THIS,SDL_Window * window,const void * data)792 static int OS2_CreateWindowFrom(_THIS, SDL_Window *window, const void *data)
793 {
794 SDL_VideoData *pVData = (SDL_VideoData *)_this->driverdata;
795 CHAR acBuf[256];
796 CLASSINFO stCI;
797 HWND hwndUser = (HWND)data;
798 HWND hwndFrame, hwnd;
799 ULONG cbText;
800 PSZ pszText;
801 WINDATA *pWinData;
802 SDL_DisplayMode *pSDLDisplayMode = _getDisplayModeForSDLWindow(window);
803 SWP swp;
804 POINTL pointl;
805
806 debug_os2("Enter");
807 if (pSDLDisplayMode == NULL)
808 return -1;
809
810 /* User can accept client OR frame window handle.
811 * Get client and frame window handles. */
812 WinQueryClassName(hwndUser, sizeof(acBuf), acBuf);
813 if (!WinQueryClassInfo(pVData->hab, acBuf, &stCI))
814 return SDL_SetError("Cannot get user window class information");
815
816 if ((stCI.flClassStyle & CS_FRAME) == 0) {
817 /* Client window handle is specified */
818 hwndFrame = WinQueryWindow(hwndUser, QW_PARENT);
819 if (hwndFrame == NULLHANDLE)
820 return SDL_SetError("Cannot get parent window handle");
821
822 if ((ULONG)WinSendMsg(hwndFrame, WM_QUERYFRAMEINFO, 0, 0) == 0)
823 return SDL_SetError("Parent window is not a frame window");
824
825 hwnd = hwndUser;
826 } else {
827 /* Frame window handle is specified */
828 hwnd = WinWindowFromID(hwndUser, FID_CLIENT);
829 if (hwnd == NULLHANDLE)
830 return SDL_SetError("Cannot get client window handle");
831
832 hwndFrame = hwndUser;
833
834 WinQueryClassName(hwnd, sizeof(acBuf), acBuf);
835 if (!WinQueryClassInfo(pVData->hab, acBuf, &stCI))
836 return SDL_SetError("Cannot get client window class information");
837 }
838
839 /* Check window's reserved storage */
840 if (stCI.cbWindowData < sizeof(ULONG))
841 return SDL_SetError("Reserved storage of window must be at least %u bytes", sizeof(ULONG));
842
843 /* Set SDL-window title */
844 cbText = WinQueryWindowTextLength(hwndFrame);
845 pszText = SDL_stack_alloc(CHAR, cbText + 1);
846
847 if (pszText != NULL)
848 cbText = (pszText != NULL)? WinQueryWindowText(hwndFrame, cbText, pszText) : 0;
849
850 if (cbText != 0)
851 window->title = OS2_SysToUTF8(pszText);
852
853 if (pszText != NULL)
854 SDL_stack_free(pszText);
855
856 /* Set SDL-window flags */
857 window->flags &= ~(SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS |
858 SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED |
859 SDL_WINDOW_MINIMIZED | SDL_WINDOW_INPUT_FOCUS);
860
861 if (WinIsWindowVisible(hwnd))
862 window->flags |= SDL_WINDOW_SHOWN;
863
864 WinSendMsg(hwndFrame, WM_QUERYBORDERSIZE, MPFROMP(&pointl), 0);
865 if (pointl.y == WinQuerySysValue(HWND_DESKTOP, SV_CYSIZEBORDER))
866 window->flags |= SDL_WINDOW_RESIZABLE;
867 else if (pointl.y <= WinQuerySysValue(HWND_DESKTOP, SV_CYBORDER))
868 window->flags |= SDL_WINDOW_BORDERLESS;
869
870 WinQueryWindowPos(hwndFrame, &swp);
871
872 if ((swp.fl & SWP_MAXIMIZE) != 0)
873 window->flags |= SDL_WINDOW_MAXIMIZED;
874 if ((swp.fl & SWP_MINIMIZE) != 0)
875 window->flags |= SDL_WINDOW_MINIMIZED;
876
877 pointl.x = 0;
878 pointl.y = 0;
879 WinMapWindowPoints(hwnd, HWND_DESKTOP, &pointl, 1);
880 window->x = pointl.x;
881 window->y = pSDLDisplayMode->h - (pointl.y + swp.cy);
882
883 WinQueryWindowPos(hwnd, &swp);
884 window->w = swp.cx;
885 window->h = swp.cy;
886
887 /* Setup window data and frame window procedure */
888 pWinData = _setupWindow(_this, window, hwndFrame, hwnd);
889 if (pWinData == NULL) {
890 SDL_free(window->title);
891 window->title = NULL;
892 return -1;
893 }
894 pWinData->fnUserWndProc = WinSubclassWindow(hwnd, wndProc);
895
896 if (WinQueryActiveWindow(HWND_DESKTOP) == hwndFrame)
897 SDL_SetKeyboardFocus(window);
898
899 return 0;
900 }
901
OS2_DestroyWindow(_THIS,SDL_Window * window)902 static void OS2_DestroyWindow(_THIS, SDL_Window * window)
903 {
904 SDL_VideoData *pVData = (SDL_VideoData *)_this->driverdata;
905 WINDATA *pWinData = (WINDATA *)window->driverdata;
906
907 debug_os2("Enter");
908 if (pWinData == NULL)
909 return;
910
911 if (pWinData->fnUserWndProc == NULL) {
912 /* Window was created by SDL (OS2_CreateWindow()),
913 * not by user (OS2_CreateWindowFrom()) */
914 WinDestroyWindow(pWinData->hwndFrame);
915 } else {
916 WinSetWindowULong(pWinData->hwnd, 0, 0);
917 }
918
919 if ((pVData != NULL) && (pWinData->pVOData != NULL)) {
920 pVData->pOutput->Close(pWinData->pVOData);
921 pWinData->pVOData = NULL;
922 }
923
924 if (pWinData->hptrIcon != NULLHANDLE) {
925 WinDestroyPointer(pWinData->hptrIcon);
926 pWinData->hptrIcon = NULLHANDLE;
927 }
928
929 SDL_free(pWinData);
930 window->driverdata = NULL;
931 }
932
OS2_SetWindowTitle(_THIS,SDL_Window * window)933 static void OS2_SetWindowTitle(_THIS, SDL_Window *window)
934 {
935 PSZ pszTitle = (window->title == NULL)? NULL : OS2_UTF8ToSys(window->title);
936
937 WinSetWindowText(((WINDATA *)window->driverdata)->hwndFrame, pszTitle);
938 SDL_free(pszTitle);
939 }
940
OS2_SetWindowIcon(_THIS,SDL_Window * window,SDL_Surface * icon)941 static void OS2_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon)
942 {
943 WINDATA *pWinData = (WINDATA *)window->driverdata;
944 HPOINTER hptr = utilCreatePointer(icon, 0, 0);
945
946 if (hptr == NULLHANDLE)
947 return;
948
949 /* Destroy old icon */
950 if (pWinData->hptrIcon != NULLHANDLE)
951 WinDestroyPointer(pWinData->hptrIcon);
952
953 /* Set new window icon */
954 pWinData->hptrIcon = hptr;
955 if (!WinSendMsg(pWinData->hwndFrame, WM_SETICON, MPFROMLONG(hptr), 0)) {
956 debug_os2("Cannot set icon for the window");
957 }
958 }
959
OS2_SetWindowPosition(_THIS,SDL_Window * window)960 static void OS2_SetWindowPosition(_THIS, SDL_Window *window)
961 {
962 WINDATA *pWinData = (WINDATA *)window->driverdata;
963 RECTL rectl;
964 ULONG ulFlags;
965 SDL_DisplayMode *pSDLDisplayMode = _getDisplayModeForSDLWindow(window);
966
967 debug_os2("Enter");
968 if (pSDLDisplayMode == NULL)
969 return;
970
971 rectl.xLeft = 0;
972 rectl.yBottom = 0;
973 rectl.xRight = window->w;
974 rectl.yTop = window->h;
975 WinCalcFrameRect(pWinData->hwndFrame, &rectl, FALSE);
976
977 if (SDL_ShouldAllowTopmost() &&
978 (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) ==
979 (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS) )
980 ulFlags = SWP_ZORDER | SWP_MOVE | SWP_SIZE;
981 else
982 ulFlags = SWP_MOVE | SWP_SIZE;
983
984 pWinData->lSkipWMSize++;
985 pWinData->lSkipWMMove++;
986 WinSetWindowPos(pWinData->hwndFrame, HWND_TOP,
987 window->x + rectl.xLeft,
988 (pSDLDisplayMode->h - window->y) - window->h + rectl.yBottom,
989 rectl.xRight - rectl.xLeft, rectl.yTop - rectl.yBottom,
990 ulFlags);
991 }
992
OS2_SetWindowSize(_THIS,SDL_Window * window)993 static void OS2_SetWindowSize(_THIS, SDL_Window *window)
994 {
995 debug_os2("Enter");
996 OS2_SetWindowPosition(_this, window);
997 }
998
OS2_ShowWindow(_THIS,SDL_Window * window)999 static void OS2_ShowWindow(_THIS, SDL_Window *window)
1000 {
1001 WINDATA *pWinData = (WINDATA *)window->driverdata;
1002
1003 debug_os2("Enter");
1004 WinShowWindow(pWinData->hwndFrame, TRUE);
1005 }
1006
OS2_HideWindow(_THIS,SDL_Window * window)1007 static void OS2_HideWindow(_THIS, SDL_Window *window)
1008 {
1009 WINDATA *pWinData = (WINDATA *)window->driverdata;
1010
1011 debug_os2("Enter");
1012 WinShowWindow(pWinData->hwndFrame, FALSE);
1013 }
1014
OS2_RaiseWindow(_THIS,SDL_Window * window)1015 static void OS2_RaiseWindow(_THIS, SDL_Window *window)
1016 {
1017 debug_os2("Enter");
1018 OS2_SetWindowPosition(_this, window);
1019 }
1020
OS2_MaximizeWindow(_THIS,SDL_Window * window)1021 static void OS2_MaximizeWindow(_THIS, SDL_Window *window)
1022 {
1023 WINDATA *pWinData = (WINDATA *)window->driverdata;
1024
1025 debug_os2("Enter");
1026 WinSetWindowPos(pWinData->hwndFrame, HWND_TOP, 0, 0, 0, 0, SWP_MAXIMIZE);
1027 }
1028
OS2_MinimizeWindow(_THIS,SDL_Window * window)1029 static void OS2_MinimizeWindow(_THIS, SDL_Window *window)
1030 {
1031 WINDATA *pWinData = (WINDATA *)window->driverdata;
1032
1033 debug_os2("Enter");
1034 WinSetWindowPos(pWinData->hwndFrame, HWND_TOP, 0, 0, 0, 0, SWP_MINIMIZE | SWP_DEACTIVATE);
1035 }
1036
OS2_RestoreWindow(_THIS,SDL_Window * window)1037 static void OS2_RestoreWindow(_THIS, SDL_Window *window)
1038 {
1039 WINDATA *pWinData = (WINDATA *)window->driverdata;
1040
1041 debug_os2("Enter");
1042 WinSetWindowPos(pWinData->hwndFrame, HWND_TOP, 0, 0, 0, 0, SWP_RESTORE);
1043 }
1044
OS2_SetWindowBordered(_THIS,SDL_Window * window,SDL_bool bordered)1045 static void OS2_SetWindowBordered(_THIS, SDL_Window * window,
1046 SDL_bool bordered)
1047 {
1048 WINDATA *pWinData = (WINDATA *)window->driverdata;
1049 ULONG ulStyle = WinQueryWindowULong(pWinData->hwndFrame, QWL_STYLE);
1050 RECTL rectl;
1051
1052 debug_os2("Enter");
1053
1054 /* New frame sytle */
1055 if (bordered)
1056 ulStyle |= ((window->flags & SDL_WINDOW_RESIZABLE) != 0) ? FS_SIZEBORDER : FS_DLGBORDER;
1057 else
1058 ulStyle &= ~(FS_SIZEBORDER | FS_BORDER | FS_DLGBORDER);
1059
1060 /* Save client window position */
1061 WinQueryWindowRect(pWinData->hwnd, &rectl);
1062 WinMapWindowPoints(pWinData->hwnd, HWND_DESKTOP, (PPOINTL)&rectl, 2);
1063
1064 /* Change the frame */
1065 WinSetWindowULong(pWinData->hwndFrame, QWL_STYLE, ulStyle);
1066 WinSendMsg(pWinData->hwndFrame, WM_UPDATEFRAME, MPFROMLONG(FCF_BORDER), 0);
1067
1068 /* Restore client window position */
1069 WinCalcFrameRect(pWinData->hwndFrame, &rectl, FALSE);
1070 pWinData->lSkipWMMove++;
1071 WinSetWindowPos(pWinData->hwndFrame, HWND_TOP, rectl.xLeft, rectl.yBottom,
1072 rectl.xRight - rectl.xLeft,
1073 rectl.yTop - rectl.yBottom,
1074 SWP_SIZE | SWP_MOVE | SWP_NOADJUST);
1075 }
1076
OS2_SetWindowFullscreen(_THIS,SDL_Window * window,SDL_VideoDisplay * display,SDL_bool fullscreen)1077 static void OS2_SetWindowFullscreen(_THIS, SDL_Window *window,
1078 SDL_VideoDisplay *display,
1079 SDL_bool fullscreen)
1080 {
1081 RECTL rectl;
1082 ULONG ulFlags;
1083 WINDATA *pWinData = (WINDATA *)window->driverdata;
1084 SDL_DisplayMode *pSDLDisplayMode = &display->current_mode;
1085
1086 debug_os2("Enter, fullscreen: %u", fullscreen);
1087
1088 if (pSDLDisplayMode == NULL)
1089 return;
1090
1091 if (SDL_ShouldAllowTopmost() &&
1092 (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS))
1093 ulFlags = SWP_SIZE | SWP_MOVE | SWP_ZORDER | SWP_NOADJUST;
1094 else
1095 ulFlags = SWP_SIZE | SWP_MOVE | SWP_NOADJUST;
1096
1097 if (fullscreen) {
1098 rectl.xLeft = 0;
1099 rectl.yBottom = 0;
1100 rectl.xRight = pSDLDisplayMode->w;
1101 rectl.yTop = pSDLDisplayMode->h;
1102 /* We need send the restore command now to allow WinCalcFrameRect() */
1103 WinSetWindowPos(pWinData->hwndFrame, HWND_TOP, 0, 0, 0, 0, SWP_RESTORE);
1104 } else {
1105 pWinData->lSkipWMMove++;
1106 rectl.xLeft = window->windowed.x;
1107 rectl.yTop = pSDLDisplayMode->h - window->windowed.y;
1108 rectl.xRight = rectl.xLeft + window->windowed.w;
1109 rectl.yBottom = rectl.yTop - window->windowed.h;
1110 }
1111
1112 if (!WinCalcFrameRect(pWinData->hwndFrame, &rectl, FALSE)) {
1113 debug_os2("WinCalcFrameRect() failed");
1114 }
1115 else if (!WinSetWindowPos(pWinData->hwndFrame, HWND_TOP,
1116 rectl.xLeft, rectl.yBottom,
1117 rectl.xRight - rectl.xLeft, rectl.yTop - rectl.yBottom,
1118 ulFlags)) {
1119 debug_os2("WinSetWindowPos() failed");
1120 }
1121 }
1122
OS2_GetWindowWMInfo(_THIS,SDL_Window * window,struct SDL_SysWMinfo * info)1123 static SDL_bool OS2_GetWindowWMInfo(_THIS, SDL_Window * window,
1124 struct SDL_SysWMinfo *info)
1125 {
1126 WINDATA *pWinData = (WINDATA *)window->driverdata;
1127
1128 if (info->version.major <= SDL_MAJOR_VERSION) {
1129 info->subsystem = SDL_SYSWM_OS2;
1130 info->info.os2.hwnd = pWinData->hwnd;
1131 info->info.os2.hwndFrame = pWinData->hwndFrame;
1132 return SDL_TRUE;
1133 }
1134
1135 SDL_SetError("Application not compiled with SDL %u.%u",
1136 SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
1137 return SDL_FALSE;
1138 }
1139
OS2_OnWindowEnter(_THIS,SDL_Window * window)1140 static void OS2_OnWindowEnter(_THIS, SDL_Window * window)
1141 {
1142 }
1143
OS2_SetWindowHitTest(SDL_Window * window,SDL_bool enabled)1144 static int OS2_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
1145 {
1146 debug_os2("Enter");
1147 return 0;
1148 }
1149
OS2_SetWindowMouseGrab(_THIS,SDL_Window * window,SDL_bool grabbed)1150 static void OS2_SetWindowMouseGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
1151 {
1152 WINDATA *pWinData = (WINDATA *)window->driverdata;
1153
1154 debug_os2("Enter, %u", grabbed);
1155 _mouseCheck(pWinData);
1156 }
1157
1158
1159 /* Shaper
1160 */
1161 typedef struct _SHAPERECTS {
1162 PRECTL pRects;
1163 ULONG cRects;
1164 ULONG ulWinHeight;
1165 } SHAPERECTS;
1166
_combineRectRegions(SDL_ShapeTree * node,void * closure)1167 static void _combineRectRegions(SDL_ShapeTree *node, void *closure)
1168 {
1169 SHAPERECTS *pShapeRects = (SHAPERECTS *)closure;
1170 PRECTL pRect;
1171
1172 /* Expand rectangles list */
1173 if ((pShapeRects->cRects & 0x0F) == 0) {
1174 pRect = SDL_realloc(pShapeRects->pRects, (pShapeRects->cRects + 0x10) * sizeof(RECTL));
1175 if (pRect == NULL)
1176 return;
1177 pShapeRects->pRects = pRect;
1178 }
1179
1180 /* Add a new rectangle */
1181 pRect = &pShapeRects->pRects[pShapeRects->cRects];
1182 pShapeRects->cRects++;
1183 /* Fill rectangle data */
1184 pRect->xLeft = node->data.shape.x;
1185 pRect->yTop = pShapeRects->ulWinHeight - node->data.shape.y;
1186 pRect->xRight += node->data.shape.w;
1187 pRect->yBottom = pRect->yTop - node->data.shape.h;
1188 }
1189
OS2_CreateShaper(SDL_Window * window)1190 static SDL_WindowShaper* OS2_CreateShaper(SDL_Window * window)
1191 {
1192 SDL_WindowShaper* pSDLShaper = SDL_malloc(sizeof(SDL_WindowShaper));
1193
1194 debug_os2("Enter");
1195 pSDLShaper->window = window;
1196 pSDLShaper->mode.mode = ShapeModeDefault;
1197 pSDLShaper->mode.parameters.binarizationCutoff = 1;
1198 pSDLShaper->userx = 0;
1199 pSDLShaper->usery = 0;
1200 pSDLShaper->driverdata = (SDL_ShapeTree *)NULL;
1201 window->shaper = pSDLShaper;
1202
1203 if (OS2_ResizeWindowShape(window) != 0) {
1204 window->shaper = NULL;
1205 SDL_free(pSDLShaper);
1206 return NULL;
1207 }
1208
1209 return pSDLShaper;
1210 }
1211
OS2_SetWindowShape(SDL_WindowShaper * shaper,SDL_Surface * shape,SDL_WindowShapeMode * shape_mode)1212 static int OS2_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape,
1213 SDL_WindowShapeMode *shape_mode)
1214 {
1215 SDL_ShapeTree *pShapeTree;
1216 WINDATA *pWinData;
1217 SHAPERECTS stShapeRects = { 0 };
1218 HPS hps;
1219
1220 debug_os2("Enter");
1221 if (shaper == NULL || shape == NULL ||
1222 (shape->format->Amask == 0 && shape_mode->mode != ShapeModeColorKey) ||
1223 shape->w != shaper->window->w || shape->h != shaper->window->h) {
1224 return SDL_INVALID_SHAPE_ARGUMENT;
1225 }
1226
1227 if (shaper->driverdata != NULL)
1228 SDL_FreeShapeTree((SDL_ShapeTree **)&shaper->driverdata);
1229
1230 pShapeTree = SDL_CalculateShapeTree(*shape_mode, shape);
1231 shaper->driverdata = pShapeTree;
1232
1233 stShapeRects.ulWinHeight = shaper->window->h;
1234 SDL_TraverseShapeTree(pShapeTree, &_combineRectRegions, &stShapeRects);
1235
1236 pWinData = (WINDATA *)shaper->window->driverdata;
1237 hps = WinGetPS(pWinData->hwnd);
1238
1239 if (pWinData->hrgnShape != NULLHANDLE)
1240 GpiDestroyRegion(hps, pWinData->hrgnShape);
1241
1242 pWinData->hrgnShape = (stShapeRects.pRects == NULL) ? NULLHANDLE :
1243 GpiCreateRegion(hps, stShapeRects.cRects, stShapeRects.pRects);
1244
1245 WinReleasePS(hps);
1246 SDL_free(stShapeRects.pRects);
1247 WinSendMsg(pWinData->hwnd, WM_VRNENABLED, 0, 0);
1248
1249 return 0;
1250 }
1251
OS2_ResizeWindowShape(SDL_Window * window)1252 static int OS2_ResizeWindowShape(SDL_Window *window)
1253 {
1254 debug_os2("Enter");
1255 if (window == NULL)
1256 return -1;
1257
1258 if (window->x != -1000) {
1259 if (window->shaper->driverdata != NULL)
1260 SDL_FreeShapeTree((SDL_ShapeTree **)window->shaper->driverdata);
1261
1262 if (window->shaper->hasshape == SDL_TRUE) {
1263 window->shaper->userx = window->x;
1264 window->shaper->usery = window->y;
1265 SDL_SetWindowPosition(window, -1000, -1000);
1266 }
1267 }
1268
1269 return 0;
1270 }
1271
1272
1273 /* Frame buffer
1274 */
OS2_DestroyWindowFramebuffer(_THIS,SDL_Window * window)1275 static void OS2_DestroyWindowFramebuffer(_THIS, SDL_Window *window)
1276 {
1277 WINDATA *pWinData = (WINDATA *)window->driverdata;
1278
1279 debug_os2("Enter");
1280 if (pWinData != NULL && pWinData->pVOData != NULL)
1281 pWinData->pOutput->VideoBufFree(pWinData->pVOData);
1282 }
1283
OS2_CreateWindowFramebuffer(_THIS,SDL_Window * window,Uint32 * format,void ** pixels,int * pitch)1284 static int OS2_CreateWindowFramebuffer(_THIS, SDL_Window *window,
1285 Uint32 *format, void **pixels,
1286 int *pitch)
1287 {
1288 WINDATA *pWinData = (WINDATA *)window->driverdata;
1289 SDL_VideoDisplay *pSDLDisplay = SDL_GetDisplayForWindow(window);
1290 SDL_DisplayMode *pSDLDisplayMode;
1291 MODEDATA *pModeData;
1292 ULONG ulWidth, ulHeight;
1293
1294 debug_os2("Enter");
1295 if (pSDLDisplay == NULL) {
1296 debug_os2("No display for the window");
1297 return -1;
1298 }
1299
1300 pSDLDisplayMode = &pSDLDisplay->current_mode;
1301 pModeData = (MODEDATA *)pSDLDisplayMode->driverdata;
1302 if (pModeData == NULL)
1303 return SDL_SetError("No mode data for the display");
1304
1305 SDL_GetWindowSize(window, (int *)&ulWidth, (int *)&ulHeight);
1306 debug_os2("Window size: %u x %u", ulWidth, ulHeight);
1307
1308 *pixels = pWinData->pOutput->VideoBufAlloc(
1309 pWinData->pVOData, ulWidth, ulHeight, pModeData->ulDepth,
1310 pModeData->fccColorEncoding, (PULONG)pitch);
1311 if (*pixels == NULL)
1312 return -1;
1313
1314 *format = pSDLDisplayMode->format;
1315 debug_os2("Pitch: %u, frame buffer: 0x%X.", *pitch, *pixels);
1316 WinSendMsg(pWinData->hwnd, WM_VRNENABLED, 0, 0);
1317
1318 return 0;
1319 }
1320
OS2_UpdateWindowFramebuffer(_THIS,SDL_Window * window,const SDL_Rect * rects,int numrects)1321 static int OS2_UpdateWindowFramebuffer(_THIS, SDL_Window * window,
1322 const SDL_Rect *rects, int numrects)
1323 {
1324 WINDATA *pWinData = (WINDATA *)window->driverdata;
1325
1326 return pWinData->pOutput->Update(pWinData->pVOData, pWinData->hwnd,
1327 (SDL_Rect *)rects, (ULONG)numrects)
1328 ? 0 : -1;
1329 }
1330
1331
1332 /* Clipboard
1333 */
OS2_SetClipboardText(_THIS,const char * text)1334 static int OS2_SetClipboardText(_THIS, const char *text)
1335 {
1336 SDL_VideoData *pVData = (SDL_VideoData *)_this->driverdata;
1337 PSZ pszClipboard;
1338 PSZ pszText = (text == NULL)? NULL : OS2_UTF8ToSys(text);
1339 ULONG cbText;
1340 ULONG ulRC;
1341 BOOL fSuccess;
1342
1343 debug_os2("Enter");
1344 if (pszText == NULL)
1345 return -1;
1346 cbText = SDL_strlen(pszText) + 1;
1347
1348 ulRC = DosAllocSharedMem((PPVOID)&pszClipboard, 0, cbText,
1349 PAG_COMMIT | PAG_READ | PAG_WRITE |
1350 OBJ_GIVEABLE | OBJ_GETTABLE | OBJ_TILE);
1351 if (ulRC != NO_ERROR) {
1352 debug_os2("DosAllocSharedMem() failed, rc = %u", ulRC);
1353 SDL_free(pszText);
1354 return -1;
1355 }
1356
1357 SDL_memcpy(pszClipboard, pszText, cbText);
1358 SDL_free(pszText);
1359
1360 if (!WinOpenClipbrd(pVData->hab)) {
1361 debug_os2("WinOpenClipbrd() failed");
1362 fSuccess = FALSE;
1363 } else {
1364 WinEmptyClipbrd(pVData->hab);
1365 fSuccess = WinSetClipbrdData(pVData->hab, (ULONG)pszClipboard, CF_TEXT, CFI_POINTER);
1366 if (!fSuccess) {
1367 debug_os2("WinOpenClipbrd() failed");
1368 }
1369 WinCloseClipbrd(pVData->hab);
1370 }
1371
1372 if (!fSuccess) {
1373 DosFreeMem(pszClipboard);
1374 return -1;
1375 }
1376 return 0;
1377 }
1378
OS2_GetClipboardText(_THIS)1379 static char *OS2_GetClipboardText(_THIS)
1380 {
1381 SDL_VideoData *pVData = (SDL_VideoData *)_this->driverdata;
1382 PSZ pszClipboard = NULL;
1383
1384 if (!WinOpenClipbrd(pVData->hab)) {
1385 debug_os2("WinOpenClipbrd() failed");
1386 } else {
1387 pszClipboard = (PSZ)WinQueryClipbrdData(pVData->hab, CF_TEXT);
1388 if (pszClipboard != NULL)
1389 pszClipboard = OS2_SysToUTF8(pszClipboard);
1390 WinCloseClipbrd(pVData->hab);
1391 }
1392
1393 return (pszClipboard == NULL) ? SDL_strdup("") : pszClipboard;
1394 }
1395
OS2_HasClipboardText(_THIS)1396 static SDL_bool OS2_HasClipboardText(_THIS)
1397 {
1398 SDL_VideoData *pVData = (SDL_VideoData *)_this->driverdata;
1399 SDL_bool fClipboard;
1400
1401 if (!WinOpenClipbrd(pVData->hab)) {
1402 debug_os2("WinOpenClipbrd() failed");
1403 return SDL_FALSE;
1404 }
1405
1406 fClipboard = ((PSZ)WinQueryClipbrdData(pVData->hab, CF_TEXT) != NULL)?
1407 SDL_TRUE : SDL_FALSE;
1408 WinCloseClipbrd(pVData->hab);
1409
1410 return fClipboard;
1411 }
1412
1413
OS2_VideoInit(_THIS)1414 static int OS2_VideoInit(_THIS)
1415 {
1416 SDL_VideoData *pVData;
1417 PTIB tib;
1418 PPIB pib;
1419
1420 /* Create SDL video driver private data */
1421 pVData = SDL_calloc(1, sizeof(SDL_VideoData));
1422 if (pVData == NULL)
1423 return SDL_OutOfMemory();
1424
1425 /* Change process type code for use Win* API from VIO session */
1426 DosGetInfoBlocks(&tib, &pib);
1427 if (pib->pib_ultype == 2 || pib->pib_ultype == 0) {
1428 /* VIO windowable or fullscreen protect-mode session */
1429 pib->pib_ultype = 3; /* Presentation Manager protect-mode session */
1430 }
1431
1432 /* PM initialization */
1433 pVData->hab = WinInitialize(0);
1434 pVData->hmq = WinCreateMsgQueue(pVData->hab, 0);
1435 if (pVData->hmq == NULLHANDLE) {
1436 SDL_free(pVData);
1437 return SDL_SetError("Message queue cannot be created.");
1438 }
1439
1440 if (!WinRegisterClass(pVData->hab, WIN_CLIENT_CLASS, wndProc,
1441 CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT,
1442 sizeof(SDL_VideoData*))) {
1443 SDL_free(pVData);
1444 return SDL_SetError("Window class not successfully registered.");
1445 }
1446
1447 if (SDL_strcasecmp(_this->name, OS2DRIVER_NAME_VMAN) == 0)
1448 pVData->pOutput = &voVMan;
1449 else
1450 pVData->pOutput = &voDive;
1451
1452 _this->driverdata = pVData;
1453
1454 /* Add display */
1455 {
1456 SDL_VideoDisplay stSDLDisplay;
1457 SDL_DisplayMode stSDLDisplayMode;
1458 DISPLAYDATA *pDisplayData;
1459 MODEDATA *pModeData;
1460 VIDEOOUTPUTINFO stVOInfo;
1461
1462 if (!pVData->pOutput->QueryInfo(&stVOInfo)) {
1463 SDL_free(pVData);
1464 return SDL_SetError("Video mode query failed.");
1465 }
1466
1467 SDL_zero(stSDLDisplay); SDL_zero(stSDLDisplayMode);
1468
1469 stSDLDisplayMode.format = _getSDLPixelFormat(stVOInfo.ulBPP,
1470 stVOInfo.fccColorEncoding);
1471 stSDLDisplayMode.w = stVOInfo.ulHorizResolution;
1472 stSDLDisplayMode.h = stVOInfo.ulVertResolution;
1473 stSDLDisplayMode.refresh_rate = 0;
1474 stSDLDisplayMode.driverdata = NULL;
1475
1476 pModeData = SDL_malloc(sizeof(MODEDATA));
1477 if (pModeData != NULL) {
1478 pModeData->ulDepth = stVOInfo.ulBPP;
1479 pModeData->fccColorEncoding = stVOInfo.fccColorEncoding;
1480 pModeData->ulScanLineBytes = stVOInfo.ulScanLineSize;
1481 stSDLDisplayMode.driverdata = pModeData;
1482 }
1483
1484 stSDLDisplay.name = "Primary";
1485 stSDLDisplay.desktop_mode = stSDLDisplayMode;
1486 stSDLDisplay.current_mode = stSDLDisplayMode;
1487 stSDLDisplay.driverdata = NULL;
1488 stSDLDisplay.num_display_modes = 0;
1489
1490 pDisplayData = SDL_malloc(sizeof(DISPLAYDATA));
1491 if (pDisplayData != NULL) {
1492 HPS hps = WinGetPS(HWND_DESKTOP);
1493 HDC hdc = GpiQueryDevice(hps);
1494
1495 /* May be we can use CAPS_HORIZONTAL_RESOLUTION and
1496 * CAPS_VERTICAL_RESOLUTION - pels per meter? */
1497 DevQueryCaps(hdc, CAPS_HORIZONTAL_FONT_RES, 1,
1498 (PLONG)&pDisplayData->ulDPIHor);
1499 DevQueryCaps(hdc, CAPS_VERTICAL_FONT_RES, 1,
1500 (PLONG)&pDisplayData->ulDPIVer);
1501 WinReleasePS(hps);
1502
1503 pDisplayData->ulDPIDiag = SDL_ComputeDiagonalDPI(
1504 stVOInfo.ulHorizResolution, stVOInfo.ulVertResolution,
1505 (float)stVOInfo.ulHorizResolution / pDisplayData->ulDPIHor,
1506 (float)stVOInfo.ulVertResolution / pDisplayData->ulDPIVer);
1507
1508 stSDLDisplayMode.driverdata = pDisplayData;
1509 }
1510
1511 SDL_AddVideoDisplay(&stSDLDisplay, SDL_FALSE);
1512 }
1513
1514 OS2_InitMouse(_this, pVData->hab);
1515
1516 return 0;
1517 }
1518
OS2_VideoQuit(_THIS)1519 static void OS2_VideoQuit(_THIS)
1520 {
1521 SDL_VideoData *pVData = (SDL_VideoData *)_this->driverdata;
1522
1523 OS2_QuitMouse(_this);
1524
1525 WinDestroyMsgQueue(pVData->hmq);
1526 WinTerminate(pVData->hab);
1527
1528 /* our caller SDL_VideoQuit() already frees display_modes, driverdata, etc. */
1529 }
1530
OS2_GetDisplayBounds(_THIS,SDL_VideoDisplay * display,SDL_Rect * rect)1531 static int OS2_GetDisplayBounds(_THIS, SDL_VideoDisplay *display,
1532 SDL_Rect *rect)
1533 {
1534 debug_os2("Enter");
1535
1536 rect->x = 0;
1537 rect->y = 0;
1538 rect->w = display->desktop_mode.w;
1539 rect->h = display->desktop_mode.h;
1540
1541 return 0;
1542 }
1543
OS2_GetDisplayDPI(_THIS,SDL_VideoDisplay * display,float * ddpi,float * hdpi,float * vdpi)1544 static int OS2_GetDisplayDPI(_THIS, SDL_VideoDisplay *display, float *ddpi,
1545 float *hdpi, float *vdpi)
1546 {
1547 DISPLAYDATA *pDisplayData = (DISPLAYDATA *)display->driverdata;
1548
1549 debug_os2("Enter");
1550 if (pDisplayData == NULL)
1551 return -1;
1552
1553 if (ddpi != NULL)
1554 *hdpi = pDisplayData->ulDPIDiag;
1555 if (hdpi != NULL)
1556 *hdpi = pDisplayData->ulDPIHor;
1557 if (vdpi != NULL)
1558 *vdpi = pDisplayData->ulDPIVer;
1559
1560 return 0;
1561 }
1562
OS2_GetDisplayModes(_THIS,SDL_VideoDisplay * display)1563 static void OS2_GetDisplayModes(_THIS, SDL_VideoDisplay *display)
1564 {
1565 SDL_DisplayMode mode;
1566
1567 debug_os2("Enter");
1568 SDL_memcpy(&mode, &display->current_mode, sizeof(SDL_DisplayMode));
1569 mode.driverdata = (MODEDATA *) SDL_malloc(sizeof(MODEDATA));
1570 if (!mode.driverdata) return; /* yikes.. */
1571 SDL_memcpy(mode.driverdata, display->current_mode.driverdata, sizeof(MODEDATA));
1572 SDL_AddDisplayMode(display, &mode);
1573 }
1574
OS2_SetDisplayMode(_THIS,SDL_VideoDisplay * display,SDL_DisplayMode * mode)1575 static int OS2_SetDisplayMode(_THIS, SDL_VideoDisplay *display,
1576 SDL_DisplayMode *mode)
1577 {
1578 debug_os2("Enter");
1579 return -1;
1580 }
1581
1582
OS2_DeleteDevice(SDL_VideoDevice * device)1583 static void OS2_DeleteDevice(SDL_VideoDevice *device)
1584 {
1585 SDL_free(device);
1586 }
1587
OS2_CreateDevice(int devindex)1588 static SDL_VideoDevice *OS2_CreateDevice(int devindex)
1589 {
1590 SDL_VideoDevice *device;
1591
1592 /* Initialize all variables that we clean on shutdown */
1593 device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
1594 if (!device) {
1595 SDL_OutOfMemory();
1596 return NULL;
1597 }
1598
1599 /* Set the function pointers */
1600 device->VideoInit = OS2_VideoInit;
1601 device->VideoQuit = OS2_VideoQuit;
1602 device->GetDisplayBounds = OS2_GetDisplayBounds;
1603 device->GetDisplayDPI = OS2_GetDisplayDPI;
1604 device->GetDisplayModes = OS2_GetDisplayModes;
1605 device->SetDisplayMode = OS2_SetDisplayMode;
1606 device->PumpEvents = OS2_PumpEvents;
1607 device->CreateSDLWindow = OS2_CreateWindow;
1608 device->CreateSDLWindowFrom = OS2_CreateWindowFrom;
1609 device->DestroyWindow = OS2_DestroyWindow;
1610 device->SetWindowTitle = OS2_SetWindowTitle;
1611 device->SetWindowIcon = OS2_SetWindowIcon;
1612 device->SetWindowPosition = OS2_SetWindowPosition;
1613 device->SetWindowSize = OS2_SetWindowSize;
1614 device->ShowWindow = OS2_ShowWindow;
1615 device->HideWindow = OS2_HideWindow;
1616 device->RaiseWindow = OS2_RaiseWindow;
1617 device->MaximizeWindow = OS2_MaximizeWindow;
1618 device->MinimizeWindow = OS2_MinimizeWindow;
1619 device->RestoreWindow = OS2_RestoreWindow;
1620 device->SetWindowBordered = OS2_SetWindowBordered;
1621 device->SetWindowFullscreen = OS2_SetWindowFullscreen;
1622 device->GetWindowWMInfo = OS2_GetWindowWMInfo;
1623 device->OnWindowEnter = OS2_OnWindowEnter;
1624 device->SetWindowHitTest = OS2_SetWindowHitTest;
1625 device->SetWindowMouseGrab = OS2_SetWindowMouseGrab;
1626 device->CreateWindowFramebuffer = OS2_CreateWindowFramebuffer;
1627 device->UpdateWindowFramebuffer = OS2_UpdateWindowFramebuffer;
1628 device->DestroyWindowFramebuffer = OS2_DestroyWindowFramebuffer;
1629
1630 device->SetClipboardText = OS2_SetClipboardText;
1631 device->GetClipboardText = OS2_GetClipboardText;
1632 device->HasClipboardText = OS2_HasClipboardText;
1633
1634 device->shape_driver.CreateShaper = OS2_CreateShaper;
1635 device->shape_driver.SetWindowShape = OS2_SetWindowShape;
1636 device->shape_driver.ResizeWindowShape = OS2_ResizeWindowShape;
1637
1638 device->free = OS2_DeleteDevice;
1639
1640 return device;
1641 }
1642
OS2DIVE_CreateDevice(int devindex)1643 static SDL_VideoDevice *OS2DIVE_CreateDevice(int devindex)
1644 {
1645 VIDEOOUTPUTINFO stVOInfo;
1646 if (!voDive.QueryInfo(&stVOInfo)) {
1647 return NULL;
1648 }
1649 return OS2_CreateDevice(devindex);
1650 }
1651
OS2VMAN_CreateDevice(int devindex)1652 static SDL_VideoDevice *OS2VMAN_CreateDevice(int devindex)
1653 {
1654 VIDEOOUTPUTINFO stVOInfo;
1655 if (!voVMan.QueryInfo(&stVOInfo)) {
1656 return NULL;
1657 }
1658 return OS2_CreateDevice(devindex);
1659 }
1660
1661
1662 /* Both bootstraps for DIVE and VMAN are uing same function OS2_CreateDevice().
1663 * Video output system will be selected in OS2_VideoInit() by driver name. */
1664 VideoBootStrap OS2DIVE_bootstrap =
1665 {
1666 OS2DRIVER_NAME_DIVE, "OS/2 video driver",
1667 OS2DIVE_CreateDevice
1668 };
1669
1670 VideoBootStrap OS2VMAN_bootstrap =
1671 {
1672 OS2DRIVER_NAME_VMAN, "OS/2 video driver",
1673 OS2VMAN_CreateDevice
1674 };
1675
1676 #endif /* SDL_VIDEO_DRIVER_OS2 */
1677
1678 /* vi: set ts=4 sw=4 expandtab: */
1679