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