1190
|
1 /*
|
|
2 SDL - Simple DirectMedia Layer
|
|
3 Copyright (C) 1997-2004 Sam Lantinga
|
|
4
|
|
5 This library is free software; you can redistribute it and/or
|
|
6 modify it under the terms of the GNU Library General Public
|
|
7 License as published by the Free Software Foundation; either
|
|
8 version 2 of the License, or (at your option) any later version.
|
|
9
|
|
10 This library is distributed in the hope that it will be useful,
|
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13 Library General Public License for more details.
|
|
14
|
|
15 You should have received a copy of the GNU Library General Public
|
|
16 License along with this library; if not, write to the Free
|
|
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
18
|
|
19 Sam Lantinga
|
|
20 slouken@libsdl.org
|
|
21 */
|
|
22
|
|
23 #include <stdio.h>
|
|
24 #include <stdlib.h>
|
|
25 #include <string.h>
|
|
26 #include <process.h>
|
|
27 #include <time.h>
|
|
28
|
|
29 #include "SDL.h"
|
|
30 #include "SDL_error.h"
|
|
31 #include "SDL_video.h"
|
|
32 #include "SDL_mouse.h"
|
|
33 #include "SDL_sysvideo.h"
|
|
34 #include "SDL_pixels_c.h"
|
|
35 #include "SDL_events_c.h"
|
|
36
|
|
37 #include "SDL_os2fslib.h"
|
|
38
|
|
39 static ULONG ulFCFToUse =
|
|
40 FCF_TITLEBAR |
|
|
41 FCF_SYSMENU |
|
|
42 FCF_MINBUTTON |
|
|
43 FCF_MAXBUTTON |
|
|
44 FCF_NOBYTEALIGN |
|
|
45 FCF_SIZEBORDER |
|
|
46 FCF_TASKLIST;
|
|
47
|
|
48 static int bMouseCaptured = 0;
|
|
49 static int bMouseCapturable = 0;
|
|
50 static HPOINTER hptrGlobalPointer = NULL;
|
|
51 static HPOINTER hptrCurrentIcon = NULL;
|
|
52 static int iWindowSizeX = 320;
|
|
53 static int iWindowSizeY = 200;
|
|
54 static int bWindowResized = 0;
|
|
55
|
|
56 #pragma pack(1)
|
|
57 typedef struct BMPINFO
|
|
58 {
|
|
59 BITMAPINFO;
|
|
60 RGB clr;
|
|
61 } BMPINFO, *PBMPINFO;
|
|
62 #pragma pack()
|
|
63
|
|
64
|
|
65 // Backdoors:
|
|
66 DECLSPEC void SDLCALL SDL_OS2FSLIB_SetFCFToUse(ULONG ulFCF)
|
|
67 {
|
|
68 ulFCFToUse = ulFCF;
|
|
69 }
|
|
70
|
|
71 // Configuration defines:
|
|
72
|
|
73 // We have to report empty alpha mask, otherwise SDL will select
|
|
74 // alpha blitters, and this will have unwanted results, as we don't
|
|
75 // support alpha channel in FSLib yet.
|
|
76 #define REPORT_EMPTY_ALPHA_MASK
|
|
77
|
|
78 // Experimental: Move every FSLib_BitBlt() call into window message
|
|
79 // processing function.
|
|
80 // This may fix dirt left on desktop. Or not.
|
|
81 //#define BITBLT_IN_WINMESSAGEPROC
|
|
82
|
|
83 // Experimental-2: Use WinLockWindowUpdate() in around bitblts!
|
|
84 // This is not enabled, because it seems to cause more problems
|
|
85 // than good.
|
|
86 //#define USE_WINLOCKWINDOWUPDATE_AROUND_BITBLTS
|
|
87
|
|
88 // Use the following to show resized image instead of black stuff
|
|
89 // even if the surface is resizable.
|
|
90 //#define RESIZE_EVEN_IF_RESIZABLE
|
|
91
|
|
92 /* The translation table from a VK keysym to a SDL keysym */
|
|
93 static SDLKey HWScanKeyMap[256];
|
|
94 static SDL_keysym *TranslateKey(int vkey, int chcode, int scancode, SDL_keysym *keysym, int iPressed);
|
|
95 static int iShiftIsPressed;
|
|
96
|
|
97 #ifdef BITBLT_IN_WINMESSAGEPROC
|
|
98 #define WM_UPDATERECTSREQUEST WM_USER+50
|
|
99 #endif
|
|
100
|
|
101 #ifdef USE_WINLOCKWINDOWUPDATE_AROUND_BITBLTS
|
|
102 #define FSLIB_BITBLT(hwnd, buffer, top, left, width, height) \
|
|
103 { \
|
|
104 WinLockWindowUpdate(HWND_DESKTOP, HWND_DESKTOP); \
|
|
105 FSLib_BitBlt(hwnd, buffer, top, left, width, height); \
|
|
106 WinLockWindowUpdate(HWND_DESKTOP, NULL); \
|
|
107 }
|
|
108 #else
|
|
109 #define FSLIB_BITBLT(hwnd, buffer, top, left, width, height) \
|
|
110 FSLib_BitBlt(hwnd, buffer, top, left, width, height);
|
|
111 #endif
|
|
112
|
|
113 /////////////////////////////////////////////////////////////////////
|
|
114 //
|
|
115 // SetAccessableWindowPos
|
|
116 //
|
|
117 // Same as WinSetWindowPos(), but takes care for the window to be
|
|
118 // always on the screen, the titlebar will be accessable everytime.
|
|
119 //
|
|
120 /////////////////////////////////////////////////////////////////////
|
|
121 static BOOL SetAccessableWindowPos(HWND hwnd, HWND hwndInsertBehind,
|
|
122 LONG x, LONG y,
|
|
123 LONG cx, LONG cy,
|
|
124 ULONG fl)
|
|
125 {
|
|
126 SWP swpDesktop, swp;
|
|
127 // Get desktop area
|
|
128 WinQueryWindowPos(HWND_DESKTOP, &swpDesktop);
|
|
129
|
|
130 if ((fl & SWP_MOVE) && (fl & SWP_SIZE))
|
|
131 {
|
|
132 // If both moving and sizing, then change size and pos now!!
|
|
133 if (x+cx>swpDesktop.cx)
|
|
134 x = swpDesktop.cx - cx;
|
|
135 if (x<0)
|
|
136 x = 0;
|
|
137 if (y<0)
|
|
138 y = 0;
|
|
139 if (y+cy>swpDesktop.cy)
|
|
140 y = swpDesktop.cy - cy;
|
|
141 return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl);
|
|
142 } else
|
|
143 if (fl & SWP_MOVE)
|
|
144 {
|
|
145 // Just moving
|
|
146 WinQueryWindowPos(hwnd, &swp);
|
|
147 if (x+swp.cx>swpDesktop.cx)
|
|
148 x = swpDesktop.cx - swp.cx;
|
|
149 if (x<0)
|
|
150 x = 0;
|
|
151 if (y<0)
|
|
152 y = 0;
|
|
153 if (y+swp.cy>swpDesktop.cy)
|
|
154 y = swpDesktop.cy - swp.cy;
|
|
155 return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl);
|
|
156 } else
|
|
157 if (fl & SWP_SIZE)
|
|
158 {
|
|
159 // Just sizing
|
|
160 WinQueryWindowPos(hwnd, &swp);
|
|
161 x = swp.x;
|
|
162 y = swp.y;
|
|
163 if (x+cx>swpDesktop.cx)
|
|
164 x = swpDesktop.cx - cx;
|
|
165 if (x<0)
|
|
166 x = 0;
|
|
167 if (y<0)
|
|
168 y = 0;
|
|
169 if (y+cy>swpDesktop.cy)
|
|
170 y = swpDesktop.cy - cy;
|
|
171 return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl | SWP_MOVE);
|
|
172 } else
|
|
173 return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl);
|
|
174 }
|
|
175
|
|
176 /////////////////////////////////////////////////////////////////////
|
|
177 //
|
|
178 // TranslateKey
|
|
179 //
|
|
180 // This creates SDL Keycodes from VK_ and hardware scan codes
|
|
181 //
|
|
182 /////////////////////////////////////////////////////////////////////
|
|
183 static SDL_keysym *TranslateKey(int vkey, int chcode, int scancode, SDL_keysym *keysym, int iPressed)
|
|
184 {
|
|
185 keysym->scancode = (unsigned char) scancode;
|
|
186 keysym->mod = KMOD_NONE;
|
|
187 keysym->unicode = 0;
|
|
188
|
|
189 if (iPressed && SDL_TranslateUNICODE)
|
|
190 {
|
|
191 // TODO:
|
|
192 // Implement real unicode conversion!
|
|
193 if (chcode)
|
|
194 keysym->unicode = chcode;
|
|
195 else
|
|
196 keysym->unicode = vkey;
|
|
197 }
|
|
198
|
|
199 keysym->sym = HWScanKeyMap[scancode];
|
|
200
|
|
201 // Now stuffs based on state of shift key(s)!
|
|
202 if (vkey == VK_SHIFT)
|
|
203 {
|
|
204 iShiftIsPressed = iPressed;
|
|
205 }
|
|
206
|
|
207 if ((iShiftIsPressed) && (SDL_TranslateUNICODE))
|
|
208 {
|
|
209 // Change syms, if Unicode stuff is required
|
|
210 // I think it's silly, but it's SDL...
|
|
211 switch (keysym->sym)
|
|
212 {
|
|
213 case SDLK_BACKQUOTE:
|
|
214 keysym->sym = '~';
|
|
215 break;
|
|
216 case SDLK_1:
|
|
217 keysym->sym = SDLK_EXCLAIM;
|
|
218 break;
|
|
219 case SDLK_2:
|
|
220 keysym->sym = SDLK_AT;
|
|
221 break;
|
|
222 case SDLK_3:
|
|
223 keysym->sym = SDLK_HASH;
|
|
224 break;
|
|
225 case SDLK_4:
|
|
226 keysym->sym = SDLK_DOLLAR;
|
|
227 break;
|
|
228 case SDLK_5:
|
|
229 keysym->sym = '%';
|
|
230 break;
|
|
231 case SDLK_6:
|
|
232 keysym->sym = SDLK_CARET;
|
|
233 break;
|
|
234 case SDLK_7:
|
|
235 keysym->sym = SDLK_AMPERSAND;
|
|
236 break;
|
|
237 case SDLK_8:
|
|
238 keysym->sym = SDLK_ASTERISK;
|
|
239 break;
|
|
240 case SDLK_9:
|
|
241 keysym->sym = SDLK_LEFTPAREN;
|
|
242 break;
|
|
243 case SDLK_0:
|
|
244 keysym->sym = SDLK_RIGHTPAREN;
|
|
245 break;
|
|
246 case SDLK_MINUS:
|
|
247 keysym->sym = SDLK_UNDERSCORE;
|
|
248 break;
|
|
249 case SDLK_PLUS:
|
|
250 keysym->sym = SDLK_EQUALS;
|
|
251 break;
|
|
252
|
|
253 case SDLK_LEFTBRACKET:
|
|
254 keysym->sym = '{';
|
|
255 break;
|
|
256 case SDLK_RIGHTBRACKET:
|
|
257 keysym->sym = '}';
|
|
258 break;
|
|
259
|
|
260 case SDLK_SEMICOLON:
|
|
261 keysym->sym = SDLK_COLON;
|
|
262 break;
|
|
263 case SDLK_QUOTE:
|
|
264 keysym->sym = SDLK_QUOTEDBL;
|
|
265 break;
|
|
266 case SDLK_BACKSLASH:
|
|
267 keysym->sym = '|';
|
|
268 break;
|
|
269
|
|
270 case SDLK_COMMA:
|
|
271 keysym->sym = SDLK_LESS;
|
|
272 break;
|
|
273 case SDLK_PERIOD:
|
|
274 keysym->sym = SDLK_GREATER;
|
|
275 break;
|
|
276 case SDLK_SLASH:
|
|
277 keysym->sym = SDLK_QUESTION;
|
|
278 break;
|
|
279
|
|
280 default:
|
|
281 break;
|
|
282 }
|
|
283 }
|
|
284 return keysym;
|
|
285 }
|
|
286
|
|
287 #define CONVERTMOUSEPOSITION() \
|
|
288 /* We have to inverse the mouse position, because every non-os/2 system */ \
|
|
289 /* has a coordinate system where the (0;0) is the top-left corner, */ \
|
|
290 /* while on os/2 it's the bottom left corner! */ \
|
|
291 if (FSLib_QueryFSMode(hwnd)) \
|
|
292 { \
|
|
293 /* We're in FS mode! */ \
|
|
294 /* In FS mode our window is as big as fullscreen mode, but not necessary as */ \
|
|
295 /* big as the source buffer (can be bigger) */ \
|
|
296 /* So, limit mouse pos to source buffer size! */ \
|
|
297 if (ppts->x<0) ppts->x = 0; \
|
|
298 if (ppts->y<0) ppts->y = 0; \
|
|
299 if (ppts->x>=pVideo->hidden->SrcBufferDesc.uiXResolution) ppts->x = pVideo->hidden->SrcBufferDesc.uiXResolution-1; \
|
|
300 if (ppts->y>=pVideo->hidden->SrcBufferDesc.uiYResolution) ppts->y = pVideo->hidden->SrcBufferDesc.uiYResolution-1; \
|
|
301 pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ \
|
|
302 ptl.x = ppts->x; ptl.y = ppts->y; \
|
|
303 WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); \
|
|
304 WinSetPointerPos(HWND_DESKTOP, ptl.x, ptl.y); \
|
|
305 /* Then convert OS/2 position to SDL position */ \
|
|
306 ppts->y = pVideo->hidden->SrcBufferDesc.uiYResolution - ppts->y - 1; \
|
|
307 } else \
|
|
308 { \
|
|
309 SWP swpClient; \
|
|
310 /* We're in windowed mode! */ \
|
|
311 WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient); \
|
|
312 /* Convert OS/2 mouse position to SDL position, and also scale it! */ \
|
|
313 (ppts->x) = (ppts->x) * pVideo->hidden->SrcBufferDesc.uiXResolution / swpClient.cx; \
|
|
314 (ppts->y) = (ppts->y) * pVideo->hidden->SrcBufferDesc.uiYResolution / swpClient.cy; \
|
|
315 (ppts->y) = pVideo->hidden->SrcBufferDesc.uiYResolution - (ppts->y) - 1; \
|
|
316 }
|
|
317
|
|
318
|
|
319
|
|
320 /////////////////////////////////////////////////////////////////////
|
|
321 //
|
|
322 // WndProc
|
|
323 //
|
|
324 // This is the message processing window procedure for the
|
|
325 // SDLWindowClass, which is the client window in our application.
|
|
326 // It handles switching back and away from the app (taking care of
|
|
327 // going out and back to and from fullscreen mode), sending keystrokes
|
|
328 // and mouse events to where it has to be sent, etc...
|
|
329 //
|
|
330 /////////////////////////////////////////////////////////////////////
|
|
331 static MRESULT EXPENTRY WndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
|
|
332 {
|
|
333 HPS ps;
|
|
334 RECTL rcl;
|
|
335 SDL_VideoDevice *pVideo = NULL;
|
|
336
|
|
337 switch (msg)
|
|
338 {
|
|
339 case WM_CHAR: // Keypress notification
|
|
340 #ifdef DEBUG_BUILD
|
|
341 // printf("WM_CHAR\n"); fflush(stdout);
|
|
342 #endif
|
|
343 pVideo = WinQueryWindowPtr(hwnd, 0);
|
|
344 if (pVideo)
|
|
345 {
|
|
346 /*
|
|
347 // We skip repeated keys:
|
|
348 if (CHARMSG(&msg)->cRepeat>1)
|
|
349 {
|
|
350 #ifdef DEBUG_BUILD
|
|
351 // printf("Repeated key (%d), skipping...\n", CHARMSG(&msg)->cRepeat); fflush(stdout);
|
|
352 #endif
|
|
353 return (MRESULT) TRUE;
|
|
354 }
|
|
355 */
|
|
356
|
|
357 // If it's not repeated, then let's see if its pressed or released!
|
|
358 if (SHORT1FROMMP(mp1) & KC_KEYUP)
|
|
359 {
|
|
360 // A key has been released
|
|
361 SDL_keysym keysym;
|
|
362
|
|
363 #ifdef DEBUG_BUILD
|
|
364 // printf("WM_CHAR, keyup, code is [0x%0x]\n", CHAR4FROMMP(mp1)); // HW scan code
|
|
365 #endif
|
|
366
|
|
367 // One problem is with F1, which gets only the keyup message because
|
|
368 // it is a system key.
|
|
369 // So, when we get keyup message, we simulate keydown too!
|
|
370 // UPDATE:
|
|
371 // This problem should be solved now, that the accelerator keys are
|
|
372 // disabled for this window!
|
|
373 /*
|
|
374 if (SHORT2FROMMP(mp2)==VK_F1)
|
|
375 {
|
|
376 SDL_PrivateKeyboard(SDL_PRESSED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code
|
|
377 SHORT1FROMMP(mp2), // Character code
|
|
378 CHAR4FROMMP(mp1), // HW Scan code
|
|
379 &keysym,0));
|
|
380 }*/
|
|
381
|
|
382 SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code
|
|
383 SHORT1FROMMP(mp2), // Character code
|
|
384 CHAR4FROMMP(mp1), // HW Scan code
|
|
385 &keysym,0));
|
|
386
|
|
387 } else
|
|
388 {
|
|
389 // A key has been pressed
|
|
390 SDL_keysym keysym;
|
|
391
|
|
392 #ifdef DEBUG_BUILD
|
|
393 // printf("WM_CHAR, keydown, code is [0x%0x]\n", CHAR4FROMMP(mp1)); // HW scan code
|
|
394 #endif
|
|
395 // Check for fastkeys: ALT+HOME to toggle FS mode
|
|
396 // ALT+END to close app
|
|
397 if ((SHORT1FROMMP(mp1) & KC_ALT) &&
|
|
398 (SHORT2FROMMP(mp2) == VK_HOME))
|
|
399 {
|
|
400 #ifdef DEBUG_BUILD
|
|
401 printf(" Pressed ALT+HOME!\n"); fflush(stdout);
|
|
402 #endif
|
|
403 // Only switch between fullscreen and back if it's not
|
|
404 // a resizable mode!
|
|
405 if (
|
|
406 (!pVideo->hidden->pSDLSurface) ||
|
|
407 ((pVideo->hidden->pSDLSurface)
|
|
408 && ((pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE)==0)
|
|
409 )
|
|
410 )
|
|
411 FSLib_ToggleFSMode(hwnd, !FSLib_QueryFSMode(hwnd));
|
|
412 #ifdef DEBUG_BUILD
|
|
413 else
|
|
414 printf(" Resizable mode, so discarding ALT+HOME!\n"); fflush(stdout);
|
|
415 #endif
|
|
416 } else
|
|
417 if ((SHORT1FROMMP(mp1) & KC_ALT) &&
|
|
418 (SHORT2FROMMP(mp2) == VK_END))
|
|
419 {
|
|
420 #ifdef DEBUG_BUILD
|
|
421 printf(" Pressed ALT+END!\n"); fflush(stdout);
|
|
422 #endif
|
|
423 // Close window, and get out of loop!
|
|
424 // Also send event to SDL application, but we won't
|
|
425 // wait for it to be processed!
|
|
426 SDL_PrivateQuit();
|
|
427 WinPostMsg(hwnd, WM_QUIT, 0, 0);
|
|
428 } else
|
|
429 {
|
|
430
|
|
431 SDL_PrivateKeyboard(SDL_PRESSED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code
|
|
432 SHORT1FROMMP(mp2), // Character code
|
|
433 CHAR4FROMMP(mp1), // HW Scan code
|
|
434 &keysym,1));
|
|
435
|
|
436 }
|
|
437 }
|
|
438 }
|
|
439 return (MRESULT) TRUE;
|
|
440
|
|
441 case WM_TRANSLATEACCEL:
|
|
442 {
|
|
443 PQMSG pqmsg;
|
|
444 pqmsg = (PQMSG) mp1;
|
|
445 if (mp1)
|
|
446 {
|
|
447 if (pqmsg->msg == WM_CHAR)
|
|
448 {
|
|
449 // WM_CHAR message!
|
|
450 // Let's filter the ALT keypress and all other acceleration keys!
|
|
451 return (MRESULT) FALSE;
|
|
452 }
|
|
453 }
|
|
454 break; // Default processing (pass to parent until frame control)
|
|
455 }
|
|
456
|
|
457 case WM_PAINT: // Window redraw!
|
|
458 #ifdef DEBUG_BUILD
|
|
459 printf("WM_PAINT (0x%x)\n", hwnd); fflush(stdout);
|
|
460 #endif
|
|
461 ps = WinBeginPaint(hwnd,0,&rcl);
|
|
462 pVideo = FSLib_GetUserParm(hwnd);
|
|
463 if (pVideo)
|
|
464 {
|
|
465 if (!pVideo->hidden->pSDLSurface)
|
|
466 {
|
|
467 RECTL rclRect;
|
|
468 // So, don't blit now!
|
|
469 #ifdef DEBUG_BUILD
|
|
470 printf("WM_PAINT : Skipping blit while resizing (Pre!)!\n"); fflush(stdout);
|
|
471 #endif
|
|
472 WinQueryWindowRect(hwnd, &rclRect);
|
|
473 // Fill with black
|
|
474 WinFillRect(ps, &rclRect, CLR_BLACK);
|
|
475 } else
|
|
476 {
|
|
477 if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, 1000)==NO_ERROR)
|
|
478 {
|
|
479 int iTop, iLeft, iWidth, iHeight;
|
|
480 int iXScaleError, iYScaleError;
|
|
481 int iXScaleError2, iYScaleError2;
|
|
482 SWP swp;
|
|
483
|
|
484 // Re-blit the modified area!
|
|
485 // For this, we have to calculate the points, scaled!
|
|
486 WinQueryWindowPos(hwnd, &swp);
|
|
487 #ifdef DEBUG_BUILD
|
|
488 printf("WM_PAINT : WinSize: %d %d, BufSize: %d %d\n",
|
|
489 swp.cx,
|
|
490 swp.cy,
|
|
491 pVideo->hidden->SrcBufferDesc.uiXResolution,
|
|
492 pVideo->hidden->SrcBufferDesc.uiYResolution
|
|
493 );
|
|
494 fflush(stdout);
|
|
495 #endif
|
|
496
|
|
497 #ifndef RESIZE_EVEN_IF_RESIZABLE
|
|
498 // But only blit if the window is not resizable, or if
|
|
499 // the window is resizable and the source buffer size is the
|
|
500 // same as the destination buffer size!
|
|
501 if ((!pVideo->hidden->pSDLSurface) ||
|
|
502 ((pVideo->hidden->pSDLSurface) &&
|
|
503 (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
|
|
504 ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) ||
|
|
505 (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution)
|
|
506 ) &&
|
|
507 (!FSLib_QueryFSMode(hwnd))
|
|
508 )
|
|
509 )
|
|
510 {
|
|
511 RECTL rclRect;
|
|
512 // Resizable surface and in resizing!
|
|
513 // So, don't blit now!
|
|
514 #ifdef DEBUG_BUILD
|
|
515 printf("WM_PAINT : Skipping blit while resizing!\n"); fflush(stdout);
|
|
516 #endif
|
|
517 WinQueryWindowRect(hwnd, &rclRect);
|
|
518 // Fill with black
|
|
519 WinFillRect(ps, &rclRect, CLR_BLACK);
|
|
520 } else
|
|
521 #endif
|
|
522 {
|
|
523
|
|
524 iXScaleError = (pVideo->hidden->SrcBufferDesc.uiXResolution-1) / swp.cx;
|
|
525 iYScaleError = (pVideo->hidden->SrcBufferDesc.uiYResolution-1) / swp.cy;
|
|
526 if (iXScaleError<0) iXScaleError = 0;
|
|
527 if (iYScaleError<0) iYScaleError = 0;
|
|
528 iXScaleError2 = (swp.cx-1)/(pVideo->hidden->SrcBufferDesc.uiXResolution);
|
|
529 iYScaleError2 = (swp.cy-1)/(pVideo->hidden->SrcBufferDesc.uiYResolution);
|
|
530 if (iXScaleError2<0) iXScaleError2 = 0;
|
|
531 if (iYScaleError2<0) iYScaleError2 = 0;
|
|
532
|
|
533 iTop = (swp.cy - rcl.yTop) * pVideo->hidden->SrcBufferDesc.uiYResolution / swp.cy - iYScaleError;
|
|
534 iLeft = rcl.xLeft * pVideo->hidden->SrcBufferDesc.uiXResolution / swp.cx - iXScaleError;
|
|
535 iWidth = ((rcl.xRight-rcl.xLeft) * pVideo->hidden->SrcBufferDesc.uiXResolution + swp.cx-1)
|
|
536 / swp.cx + 2*iXScaleError;
|
|
537 iHeight = ((rcl.yTop-rcl.yBottom) * pVideo->hidden->SrcBufferDesc.uiYResolution + swp.cy-1)
|
|
538 / swp.cy + 2*iYScaleError;
|
|
539
|
|
540 iWidth+=iXScaleError2;
|
|
541 iHeight+=iYScaleError2;
|
|
542
|
|
543 if (iTop<0) iTop = 0;
|
|
544 if (iLeft<0) iLeft = 0;
|
|
545 if (iTop+iHeight>pVideo->hidden->SrcBufferDesc.uiYResolution) iHeight = pVideo->hidden->SrcBufferDesc.uiYResolution-iTop;
|
|
546 if (iLeft+iWidth>pVideo->hidden->SrcBufferDesc.uiXResolution) iWidth = pVideo->hidden->SrcBufferDesc.uiXResolution-iLeft;
|
|
547
|
|
548 #ifdef DEBUG_BUILD
|
|
549 printf("WM_PAINT : BitBlt: %d %d -> %d %d (Buf %d x %d)\n",
|
|
550 iTop, iLeft, iWidth, iHeight,
|
|
551 pVideo->hidden->SrcBufferDesc.uiXResolution,
|
|
552 pVideo->hidden->SrcBufferDesc.uiYResolution
|
|
553 );
|
|
554 fflush(stdout);
|
|
555 #endif
|
|
556
|
|
557 FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer, iTop, iLeft, iWidth, iHeight);
|
|
558 }
|
|
559
|
|
560 DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer);
|
|
561 }
|
|
562 }
|
|
563 }
|
|
564 #ifdef DEBUG_BUILD
|
|
565 else
|
|
566 {
|
|
567 printf("WM_PAINT : No pVideo!\n"); fflush(stdout);
|
|
568 }
|
|
569 #endif
|
|
570 WinEndPaint(ps);
|
|
571 #ifdef DEBUG_BUILD
|
|
572 printf("WM_PAINT : Done.\n");
|
|
573 fflush(stdout);
|
|
574 #endif
|
|
575 return 0;
|
|
576
|
|
577 case WM_SIZE:
|
|
578 {
|
|
579 #ifdef DEBUG_BUILD
|
|
580 printf("WM_SIZE : (%d %d)\n",
|
|
581 SHORT1FROMMP(mp2), SHORT2FROMMP(mp2)); fflush(stdout);
|
|
582 #endif
|
|
583 iWindowSizeX = SHORT1FROMMP(mp2);
|
|
584 iWindowSizeY = SHORT2FROMMP(mp2);
|
|
585 bWindowResized = 1;
|
|
586
|
|
587 // Make sure the window will be redrawn
|
|
588 WinInvalidateRegion(hwnd, NULL, TRUE);
|
|
589 }
|
|
590 break;
|
|
591
|
|
592 case WM_FSLIBNOTIFICATION:
|
|
593 #ifdef DEBUG_BUILD
|
|
594 printf("WM_FSLIBNOTIFICATION\n"); fflush(stdout);
|
|
595 #endif
|
|
596 if ((int)mp1 == FSLN_TOGGLEFSMODE)
|
|
597 {
|
|
598 // FS mode changed, reblit image!
|
|
599 pVideo = FSLib_GetUserParm(hwnd);
|
|
600 if (pVideo)
|
|
601 {
|
|
602 if (!pVideo->hidden->pSDLSurface)
|
|
603 {
|
|
604 // Resizable surface and in resizing!
|
|
605 // So, don't blit now!
|
|
606 #ifdef DEBUG_BUILD
|
|
607 printf("WM_FSLIBNOTIFICATION : Can not blit if there is no surface, doing nothing.\n"); fflush(stdout);
|
|
608 #endif
|
|
609 } else
|
|
610 {
|
|
611 if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, 1000)==NO_ERROR)
|
|
612 {
|
|
613 if (pVideo->hidden->pSDLSurface)
|
|
614 {
|
|
615 #ifndef RESIZE_EVEN_IF_RESIZABLE
|
|
616 SWP swp;
|
|
617
|
|
618 // But only blit if the window is not resizable, or if
|
|
619 // the window is resizable and the source buffer size is the
|
|
620 // same as the destination buffer size!
|
|
621 WinQueryWindowPos(hwnd, &swp);
|
|
622 if ((!pVideo->hidden->pSDLSurface) ||
|
|
623 (
|
|
624 (pVideo->hidden->pSDLSurface) &&
|
|
625 (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
|
|
626 ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) ||
|
|
627 (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution)
|
|
628 ) &&
|
|
629 (!FSLib_QueryFSMode(hwnd))
|
|
630 )
|
|
631 )
|
|
632 {
|
|
633 // Resizable surface and in resizing!
|
|
634 // So, don't blit now!
|
|
635 #ifdef DEBUG_BUILD
|
|
636 printf("WM_FSLIBNOTIFICATION : Cannot blit while resizing, doing nothing.\n"); fflush(stdout);
|
|
637 #endif
|
|
638 } else
|
|
639 #endif
|
|
640 {
|
|
641 #ifdef DEBUG_BUILD
|
|
642 printf("WM_FSLIBNOTIFICATION : Blitting!\n"); fflush(stdout);
|
|
643 #endif
|
|
644 FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer,
|
|
645 0, 0,
|
|
646 pVideo->hidden->SrcBufferDesc.uiXResolution,
|
|
647 pVideo->hidden->SrcBufferDesc.uiYResolution);
|
|
648 }
|
|
649 }
|
|
650 #ifdef DEBUG_BUILD
|
|
651 else
|
|
652 printf("WM_FSLIBNOTIFICATION : No public surface!\n"); fflush(stdout);
|
|
653 #endif
|
|
654
|
|
655 DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer);
|
|
656 }
|
|
657 }
|
|
658 }
|
|
659 }
|
|
660 return (MPARAM) 1;
|
|
661
|
|
662 case WM_ACTIVATE:
|
|
663 #ifdef DEBUG_BUILD
|
|
664 printf("WM_ACTIVATE\n"); fflush(stdout);
|
|
665 #endif
|
|
666
|
|
667 pVideo = FSLib_GetUserParm(hwnd);
|
|
668 if (pVideo)
|
|
669 {
|
|
670 pVideo->hidden->fInFocus = (int) mp1;
|
|
671 if (pVideo->hidden->fInFocus)
|
|
672 {
|
|
673 // Went into focus
|
|
674 if ((pVideo->hidden->iMouseVisible) && (!bMouseCaptured))
|
|
675 WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
|
|
676 else
|
|
677 WinSetPointer(HWND_DESKTOP, NULL);
|
|
678
|
|
679 if (bMouseCapturable)
|
|
680 {
|
|
681 // Re-capture the mouse, if we captured it before!
|
|
682 WinSetCapture(HWND_DESKTOP, hwnd);
|
|
683 bMouseCaptured = 1;
|
|
684 {
|
|
685 SWP swpClient;
|
|
686 POINTL ptl;
|
|
687 // Center the mouse to the middle of the window!
|
|
688 WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
|
|
689 ptl.x = 0; ptl.y = 0;
|
|
690 WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
|
|
691 pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
|
|
692 WinSetPointerPos(HWND_DESKTOP,
|
|
693 ptl.x + swpClient.cx/2,
|
|
694 ptl.y + swpClient.cy/2);
|
|
695 }
|
|
696 }
|
|
697 } else
|
|
698 {
|
|
699 // Went out of focus
|
|
700 WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
|
|
701
|
|
702 if (bMouseCaptured)
|
|
703 {
|
|
704 // Release the mouse
|
|
705 WinSetCapture(HWND_DESKTOP, hwnd);
|
|
706 bMouseCaptured = 0;
|
|
707 }
|
|
708 }
|
|
709 }
|
|
710 #ifdef DEBUG_BUILD
|
|
711 printf("WM_ACTIVATE done\n"); fflush(stdout);
|
|
712 #endif
|
|
713
|
|
714 break;
|
|
715
|
|
716 case WM_BUTTON1DOWN:
|
|
717 #ifdef DEBUG_BUILD
|
|
718 printf("WM_BUTTON1DOWN\n"); fflush(stdout);
|
|
719 #endif
|
|
720
|
|
721 pVideo = FSLib_GetUserParm(hwnd);
|
|
722 if (pVideo)
|
|
723 {
|
|
724 SDL_PrivateMouseButton(SDL_PRESSED,
|
|
725 SDL_BUTTON_LEFT,
|
|
726 0, 0); // Don't report mouse movement!
|
|
727
|
|
728 if (bMouseCapturable)
|
|
729 {
|
|
730 // We should capture the mouse!
|
|
731 if (!bMouseCaptured)
|
|
732 {
|
|
733 WinSetCapture(HWND_DESKTOP, hwnd);
|
|
734 WinSetPointer(HWND_DESKTOP, NULL);
|
|
735 bMouseCaptured = 1;
|
|
736 {
|
|
737 SWP swpClient;
|
|
738 POINTL ptl;
|
|
739 // Center the mouse to the middle of the window!
|
|
740 WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
|
|
741 ptl.x = 0; ptl.y = 0;
|
|
742 WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
|
|
743 pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
|
|
744 WinSetPointerPos(HWND_DESKTOP,
|
|
745 ptl.x + swpClient.cx/2,
|
|
746 ptl.y + swpClient.cy/2);
|
|
747 }
|
|
748 }
|
|
749 }
|
|
750 }
|
|
751 break;
|
|
752 case WM_BUTTON1UP:
|
|
753 #ifdef DEBUG_BUILD
|
|
754 printf("WM_BUTTON1UP\n"); fflush(stdout);
|
|
755 #endif
|
|
756 SDL_PrivateMouseButton(SDL_RELEASED,
|
|
757 SDL_BUTTON_LEFT,
|
|
758 0, 0); // Don't report mouse movement!
|
|
759 break;
|
|
760 case WM_BUTTON2DOWN:
|
|
761 #ifdef DEBUG_BUILD
|
|
762 printf("WM_BUTTON2DOWN\n"); fflush(stdout);
|
|
763 #endif
|
|
764
|
|
765 pVideo = FSLib_GetUserParm(hwnd);
|
|
766 if (pVideo)
|
|
767 {
|
|
768 SDL_PrivateMouseButton(SDL_PRESSED,
|
|
769 SDL_BUTTON_RIGHT,
|
|
770 0, 0); // Don't report mouse movement!
|
|
771
|
|
772 if (bMouseCapturable)
|
|
773 {
|
|
774 // We should capture the mouse!
|
|
775 if (!bMouseCaptured)
|
|
776 {
|
|
777 WinSetCapture(HWND_DESKTOP, hwnd);
|
|
778 WinSetPointer(HWND_DESKTOP, NULL);
|
|
779 bMouseCaptured = 1;
|
|
780 {
|
|
781 SWP swpClient;
|
|
782 POINTL ptl;
|
|
783 // Center the mouse to the middle of the window!
|
|
784 WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
|
|
785 ptl.x = 0; ptl.y = 0;
|
|
786 WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
|
|
787 pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
|
|
788 WinSetPointerPos(HWND_DESKTOP,
|
|
789 ptl.x + swpClient.cx/2,
|
|
790 ptl.y + swpClient.cy/2);
|
|
791 }
|
|
792 }
|
|
793 }
|
|
794
|
|
795 }
|
|
796 break;
|
|
797 case WM_BUTTON2UP:
|
|
798 #ifdef DEBUG_BUILD
|
|
799 printf("WM_BUTTON2UP\n"); fflush(stdout);
|
|
800 #endif
|
|
801 SDL_PrivateMouseButton(SDL_RELEASED,
|
|
802 SDL_BUTTON_RIGHT,
|
|
803 0, 0); // Don't report mouse movement!
|
|
804 break;
|
|
805 case WM_BUTTON3DOWN:
|
|
806 #ifdef DEBUG_BUILD
|
|
807 printf("WM_BUTTON3DOWN\n"); fflush(stdout);
|
|
808 #endif
|
|
809
|
|
810 pVideo = FSLib_GetUserParm(hwnd);
|
|
811 if (pVideo)
|
|
812 {
|
|
813 SDL_PrivateMouseButton(SDL_PRESSED,
|
|
814 SDL_BUTTON_MIDDLE,
|
|
815 0, 0); // Don't report mouse movement!
|
|
816
|
|
817 if (bMouseCapturable)
|
|
818 {
|
|
819 // We should capture the mouse!
|
|
820 if (!bMouseCaptured)
|
|
821 {
|
|
822 WinSetCapture(HWND_DESKTOP, hwnd);
|
|
823 WinSetPointer(HWND_DESKTOP, NULL);
|
|
824 bMouseCaptured = 1;
|
|
825 {
|
|
826 SWP swpClient;
|
|
827 POINTL ptl;
|
|
828 // Center the mouse to the middle of the window!
|
|
829 WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
|
|
830 ptl.x = 0; ptl.y = 0;
|
|
831 WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
|
|
832 pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
|
|
833 WinSetPointerPos(HWND_DESKTOP,
|
|
834 ptl.x + swpClient.cx/2,
|
|
835 ptl.y + swpClient.cy/2);
|
|
836 }
|
|
837 }
|
|
838 }
|
|
839 }
|
|
840 break;
|
|
841 case WM_BUTTON3UP:
|
|
842 #ifdef DEBUG_BUILD
|
|
843 printf("WM_BUTTON3UP\n"); fflush(stdout);
|
|
844 #endif
|
|
845 SDL_PrivateMouseButton(SDL_RELEASED,
|
|
846 SDL_BUTTON_MIDDLE,
|
|
847 0, 0); // Don't report mouse movement!
|
|
848 break;
|
|
849 case WM_MOUSEMOVE:
|
|
850 #ifdef DEBUG_BUILD
|
|
851 // printf("WM_MOUSEMOVE\n"); fflush(stdout);
|
|
852 #endif
|
|
853
|
|
854 pVideo = FSLib_GetUserParm(hwnd);
|
|
855 if (pVideo)
|
|
856 {
|
|
857 if (pVideo->hidden->iSkipWMMOUSEMOVE)
|
|
858 {
|
|
859 pVideo->hidden->iSkipWMMOUSEMOVE--;
|
|
860 } else
|
|
861 {
|
|
862 POINTS *ppts = (POINTS *) (&mp1);
|
|
863 POINTL ptl;
|
|
864
|
|
865 CONVERTMOUSEPOSITION();
|
|
866
|
|
867 if (bMouseCaptured)
|
|
868 {
|
|
869 SWP swpClient;
|
|
870 // Send relative mouse position, and re-center the mouse
|
|
871 // Reposition the mouse to the center of the screen/window
|
|
872 SDL_PrivateMouseMotion(0, // Buttons not changed
|
|
873 1, // Relative position
|
|
874 ppts->x - (pVideo->hidden->SrcBufferDesc.uiXResolution/2),
|
|
875 ppts->y+1 - (pVideo->hidden->SrcBufferDesc.uiYResolution/2));
|
|
876
|
|
877 WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
|
|
878 ptl.x = 0; ptl.y = 0;
|
|
879 WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
|
|
880 pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
|
|
881 // Center the mouse to the middle of the window!
|
|
882 WinSetPointerPos(HWND_DESKTOP,
|
|
883 ptl.x + swpClient.cx/2,
|
|
884 ptl.y + swpClient.cy/2);
|
|
885 } else
|
|
886 {
|
|
887 // Send absolute mouse position
|
|
888 SDL_PrivateMouseMotion(0, // Buttons not changed
|
|
889 0, // Absolute position
|
|
890 ppts->x,
|
|
891 ppts->y);
|
|
892 }
|
|
893 }
|
|
894 if ((pVideo->hidden->iMouseVisible) && (!bMouseCaptured))
|
|
895 {
|
|
896 #ifdef DEBUG_BUILD
|
|
897 // printf("WM_MOUSEMOVE : ptr = %p\n", hptrGlobalPointer); fflush(stdout);
|
|
898 #endif
|
|
899
|
|
900 if (hptrGlobalPointer)
|
|
901 WinSetPointer(HWND_DESKTOP, hptrGlobalPointer);
|
|
902 else
|
|
903 WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
|
|
904 }
|
|
905 else
|
|
906 {
|
|
907 WinSetPointer(HWND_DESKTOP, NULL);
|
|
908 }
|
|
909 }
|
|
910 #ifdef DEBUG_BUILD
|
|
911 // printf("WM_MOUSEMOVE done\n"); fflush(stdout);
|
|
912 #endif
|
|
913
|
|
914 return (MRESULT) FALSE;
|
|
915 case WM_CLOSE: // Window close
|
|
916 #ifdef DEBUG_BUILD
|
|
917 printf("WM_CLOSE\n"); fflush(stdout);
|
|
918 #endif
|
|
919
|
|
920 pVideo = FSLib_GetUserParm(hwnd);
|
|
921 if (pVideo)
|
|
922 {
|
|
923 // Send Quit message to the SDL application!
|
|
924 SDL_PrivateQuit();
|
|
925 return 0;
|
|
926 }
|
|
927 break;
|
|
928
|
|
929 #ifdef BITBLT_IN_WINMESSAGEPROC
|
|
930 case WM_UPDATERECTSREQUEST:
|
|
931 pVideo = FSLib_GetUserParm(hwnd);
|
|
932 if ((pVideo) && (pVideo->hidden->pSDLSurface))
|
|
933 {
|
|
934 if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR)
|
|
935 {
|
|
936 int numrects;
|
|
937 SDL_Rect *rects;
|
|
938 int i;
|
|
939 SWP swp;
|
|
940
|
|
941 numrects = (int) mp1;
|
|
942 rects = (SDL_Rect *) mp2;
|
|
943
|
|
944 WinQueryWindowPos(hwnd, &swp);
|
|
945 #ifndef RESIZE_EVEN_IF_RESIZABLE
|
|
946 if ((!pVideo->hidden->pSDLSurface) ||
|
|
947 (
|
|
948 (pVideo->hidden->pSDLSurface) &&
|
|
949 (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
|
|
950 ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) ||
|
|
951 (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution)
|
|
952 ) &&
|
|
953 (!FSLib_QueryFSMode(hwnd))
|
|
954 )
|
|
955 )
|
|
956 {
|
|
957 // Resizable surface and in resizing!
|
|
958 // So, don't blit now!
|
|
959 #ifdef DEBUG_BUILD
|
|
960 printf("[WM_UPDATERECTSREQUEST] : Skipping blit while resizing!\n"); fflush(stdout);
|
|
961 #endif
|
|
962 } else
|
|
963 #endif
|
|
964 {
|
|
965 #ifdef DEBUG_BUILD
|
|
966 printf("[WM_UPDATERECTSREQUEST] : Blitting!\n"); fflush(stdout);
|
|
967 #endif
|
|
968
|
|
969 // Blit the changed areas
|
|
970 for (i=0; i<numrects; i++)
|
|
971 FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer,
|
|
972 rects[i].y, rects[i].x, rects[i].w, rects[i].h);
|
|
973 }
|
|
974 DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer);
|
|
975 }
|
|
976 }
|
|
977 return 0;
|
|
978 #endif
|
|
979
|
|
980 default:
|
|
981 #ifdef DEBUG_BUILD
|
|
982 printf("Unhandled: %x\n", msg); fflush(stdout);
|
|
983 #endif
|
|
984
|
|
985 break;
|
|
986 }
|
|
987 // Run the default window procedure for unhandled stuffs
|
|
988 return WinDefWindowProc(hwnd, msg, mp1, mp2);
|
|
989 }
|
|
990
|
|
991 /////////////////////////////////////////////////////////////////////
|
|
992 //
|
|
993 // PMThreadFunc
|
|
994 //
|
|
995 // This function implements the PM-Thread, which initializes the
|
|
996 // application window itself, the DIVE, and start message processing.
|
|
997 //
|
|
998 /////////////////////////////////////////////////////////////////////
|
|
999 int iNumOfPMThreadInstances = 0; // Global!
|
|
1000 static void PMThreadFunc(void *pParm)
|
|
1001 {
|
|
1002 SDL_VideoDevice *pVideo = pParm;
|
|
1003 HAB hab;
|
|
1004 HMQ hmq;
|
|
1005 QMSG msg;
|
|
1006 ULONG fcf;
|
|
1007
|
|
1008 #ifdef DEBUG_BUILD
|
|
1009 printf("[PMThreadFunc] : Starting\n"); fflush(stdout);
|
|
1010 #endif
|
|
1011
|
|
1012 iNumOfPMThreadInstances++;
|
|
1013
|
|
1014 // Initialize PM, create a message queue.
|
|
1015
|
|
1016 hab=WinInitialize(0);
|
|
1017 hmq=WinCreateMsgQueue(hab,0);
|
|
1018 if (hmq==0)
|
|
1019 {
|
|
1020 #ifdef DEBUG_BUILD
|
|
1021 printf("[PMThreadFunc] : Could not create message queue!\n");
|
|
1022 printf(" It might be that the application using SDL is not a PM app!\n");
|
|
1023 fflush(stdout);
|
|
1024 #endif
|
|
1025 pVideo->hidden->iPMThreadStatus = 2;
|
|
1026 } else
|
|
1027 {
|
|
1028 int rc;
|
|
1029 RECTL rectl;
|
|
1030
|
|
1031 fcf = ulFCFToUse; // Get from global setting
|
|
1032
|
|
1033 #ifdef DEBUG_BUILD
|
|
1034 printf("[PMThreadFunc] : FSLib_CreateWindow()!\n");
|
|
1035 fflush(stdout);
|
|
1036 #endif
|
|
1037
|
|
1038 rc = FSLib_CreateWindow(HWND_DESKTOP, 0, &fcf,
|
|
1039 "SDL Application",
|
|
1040 NULLHANDLE, 0,
|
|
1041 &(pVideo->hidden->SrcBufferDesc),
|
|
1042 WndProc,
|
|
1043 &(pVideo->hidden->hwndClient),
|
|
1044 &(pVideo->hidden->hwndFrame));
|
|
1045
|
|
1046 #ifdef DEBUG_BUILD
|
|
1047 printf("[PMThreadFunc] : FSLib_CreateWindow() rc = %d\n", rc);
|
|
1048 fflush(stdout);
|
|
1049 #endif
|
|
1050
|
|
1051 if (!rc)
|
|
1052 {
|
|
1053 #ifdef DEBUG_BUILD
|
|
1054 printf("[PMThreadFunc] : Could not create FSLib window!\n");
|
|
1055 fflush(stdout);
|
|
1056 #endif
|
|
1057 pVideo->hidden->iPMThreadStatus = 3;
|
|
1058 } else
|
|
1059 {
|
|
1060 #ifdef DEBUG_BUILD
|
|
1061 printf("[PMThreadFunc] : FSLib_AddUserParm()!\n");
|
|
1062 fflush(stdout);
|
|
1063 #endif
|
|
1064
|
|
1065 // Store pVideo pointer in window data for client window, so
|
|
1066 // it will know the instance to which it belongs to.
|
|
1067 FSLib_AddUserParm(pVideo->hidden->hwndClient, pVideo);
|
|
1068
|
|
1069 // Now set default image width height and fourcc!
|
|
1070 #ifdef DEBUG_BUILD
|
|
1071 printf("[PMThreadFunc] : SetWindowPos()!\n");
|
|
1072 fflush(stdout);
|
|
1073 #endif
|
|
1074
|
|
1075 // Set the position and size of the main window,
|
|
1076 // and make it visible!
|
|
1077 // Calculate frame window size from client window size
|
|
1078 rectl.xLeft = 0;
|
|
1079 rectl.yBottom = 0;
|
|
1080 rectl.xRight = pVideo->hidden->SrcBufferDesc.uiXResolution; // Noninclusive
|
|
1081 rectl.yTop = pVideo->hidden->SrcBufferDesc.uiYResolution; // Noninclusive
|
|
1082 WinCalcFrameRect(pVideo->hidden->hwndFrame, &rectl, FALSE);
|
|
1083
|
|
1084 SetAccessableWindowPos(pVideo->hidden->hwndFrame,
|
|
1085 HWND_TOP,
|
|
1086 (WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN) - (rectl.xRight-rectl.xLeft)) / 2,
|
|
1087 (WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN) - (rectl.yTop-rectl.yBottom)) / 2,
|
|
1088 (rectl.xRight-rectl.xLeft),
|
|
1089 (rectl.yTop-rectl.yBottom),
|
|
1090 SWP_SIZE | SWP_ACTIVATE | SWP_SHOW | SWP_MOVE);
|
|
1091
|
|
1092 #ifdef DEBUG_BUILD
|
|
1093 printf("[PMThreadFunc] : Entering message loop\n"); fflush(stdout);
|
|
1094 #endif
|
|
1095 pVideo->hidden->iPMThreadStatus = 1;
|
|
1096
|
|
1097 while (WinGetMsg(hab, (PQMSG)&msg, 0, 0, 0))
|
|
1098 WinDispatchMsg(hab, (PQMSG) &msg);
|
|
1099
|
|
1100 #ifdef DEBUG_BUILD
|
|
1101 printf("[PMThreadFunc] : Leaving message loop\n"); fflush(stdout);
|
|
1102 #endif
|
|
1103 // We should release the captured the mouse!
|
|
1104 if (bMouseCaptured)
|
|
1105 {
|
|
1106 WinSetCapture(HWND_DESKTOP, NULLHANDLE);
|
|
1107 bMouseCaptured = 0;
|
|
1108 }
|
|
1109 // Destroy our window
|
|
1110 WinDestroyWindow(pVideo->hidden->hwndFrame); pVideo->hidden->hwndFrame=NULL;
|
|
1111 // Show pointer to make sure it will not be left hidden.
|
|
1112 WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
|
|
1113 WinShowPointer(HWND_DESKTOP, TRUE);
|
|
1114 }
|
|
1115 // Uninitialize PM
|
|
1116 WinDestroyMsgQueue(hmq);
|
|
1117 // All done!
|
|
1118 pVideo->hidden->iPMThreadStatus = 0;
|
|
1119 }
|
|
1120 WinTerminate(hab);
|
|
1121 /* Commented out, should not be needed anymore, because we send it
|
|
1122 from WM_CLOSE.
|
|
1123 // Notify SDL that it should really die now...
|
|
1124 SDL_PrivateQuit(); SDL_PrivateQuit(); SDL_PrivateQuit(); //... :))
|
|
1125 */
|
|
1126 #ifdef DEBUG_BUILD
|
|
1127 printf("[PMThreadFunc] : End, status is %d!\n", pVideo->hidden->iPMThreadStatus); fflush(stdout);
|
|
1128 #endif
|
|
1129
|
|
1130 iNumOfPMThreadInstances--;
|
|
1131
|
|
1132 // HACK to prevent zombie and hanging SDL applications, which does not take
|
|
1133 // care of closing the window for some reason:
|
|
1134 // There are some apps which do not process messages, so do a lot of things
|
|
1135 // without noticing that the application should close. To close these,
|
|
1136 // I've thought about the following:
|
|
1137 // If the window is closed (the execution came here), I wait a bit to
|
|
1138 // give time to the app to finish its execution. If it does not, I kill it
|
|
1139 // using DosExit(). Brute force, but should work.
|
|
1140 if (pVideo->hidden->iPMThreadStatus==0)
|
|
1141 {
|
|
1142 DosSleep(5000); // Wait 5 secs
|
|
1143 // If a new PM thread has been spawned (reinitializing video mode), then all right.
|
|
1144 // Otherwise, we have a problem, the app doesn't want to stop. Kill!
|
|
1145 if (iNumOfPMThreadInstances==0)
|
|
1146 {
|
|
1147 #ifdef DEBUG_BUILD
|
|
1148 printf("[PMThreadFunc] : It seems that the application haven't terminated itself\n"); fflush(stdout);
|
|
1149 printf("[PMThreadFunc] : in the last 5 seconds, so we go berserk.\n"); fflush(stdout);
|
|
1150 printf("[PMThreadFunc] : Brute force mode. :) Killing process! Dieeeee...\n"); fflush(stdout);
|
|
1151 #endif
|
|
1152 DosExit(EXIT_PROCESS, -1);
|
|
1153 }
|
|
1154 }
|
|
1155 _endthread();
|
|
1156 }
|
|
1157
|
|
1158 struct WMcursor
|
|
1159 {
|
|
1160 HBITMAP hbm;
|
|
1161 HPOINTER hptr;
|
|
1162 char *pchData;
|
|
1163 };
|
|
1164
|
|
1165 /* Free a window manager cursor */
|
|
1166 void os2fslib_FreeWMCursor(_THIS, WMcursor *cursor)
|
|
1167 {
|
|
1168 if (cursor)
|
|
1169 {
|
|
1170 GpiDeleteBitmap(cursor->hbm);
|
|
1171 WinDestroyPointer(cursor->hptr);
|
|
1172 free(cursor->pchData);
|
|
1173 free(cursor);
|
|
1174 }
|
|
1175 }
|
|
1176
|
|
1177 /* Local functions to convert the SDL cursor mask into OS/2 format */
|
|
1178 static void memnot(Uint8 *dst, Uint8 *src, int len)
|
|
1179 {
|
|
1180 while ( len-- > 0 )
|
|
1181 *dst++ = ~*src++;
|
|
1182 }
|
|
1183 static void memxor(Uint8 *dst, Uint8 *src1, Uint8 *src2, int len)
|
|
1184 {
|
|
1185 while ( len-- > 0 )
|
|
1186 *dst++ = (*src1++)^(*src2++);
|
|
1187 }
|
|
1188
|
|
1189 /* Create a black/white window manager cursor */
|
|
1190 WMcursor *os2fslib_CreateWMCursor_Win(_THIS, Uint8 *data, Uint8 *mask,
|
|
1191 int w, int h, int hot_x, int hot_y)
|
|
1192 {
|
|
1193 HPOINTER hptr;
|
|
1194 HBITMAP hbm;
|
|
1195 BITMAPINFOHEADER bmih;
|
|
1196 BMPINFO bmi;
|
|
1197 HPS hps;
|
|
1198 char *pchTemp;
|
|
1199 char *xptr, *aptr;
|
|
1200 int maxx, maxy;
|
|
1201 int i, run, pad;
|
|
1202 WMcursor *pResult;
|
|
1203
|
|
1204 maxx = WinQuerySysValue(HWND_DESKTOP, SV_CXPOINTER);
|
|
1205 maxy = WinQuerySysValue(HWND_DESKTOP, SV_CYPOINTER);
|
|
1206
|
|
1207 // Check for max size!
|
|
1208 if ((w>maxx) || (h>maxy))
|
|
1209 return (WMcursor *) NULL;
|
|
1210
|
|
1211 pResult = (WMcursor *) malloc(sizeof(WMcursor));
|
|
1212 if (!pResult) return (WMcursor *) NULL;
|
|
1213
|
|
1214 pchTemp = (char *) malloc((maxx + 7)/8 * maxy*2);
|
|
1215 if (!pchTemp)
|
|
1216 {
|
|
1217 free(pResult);
|
|
1218 return (WMcursor *) NULL;
|
|
1219 }
|
|
1220
|
|
1221 memset(pchTemp, 0, (maxx + 7)/8 * maxy*2);
|
|
1222
|
|
1223 hps = WinGetPS(_this->hidden->hwndClient);
|
|
1224
|
|
1225 bmi.cbFix = sizeof(BITMAPINFOHEADER);
|
|
1226 bmi.cx = maxx;
|
|
1227 bmi.cy = 2*maxy;
|
|
1228 bmi.cPlanes = 1;
|
|
1229 bmi.cBitCount = 1;
|
|
1230 bmi.argbColor[0].bBlue = 0x00;
|
|
1231 bmi.argbColor[0].bGreen = 0x00;
|
|
1232 bmi.argbColor[0].bRed = 0x00;
|
|
1233 bmi.argbColor[1].bBlue = 0x00;
|
|
1234 bmi.argbColor[1].bGreen = 0x00;
|
|
1235 bmi.argbColor[1].bRed = 0xff;
|
|
1236
|
|
1237 memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
|
|
1238 bmih.cbFix = sizeof(BITMAPINFOHEADER);
|
|
1239 bmih.cx = maxx;
|
|
1240 bmih.cy = 2*maxy;
|
|
1241 bmih.cPlanes = 1;
|
|
1242 bmih.cBitCount = 1;
|
|
1243
|
|
1244 run = (w+7)/8;
|
|
1245 pad = (maxx+7)/8 - run;
|
|
1246
|
|
1247 for (i=0; i<h; i++)
|
|
1248 {
|
|
1249 xptr = pchTemp + (maxx+7)/8 * (maxy-1-i);
|
|
1250 aptr = pchTemp + (maxx+7)/8 * (maxy+maxy-1-i);
|
|
1251 memxor(xptr, data, mask, run);
|
|
1252 xptr += run;
|
|
1253 data += run;
|
|
1254 memnot(aptr, mask, run);
|
|
1255 mask += run;
|
|
1256 aptr += run;
|
|
1257 memset(xptr, 0, pad);
|
|
1258 xptr += pad;
|
|
1259 memset(aptr, ~0, pad);
|
|
1260 aptr += pad;
|
|
1261 }
|
|
1262 pad += run;
|
|
1263 for (i=h ; i<maxy; i++ )
|
|
1264 {
|
|
1265 xptr = pchTemp + (maxx+7)/8 * (maxy-1-i);
|
|
1266 aptr = pchTemp + (maxx+7)/8 * (maxy+maxy-1-i);
|
|
1267
|
|
1268 memset(xptr, 0, (maxx+7)/8);
|
|
1269 xptr += (maxx+7)/8;
|
|
1270 memset(aptr, ~0, (maxx+7)/8);
|
|
1271 aptr += (maxx+7)/8;
|
|
1272 }
|
|
1273
|
|
1274 hbm = GpiCreateBitmap(hps, (PBITMAPINFOHEADER2)&bmih, CBM_INIT, (PBYTE) pchTemp, (PBITMAPINFO2)&bmi);
|
|
1275 hptr = WinCreatePointer(HWND_DESKTOP, hbm, TRUE, hot_x, maxy - hot_y - 1);
|
|
1276
|
|
1277 #ifdef DEBUG_BUILD
|
|
1278 printf("HotSpot : %d ; %d\n", hot_x, hot_y);
|
|
1279 printf("HPS returned : %x\n", (ULONG)hps);
|
|
1280 printf("HBITMAP returned : %x\n", (ULONG)hbm);
|
|
1281 printf("HPOINTER returned: %x\n", (ULONG)hptr);
|
|
1282 #endif
|
|
1283
|
|
1284 WinReleasePS(hps);
|
|
1285
|
|
1286 #ifdef DEBUG_BUILD
|
|
1287 printf("[CreateWMCursor] : ptr = %p\n", hptr); fflush(stdout);
|
|
1288 #endif
|
|
1289
|
|
1290 pResult->hptr = hptr;
|
|
1291 pResult->hbm = hbm;
|
|
1292 pResult->pchData = pchTemp;
|
|
1293
|
|
1294 #ifdef DEBUG_BUILD
|
|
1295 printf("[CreateWMCursor] : ptr = %p return.\n", hptr); fflush(stdout);
|
|
1296 #endif
|
|
1297
|
|
1298 return (WMcursor *) pResult;
|
|
1299 }
|
|
1300
|
|
1301 WMcursor *os2fslib_CreateWMCursor_FS(_THIS, Uint8 *data, Uint8 *mask,
|
|
1302 int w, int h, int hot_x, int hot_y)
|
|
1303 {
|
|
1304 #ifdef DEBUG_BUILD
|
|
1305 printf("[CreateWMCursor_FS] : returning pointer NULL\n"); fflush(stdout);
|
|
1306 #endif
|
|
1307
|
|
1308 // In FS mode we'll use software cursor
|
|
1309 return (WMcursor *) NULL;
|
|
1310 }
|
|
1311
|
|
1312 /* Show the specified cursor, or hide if cursor is NULL */
|
|
1313 int os2fslib_ShowWMCursor(_THIS, WMcursor *cursor)
|
|
1314 {
|
|
1315 #ifdef DEBUG_BUILD
|
|
1316 printf("[ShowWMCursor] : ptr = %p\n", cursor); fflush(stdout);
|
|
1317 #endif
|
|
1318
|
|
1319 if (cursor)
|
|
1320 {
|
|
1321 WinSetPointer(HWND_DESKTOP, cursor->hptr);
|
|
1322 hptrGlobalPointer = cursor->hptr;
|
|
1323 _this->hidden->iMouseVisible = 1;
|
|
1324 }
|
|
1325 else
|
|
1326 {
|
|
1327 WinSetPointer(HWND_DESKTOP, FALSE);
|
|
1328 hptrGlobalPointer = NULL;
|
|
1329 _this->hidden->iMouseVisible = 0;
|
|
1330 }
|
|
1331
|
|
1332 #ifdef DEBUG_BUILD
|
|
1333 printf("[ShowWMCursor] : ptr = %p, DONE\n", cursor); fflush(stdout);
|
|
1334 #endif
|
|
1335
|
|
1336 return 1;
|
|
1337 }
|
|
1338
|
|
1339 /* Warp the window manager cursor to (x,y)
|
|
1340 If NULL, a mouse motion event is posted internally.
|
|
1341 */
|
|
1342 void os2fslib_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
|
|
1343 {
|
|
1344 LONG lx, ly;
|
|
1345 SWP swpClient;
|
|
1346 POINTL ptlPoints;
|
|
1347 WinQueryWindowPos(_this->hidden->hwndClient, &swpClient);
|
|
1348 ptlPoints.x = swpClient.x;
|
|
1349 ptlPoints.y = swpClient.y;
|
|
1350 WinMapWindowPoints(_this->hidden->hwndFrame, HWND_DESKTOP, &ptlPoints, 1);
|
|
1351 lx = ptlPoints.x + (x*swpClient.cx) / _this->hidden->SrcBufferDesc.uiXResolution;
|
|
1352 ly = ptlPoints.y + swpClient.cy - ((y*swpClient.cy) / _this->hidden->SrcBufferDesc.uiYResolution) - 1;
|
|
1353
|
|
1354 SDL_PrivateMouseMotion(0, // Buttons not changed
|
|
1355 0, // Absolute position
|
|
1356 x,
|
|
1357 y);
|
|
1358
|
|
1359 WinSetPointerPos(HWND_DESKTOP, lx, ly);
|
|
1360
|
|
1361 }
|
|
1362
|
|
1363 /* If not NULL, this is called when a mouse motion event occurs */
|
|
1364 void os2fslib_MoveWMCursor(_THIS, int x, int y)
|
|
1365 {
|
|
1366 /*
|
|
1367 SDL_Rect rect;
|
|
1368
|
|
1369 #ifdef DEBUG_BUILD
|
|
1370 printf("[MoveWMCursor] : at %d ; %d\n", x, y); fflush(stdout);
|
|
1371 #endif
|
|
1372
|
|
1373 rect.x = x;
|
|
1374 rect.y = y;
|
|
1375 rect.w = 32;
|
|
1376 rect.h = 32;
|
|
1377 os2fslib_UpdateRects(_this, 1, &rect);
|
|
1378 // TODO!
|
|
1379 */
|
|
1380 }
|
|
1381
|
|
1382 /* Determine whether the mouse should be in relative mode or not.
|
|
1383 This function is called when the input grab state or cursor
|
|
1384 visibility state changes.
|
|
1385 If the cursor is not visible, and the input is grabbed, the
|
|
1386 driver can place the mouse in relative mode, which may result
|
|
1387 in higher accuracy sampling of the pointer motion.
|
|
1388 */
|
|
1389 void os2fslib_CheckMouseMode(_THIS)
|
|
1390 {
|
|
1391 }
|
|
1392
|
|
1393 static void os2fslib_PumpEvents(_THIS)
|
|
1394 {
|
|
1395 // Notify SDL that if window has been resized!
|
|
1396 if (
|
|
1397 (_this->hidden->pSDLSurface) &&
|
|
1398 (_this->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
|
|
1399 (
|
|
1400 (_this->hidden->SrcBufferDesc.uiXResolution!=iWindowSizeX) ||
|
|
1401 (_this->hidden->SrcBufferDesc.uiYResolution!=iWindowSizeY)
|
|
1402 ) &&
|
|
1403 (iWindowSizeX>0) &&
|
|
1404 (iWindowSizeY>0)
|
|
1405 )
|
|
1406 {
|
|
1407 static time_t prev_time;
|
|
1408 time_t curr_time;
|
|
1409
|
|
1410 curr_time = time(NULL);
|
|
1411 if ((difftime(curr_time, prev_time)>=0.25) ||
|
|
1412 (bWindowResized))
|
|
1413 {
|
|
1414 // Make sure we won't flood the event queue with resize events,
|
|
1415 // only send them at 250 msecs!
|
|
1416 // (or when the window is resized)
|
|
1417 #ifdef DEBUG_BUILD
|
|
1418 printf("[os2fslib_PumpEvents] : Calling PrivateResize (%d %d).\n",
|
|
1419 iWindowSizeX, iWindowSizeY);
|
|
1420 fflush(stdout);
|
|
1421 #endif
|
|
1422 // Tell SDL the new size
|
|
1423 SDL_PrivateResize(iWindowSizeX, iWindowSizeY);
|
|
1424 prev_time = curr_time;
|
|
1425 bWindowResized = 0;
|
|
1426 }
|
|
1427 }
|
|
1428 }
|
|
1429
|
|
1430 /* We don't actually allow hardware surfaces other than the main one */
|
|
1431 static int os2fslib_AllocHWSurface(_THIS, SDL_Surface *surface)
|
|
1432 {
|
|
1433 return(-1);
|
|
1434 }
|
|
1435 static void os2fslib_FreeHWSurface(_THIS, SDL_Surface *surface)
|
|
1436 {
|
|
1437 return;
|
|
1438 }
|
|
1439
|
|
1440 /* We need to wait for vertical retrace on page flipped displays */
|
|
1441 static int os2fslib_LockHWSurface(_THIS, SDL_Surface *surface)
|
|
1442 {
|
|
1443 return(0);
|
|
1444 }
|
|
1445
|
|
1446 static void os2fslib_UnlockHWSurface(_THIS, SDL_Surface *surface)
|
|
1447 {
|
|
1448 return;
|
|
1449 }
|
|
1450
|
|
1451 static int os2fslib_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
|
|
1452 {
|
|
1453 printf("[os2fslib_SetColors] : TODO!\n"); fflush(stdout);
|
|
1454 // TODO: Implement paletted modes
|
|
1455 return(1);
|
|
1456 }
|
|
1457
|
|
1458 static void os2fslib_DestroyIcon(HWND hwndFrame)
|
|
1459 {
|
|
1460 if (hptrCurrentIcon)
|
|
1461 {
|
|
1462 WinDestroyPointer(hptrCurrentIcon);
|
|
1463 hptrCurrentIcon = NULL;
|
|
1464
|
|
1465 WinSendMsg(hwndFrame,
|
|
1466 WM_SETICON,
|
|
1467 NULL,
|
|
1468 NULL);
|
|
1469 }
|
|
1470
|
|
1471 }
|
|
1472
|
|
1473 /* Set the window icon image */
|
|
1474 void os2fslib_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask)
|
|
1475 {
|
|
1476 HWND hwndFrame;
|
|
1477 SDL_Surface *icon_rgb;
|
|
1478 HPOINTER hptrIcon;
|
|
1479 HBITMAP hbm;
|
|
1480 BITMAPINFOHEADER bmih;
|
|
1481 BMPINFO bmi;
|
|
1482 HPS hps;
|
|
1483 char *pchTemp;
|
|
1484 char *pptr, *mptr, *dptr, *dmptr;
|
|
1485 int maxx, maxy, w, h, x, y;
|
|
1486 SDL_Rect bounds;
|
|
1487
|
|
1488 #ifdef DEBUG_BUILD
|
|
1489 printf("[os2fslib_SetIcon] : Creating and setting new icon\n"); fflush(stdout);
|
|
1490 #endif
|
|
1491
|
|
1492 hwndFrame = WinQueryWindow(_this->hidden->hwndClient, QW_PARENT);
|
|
1493
|
|
1494 // Make sure the old icon resource will be free'd!
|
|
1495 os2fslib_DestroyIcon(hwndFrame);
|
|
1496
|
|
1497 if ((!icon) || (!mask))
|
|
1498 return;
|
|
1499
|
|
1500 w = icon->w;
|
|
1501 h = icon->h;
|
|
1502
|
|
1503 maxx = WinQuerySysValue(HWND_DESKTOP, SV_CXICON);
|
|
1504 maxy = WinQuerySysValue(HWND_DESKTOP, SV_CYICON);
|
|
1505
|
|
1506 // Check for max size!
|
|
1507 if ((w>maxx) || (h>maxy))
|
|
1508 return;
|
|
1509
|
|
1510 pchTemp = (char *) malloc(w * h*2 * 4);
|
|
1511 if (!pchTemp)
|
|
1512 return;
|
|
1513
|
|
1514 memset(pchTemp, 0, w * h*2 * 4);
|
|
1515
|
|
1516 // Convert surface to RGB, if it's not RGB yet!
|
|
1517 icon_rgb = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h,
|
|
1518 32, 0, 0, 0, 0);
|
|
1519 if ( icon_rgb == NULL )
|
|
1520 {
|
|
1521 free(pchTemp);
|
|
1522 return;
|
|
1523 }
|
|
1524 bounds.x = 0;
|
|
1525 bounds.y = 0;
|
|
1526 bounds.w = icon->w;
|
|
1527 bounds.h = icon->h;
|
|
1528 if ( SDL_LowerBlit(icon, &bounds, icon_rgb, &bounds) < 0 )
|
|
1529 {
|
|
1530 SDL_FreeSurface(icon_rgb);
|
|
1531 free(pchTemp);
|
|
1532 return;
|
|
1533 }
|
|
1534
|
|
1535 /* Copy pixels upside-down from RGB surface into BMP, masked with the icon mask */
|
|
1536
|
|
1537 // Pixels
|
|
1538 pptr = (char *) (icon_rgb->pixels);
|
|
1539 // Mask
|
|
1540 mptr = mask;
|
|
1541
|
|
1542 for (y=0; y<h; y++)
|
|
1543 {
|
|
1544 unsigned char uchMaskByte;
|
|
1545
|
|
1546 // Destination
|
|
1547 dptr = pchTemp + w*4 * (h-y-1);
|
|
1548 // Destination mask
|
|
1549 dmptr = pchTemp + w*h*4 + w*4 * (h-y-1);
|
|
1550
|
|
1551 for (x=0; x<w; x++)
|
|
1552 {
|
|
1553 if (x%8==0)
|
|
1554 {
|
|
1555 uchMaskByte = (unsigned char) (*mptr);
|
|
1556 mptr++;
|
|
1557 } else
|
|
1558 uchMaskByte <<= 1;
|
|
1559
|
|
1560 if (uchMaskByte & 0x80)
|
|
1561 {
|
|
1562 // Copy RGB
|
|
1563 *dptr++ = *pptr++;
|
|
1564 *dptr++ = *pptr++;
|
|
1565 *dptr++ = *pptr++;
|
|
1566 *dptr++ = *pptr++;
|
|
1567
|
|
1568 *dmptr++ = 0;
|
|
1569 *dmptr++ = 0;
|
|
1570 *dmptr++ = 0;
|
|
1571 *dmptr++ = 0;
|
|
1572 } else
|
|
1573 {
|
|
1574 // Set pixels to fully transparent
|
|
1575 *dptr++ = 0; pptr++;
|
|
1576 *dptr++ = 0; pptr++;
|
|
1577 *dptr++ = 0; pptr++;
|
|
1578 *dptr++ = 0; pptr++;
|
|
1579
|
|
1580 *dmptr++ = 255;
|
|
1581 *dmptr++ = 255;
|
|
1582 *dmptr++ = 255;
|
|
1583 *dmptr++ = 255;
|
|
1584 }
|
|
1585 }
|
|
1586 }
|
|
1587
|
|
1588 // There is no more need for the RGB surface
|
|
1589 SDL_FreeSurface(icon_rgb);
|
|
1590
|
|
1591 hps = WinGetPS(_this->hidden->hwndClient);
|
|
1592
|
|
1593 bmi.cbFix = sizeof(BITMAPINFOHEADER);
|
|
1594 bmi.cx = w;
|
|
1595 bmi.cy = 2*h;
|
|
1596 bmi.cPlanes = 1;
|
|
1597 bmi.cBitCount = 32;
|
|
1598
|
|
1599 memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
|
|
1600 bmih.cbFix = sizeof(BITMAPINFOHEADER);
|
|
1601 bmih.cx = w;
|
|
1602 bmih.cy = 2*h;
|
|
1603 bmih.cPlanes = 1;
|
|
1604 bmih.cBitCount = 32;
|
|
1605
|
|
1606 hbm = GpiCreateBitmap(hps, (PBITMAPINFOHEADER2)&bmih, CBM_INIT, (PBYTE) pchTemp, (PBITMAPINFO2)&bmi);
|
|
1607 hptrIcon = WinCreatePointer(HWND_DESKTOP, hbm, FALSE, 0, 0);
|
|
1608
|
|
1609 WinReleasePS(hps);
|
|
1610
|
|
1611 // Free pixel array
|
|
1612 free(pchTemp);
|
|
1613
|
|
1614 // Change icon in frame window
|
|
1615 WinSendMsg(hwndFrame,
|
|
1616 WM_SETICON,
|
|
1617 (MPARAM) hptrIcon,
|
|
1618 NULL);
|
|
1619
|
|
1620 /*
|
|
1621 // Change icon in switchlist
|
|
1622 // Seems like it's not needed, the WM_SETICON already does it.
|
|
1623 {
|
|
1624 PID pidFrame;
|
|
1625 HSWITCH hswitchFrame;
|
|
1626 SWCNTRL swctl;
|
|
1627
|
|
1628 WinQueryWindowProcess(hwndFrame, &pidFrame, NULL);
|
|
1629 hswitchFrame = WinQuerySwitchHandle(hwndFrame, pidFrame);
|
|
1630 WinQuerySwitchEntry(hswitchFrame, &swctl);
|
|
1631
|
|
1632 swctl.hwndIcon = hptrIcon;
|
|
1633
|
|
1634 WinChangeSwitchEntry(hswitchFrame, &swctl);
|
|
1635 }
|
|
1636 */
|
|
1637
|
|
1638 // Store icon handle in global variable
|
|
1639 hptrCurrentIcon = hptrIcon;
|
|
1640 }
|
|
1641
|
|
1642 // ------------------------ REAL FUNCTIONS -----------------
|
|
1643
|
|
1644
|
|
1645 static void os2fslib_SetCursorManagementFunctions(_THIS, int iForWindowedMode)
|
|
1646 {
|
|
1647 if (iForWindowedMode)
|
|
1648 {
|
|
1649 _this->FreeWMCursor = os2fslib_FreeWMCursor;
|
|
1650 _this->CreateWMCursor = os2fslib_CreateWMCursor_Win;
|
|
1651 _this->ShowWMCursor = os2fslib_ShowWMCursor;
|
|
1652 _this->WarpWMCursor = os2fslib_WarpWMCursor;
|
|
1653 _this->MoveWMCursor = os2fslib_MoveWMCursor;
|
|
1654 _this->CheckMouseMode = NULL;//os2fslib_CheckMouseMode;
|
|
1655 } else
|
|
1656 {
|
|
1657 // We'll have software mouse cursor in FS mode!
|
|
1658 _this->FreeWMCursor = os2fslib_FreeWMCursor;
|
|
1659 _this->CreateWMCursor = os2fslib_CreateWMCursor_FS;
|
|
1660 _this->ShowWMCursor = os2fslib_ShowWMCursor;
|
|
1661 _this->WarpWMCursor = os2fslib_WarpWMCursor;
|
|
1662 _this->MoveWMCursor = os2fslib_MoveWMCursor;
|
|
1663 _this->CheckMouseMode = NULL;//os2fslib_CheckMouseMode;
|
|
1664 }
|
|
1665 }
|
|
1666
|
|
1667 static void os2fslib_InitOSKeymap(_THIS)
|
|
1668 {
|
|
1669 int i;
|
|
1670
|
|
1671 iShiftIsPressed = 0;
|
|
1672
|
|
1673 /* Map the VK and CH keysyms */
|
|
1674 for ( i=0; i<=255; ++i )
|
|
1675 HWScanKeyMap[i] = SDLK_UNKNOWN;
|
|
1676
|
|
1677 // First line of keyboard:
|
|
1678 HWScanKeyMap[0x1] = SDLK_ESCAPE;
|
|
1679 HWScanKeyMap[0x3b] = SDLK_F1;
|
|
1680 HWScanKeyMap[0x3c] = SDLK_F2;
|
|
1681 HWScanKeyMap[0x3d] = SDLK_F3;
|
|
1682 HWScanKeyMap[0x3e] = SDLK_F4;
|
|
1683 HWScanKeyMap[0x3f] = SDLK_F5;
|
|
1684 HWScanKeyMap[0x40] = SDLK_F6;
|
|
1685 HWScanKeyMap[0x41] = SDLK_F7;
|
|
1686 HWScanKeyMap[0x42] = SDLK_F8;
|
|
1687 HWScanKeyMap[0x43] = SDLK_F9;
|
|
1688 HWScanKeyMap[0x44] = SDLK_F10;
|
|
1689 HWScanKeyMap[0x57] = SDLK_F11;
|
|
1690 HWScanKeyMap[0x58] = SDLK_F12;
|
|
1691 HWScanKeyMap[0x5d] = SDLK_PRINT;
|
|
1692 HWScanKeyMap[0x46] = SDLK_SCROLLOCK;
|
|
1693 HWScanKeyMap[0x5f] = SDLK_PAUSE;
|
|
1694
|
|
1695 // Second line of keyboard:
|
|
1696 HWScanKeyMap[0x29] = SDLK_BACKQUOTE;
|
|
1697 HWScanKeyMap[0x2] = SDLK_1;
|
|
1698 HWScanKeyMap[0x3] = SDLK_2;
|
|
1699 HWScanKeyMap[0x4] = SDLK_3;
|
|
1700 HWScanKeyMap[0x5] = SDLK_4;
|
|
1701 HWScanKeyMap[0x6] = SDLK_5;
|
|
1702 HWScanKeyMap[0x7] = SDLK_6;
|
|
1703 HWScanKeyMap[0x8] = SDLK_7;
|
|
1704 HWScanKeyMap[0x9] = SDLK_8;
|
|
1705 HWScanKeyMap[0xa] = SDLK_9;
|
|
1706 HWScanKeyMap[0xb] = SDLK_0;
|
|
1707 HWScanKeyMap[0xc] = SDLK_MINUS;
|
|
1708 HWScanKeyMap[0xd] = SDLK_EQUALS;
|
|
1709 HWScanKeyMap[0xe] = SDLK_BACKSPACE;
|
|
1710 HWScanKeyMap[0x68] = SDLK_INSERT;
|
|
1711 HWScanKeyMap[0x60] = SDLK_HOME;
|
|
1712 HWScanKeyMap[0x62] = SDLK_PAGEUP;
|
|
1713 HWScanKeyMap[0x45] = SDLK_NUMLOCK;
|
|
1714 HWScanKeyMap[0x5c] = SDLK_KP_DIVIDE;
|
|
1715 HWScanKeyMap[0x37] = SDLK_KP_MULTIPLY;
|
|
1716 HWScanKeyMap[0x4a] = SDLK_KP_MINUS;
|
|
1717
|
|
1718 // Third line of keyboard:
|
|
1719 HWScanKeyMap[0xf] = SDLK_TAB;
|
|
1720 HWScanKeyMap[0x10] = SDLK_q;
|
|
1721 HWScanKeyMap[0x11] = SDLK_w;
|
|
1722 HWScanKeyMap[0x12] = SDLK_e;
|
|
1723 HWScanKeyMap[0x13] = SDLK_r;
|
|
1724 HWScanKeyMap[0x14] = SDLK_t;
|
|
1725 HWScanKeyMap[0x15] = SDLK_y;
|
|
1726 HWScanKeyMap[0x16] = SDLK_u;
|
|
1727 HWScanKeyMap[0x17] = SDLK_i;
|
|
1728 HWScanKeyMap[0x18] = SDLK_o;
|
|
1729 HWScanKeyMap[0x19] = SDLK_p;
|
|
1730 HWScanKeyMap[0x1a] = SDLK_LEFTBRACKET;
|
|
1731 HWScanKeyMap[0x1b] = SDLK_RIGHTBRACKET;
|
|
1732 HWScanKeyMap[0x1c] = SDLK_RETURN;
|
|
1733 HWScanKeyMap[0x69] = SDLK_DELETE;
|
|
1734 HWScanKeyMap[0x65] = SDLK_END;
|
|
1735 HWScanKeyMap[0x67] = SDLK_PAGEDOWN;
|
|
1736 HWScanKeyMap[0x47] = SDLK_KP7;
|
|
1737 HWScanKeyMap[0x48] = SDLK_KP8;
|
|
1738 HWScanKeyMap[0x49] = SDLK_KP9;
|
|
1739 HWScanKeyMap[0x4e] = SDLK_KP_PLUS;
|
|
1740
|
|
1741 // Fourth line of keyboard:
|
|
1742 HWScanKeyMap[0x3a] = SDLK_CAPSLOCK;
|
|
1743 HWScanKeyMap[0x1e] = SDLK_a;
|
|
1744 HWScanKeyMap[0x1f] = SDLK_s;
|
|
1745 HWScanKeyMap[0x20] = SDLK_d;
|
|
1746 HWScanKeyMap[0x21] = SDLK_f;
|
|
1747 HWScanKeyMap[0x22] = SDLK_g;
|
|
1748 HWScanKeyMap[0x23] = SDLK_h;
|
|
1749 HWScanKeyMap[0x24] = SDLK_j;
|
|
1750 HWScanKeyMap[0x25] = SDLK_k;
|
|
1751 HWScanKeyMap[0x26] = SDLK_l;
|
|
1752 HWScanKeyMap[0x27] = SDLK_SEMICOLON;
|
|
1753 HWScanKeyMap[0x28] = SDLK_QUOTE;
|
|
1754 HWScanKeyMap[0x2b] = SDLK_BACKSLASH;
|
|
1755 HWScanKeyMap[0x4b] = SDLK_KP4;
|
|
1756 HWScanKeyMap[0x4c] = SDLK_KP5;
|
|
1757 HWScanKeyMap[0x4d] = SDLK_KP6;
|
|
1758
|
|
1759 // Fifth line of keyboard:
|
|
1760 HWScanKeyMap[0x2a] = SDLK_LSHIFT;
|
|
1761 HWScanKeyMap[0x56] = SDLK_WORLD_1; // Code 161, letter i' on hungarian keyboard
|
|
1762 HWScanKeyMap[0x2c] = SDLK_z;
|
|
1763 HWScanKeyMap[0x2d] = SDLK_x;
|
|
1764 HWScanKeyMap[0x2e] = SDLK_c;
|
|
1765 HWScanKeyMap[0x2f] = SDLK_v;
|
|
1766 HWScanKeyMap[0x30] = SDLK_b;
|
|
1767 HWScanKeyMap[0x31] = SDLK_n;
|
|
1768 HWScanKeyMap[0x32] = SDLK_m;
|
|
1769 HWScanKeyMap[0x33] = SDLK_COMMA;
|
|
1770 HWScanKeyMap[0x34] = SDLK_PERIOD;
|
|
1771 HWScanKeyMap[0x35] = SDLK_SLASH;
|
|
1772 HWScanKeyMap[0x36] = SDLK_RSHIFT;
|
|
1773 HWScanKeyMap[0x61] = SDLK_UP;
|
|
1774 HWScanKeyMap[0x4f] = SDLK_KP1;
|
|
1775 HWScanKeyMap[0x50] = SDLK_KP2;
|
|
1776 HWScanKeyMap[0x51] = SDLK_KP3;
|
|
1777 HWScanKeyMap[0x5a] = SDLK_KP_ENTER;
|
|
1778
|
|
1779 // Sixth line of keyboard:
|
|
1780 HWScanKeyMap[0x1d] = SDLK_LCTRL;
|
|
1781 HWScanKeyMap[0x7e] = SDLK_LSUPER; // Windows key
|
|
1782 HWScanKeyMap[0x38] = SDLK_LALT;
|
|
1783 HWScanKeyMap[0x39] = SDLK_SPACE;
|
|
1784 HWScanKeyMap[0x5e] = SDLK_RALT;// Actually, altgr on my keyboard...
|
|
1785 HWScanKeyMap[0x7f] = SDLK_RSUPER;
|
|
1786 HWScanKeyMap[0x7c] = SDLK_MENU;
|
|
1787 HWScanKeyMap[0x5b] = SDLK_RCTRL;
|
|
1788 HWScanKeyMap[0x63] = SDLK_LEFT;
|
|
1789 HWScanKeyMap[0x66] = SDLK_DOWN;
|
|
1790 HWScanKeyMap[0x64] = SDLK_RIGHT;
|
|
1791 HWScanKeyMap[0x52] = SDLK_KP0;
|
|
1792 HWScanKeyMap[0x53] = SDLK_KP_PERIOD;
|
|
1793 }
|
|
1794
|
|
1795
|
|
1796 /* Iconify the window.
|
|
1797 This function returns 1 if there is a window manager and the
|
|
1798 window was actually iconified, it returns 0 otherwise.
|
|
1799 */
|
|
1800 int os2fslib_IconifyWindow(_THIS)
|
|
1801 {
|
|
1802 HAB hab;
|
|
1803 HMQ hmq;
|
|
1804 ERRORID hmqerror;
|
|
1805
|
|
1806 // If there is no more window, nothing we can do!
|
|
1807 if (_this->hidden->iPMThreadStatus!=1) return 0;
|
|
1808
|
|
1809 // Cannot do anything in fullscreen mode!
|
|
1810 if (FSLib_QueryFSMode(_this->hidden->hwndClient))
|
|
1811 return 0;
|
|
1812
|
|
1813 // Make sure this thread is prepared for using the Presentation Manager!
|
|
1814 hab = WinInitialize(0);
|
|
1815 hmq = WinCreateMsgQueue(hab,0);
|
|
1816 // Remember if there was an error at WinCreateMsgQueue(), because we don't
|
|
1817 // want to destroy somebody else's queue later. :)
|
|
1818 hmqerror = WinGetLastError(hab);
|
|
1819
|
|
1820 WinSetWindowPos(_this->hidden->hwndFrame, HWND_TOP,
|
|
1821 0, 0, 0, 0, SWP_MINIMIZE);
|
|
1822
|
|
1823 // Now destroy the message queue, if we've created it!
|
|
1824 if (ERRORIDERROR(hmqerror)==0)
|
|
1825 WinDestroyMsgQueue(hmq);
|
|
1826
|
|
1827 return 1;
|
|
1828 }
|
|
1829
|
|
1830 static SDL_GrabMode os2fslib_GrabInput(_THIS, SDL_GrabMode mode)
|
|
1831 {
|
|
1832 HAB hab;
|
|
1833 HMQ hmq;
|
|
1834 ERRORID hmqerror;
|
|
1835
|
|
1836
|
|
1837 // If there is no more window, nothing we can do!
|
|
1838 if (_this->hidden->iPMThreadStatus!=1)
|
|
1839 return SDL_GRAB_OFF;
|
|
1840
|
|
1841 // Make sure this thread is prepared for using the Presentation Manager!
|
|
1842 hab = WinInitialize(0);
|
|
1843 hmq = WinCreateMsgQueue(hab,0);
|
|
1844 // Remember if there was an error at WinCreateMsgQueue(), because we don't
|
|
1845 // want to destroy somebody else's queue later. :)
|
|
1846 hmqerror = WinGetLastError(hab);
|
|
1847
|
|
1848
|
|
1849 if (mode == SDL_GRAB_OFF)
|
|
1850 {
|
|
1851 #ifdef DEBUG_BUILD
|
|
1852 printf("[os2fslib_GrabInput] : Releasing mouse\n"); fflush(stdout);
|
|
1853 #endif
|
|
1854
|
|
1855 // Release the mouse
|
|
1856 bMouseCapturable = 0;
|
|
1857 if (bMouseCaptured)
|
|
1858 {
|
|
1859 WinSetCapture(HWND_DESKTOP, NULLHANDLE);
|
|
1860 bMouseCaptured = 0;
|
|
1861 }
|
|
1862 } else
|
|
1863 {
|
|
1864 #ifdef DEBUG_BUILD
|
|
1865 printf("[os2fslib_GrabInput] : Capturing mouse\n"); fflush(stdout);
|
|
1866 #endif
|
|
1867
|
|
1868 // Capture the mouse
|
|
1869 bMouseCapturable = 1;
|
|
1870 if (WinQueryFocus(HWND_DESKTOP) == _this->hidden->hwndClient)
|
|
1871 {
|
|
1872 WinSetCapture(HWND_DESKTOP, _this->hidden->hwndClient);
|
|
1873 bMouseCaptured = 1;
|
|
1874 {
|
|
1875 SWP swpClient;
|
|
1876 POINTL ptl;
|
|
1877 // Center the mouse to the middle of the window!
|
|
1878 WinQueryWindowPos(_this->hidden->hwndClient, &swpClient);
|
|
1879 ptl.x = 0; ptl.y = 0;
|
|
1880 WinMapWindowPoints(_this->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
|
|
1881 _this->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
|
|
1882 WinSetPointerPos(HWND_DESKTOP,
|
|
1883 ptl.x + swpClient.cx/2,
|
|
1884 ptl.y + swpClient.cy/2);
|
|
1885 }
|
|
1886 }
|
|
1887 }
|
|
1888
|
|
1889 // Now destroy the message queue, if we've created it!
|
|
1890 if (ERRORIDERROR(hmqerror)==0)
|
|
1891 WinDestroyMsgQueue(hmq);
|
|
1892
|
|
1893 return mode;
|
|
1894 }
|
|
1895
|
|
1896 /* Set the title and icon text */
|
|
1897 static void os2fslib_SetCaption(_THIS, const char *title, const char *icon)
|
|
1898 {
|
|
1899 HAB hab;
|
|
1900 HMQ hmq;
|
|
1901 ERRORID hmqerror;
|
|
1902
|
|
1903 // If there is no more window, nothing we can do!
|
|
1904 if (_this->hidden->iPMThreadStatus!=1) return;
|
|
1905
|
|
1906 // Make sure this thread is prepared for using the Presentation Manager!
|
|
1907 hab = WinInitialize(0);
|
|
1908 hmq = WinCreateMsgQueue(hab,0);
|
|
1909 // Remember if there was an error at WinCreateMsgQueue(), because we don't
|
|
1910 // want to destroy somebody else's queue later. :)
|
|
1911 hmqerror = WinGetLastError(hab);
|
|
1912
|
|
1913 WinSetWindowText(_this->hidden->hwndFrame, (char *) title);
|
|
1914
|
|
1915 // Now destroy the message queue, if we've created it!
|
|
1916 if (ERRORIDERROR(hmqerror)==0)
|
|
1917 WinDestroyMsgQueue(hmq);
|
|
1918 }
|
|
1919
|
|
1920 static int os2fslib_ToggleFullScreen(_THIS, int on)
|
|
1921 {
|
|
1922 #ifdef DEBUG_BUILD
|
|
1923 printf("[os2fslib_ToggleFullScreen] : %d\n", on); fflush(stdout);
|
|
1924 #endif
|
|
1925 // If there is no more window, nothing we can do!
|
|
1926 if (_this->hidden->iPMThreadStatus!=1) return 0;
|
|
1927
|
|
1928 FSLib_ToggleFSMode(_this->hidden->hwndClient, on);
|
|
1929 /* Cursor manager functions to Windowed/FS mode*/
|
|
1930 os2fslib_SetCursorManagementFunctions(_this, !on);
|
|
1931 return 1;
|
|
1932 }
|
|
1933
|
|
1934 /* This is called after the video mode has been set, to get the
|
|
1935 initial mouse state. It should queue events as necessary to
|
|
1936 properly represent the current mouse focus and position.
|
|
1937 */
|
|
1938 static void os2fslib_UpdateMouse(_THIS)
|
|
1939 {
|
|
1940 POINTL ptl;
|
|
1941 HAB hab;
|
|
1942 HMQ hmq;
|
|
1943 ERRORID hmqerror;
|
|
1944 SWP swpClient;
|
|
1945
|
|
1946 // If there is no more window, nothing we can do!
|
|
1947 if (_this->hidden->iPMThreadStatus!=1) return;
|
|
1948
|
|
1949
|
|
1950 // Make sure this thread is prepared for using the Presentation Manager!
|
|
1951 hab = WinInitialize(0);
|
|
1952 hmq = WinCreateMsgQueue(hab,0);
|
|
1953 // Remember if there was an error at WinCreateMsgQueue(), because we don't
|
|
1954 // want to destroy somebody else's queue later. :)
|
|
1955 hmqerror = WinGetLastError(hab);
|
|
1956
|
|
1957
|
|
1958
|
|
1959 if (_this->hidden->fInFocus)
|
|
1960 {
|
|
1961 // If our app is in focus
|
|
1962 SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
|
|
1963 SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
|
|
1964 SDL_PrivateAppActive(1, SDL_APPACTIVE);
|
|
1965 WinQueryPointerPos(HWND_DESKTOP, &ptl);
|
|
1966 WinMapWindowPoints(HWND_DESKTOP, _this->hidden->hwndClient, &ptl, 1);
|
|
1967 WinQueryWindowPos(_this->hidden->hwndClient, &swpClient);
|
|
1968 // Convert OS/2 mouse position to SDL position, and also scale it!
|
|
1969 ptl.x = ptl.x * _this->hidden->SrcBufferDesc.uiXResolution / swpClient.cx;
|
|
1970 ptl.y = ptl.y * _this->hidden->SrcBufferDesc.uiYResolution / swpClient.cy;
|
|
1971 ptl.y = _this->hidden->SrcBufferDesc.uiYResolution - ptl.y - 1;
|
|
1972 SDL_PrivateMouseMotion(0, 0, (Sint16) (ptl.x), (Sint16) (ptl.y));
|
|
1973 } else
|
|
1974 {
|
|
1975 // If we're not in focus
|
|
1976 SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
|
|
1977 SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
|
|
1978 SDL_PrivateAppActive(0, SDL_APPACTIVE);
|
|
1979 SDL_PrivateMouseMotion(0, 0, (Sint16) -1, (Sint16) -1);
|
|
1980 }
|
|
1981
|
|
1982 // Now destroy the message queue, if we've created it!
|
|
1983 if (ERRORIDERROR(hmqerror)==0)
|
|
1984 WinDestroyMsgQueue(hmq);
|
|
1985
|
|
1986 }
|
|
1987
|
|
1988 /* This pointer should exist in the native video subsystem and should
|
|
1989 point to an appropriate update function for the current video mode
|
|
1990 */
|
|
1991 static void os2fslib_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
|
|
1992 {
|
|
1993 // If there is no more window, nothing we can do!
|
|
1994 if (_this->hidden->iPMThreadStatus!=1) return;
|
|
1995
|
|
1996 #ifdef BITBLT_IN_WINMESSAGEPROC
|
|
1997 WinSendMsg(_this->hidden->hwndClient,
|
|
1998 WM_UPDATERECTSREQUEST,
|
|
1999 (MPARAM) numrects,
|
|
2000 (MPARAM) rects);
|
|
2001 #else
|
|
2002 if (DosRequestMutexSem(_this->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR)
|
|
2003 {
|
|
2004 int i;
|
|
2005
|
|
2006 if (_this->hidden->pSDLSurface)
|
|
2007 {
|
|
2008 #ifndef RESIZE_EVEN_IF_RESIZABLE
|
|
2009 SWP swp;
|
|
2010 // But only blit if the window is not resizable, or if
|
|
2011 // the window is resizable and the source buffer size is the
|
|
2012 // same as the destination buffer size!
|
|
2013 WinQueryWindowPos(_this->hidden->hwndClient, &swp);
|
|
2014 if ((_this->hidden->pSDLSurface) &&
|
|
2015 (_this->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
|
|
2016 ((swp.cx != _this->hidden->SrcBufferDesc.uiXResolution) ||
|
|
2017 (swp.cy != _this->hidden->SrcBufferDesc.uiYResolution)
|
|
2018 ) &&
|
|
2019 (!FSLib_QueryFSMode(_this->hidden->hwndClient))
|
|
2020 )
|
|
2021 {
|
|
2022 // Resizable surface and in resizing!
|
|
2023 // So, don't blit now!
|
|
2024 #ifdef DEBUG_BUILD
|
|
2025 printf("[UpdateRects] : Skipping blit while resizing!\n"); fflush(stdout);
|
|
2026 #endif
|
|
2027 } else
|
|
2028 #endif
|
|
2029 {
|
|
2030 /*
|
|
2031 // Blit the whole window
|
|
2032 FSLIB_BITBLT(_this->hidden->hwndClient, _this->hidden->pchSrcBuffer,
|
|
2033 0, 0,
|
|
2034 _this->hidden->SrcBufferDesc.uiXResolution,
|
|
2035 _this->hidden->SrcBufferDesc.uiYResolution);
|
|
2036 */
|
|
2037 #ifdef DEBUG_BUILD
|
|
2038 printf("[os2fslib_UpdateRects] : Blitting!\n"); fflush(stdout);
|
|
2039 #endif
|
|
2040
|
|
2041 // Blit the changed areas
|
|
2042 for (i=0; i<numrects; i++)
|
|
2043 FSLIB_BITBLT(_this->hidden->hwndClient, _this->hidden->pchSrcBuffer,
|
|
2044 rects[i].y, rects[i].x, rects[i].w, rects[i].h);
|
|
2045 }
|
|
2046 }
|
|
2047 #ifdef DEBUG_BUILD
|
|
2048 else
|
|
2049 printf("[os2fslib_UpdateRects] : No public surface!\n"); fflush(stdout);
|
|
2050 #endif
|
|
2051 DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer);
|
|
2052 }
|
|
2053 #ifdef DEBUG_BUILD
|
|
2054 else
|
|
2055 printf("[os2fslib_UpdateRects] : Error in mutex!\n"); fflush(stdout);
|
|
2056 #endif
|
|
2057 #endif
|
|
2058 }
|
|
2059
|
|
2060
|
|
2061 /* Reverse the effects VideoInit() -- called if VideoInit() fails
|
|
2062 or if the application is shutting down the video subsystem.
|
|
2063 */
|
|
2064 static void os2fslib_VideoQuit(_THIS)
|
|
2065 {
|
|
2066 #ifdef DEBUG_BUILD
|
|
2067 printf("[os2fslib_VideoQuit]\n"); fflush(stdout);
|
|
2068 #endif
|
|
2069 // Close PM stuff if running!
|
|
2070 if (_this->hidden->iPMThreadStatus == 1)
|
|
2071 {
|
|
2072 int iTimeout;
|
|
2073 WinPostMsg(_this->hidden->hwndFrame, WM_QUIT, (MPARAM) 0, (MPARAM) 0);
|
|
2074 // HACK: We had this line before:
|
|
2075 //DosWaitThread((TID *) &(_this->hidden->tidPMThread), DCWW_WAIT);
|
|
2076 // We don't use it, because the PMThread will never stop, or if it stops,
|
|
2077 // it will kill the whole process as a emergency fallback.
|
|
2078 // So, we only check for the iPMThreadStatus stuff!
|
|
2079 #ifdef DEBUG_BUILD
|
|
2080 printf("[os2fslib_VideoQuit] : Waiting for PM thread to die\n"); fflush(stdout);
|
|
2081 #endif
|
|
2082
|
|
2083 iTimeout=0;
|
|
2084 while ((_this->hidden->iPMThreadStatus == 1) && (iTimeout<100))
|
|
2085 {
|
|
2086 iTimeout++;
|
|
2087 DosSleep(64);
|
|
2088 }
|
|
2089
|
|
2090 #ifdef DEBUG_BUILD
|
|
2091 printf("[os2fslib_VideoQuit] : End of wait.\n"); fflush(stdout);
|
|
2092 #endif
|
|
2093
|
|
2094 if (_this->hidden->iPMThreadStatus == 1)
|
|
2095 {
|
|
2096 #ifdef DEBUG_BUILD
|
|
2097 printf("[os2fslib_VideoQuit] : Killing PM thread!\n"); fflush(stdout);
|
|
2098 #endif
|
|
2099
|
|
2100 _this->hidden->iPMThreadStatus = 0;
|
|
2101 DosKillThread(_this->hidden->tidPMThread);
|
|
2102
|
|
2103 if (_this->hidden->hwndFrame)
|
|
2104 {
|
|
2105 #ifdef DEBUG_BUILD
|
|
2106 printf("[os2fslib_VideoQuit] : Destroying PM window!\n"); fflush(stdout);
|
|
2107 #endif
|
|
2108
|
|
2109 WinDestroyWindow(_this->hidden->hwndFrame); _this->hidden->hwndFrame=NULL;
|
|
2110 }
|
|
2111 }
|
|
2112
|
|
2113 }
|
|
2114
|
|
2115 // Free result of an old ListModes() call, because there is
|
|
2116 // no FreeListModes() call in SDL!
|
|
2117 if (_this->hidden->pListModesResult)
|
|
2118 {
|
|
2119 free(_this->hidden->pListModesResult); _this->hidden->pListModesResult = NULL;
|
|
2120 }
|
|
2121
|
|
2122 // Free list of available fullscreen modes
|
|
2123 if (_this->hidden->pAvailableFSLibVideoModes)
|
|
2124 {
|
|
2125 FSLib_FreeVideoModeList(_this->hidden->pAvailableFSLibVideoModes);
|
|
2126 _this->hidden->pAvailableFSLibVideoModes = NULL;
|
|
2127 }
|
|
2128
|
|
2129 // Free application icon if we had one
|
|
2130 if (hptrCurrentIcon)
|
|
2131 {
|
|
2132 WinDestroyPointer(hptrCurrentIcon);
|
|
2133 hptrCurrentIcon = NULL;
|
|
2134 }
|
|
2135 }
|
|
2136
|
|
2137 /* Set the requested video mode, returning a surface which will be
|
|
2138 set to the SDL_VideoSurface. The width and height will already
|
|
2139 be verified by ListModes(), and the video subsystem is free to
|
|
2140 set the mode to a supported bit depth different from the one
|
|
2141 specified -- the desired bpp will be emulated with a shadow
|
|
2142 surface if necessary. If a new mode is returned, this function
|
|
2143 should take care of cleaning up the current mode.
|
|
2144 */
|
|
2145 static SDL_Surface *os2fslib_SetVideoMode(_THIS, SDL_Surface *current,
|
|
2146 int width, int height, int bpp, Uint32 flags)
|
|
2147 {
|
|
2148 static int bFirstCall = 1;
|
|
2149 FSLib_VideoMode_p pModeInfo, pModeInfoFound;
|
|
2150 FSLib_VideoMode TempModeInfo;
|
|
2151 HAB hab;
|
|
2152 HMQ hmq;
|
|
2153 ERRORID hmqerror;
|
|
2154 RECTL rectl;
|
|
2155 SDL_Surface *pResult;
|
|
2156
|
|
2157 // If there is no more window, nothing we can do!
|
|
2158 if (_this->hidden->iPMThreadStatus!=1) return NULL;
|
|
2159
|
|
2160 #ifdef DEBUG_BUILD
|
|
2161 printf("[os2fslib_SetVideoMode] : Request for %dx%d @ %dBPP, flags=0x%x\n", width, height, bpp, flags); fflush(stdout);
|
|
2162 #endif
|
|
2163
|
|
2164 // We don't support palette modes!
|
|
2165 if (bpp==8) bpp=32;
|
|
2166
|
|
2167 // Also, we don't support resizable modes in fullscreen mode.
|
|
2168 if (flags & SDL_RESIZABLE)
|
|
2169 flags &= ~SDL_FULLSCREEN;
|
|
2170
|
|
2171 // No double buffered mode
|
|
2172 if (flags & SDL_DOUBLEBUF)
|
|
2173 flags &= ~SDL_DOUBLEBUF;
|
|
2174
|
|
2175 // And, we don't support HWSURFACE yet.
|
|
2176 if (flags & SDL_HWSURFACE)
|
|
2177 {
|
|
2178 flags &= ~SDL_HWSURFACE;
|
|
2179 flags |= SDL_SWSURFACE;
|
|
2180 }
|
|
2181
|
|
2182 #ifdef DEBUG_BUILD
|
|
2183 printf("[os2fslib_SetVideoMode] : Changed request to %dx%d @ %dBPP, flags=0x%x\n", width, height, bpp, flags); fflush(stdout);
|
|
2184 #endif
|
|
2185
|
|
2186 // First check if there is such a video mode they want!
|
|
2187 pModeInfoFound = NULL;
|
|
2188
|
|
2189 // For fullscreen mode we don't support every resolution!
|
|
2190 // So, go through the video modes, and check for such a resolution!
|
|
2191 pModeInfoFound = NULL;
|
|
2192 pModeInfo = _this->hidden->pAvailableFSLibVideoModes;
|
|
2193
|
|
2194 while (pModeInfo)
|
|
2195 {
|
|
2196 // Check all available fullscreen modes for this resolution
|
|
2197 if ((pModeInfo->uiXResolution == width) &&
|
|
2198 (pModeInfo->uiYResolution == height) &&
|
|
2199 (pModeInfo->uiBPP!=8)) // palettized modes not yet supported
|
|
2200 {
|
|
2201 // If good resolution, try to find the exact BPP, or at least
|
|
2202 // something similar...
|
|
2203 if (!pModeInfoFound)
|
|
2204 pModeInfoFound = pModeInfo;
|
|
2205 else
|
|
2206 if ((pModeInfoFound->uiBPP!=bpp) &&
|
|
2207 (pModeInfoFound->uiBPP<pModeInfo->uiBPP))
|
|
2208 pModeInfoFound = pModeInfo;
|
|
2209 }
|
|
2210 pModeInfo = pModeInfo->pNext;
|
|
2211 }
|
|
2212
|
|
2213 // If we did not find a good fullscreen mode, then try a similar
|
|
2214 if (!pModeInfoFound)
|
|
2215 {
|
|
2216 #ifdef DEBUG_BUILD
|
|
2217 printf("[os2fslib_SetVideoMode] : Requested video mode not found, looking for a similar one!\n"); fflush(stdout);
|
|
2218 #endif
|
|
2219 // Go through the video modes again, and find a similar resolution!
|
|
2220 pModeInfo = _this->hidden->pAvailableFSLibVideoModes;
|
|
2221 while (pModeInfo)
|
|
2222 {
|
|
2223 // Check all available fullscreen modes for this resolution
|
|
2224 if ((pModeInfo->uiXResolution >= width) &&
|
|
2225 (pModeInfo->uiYResolution >= height) &&
|
|
2226 (pModeInfo->uiBPP == bpp))
|
|
2227 {
|
|
2228 if (!pModeInfoFound)
|
|
2229 pModeInfoFound = pModeInfo;
|
|
2230 else
|
|
2231 if (((pModeInfoFound->uiXResolution-width)*(pModeInfoFound->uiYResolution-height))>
|
|
2232 ((pModeInfo->uiXResolution-width)*(pModeInfo->uiYResolution-height)))
|
|
2233 {
|
|
2234 // Found a mode which is closer than the current one
|
|
2235 pModeInfoFound = pModeInfo;
|
|
2236 }
|
|
2237 }
|
|
2238 pModeInfo = pModeInfo->pNext;
|
|
2239 }
|
|
2240 }
|
|
2241
|
|
2242 // If we did not find a good fullscreen mode, then return NULL
|
|
2243 if (!pModeInfoFound)
|
|
2244 {
|
|
2245 #ifdef DEBUG_BUILD
|
|
2246 printf("[os2fslib_SetVideoMode] : Requested video mode not found!\n"); fflush(stdout);
|
|
2247 #endif
|
|
2248 return NULL;
|
|
2249 }
|
|
2250
|
|
2251 #ifdef DEBUG_BUILD
|
|
2252 printf("[os2fslib_SetVideoMode] : Found mode!\n"); fflush(stdout);
|
|
2253 #endif
|
|
2254
|
|
2255 // We'll possibly adjust the structure, so copy out the values
|
|
2256 // into TempModeInfo!
|
|
2257 memcpy(&TempModeInfo, pModeInfoFound, sizeof(TempModeInfo));
|
|
2258 pModeInfoFound = &TempModeInfo;
|
|
2259
|
|
2260 if (flags & SDL_RESIZABLE)
|
|
2261 {
|
|
2262 #ifdef DEBUG_BUILD
|
|
2263 printf("[os2fslib_SetVideoMode] : Requested mode is resizable, changing width/height\n"); fflush(stdout);
|
|
2264 #endif
|
|
2265 // Change width and height to requested one!
|
|
2266 TempModeInfo.uiXResolution = width;
|
|
2267 TempModeInfo.uiYResolution = height;
|
|
2268 TempModeInfo.uiScanLineSize = width * ((TempModeInfo.uiBPP+7)/8);
|
|
2269 }
|
|
2270
|
|
2271 // We can try create new surface!
|
|
2272
|
|
2273 // Make sure this thread is prepared for using the Presentation Manager!
|
|
2274 hab = WinInitialize(0);
|
|
2275 hmq = WinCreateMsgQueue(hab,0);
|
|
2276 // Remember if there was an error at WinCreateMsgQueue(), because we don't
|
|
2277 // want to destroy somebody else's queue later. :)
|
|
2278 hmqerror = WinGetLastError(hab);
|
|
2279
|
|
2280
|
|
2281
|
|
2282 if (DosRequestMutexSem(_this->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR)
|
|
2283 {
|
|
2284 #ifdef DEBUG_BUILD
|
|
2285 printf("[os2fslib_SetVideoMode] : Creating new SW surface\n"); fflush(stdout);
|
|
2286 #endif
|
|
2287
|
|
2288 // Create new software surface!
|
|
2289 pResult = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
|
2290 pModeInfoFound->uiXResolution,
|
|
2291 pModeInfoFound->uiYResolution,
|
|
2292 pModeInfoFound->uiBPP,
|
|
2293 ((unsigned int) pModeInfoFound->PixelFormat.ucRedMask) << pModeInfoFound->PixelFormat.ucRedPosition,
|
|
2294 ((unsigned int) pModeInfoFound->PixelFormat.ucGreenMask) << pModeInfoFound->PixelFormat.ucGreenPosition,
|
|
2295 ((unsigned int) pModeInfoFound->PixelFormat.ucBlueMask) << pModeInfoFound->PixelFormat.ucBluePosition,
|
|
2296 ((unsigned int) pModeInfoFound->PixelFormat.ucAlphaMask) << pModeInfoFound->PixelFormat.ucAlphaPosition);
|
|
2297
|
|
2298 if (pResult == NULL)
|
|
2299 {
|
|
2300 DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer);
|
|
2301 SDL_OutOfMemory();
|
|
2302 return NULL;
|
|
2303 }
|
|
2304
|
|
2305 #ifdef DEBUG_BUILD
|
|
2306 printf("[os2fslib_SetVideoMode] : Adjusting pixel format\n"); fflush(stdout);
|
|
2307 #endif
|
|
2308
|
|
2309 // Adjust pixel format mask!
|
|
2310 pResult->format->Rmask = ((unsigned int) pModeInfoFound->PixelFormat.ucRedMask) << pModeInfoFound->PixelFormat.ucRedPosition;
|
|
2311 pResult->format->Rshift = pModeInfoFound->PixelFormat.ucRedPosition;
|
|
2312 pResult->format->Rloss = pModeInfoFound->PixelFormat.ucRedAdjust;
|
|
2313 pResult->format->Gmask = ((unsigned int) pModeInfoFound->PixelFormat.ucGreenMask) << pModeInfoFound->PixelFormat.ucGreenPosition;
|
|
2314 pResult->format->Gshift = pModeInfoFound->PixelFormat.ucGreenPosition;
|
|
2315 pResult->format->Gloss = pModeInfoFound->PixelFormat.ucGreenAdjust;
|
|
2316 pResult->format->Bmask = ((unsigned int) pModeInfoFound->PixelFormat.ucBlueMask) << pModeInfoFound->PixelFormat.ucBluePosition;
|
|
2317 pResult->format->Bshift = pModeInfoFound->PixelFormat.ucBluePosition;
|
|
2318 pResult->format->Bloss = pModeInfoFound->PixelFormat.ucBlueAdjust;
|
|
2319 pResult->format->Amask = ((unsigned int) pModeInfoFound->PixelFormat.ucAlphaMask) << pModeInfoFound->PixelFormat.ucAlphaPosition;
|
|
2320 pResult->format->Ashift = pModeInfoFound->PixelFormat.ucAlphaPosition;
|
|
2321 pResult->format->Aloss = pModeInfoFound->PixelFormat.ucAlphaAdjust;
|
|
2322
|
|
2323 #ifdef REPORT_EMPTY_ALPHA_MASK
|
|
2324 pResult->format->Amask =
|
|
2325 pResult->format->Ashift =
|
|
2326 pResult->format->Aloss = 0;
|
|
2327 #endif
|
|
2328
|
|
2329 // Adjust surface flags
|
|
2330 pResult->flags |= (flags & SDL_FULLSCREEN);
|
|
2331 pResult->flags |= (flags & SDL_RESIZABLE);
|
|
2332
|
|
2333 // It might be that the software surface pitch is not the same as
|
|
2334 // the pitch we have, so adjust that!
|
|
2335 pModeInfoFound->uiScanLineSize = pResult->pitch;
|
|
2336
|
|
2337 // Store new source buffer parameters!
|
|
2338 memcpy(&(_this->hidden->SrcBufferDesc), pModeInfoFound, sizeof(*pModeInfoFound));
|
|
2339 _this->hidden->pchSrcBuffer = pResult->pixels;
|
|
2340
|
|
2341 #ifdef DEBUG_BUILD
|
|
2342 printf("[os2fslib_SetVideoMode] : Telling FSLib the stuffs\n"); fflush(stdout);
|
|
2343 #endif
|
|
2344
|
|
2345 // Tell the FSLib window the new source image format
|
|
2346 FSLib_SetSrcBufferDesc(_this->hidden->hwndClient, &(_this->hidden->SrcBufferDesc));
|
|
2347
|
|
2348 if (
|
|
2349 ((flags & SDL_RESIZABLE)==0) ||
|
|
2350 (bFirstCall)
|
|
2351 )
|
|
2352 {
|
|
2353 bFirstCall = 0;
|
|
2354 #ifdef DEBUG_BUILD
|
|
2355 printf("[os2fslib_SetVideoMode] : Modifying window size\n"); fflush(stdout);
|
|
2356 #endif
|
|
2357
|
|
2358 // Calculate frame window size from client window size
|
|
2359 rectl.xLeft = 0;
|
|
2360 rectl.yBottom = 0;
|
|
2361 rectl.xRight = pModeInfoFound->uiXResolution; // Noninclusive
|
|
2362 rectl.yTop = pModeInfoFound->uiYResolution; // Noninclusive
|
|
2363 WinCalcFrameRect(_this->hidden->hwndFrame, &rectl, FALSE);
|
|
2364
|
|
2365 // Set the new size of the main window
|
|
2366 SetAccessableWindowPos(_this->hidden->hwndFrame,
|
|
2367 HWND_TOP,
|
|
2368 0, 0,
|
|
2369 (rectl.xRight-rectl.xLeft),
|
|
2370 (rectl.yTop-rectl.yBottom),
|
|
2371 SWP_SIZE | SWP_ACTIVATE | SWP_SHOW);
|
|
2372 }
|
|
2373
|
|
2374 // Set fullscreen mode flag, and switch to fullscreen if needed!
|
|
2375 if (flags & SDL_FULLSCREEN)
|
|
2376 {
|
|
2377 #ifdef DEBUG_BUILD
|
|
2378 printf("[os2fslib_SetVideoMode] : Also trying to switch to fullscreen\n");
|
|
2379 fflush(stdout);
|
|
2380 #endif
|
|
2381 FSLib_ToggleFSMode(_this->hidden->hwndClient, 1);
|
|
2382 /* Cursor manager functions to FS mode*/
|
|
2383 os2fslib_SetCursorManagementFunctions(_this, 0);
|
|
2384 } else
|
|
2385 {
|
|
2386 #ifdef DEBUG_BUILD
|
|
2387 printf("[os2fslib_SetVideoMode] : Also trying to switch to desktop mode\n");
|
|
2388 fflush(stdout);
|
|
2389 #endif
|
|
2390 FSLib_ToggleFSMode(_this->hidden->hwndClient, 0);
|
|
2391 /* Cursor manager functions to Windowed mode*/
|
|
2392 os2fslib_SetCursorManagementFunctions(_this, 1);
|
|
2393 }
|
|
2394
|
|
2395 _this->hidden->pSDLSurface = pResult;
|
|
2396
|
|
2397 DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer);
|
|
2398 } else
|
|
2399 {
|
|
2400 #ifdef DEBUG_BUILD
|
|
2401 printf("[os2fslib_SetVideoMode] : Could not get hmtxUseSrcBuffer!\n"); fflush(stdout);
|
|
2402 #endif
|
|
2403
|
|
2404 pResult = NULL;
|
|
2405 }
|
|
2406
|
|
2407 // As we have the new surface, we don't need the current one anymore!
|
|
2408 if ((pResult) && (current))
|
|
2409 {
|
|
2410 #ifdef DEBUG_BUILD
|
|
2411 printf("[os2fslib_SetVideoMode] : Freeing old surface\n"); fflush(stdout);
|
|
2412 #endif
|
|
2413 SDL_FreeSurface(current);
|
|
2414 }
|
|
2415
|
|
2416 // Redraw window
|
|
2417 WinInvalidateRegion(_this->hidden->hwndClient, NULL, TRUE);
|
|
2418
|
|
2419 // Now destroy the message queue, if we've created it!
|
|
2420 if (ERRORIDERROR(hmqerror)==0)
|
|
2421 {
|
|
2422 #ifdef DEBUG_BUILD
|
|
2423 printf("[os2fslib_SetVideoMode] : Destroying message queue\n"); fflush(stdout);
|
|
2424 #endif
|
|
2425 WinDestroyMsgQueue(hmq);
|
|
2426 }
|
|
2427
|
|
2428 #ifdef DEBUG_BUILD
|
|
2429 printf("[os2fslib_SetVideoMode] : Done\n"); fflush(stdout);
|
|
2430 #endif
|
|
2431
|
|
2432 /* We're done */
|
|
2433
|
|
2434 // Return with the new surface!
|
|
2435 return pResult;
|
|
2436 }
|
|
2437
|
|
2438 /* List the available video modes for the given pixel format, sorted
|
|
2439 from largest to smallest.
|
|
2440 */
|
|
2441 static SDL_Rect **os2fslib_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
|
|
2442 {
|
|
2443 #ifdef DEBUG_BUILD
|
|
2444 printf("[os2fslib_ListModes] : ListModes of %d Bpp\n", format->BitsPerPixel);
|
|
2445 #endif
|
|
2446 // Destroy result of previous call, if there is any
|
|
2447 if (_this->hidden->pListModesResult)
|
|
2448 {
|
|
2449 free(_this->hidden->pListModesResult); _this->hidden->pListModesResult = NULL;
|
|
2450 }
|
|
2451
|
|
2452 // For resizable and windowed mode we support every resolution!
|
|
2453 if ((flags & SDL_RESIZABLE) && ((flags & SDL_FULLSCREEN) == 0))
|
|
2454 return (SDL_Rect **)-1;
|
|
2455
|
|
2456 // Check if they need fullscreen or non-fullscreen video modes!
|
|
2457 if ((flags & SDL_FULLSCREEN) == 0)
|
|
2458
|
|
2459 {
|
|
2460 // For windowed mode we support every resolution!
|
|
2461 return (SDL_Rect **)-1;
|
|
2462 } else
|
|
2463 {
|
|
2464 FSLib_VideoMode_p pFSMode;
|
|
2465 // For fullscreen mode we don't support every resolution!
|
|
2466 // Now create a new list
|
|
2467 pFSMode = _this->hidden->pAvailableFSLibVideoModes;
|
|
2468 while (pFSMode)
|
|
2469 {
|
|
2470 if (pFSMode->uiBPP == format->BitsPerPixel)
|
|
2471 {
|
|
2472 SDL_Rect *pRect = (SDL_Rect *) malloc(sizeof(SDL_Rect));
|
|
2473 if (pRect)
|
|
2474 {
|
|
2475 // Fill description
|
|
2476 pRect->x = 0;
|
|
2477 pRect->y = 0;
|
|
2478 pRect->w = pFSMode->uiXResolution;
|
|
2479 pRect->h = pFSMode->uiYResolution;
|
|
2480 #ifdef DEBUG_BUILD
|
|
2481 // printf("!!! Seems to be good!\n");
|
|
2482 // printf("F: %dx%d\n", pRect->w, pRect->h);
|
|
2483 #endif
|
|
2484 // And insert into list of pRects
|
|
2485 if (!(_this->hidden->pListModesResult))
|
|
2486 {
|
|
2487 #ifdef DEBUG_BUILD
|
|
2488 // printf("!!! Inserting to beginning\n");
|
|
2489 #endif
|
|
2490
|
|
2491 // We're the first one to be inserted!
|
|
2492 _this->hidden->pListModesResult = (SDL_Rect**) malloc(2*sizeof(SDL_Rect*));
|
|
2493 if (_this->hidden->pListModesResult)
|
|
2494 {
|
|
2495 _this->hidden->pListModesResult[0] = pRect;
|
|
2496 _this->hidden->pListModesResult[1] = NULL;
|
|
2497 } else
|
|
2498 {
|
|
2499 free(pRect);
|
|
2500 }
|
|
2501 } else
|
|
2502 {
|
|
2503 // We're not the first ones, so find the place where we
|
|
2504 // have to insert ourselves
|
|
2505 SDL_Rect **pNewList;
|
|
2506 int iPlace, iNumOfSlots, i;
|
|
2507
|
|
2508 #ifdef DEBUG_BUILD
|
|
2509 // printf("!!! Searching where to insert\n");
|
|
2510 #endif
|
|
2511
|
|
2512 iPlace = -1; iNumOfSlots = 1; // Count the last NULL too!
|
|
2513 for (i=0; _this->hidden->pListModesResult[i]; i++)
|
|
2514 {
|
|
2515 iNumOfSlots++;
|
|
2516 if (iPlace==-1)
|
|
2517 {
|
|
2518 if ((_this->hidden->pListModesResult[i]->w*_this->hidden->pListModesResult[i]->h)<
|
|
2519 (pRect->w*pRect->h))
|
|
2520 {
|
|
2521 iPlace = i;
|
|
2522 }
|
|
2523 }
|
|
2524 }
|
|
2525 if (iPlace==-1) iPlace = iNumOfSlots-1;
|
|
2526
|
|
2527 #ifdef DEBUG_BUILD
|
|
2528 // printf("!!! From %d slots, it will be at %d\n", iNumOfSlots, iPlace);
|
|
2529 #endif
|
|
2530
|
|
2531 pNewList = (SDL_Rect**) realloc(_this->hidden->pListModesResult, (iNumOfSlots+1)*sizeof(SDL_Rect*));
|
|
2532 if (pNewList)
|
|
2533 {
|
|
2534 for (i=iNumOfSlots;i>iPlace;i--)
|
|
2535 pNewList[i] = pNewList[i-1];
|
|
2536 pNewList[iPlace] = pRect;
|
|
2537 _this->hidden->pListModesResult = pNewList;
|
|
2538 } else
|
|
2539 {
|
|
2540 free(pRect);
|
|
2541 }
|
|
2542 }
|
|
2543 }
|
|
2544 }
|
|
2545 pFSMode = pFSMode->pNext;
|
|
2546 }
|
|
2547 }
|
|
2548 #ifdef DEBUG_BUILD
|
|
2549 // printf("Returning list\n");
|
|
2550 #endif
|
|
2551 return _this->hidden->pListModesResult;
|
|
2552 }
|
|
2553
|
|
2554 /* Initialize the native video subsystem, filling 'vformat' with the
|
|
2555 "best" display pixel format, returning 0 or -1 if there's an error.
|
|
2556 */
|
|
2557 static int os2fslib_VideoInit(_THIS, SDL_PixelFormat *vformat)
|
|
2558 {
|
|
2559 FSLib_VideoMode_p pDesktopMode;
|
|
2560
|
|
2561 #ifdef DEBUG_BUILD
|
|
2562 printf("[os2fslib_VideoInit] : Enter\n"); fflush(stdout);
|
|
2563 #endif
|
|
2564
|
|
2565 // Report the best pixel format. For this,
|
|
2566 // we'll use the current desktop format.
|
|
2567 pDesktopMode = FSLib_GetDesktopVideoMode();
|
|
2568 if (!pDesktopMode)
|
|
2569 {
|
|
2570 SDL_SetError("Could not query desktop video mode!");
|
|
2571 #ifdef DEBUG_BUILD
|
|
2572 printf("[os2fslib_VideoInit] : Could not query desktop video mode!\n");
|
|
2573 #endif
|
|
2574 return -1;
|
|
2575 }
|
|
2576
|
|
2577 /* Determine the screen depth */
|
|
2578 vformat->BitsPerPixel = pDesktopMode->uiBPP;
|
|
2579 vformat->BytesPerPixel = (vformat->BitsPerPixel+7)/8;
|
|
2580
|
|
2581 vformat->Rmask = ((unsigned int) pDesktopMode->PixelFormat.ucRedMask) << pDesktopMode->PixelFormat.ucRedPosition;
|
|
2582 vformat->Rshift = pDesktopMode->PixelFormat.ucRedPosition;
|
|
2583 vformat->Rloss = pDesktopMode->PixelFormat.ucRedAdjust;
|
|
2584 vformat->Gmask = ((unsigned int) pDesktopMode->PixelFormat.ucGreenMask) << pDesktopMode->PixelFormat.ucGreenPosition;
|
|
2585 vformat->Gshift = pDesktopMode->PixelFormat.ucGreenPosition;
|
|
2586 vformat->Gloss = pDesktopMode->PixelFormat.ucGreenAdjust;
|
|
2587 vformat->Bmask = ((unsigned int) pDesktopMode->PixelFormat.ucBlueMask) << pDesktopMode->PixelFormat.ucBluePosition;
|
|
2588 vformat->Bshift = pDesktopMode->PixelFormat.ucBluePosition;
|
|
2589 vformat->Bloss = pDesktopMode->PixelFormat.ucBlueAdjust;
|
|
2590 vformat->Amask = ((unsigned int) pDesktopMode->PixelFormat.ucAlphaMask) << pDesktopMode->PixelFormat.ucAlphaPosition;
|
|
2591 vformat->Ashift = pDesktopMode->PixelFormat.ucAlphaPosition;
|
|
2592 vformat->Aloss = pDesktopMode->PixelFormat.ucAlphaAdjust;
|
|
2593
|
|
2594 #ifdef REPORT_EMPTY_ALPHA_MASK
|
|
2595 vformat->Amask =
|
|
2596 vformat->Ashift =
|
|
2597 vformat->Aloss = 0;
|
|
2598 #endif
|
|
2599
|
|
2600 // Fill in some window manager capabilities
|
|
2601 _this->info.wm_available = 1;
|
|
2602
|
|
2603 // Initialize some internal variables
|
|
2604 _this->hidden->pListModesResult = NULL;
|
|
2605 _this->hidden->fInFocus = 0;
|
|
2606 _this->hidden->iSkipWMMOUSEMOVE = 0;
|
|
2607 _this->hidden->iMouseVisible = 1;
|
|
2608 DosCreateMutexSem(NULL, &(_this->hidden->hmtxUseSrcBuffer), 0, FALSE);
|
|
2609
|
|
2610 // Now create our window with a default size
|
|
2611
|
|
2612 // For this, we select the first available fullscreen mode as
|
|
2613 // current window size!
|
|
2614 memcpy(&(_this->hidden->SrcBufferDesc), _this->hidden->pAvailableFSLibVideoModes, sizeof(_this->hidden->SrcBufferDesc));
|
|
2615 // Allocate new video buffer!
|
|
2616 _this->hidden->pchSrcBuffer = (char *) malloc(_this->hidden->pAvailableFSLibVideoModes->uiScanLineSize * _this->hidden->pAvailableFSLibVideoModes->uiYResolution);
|
|
2617 if (!_this->hidden->pchSrcBuffer)
|
|
2618 {
|
|
2619 #ifdef DEBUG_BUILD
|
|
2620 printf("[os2fslib_VideoInit] : Yikes, not enough memory for new video buffer!\n"); fflush(stdout);
|
|
2621 #endif
|
|
2622 SDL_SetError("Not enough memory for new video buffer!\n");
|
|
2623 return -1;
|
|
2624 }
|
|
2625
|
|
2626 // For this, we need a message processing thread.
|
|
2627 // We'll create a new thread for this, which will do everything
|
|
2628 // what is related to PM
|
|
2629 _this->hidden->iPMThreadStatus = 0;
|
|
2630 _this->hidden->tidPMThread = _beginthread(PMThreadFunc, NULL, 65536, (void *) _this);
|
|
2631 if (_this->hidden->tidPMThread <= 0)
|
|
2632 {
|
|
2633 #ifdef DEBUG_BUILD
|
|
2634 printf("[os2fslib_VideoInit] : Could not create PM thread!\n");
|
|
2635 #endif
|
|
2636 SDL_SetError("Could not create PM thread");
|
|
2637 return -1;
|
|
2638 }
|
|
2639 #ifdef USE_DOSSETPRIORITY
|
|
2640 // Burst the priority of PM Thread!
|
|
2641 DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, _this->hidden->tidPMThread);
|
|
2642 #endif
|
|
2643 // Wait for the PM thread to initialize!
|
|
2644 while (_this->hidden->iPMThreadStatus==0)
|
|
2645 DosSleep(32);
|
|
2646 // If the PM thread could not set up everything, then
|
|
2647 // report an error!
|
|
2648 if (_this->hidden->iPMThreadStatus!=1)
|
|
2649 {
|
|
2650 #ifdef DEBUG_BUILD
|
|
2651 printf("[os2fslib_VideoInit] : PMThread reported an error : %d\n", _this->hidden->iPMThreadStatus);
|
|
2652 #endif
|
|
2653 SDL_SetError("Error initializing PM thread");
|
|
2654 return -1;
|
|
2655 }
|
|
2656
|
|
2657 return 0;
|
|
2658 }
|
|
2659
|
|
2660
|
|
2661 static void os2fslib_DeleteDevice(_THIS)
|
|
2662 {
|
|
2663 #ifdef DEBUG_BUILD
|
|
2664 printf("[os2fslib_DeleteDevice]\n"); fflush(stdout);
|
|
2665 #endif
|
|
2666 // Free used memory
|
|
2667 FSLib_FreeVideoModeList(_this->hidden->pAvailableFSLibVideoModes);
|
|
2668 if (_this->hidden->pListModesResult)
|
|
2669 free(_this->hidden->pListModesResult);
|
|
2670 if (_this->hidden->pchSrcBuffer)
|
|
2671 free(_this->hidden->pchSrcBuffer);
|
|
2672 DosCloseMutexSem(_this->hidden->hmtxUseSrcBuffer);
|
|
2673 free(_this->hidden);
|
|
2674 free(_this);
|
|
2675 FSLib_Uninitialize();
|
|
2676 }
|
|
2677
|
|
2678 static int os2fslib_Available(void)
|
|
2679 {
|
|
2680
|
|
2681 // If we can run, it means that we could load FSLib,
|
|
2682 // so we assume that it's available then!
|
|
2683 return 1;
|
|
2684 }
|
|
2685
|
|
2686 static void os2fslib_MorphToPM()
|
|
2687 {
|
|
2688 PPIB pib;
|
|
2689 PTIB tib;
|
|
2690
|
|
2691 DosGetInfoBlocks(&tib, &pib);
|
|
2692
|
|
2693 // Change flag from VIO to PM:
|
|
2694 if (pib->pib_ultype==2) pib->pib_ultype = 3;
|
|
2695 }
|
|
2696
|
|
2697 static SDL_VideoDevice *os2fslib_CreateDevice(int devindex)
|
|
2698 {
|
|
2699 SDL_VideoDevice *device;
|
|
2700
|
|
2701 #ifdef DEBUG_BUILD
|
|
2702 printf("[os2fslib_CreateDevice] : Enter\n"); fflush(stdout);
|
|
2703 #endif
|
|
2704
|
|
2705 /* Initialize all variables that we clean on shutdown */
|
|
2706 device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
|
|
2707 if ( device )
|
|
2708 {
|
|
2709 memset(device, 0, (sizeof *device));
|
|
2710 // Also allocate memory for private data
|
|
2711 device->hidden = (struct SDL_PrivateVideoData *) malloc((sizeof(struct SDL_PrivateVideoData)));
|
|
2712 }
|
|
2713 if ( (device == NULL) || (device->hidden == NULL) )
|
|
2714 {
|
|
2715 SDL_OutOfMemory();
|
|
2716 if ( device )
|
|
2717 free(device);
|
|
2718 return NULL;
|
|
2719 }
|
|
2720 memset(device->hidden, 0, (sizeof *device->hidden));
|
|
2721
|
|
2722 /* Set the function pointers */
|
|
2723 #ifdef DEBUG_BUILD
|
|
2724 printf("[os2fslib_CreateDevice] : VideoInit is %p\n", os2fslib_VideoInit); fflush(stdout);
|
|
2725 #endif
|
|
2726
|
|
2727 /* Initialization/Query functions */
|
|
2728 device->VideoInit = os2fslib_VideoInit;
|
|
2729 device->ListModes = os2fslib_ListModes;
|
|
2730 device->SetVideoMode = os2fslib_SetVideoMode;
|
|
2731 device->ToggleFullScreen = os2fslib_ToggleFullScreen;
|
|
2732 device->UpdateMouse = os2fslib_UpdateMouse;
|
|
2733 device->CreateYUVOverlay = NULL;
|
|
2734 device->SetColors = os2fslib_SetColors;
|
|
2735 device->UpdateRects = os2fslib_UpdateRects;
|
|
2736 device->VideoQuit = os2fslib_VideoQuit;
|
|
2737 /* Hardware acceleration functions */
|
|
2738 device->AllocHWSurface = os2fslib_AllocHWSurface;
|
|
2739 device->CheckHWBlit = NULL;
|
|
2740 device->FillHWRect = NULL;
|
|
2741 device->SetHWColorKey = NULL;
|
|
2742 device->SetHWAlpha = NULL;
|
|
2743 device->LockHWSurface = os2fslib_LockHWSurface;
|
|
2744 device->UnlockHWSurface = os2fslib_UnlockHWSurface;
|
|
2745 device->FlipHWSurface = NULL;
|
|
2746 device->FreeHWSurface = os2fslib_FreeHWSurface;
|
|
2747 /* Window manager functions */
|
|
2748 device->SetCaption = os2fslib_SetCaption;
|
|
2749 device->SetIcon = os2fslib_SetIcon;
|
|
2750 device->IconifyWindow = os2fslib_IconifyWindow;
|
|
2751 device->GrabInput = os2fslib_GrabInput;
|
|
2752 device->GetWMInfo = NULL;
|
|
2753 /* Cursor manager functions to Windowed mode*/
|
|
2754 os2fslib_SetCursorManagementFunctions(device, 1);
|
|
2755 /* Event manager functions */
|
|
2756 device->InitOSKeymap = os2fslib_InitOSKeymap;
|
|
2757 device->PumpEvents = os2fslib_PumpEvents;
|
|
2758 /* The function used to dispose of this structure */
|
|
2759 device->free = os2fslib_DeleteDevice;
|
|
2760
|
|
2761 // Make sure we'll be able to use Win* API even if the application
|
|
2762 // was linked to be a VIO application!
|
|
2763 os2fslib_MorphToPM();
|
|
2764
|
|
2765 // Now initialize FSLib, and query available video modes!
|
|
2766 if (!FSLib_Initialize())
|
|
2767 {
|
|
2768 // Could not initialize FSLib!
|
|
2769 #ifdef DEBUG_BUILD
|
|
2770 printf("[os2fslib_CreateDevice] : Could not initialize FSLib!\n");
|
|
2771 #endif
|
|
2772 SDL_SetError("Could not initialize FSLib!");
|
|
2773 free(device->hidden);
|
|
2774 free(device);
|
|
2775 return NULL;
|
|
2776 }
|
|
2777 device->hidden->pAvailableFSLibVideoModes =
|
|
2778 FSLib_GetVideoModeList();
|
|
2779
|
|
2780 return device;
|
|
2781 }
|
|
2782
|
|
2783 VideoBootStrap OS2FSLib_bootstrap = {
|
|
2784 "os2fslib", "OS/2 Video Output using FSLib",
|
|
2785 os2fslib_Available, os2fslib_CreateDevice
|
|
2786 };
|
|
2787
|