comparison src/video/os2fslib/SDL_os2fslib.c @ 1190:173c063d4f55

OS/2 port! This was mostly, if not entirely, written by "Doodle" and "Caetano": doodle@scenergy.dfmk.hu daniel@caetano.eng.br --ryan.
author Ryan C. Gordon <icculus@icculus.org>
date Wed, 23 Nov 2005 07:29:56 +0000
parents
children 3692456e7b0f
comparison
equal deleted inserted replaced
1189:c96b326b90ba 1190:173c063d4f55
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