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