Home | History | Annotate | Download | only in cybergfx
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2006 Sam Lantinga
      4 
      5     This library is free software; you can redistribute it and/or
      6     modify it under the terms of the GNU Lesser General Public
      7     License as published by the Free Software Foundation; either
      8     version 2.1 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     Lesser General Public License for more details.
     14 
     15     You should have received a copy of the GNU Lesser General Public
     16     License along with this library; if not, write to the Free Software
     17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     18 
     19     Sam Lantinga
     20     slouken (at) libsdl.org
     21 */
     22 #include "SDL_config.h"
     23 
     24 /* Handle the event stream, converting Amiga events into SDL events */
     25 #include "SDL.h"
     26 
     27 #include "SDL_syswm.h"
     28 #include "../SDL_sysvideo.h"
     29 #include "../../events/SDL_sysevents.h"
     30 #include "../../events/SDL_events_c.h"
     31 #include "SDL_cgxvideo.h"
     32 #include "SDL_cgxmodes_c.h"
     33 #include "SDL_cgximage_c.h"
     34 #include "SDL_cgxwm_c.h"
     35 #include "SDL_amigaevents_c.h"
     36 
     37 
     38 /* The translation tables from an Amiga keysym to a SDL keysym */
     39 static SDLKey MISC_keymap[256];
     40 SDL_keysym *amiga_TranslateKey(int code, SDL_keysym *keysym);
     41 struct IOStdReq *ConReq=NULL;
     42 struct MsgPort *ConPort=NULL;
     43 
     44 /* Note:  The X server buffers and accumulates mouse motion events, so
     45    the motion event generated by the warp may not appear exactly as we
     46    expect it to.  We work around this (and improve performance) by only
     47    warping the pointer when it reaches the edge, and then wait for it.
     48 */
     49 #define MOUSE_FUDGE_FACTOR	8
     50 
     51 #if 0
     52 
     53 static inline int amiga_WarpedMotion(_THIS, struct IntuiMessage *m)
     54 {
     55 	int w, h, i;
     56 	int deltax, deltay;
     57 	int posted;
     58 
     59 	w = SDL_VideoSurface->w;
     60 	h = SDL_VideoSurface->h;
     61 	deltax = xevent->xmotion.x - mouse_last.x;
     62 	deltay = xevent->xmotion.y - mouse_last.y;
     63 #ifdef DEBUG_MOTION
     64   printf("Warped mouse motion: %d,%d\n", deltax, deltay);
     65 #endif
     66 	mouse_last.x = xevent->xmotion.x;
     67 	mouse_last.y = xevent->xmotion.y;
     68 	posted = SDL_PrivateMouseMotion(0, 1, deltax, deltay);
     69 
     70 	if ( (xevent->xmotion.x < MOUSE_FUDGE_FACTOR) ||
     71 	     (xevent->xmotion.x > (w-MOUSE_FUDGE_FACTOR)) ||
     72 	     (xevent->xmotion.y < MOUSE_FUDGE_FACTOR) ||
     73 	     (xevent->xmotion.y > (h-MOUSE_FUDGE_FACTOR)) ) {
     74 		/* Get the events that have accumulated */
     75 		while ( XCheckTypedEvent(SDL_Display, MotionNotify, xevent) ) {
     76 			deltax = xevent->xmotion.x - mouse_last.x;
     77 			deltay = xevent->xmotion.y - mouse_last.y;
     78 #ifdef DEBUG_MOTION
     79   printf("Extra mouse motion: %d,%d\n", deltax, deltay);
     80 #endif
     81 			mouse_last.x = xevent->xmotion.x;
     82 			mouse_last.y = xevent->xmotion.y;
     83 			posted += SDL_PrivateMouseMotion(0, 1, deltax, deltay);
     84 		}
     85 		mouse_last.x = w/2;
     86 		mouse_last.y = h/2;
     87 		XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0,
     88 					mouse_last.x, mouse_last.y);
     89 		for ( i=0; i<10; ++i ) {
     90         		XMaskEvent(SDL_Display, PointerMotionMask, xevent);
     91 			if ( (xevent->xmotion.x >
     92 			          (mouse_last.x-MOUSE_FUDGE_FACTOR)) &&
     93 			     (xevent->xmotion.x <
     94 			          (mouse_last.x+MOUSE_FUDGE_FACTOR)) &&
     95 			     (xevent->xmotion.y >
     96 			          (mouse_last.y-MOUSE_FUDGE_FACTOR)) &&
     97 			     (xevent->xmotion.y <
     98 			          (mouse_last.y+MOUSE_FUDGE_FACTOR)) ) {
     99 				break;
    100 			}
    101 #ifdef DEBUG_XEVENTS
    102   printf("Lost mouse motion: %d,%d\n", xevent->xmotion.x, xevent->xmotion.y);
    103 #endif
    104 		}
    105 #ifdef DEBUG_XEVENTS
    106 		if ( i == 10 ) {
    107 			printf("Warning: didn't detect mouse warp motion\n");
    108 		}
    109 #endif
    110 	}
    111 	return(posted);
    112 }
    113 
    114 #endif
    115 
    116 static int amiga_GetButton(int code)
    117 {
    118 	switch(code)
    119 	{
    120 		case IECODE_MBUTTON:
    121 			return SDL_BUTTON_MIDDLE;
    122 		case IECODE_RBUTTON:
    123 			return SDL_BUTTON_RIGHT;
    124 		default:
    125 			return SDL_BUTTON_LEFT;
    126 	}
    127 }
    128 
    129 static int amiga_DispatchEvent(_THIS,struct IntuiMessage *msg)
    130 {
    131 	int class=msg->Class,code=msg->Code;
    132 	int posted;
    133 
    134 	posted = 0;
    135 	switch (class) {
    136 	    /* Gaining mouse coverage? */
    137 	    case IDCMP_ACTIVEWINDOW:
    138 			posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
    139 			break;
    140 
    141 	    /* Losing mouse coverage? */
    142 	    case IDCMP_INACTIVEWINDOW:
    143 			posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
    144 			break;
    145 #if 0
    146 	    /* Gaining input focus? */
    147 	    case IDCMP_ACTIVEWINDOW:
    148 			posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
    149 
    150 			/* Queue entry into fullscreen mode */
    151 			switch_waiting = 0x01 | SDL_FULLSCREEN;
    152 			switch_time = SDL_GetTicks() + 1500;
    153 		    break;
    154 
    155 	    /* Losing input focus? */
    156 	    case IDCMP_INACTIVEWINDOW:
    157 			posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
    158 
    159 		/* Queue leaving fullscreen mode */
    160 			switch_waiting = 0x01;
    161 			switch_time = SDL_GetTicks() + 200;
    162 		    break;
    163 #endif
    164 	    /* Mouse motion? */
    165 	    case IDCMP_MOUSEMOVE:
    166 			if ( SDL_VideoSurface ) {
    167 				posted = SDL_PrivateMouseMotion(0, 0,
    168 						msg->MouseX-SDL_Window->BorderLeft,
    169 						msg->MouseY-SDL_Window->BorderTop);
    170 			}
    171 	    	break;
    172 
    173 	    /* Mouse button press? */
    174 		case IDCMP_MOUSEBUTTONS:
    175 
    176 			if(!(code&IECODE_UP_PREFIX))
    177 			{
    178 				posted = SDL_PrivateMouseButton(SDL_PRESSED,
    179 						amiga_GetButton(code), 0, 0);
    180 			    }
    181 	    /* Mouse button release? */
    182 			else
    183 			{
    184 				code&=~IECODE_UP_PREFIX;
    185 				posted = SDL_PrivateMouseButton(SDL_RELEASED,
    186 						amiga_GetButton(code), 0, 0);
    187 			}
    188 			break;
    189 
    190 	    case IDCMP_RAWKEY:
    191 
    192 		    /* Key press? */
    193 
    194 		    if( !(code&IECODE_UP_PREFIX) )
    195 		    {
    196 				SDL_keysym keysym;
    197 				posted = SDL_PrivateKeyboard(SDL_PRESSED,
    198 					amiga_TranslateKey(code, &keysym));
    199 		    }
    200 		    else
    201 		    {
    202 	    /* Key release? */
    203 
    204 				SDL_keysym keysym;
    205 				code&=~IECODE_UP_PREFIX;
    206 
    207 			/* Check to see if this is a repeated key */
    208 /*			if ( ! X11_KeyRepeat(SDL_Display, &xevent) )  */
    209 
    210 				posted = SDL_PrivateKeyboard(SDL_RELEASED,
    211 					amiga_TranslateKey(code, &keysym));
    212 		    }
    213 		    break;
    214 	    /* Have we been iconified? */
    215 #if 0
    216 	    case UnmapNotify: {
    217 #ifdef DEBUG_XEVENTS
    218 printf("UnmapNotify!\n");
    219 #endif
    220 		posted=SDL_PrivateAppActive(0, SDL_APPACTIVE|SDL_APPINPUTFOCUS);
    221 	    }
    222 	    break;
    223 
    224 	    /* Have we been restored? */
    225 
    226 	    case MapNotify: {
    227 #ifdef DEBUG_XEVENTS
    228 printf("MapNotify!\n");
    229 #endif
    230 
    231 		posted = SDL_PrivateAppActive(1, SDL_APPACTIVE);
    232 
    233 		if ( SDL_VideoSurface &&
    234 		     (SDL_VideoSurface->flags & SDL_FULLSCREEN) )
    235 		{
    236 			CGX_EnterFullScreen(this);
    237 		} else {
    238 			X11_GrabInputNoLock(this, this->input_grab);
    239 		}
    240 		if ( SDL_VideoSurface ) {
    241 			CGX_RefreshDisplay(this);
    242 		}
    243 	    }
    244 	    break;
    245 	    case Expose:
    246 		if ( SDL_VideoSurface && (xevent.xexpose.count == 0) ) {
    247 			CGX_RefreshDisplay(this);
    248 		}
    249 		break;
    250 #endif
    251 
    252 	    /* Have we been resized? */
    253 	    case IDCMP_NEWSIZE:
    254 			SDL_PrivateResize(SDL_Window->Width-SDL_Window->BorderLeft-SDL_Window->BorderRight,
    255 		                  SDL_Window->Height-SDL_Window->BorderTop-SDL_Window->BorderBottom);
    256 
    257 			break;
    258 
    259 	    /* Have we been requested to quit? */
    260 	    case IDCMP_CLOSEWINDOW:
    261 		posted = SDL_PrivateQuit();
    262 		break;
    263 
    264 	    /* Do we need to refresh ourselves? */
    265 
    266 	    default: {
    267 		/* Only post the event if we're watching for it */
    268 		if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) {
    269 			SDL_SysWMmsg wmmsg;
    270 
    271 			SDL_VERSION(&wmmsg.version);
    272 #if 0
    273 			wmmsg.subsystem = SDL_SYSWM_CGX;
    274 			wmmsg.event.xevent = xevent;
    275 #endif
    276 			posted = SDL_PrivateSysWMEvent(&wmmsg);
    277 		}
    278 	    }
    279 	    break;
    280 	}
    281 	ReplyMsg((struct Message *)msg);
    282 
    283 
    284 	return(posted);
    285 }
    286 
    287 void amiga_PumpEvents(_THIS)
    288 {
    289 	int pending;
    290 	struct IntuiMessage *m;
    291 
    292 	/* Keep processing pending events */
    293 	pending = 0;
    294 	while ( m=(struct IntuiMessage *)GetMsg(SDL_Window->UserPort) ) {
    295 		amiga_DispatchEvent(this,m);
    296 		++pending;
    297 	}
    298 }
    299 
    300 void amiga_InitKeymap(void)
    301 {
    302 	int i;
    303 
    304 	/* Map the miscellaneous keys */
    305 	for ( i=0; i<SDL_arraysize(MISC_keymap); ++i )
    306 		MISC_keymap[i] = SDLK_UNKNOWN;
    307 
    308 	/* These X keysyms have 0xFF as the high byte */
    309 	MISC_keymap[65] = SDLK_BACKSPACE;
    310 	MISC_keymap[66] = SDLK_TAB;
    311 	MISC_keymap[70] = SDLK_CLEAR;
    312 	MISC_keymap[70] = SDLK_DELETE;
    313 	MISC_keymap[68] = SDLK_RETURN;
    314 //	MISC_keymap[XK_Pause&0xFF] = SDLK_PAUSE;
    315 	MISC_keymap[69] = SDLK_ESCAPE;
    316 	MISC_keymap[70] = SDLK_DELETE;
    317 /*
    318 	SDLK_SPACE		= 32,
    319 	SDLK_MINUS		= 45,
    320 	SDLK_LESS		= 60,
    321 	SDLK_COMMA		= 44,
    322 	SDLK_PERIOD		= 46,
    323 	SDLK_0			= 48,
    324 	SDLK_1			= 49,
    325 	SDLK_2			= 50,
    326 	SDLK_3			= 51,
    327 	SDLK_4			= 52,
    328 	SDLK_5			= 53,
    329 	SDLK_6			= 54,
    330 	SDLK_7			= 55,
    331 	SDLK_8			= 56,
    332 	SDLK_9			= 57,
    333 	SDLK_BACKQUOTE		= 96,
    334 	SDLK_BACKSLASH		= 92,
    335 	SDLK_a			= 97,
    336 	SDLK_b			= 98,
    337 	SDLK_c			= 99,
    338 	SDLK_d			= 100,
    339 	SDLK_e			= 101,
    340 	SDLK_f			= 102,
    341 	SDLK_g			= 103,
    342 	SDLK_h			= 104,
    343 	SDLK_i			= 105,
    344 	SDLK_j			= 106,
    345 	SDLK_k			= 107,
    346 	SDLK_l			= 108,
    347 	SDLK_m			= 109,
    348 	SDLK_n			= 110,
    349 	SDLK_o			= 111,
    350 	SDLK_p			= 112,
    351 	SDLK_q			= 113,
    352 	SDLK_r			= 114,
    353 	SDLK_s			= 115,
    354 	SDLK_t			= 116,
    355 	SDLK_u			= 117,
    356 	SDLK_v			= 118,
    357 	SDLK_w			= 119,
    358 	SDLK_x			= 120,
    359 	SDLK_y			= 121,
    360 	SDLK_z			= 122,
    361 */
    362 	MISC_keymap[15] = SDLK_KP0;		/* Keypad 0-9 */
    363 	MISC_keymap[29] = SDLK_KP1;
    364 	MISC_keymap[30] = SDLK_KP2;
    365 	MISC_keymap[31] = SDLK_KP3;
    366 	MISC_keymap[45] = SDLK_KP4;
    367 	MISC_keymap[46] = SDLK_KP5;
    368 	MISC_keymap[47] = SDLK_KP6;
    369 	MISC_keymap[61] = SDLK_KP7;
    370 	MISC_keymap[62] = SDLK_KP8;
    371 	MISC_keymap[63] = SDLK_KP9;
    372 	MISC_keymap[60] = SDLK_KP_PERIOD;
    373 	MISC_keymap[92] = SDLK_KP_DIVIDE;
    374 	MISC_keymap[93] = SDLK_KP_MULTIPLY;
    375 	MISC_keymap[74] = SDLK_KP_MINUS;
    376 	MISC_keymap[94] = SDLK_KP_PLUS;
    377 	MISC_keymap[67] = SDLK_KP_ENTER;
    378 //	MISC_keymap[XK_KP_Equal&0xFF] = SDLK_KP_EQUALS;
    379 
    380 	MISC_keymap[76] = SDLK_UP;
    381 	MISC_keymap[77] = SDLK_DOWN;
    382 	MISC_keymap[78] = SDLK_RIGHT;
    383 	MISC_keymap[79] = SDLK_LEFT;
    384 /*
    385 	MISC_keymap[XK_Insert&0xFF] = SDLK_INSERT;
    386 	MISC_keymap[XK_Home&0xFF] = SDLK_HOME;
    387 	MISC_keymap[XK_End&0xFF] = SDLK_END;
    388 */
    389 // Mappati sulle parentesi del taastierino
    390 	MISC_keymap[90] = SDLK_PAGEUP;
    391 	MISC_keymap[91] = SDLK_PAGEDOWN;
    392 
    393 	MISC_keymap[80] = SDLK_F1;
    394 	MISC_keymap[81] = SDLK_F2;
    395 	MISC_keymap[82] = SDLK_F3;
    396 	MISC_keymap[83] = SDLK_F4;
    397 	MISC_keymap[84] = SDLK_F5;
    398 	MISC_keymap[85] = SDLK_F6;
    399 	MISC_keymap[86] = SDLK_F7;
    400 	MISC_keymap[87] = SDLK_F8;
    401 	MISC_keymap[88] = SDLK_F9;
    402 	MISC_keymap[89] = SDLK_F10;
    403 //	MISC_keymap[XK_F11&0xFF] = SDLK_F11;
    404 //	MISC_keymap[XK_F12&0xFF] = SDLK_F12;
    405 //	MISC_keymap[XK_F13&0xFF] = SDLK_F13;
    406 //	MISC_keymap[XK_F14&0xFF] = SDLK_F14;
    407 //	MISC_keymap[XK_F15&0xFF] = SDLK_F15;
    408 
    409 //	MISC_keymap[XK_Num_Lock&0xFF] = SDLK_NUMLOCK;
    410 	MISC_keymap[98] = SDLK_CAPSLOCK;
    411 //	MISC_keymap[XK_Scroll_Lock&0xFF] = SDLK_SCROLLOCK;
    412 	MISC_keymap[97] = SDLK_RSHIFT;
    413 	MISC_keymap[96] = SDLK_LSHIFT;
    414 	MISC_keymap[99] = SDLK_LCTRL;
    415 	MISC_keymap[99] = SDLK_LCTRL;
    416 	MISC_keymap[101] = SDLK_RALT;
    417 	MISC_keymap[100] = SDLK_LALT;
    418 //	MISC_keymap[XK_Meta_R&0xFF] = SDLK_RMETA;
    419 //	MISC_keymap[XK_Meta_L&0xFF] = SDLK_LMETA;
    420 	MISC_keymap[103] = SDLK_LSUPER; /* Left "Windows" */
    421 	MISC_keymap[102] = SDLK_RSUPER; /* Right "Windows */
    422 
    423 	MISC_keymap[95] = SDLK_HELP;
    424 }
    425 
    426 SDL_keysym *amiga_TranslateKey(int code, SDL_keysym *keysym)
    427 {
    428 	#ifdef STORMC4_WOS
    429 	static struct Library *KeymapBase=NULL; /* Linking failed in WOS version if ConsoleDevice was used */
    430 	#else
    431 	static struct Library *ConsoleDevice=NULL;
    432 	#endif
    433 
    434 	/* Get the raw keyboard scancode */
    435 	keysym->scancode = code;
    436 	keysym->sym = MISC_keymap[code];
    437 
    438 #ifdef DEBUG_KEYS
    439 	fprintf(stderr, "Translating key 0x%.4x (%d)\n", xsym, xkey->keycode);
    440 #endif
    441 	/* Get the translated SDL virtual keysym */
    442 	if ( keysym->sym==SDLK_UNKNOWN )
    443 	{
    444 		#ifdef STORMC4_WOS
    445 		if(!KeymapBase)
    446 		#else
    447 		if(!ConsoleDevice)
    448 		#endif
    449 		{
    450 			#ifdef STORMC4_WOS
    451 			KeymapBase=OpenLibrary("keymap.library", 0L);
    452 			#else
    453 			if(ConPort=CreateMsgPort())
    454 			{
    455 				if(ConReq=CreateIORequest(ConPort,sizeof(struct IOStdReq)))
    456 				{
    457 					if(!OpenDevice("console.device",-1,(struct IORequest *)ConReq,0))
    458 						ConsoleDevice=(struct Library *)ConReq->io_Device;
    459 					else
    460 					{
    461 						DeleteIORequest(ConReq);
    462 						ConReq=NULL;
    463 					}
    464 				}
    465 				else
    466 				{
    467 					DeleteMsgPort(ConPort);
    468 					ConPort=NULL;
    469 				}
    470 			}
    471 			#endif
    472 		}
    473 
    474 		#ifdef STORMC4_WOS
    475 		if(KeymapBase)
    476 		#else
    477 		if(ConsoleDevice)
    478 		#endif
    479 		{
    480 			struct InputEvent event;
    481 			long actual;
    482 			char buffer[5];
    483 
    484 			event.ie_Qualifier=0;
    485 			event.ie_Class=IECLASS_RAWKEY;
    486 			event.ie_SubClass=0L;
    487 			event.ie_Code=code;
    488 			event.ie_X=event.ie_Y=0;
    489 			event.ie_EventAddress=NULL;
    490 			event.ie_NextEvent=NULL;
    491 			event.ie_Prev1DownCode=event.ie_Prev1DownQual=event.ie_Prev2DownCode=event.ie_Prev2DownQual=0;
    492 
    493 			#ifdef STORMC4_WOS
    494 			if( (actual=MapRawKey(&event,buffer,5,NULL))>=0)
    495 			#else
    496 			if( (actual=RawKeyConvert(&event,buffer,5,NULL))>=0)
    497 			#endif
    498 			{
    499 				if(actual>1)
    500 				{
    501 					D(bug("Warning (%ld) character conversion!\n",actual));
    502 				}
    503 				else if(actual==1)
    504 				{
    505 					keysym->sym=*buffer;
    506 					D(bug("Converted rawcode %ld to <%lc>\n",code,*buffer));
    507 // Bufferizzo x le successive chiamate!
    508 					MISC_keymap[code]=*buffer;
    509 				}
    510 			}
    511 		}
    512 
    513 	}
    514 	keysym->mod = KMOD_NONE;
    515 
    516 	/* If UNICODE is on, get the UNICODE value for the key */
    517 	keysym->unicode = 0;
    518 	if ( SDL_TranslateUNICODE ) {
    519 #if 0
    520 		static XComposeStatus state;
    521 		/* Until we handle the IM protocol, use XLookupString() */
    522 		unsigned char keybuf[32];
    523 		if ( XLookupString(xkey, (char *)keybuf, sizeof(keybuf),
    524 							NULL, &state) ) {
    525 			keysym->unicode = keybuf[0];
    526 		}
    527 #endif
    528 	}
    529 	return(keysym);
    530 }
    531 
    532 void amiga_InitOSKeymap(_THIS)
    533 {
    534 	amiga_InitKeymap();
    535 }
    536