Skip to content
Snippets Groups Projects
sdl_con.c 36.9 KiB
Newer Older
			case SDL_MOUSEWHEEL:
				pthread_once(&ciolib_mouse_initialized, init_mouse);
				if (ev.wheel.y) {
#if (SDL_MINOR_VERSION > 0) || (SDL_PATCHLEVEL > 3)
					if (ev.wheel.direction == SDL_MOUSEWHEEL_FLIPPED)
						ev.wheel.y = 0 - ev.wheel.y;
					if (ev.wheel.y > 0)
						ciomouse_gotevent(CIOLIB_BUTTON_PRESS(4), -1, -1, -1, -1);
					if (ev.wheel.y < 0)
						ciomouse_gotevent(CIOLIB_BUTTON_PRESS(5), -1, -1, -1, -1);
				}
				break;
			case SDL_MOUSEBUTTONUP:
				pthread_once(&ciolib_mouse_initialized, init_mouse);
				switch(ev.button.button) {
					case SDL_BUTTON_LEFT:
						ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(1),win_to_text_xpos(ev.button.x, &cvstat),win_to_text_ypos(ev.button.y, &cvstat), win_to_res_xpos(ev.button.x, &cvstat), win_to_res_ypos(ev.button.y, &cvstat));
deuce's avatar
deuce committed
						break;
					case SDL_BUTTON_MIDDLE:
						ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(2),win_to_text_xpos(ev.button.x, &cvstat),win_to_text_ypos(ev.button.y, &cvstat), win_to_res_xpos(ev.button.x, &cvstat), win_to_res_ypos(ev.button.y, &cvstat));
						break;
					case SDL_BUTTON_RIGHT:
						ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(3),win_to_text_xpos(ev.button.x, &cvstat),win_to_text_ypos(ev.button.y, &cvstat), win_to_res_xpos(ev.button.x, &cvstat), win_to_res_ypos(ev.button.y, &cvstat));
						break;
				}
				break;
			case SDL_QUIT:
				/*
				 * SDL2: Do we still need the reaper?
				 * This is what exit()s programs when the
				 * X is hit.
				 */
				if (ciolib_reaper)
					sdl_user_func(SDL_USEREVENT_QUIT);
Deucе's avatar
Deucе committed
				else {
					if (sdl_init_good)
						sdl_add_key(CIO_KEY_QUIT, &cvstat);
					else
Deucе's avatar
Deucе committed
						return;
Deucе's avatar
Deucе committed
				}
				break;
			case SDL_WINDOWEVENT:
				switch(ev.window.event) {
					case SDL_WINDOWEVENT_MAXIMIZED:
					case SDL_WINDOWEVENT_RESTORED:
#if defined(__DARWIN__)
						fullscreen = (sdl.GetWindowFlags(win) & SDL_WINDOW_MAXIMIZED) != 0;
						cio_api.mode=fullscreen?CIOLIB_MODE_SDL_FULLSCREEN:CIOLIB_MODE_SDL;
Deucе's avatar
Deucе committed
						update_cvstat(&cvstat);
#endif
						// Fall-through
					case SDL_WINDOWEVENT_SIZE_CHANGED:
						// SDL2: User resized window
					case SDL_WINDOWEVENT_RESIZED:
Deucе's avatar
Deucе committed
						pthread_mutex_lock(&sdl_mode_mutex);
						if (sdl_mode) {
							pthread_mutex_unlock(&sdl_mode_mutex);
Deucе's avatar
Deucе committed
						pthread_mutex_unlock(&sdl_mode_mutex);
						internal_setwinsize(&cvstat, false);
Deucе's avatar
Deucе committed
						break;
					case SDL_WINDOWEVENT_EXPOSED:
						bitmap_drv_request_pixels();
						break;
				}
				break;
			case SDL_USEREVENT: {
				struct rectlist *list;
				struct rectlist *old_next;
				switch(ev.user.code) {
					case SDL_USEREVENT_QUIT:
						sdl_ufunc_retval=0;
						if (ciolib_reaper)
							exit(0);
						sem_post(&sdl_ufunc_ret);
						return;
					case SDL_USEREVENT_FLUSH:
						update_cvstat(&cvstat);
						pthread_mutex_lock(&vstatlock);
						// Get correct aspect ratio for dst...
						int sw = cvstat.scrnwidth;
						int sh = cvstat.scrnheight;
						bitmap_get_scaled_win_size(cvstat.scaling, &dst.w, &dst.h, cvstat.winwidth, cvstat.winheight);
						pthread_mutex_unlock(&vstatlock);
						pthread_mutex_lock(&win_mutex);
						if (win != NULL) {
							pthread_mutex_unlock(&win_mutex);
							pthread_mutex_lock(&sdl_headlock);
Deucе's avatar
Deucе committed
							pthread_mutex_lock(&sdl_mode_mutex);
							list = update_list;
							update_list = update_list_tail = NULL;
Deucе's avatar
Deucе committed
							bool skipit = sdl_mode;
							pthread_mutex_unlock(&sdl_mode_mutex);
							pthread_mutex_unlock(&sdl_headlock);
							for (; list; list = old_next) {
								SDL_Rect src;

								old_next = list->next;
								if (list->next == NULL && !skipit && sw == list->rect.width && sh == list->rect.height) {
									void *pixels;
									int pitch;
									int row;
									int tw, th;

									if (internal_scaling) {
										struct graphics_buffer *gb;
										gb = do_scale(list, dst.w, dst.h);
										src.x = 0;
										src.y = 0;
										src.w = gb->w;
										src.h = gb->h;
Deucе's avatar
Deucе committed
										if (sdl.QueryTexture(texture, NULL, NULL, &tw, &th) != 0)
											fprintf(stderr, "Unable to query texture (%s)\n", sdl.GetError());
Deucе's avatar
Deucе committed
										if (sdl.LockTexture(texture, &src, &pixels, &pitch) != 0)
											fprintf(stderr, "Unable to lock texture (%s)\n", sdl.GetError());
										if (pitch != gb->w * sizeof(gb->data[0])) {
											// If this happens, we need to copy a row at a time...
											for (row = 0; row < gb->h && row < th; row++) {
												if (pitch < gb->w * sizeof(gb->data[0]))
													memcpy(pixels, &gb->data[gb->w * row], pitch);
												else
													memcpy(pixels, &gb->data[gb->w * row], gb->w * sizeof(gb->data[0]));
												pixels = (void *)((char*)pixels + pitch);
											}
										}
										else {
											int ch = gb->h;
											if (ch > th)
												ch = th;
											memcpy(pixels, gb->data, gb->w * ch * sizeof(gb->data[0]));
										sdl.UnlockTexture(texture);
										dst.x = (cvstat.winwidth - gb->w) / 2;
										dst.y = (cvstat.winheight - gb->h) / 2;
										src.x = 0;
										src.y = 0;
										src.w = list->rect.width;
										src.h = list->rect.height;
Deucе's avatar
Deucе committed
										if (sdl.QueryTexture(texture, NULL, NULL, &tw, &th) != 0)
											fprintf(stderr, "Unable to query texture (%s)\n", sdl.GetError());
Deucе's avatar
Deucе committed
										if (sdl.LockTexture(texture, &src, &pixels, &pitch) != 0)
											fprintf(stderr, "Unable to lock texture (%s)\n", sdl.GetError());
										if (pitch != list->rect.width * sizeof(list->data[0])) {
											// If this happens, we need to copy a row at a time...
											for (row = 0; row < list->rect.height && row < th; row++) {
												if (pitch < list->rect.width * sizeof(list->data[0]))
													memcpy(pixels, &list->data[list->rect.width * row], pitch);
												else
													memcpy(pixels, &list->data[list->rect.width * row], list->rect.width * sizeof(list->data[0]));
												pixels = (void *)((char*)pixels + pitch);
											}
										}
										else {
											int ch = list->rect.height;
											if (ch > th)
												ch = th;
											memcpy(pixels, list->data, list->rect.width * ch * sizeof(list->data[0]));
										}
										sdl.UnlockTexture(texture);
										//aspect_fix(&dst.w, &dst.h, cvstat.aspect_width, cvstat.aspect_height);
										dst.x = (cvstat.winwidth - dst.w) / 2;
										dst.y = (cvstat.winheight - dst.h) / 2;
									if (sdl.RenderCopy(renderer, texture, &src, &dst))
										fprintf(stderr, "RenderCopy() failed! (%s)\n", sdl.GetError());
								bitmap_drv_free_rect(list);
						else
							pthread_mutex_unlock(&win_mutex);
Deucе's avatar
Deucе committed

						break;
					case SDL_USEREVENT_SETNAME:
						pthread_mutex_lock(&win_mutex);
						sdl.SetWindowTitle(win, (char *)ev.user.data1);
						pthread_mutex_unlock(&win_mutex);
						free(ev.user.data1);
						break;
					case SDL_USEREVENT_SETICON:
						if(sdl_icon != NULL)
							sdl.FreeSurface(sdl_icon);
						sdl_icon=sdl.CreateRGBSurfaceFrom(ev.user.data1
								, *(unsigned long *)ev.user.data2
								, *(unsigned long *)ev.user.data2
								, 32
								, *(unsigned long *)ev.user.data2*4
								, *(DWORD *)"\377\0\0\0"
								, *(DWORD *)"\0\377\0\0"
								, *(DWORD *)"\0\0\377\0"
								, *(DWORD *)"\0\0\0\377"
						);
						pthread_mutex_lock(&win_mutex);
						sdl.SetWindowIcon(win, sdl_icon);
						pthread_mutex_unlock(&win_mutex);
						free(ev.user.data2);
						break;
					case SDL_USEREVENT_SETTITLE:
						pthread_mutex_lock(&win_mutex);
						sdl.SetWindowTitle(win, (char *)ev.user.data1);
						pthread_mutex_unlock(&win_mutex);
						free(ev.user.data1);
						break;
					case SDL_USEREVENT_SETVIDMODE:
Deucе's avatar
Deucе committed
						pthread_mutex_lock(&sdl_mode_mutex);
						sdl_mode = false;
						pthread_mutex_unlock(&sdl_mode_mutex);

						cvstat.winwidth = (intptr_t)ev.user.data1;
						cvstat.winheight = (intptr_t)ev.user.data2;
						internal_setwinsize(&cvstat, true);
						sdl_ufunc_retval=0;
						sem_post(&sdl_ufunc_ret);
						break;
					case SDL_USEREVENT_HIDEMOUSE:
						sdl.ShowCursor(SDL_DISABLE);
						break;
					case SDL_USEREVENT_SHOWMOUSE:
						sdl.ShowCursor(SDL_ENABLE);
						break;
					case SDL_USEREVENT_INIT:
						if(!sdl_init_good) {
							if(sdl.WasInit(SDL_INIT_VIDEO)==SDL_INIT_VIDEO) {
								pthread_mutex_lock(&win_mutex);
								_beginthread(sdl_mouse_thread, 0, NULL);
								sdl_init_good=1;
								pthread_mutex_unlock(&win_mutex);
						}
						sdl_ufunc_retval=0;
						sem_post(&sdl_ufunc_ret);
						break;
					case SDL_USEREVENT_GETWINPOS:
						sdl.GetWindowPosition(win, ev.user.data1, ev.user.data2);
						sem_post(&sdl_ufunc_ret);
						break;
					case SDL_USEREVENT_MOUSEPOINTER:
					{
						int cid = INT_MIN;
						SDL_Cursor *oc = curs;
						switch((intptr_t)ev.user.data1) {
							case CIOLIB_MOUSEPTR_ARROW:
								break;	// Default
							case CIOLIB_MOUSEPTR_BAR:
								cid = SDL_SYSTEM_CURSOR_IBEAM;
								break;
						}
						if (cid == INT_MIN) {
							sdl.SetCursor(sdl.GetDefaultCursor());
							curs = NULL;
						}
						else {
							curs = sdl.CreateSystemCursor(cid);
							if (curs == NULL)
								sdl.SetCursor(sdl.GetDefaultCursor());
							else
								sdl.SetCursor(curs);
						if (oc)
							sdl.FreeCursor(oc);
						break;
			case SDL_SYSWMEVENT:			/* ToDo... This is where Copy/Paste needs doing */

			/* Ignore this stuff */
			case SDL_JOYAXISMOTION:
			case SDL_JOYBALLMOTION:
			case SDL_JOYHATMOTION:
			case SDL_JOYBUTTONDOWN:
			case SDL_JOYBUTTONUP:
			default:
				break;
deuce's avatar
deuce committed
	return;
Deucе's avatar
Deucе committed
static int
sdl_initsync(void)
#if defined(__DARWIN__)
	if (initsdl_ret) {
#else
	if(init_sdl_video()) {
		fprintf(stderr,"SDL Video Initialization Failed\n");
	sem_init(&sdl_key_pending, 0, 0);
	sem_init(&sdl_ufunc_ret, 0, 0);
	sem_init(&sdl_ufunc_rec, 0, 0);
	pthread_mutex_init(&sdl_ufunc_mtx, NULL);
	pthread_mutex_init(&sdl_headlock, NULL);
	pthread_mutex_init(&win_mutex, NULL);
	pthread_mutex_init(&sdl_keylock, NULL);
Deucе's avatar
Deucе committed
	pthread_mutex_init(&sdl_mode_mutex, NULL);
Deucе's avatar
Deucе committed
	sdl_sync_initialized = true;
	return 0;
}

int sdl_initciolib(int mode)
{
	if (sdl_initsync() == -1)
		return -1;

void
sdl_beep(void)
{
        static unsigned char wave[2206];

	if (wave[2205] == 0) {
		xptone_makewave(440, wave, 2205, WAVE_SHAPE_SINE_SAW_HARM);
		wave[2205] = 1;
	}
        xp_play_sample(wave, 2205, TRUE);
}

/* Called from main thread only (Passes Event) */
int sdl_mousepointer(enum ciolib_mouse_ptr type)
{
	sdl_user_func(SDL_USEREVENT_MOUSEPOINTER,type);
	return(0);
}
sdl_getscaling(void)
{

	// TODO: I hate having nested locks like this. :(
	pthread_mutex_lock(&vstatlock);
	ret = bitmap_double_mult_inside(vstat.winwidth, vstat.winheight);
	pthread_mutex_unlock(&vstatlock);
	return ret;
}

void
sdl_setscaling(double newval)
{
	int w, h;

	pthread_mutex_lock(&vstatlock);
	bitmap_get_scaled_win_size(newval, &w, &h, 0, 0);
	pthread_mutex_unlock(&vstatlock);
	sdl_setwinsize(w, h);
}

enum ciolib_scaling
sdl_getscaling_type(void)
{
	enum ciolib_scaling ret;

	pthread_mutex_lock(&vstatlock);
	ret = (internal_scaling ? CIOLIB_SCALING_INTERNAL : CIOLIB_SCALING_EXTERNAL);
	pthread_mutex_unlock(&vstatlock);
	return ret;
}

void
sdl_setscaling_type(enum ciolib_scaling newval)
{
	struct video_stats cvstat = vstat;
	int w, h;

	update_cvstat(&cvstat);
	pthread_mutex_lock(&vstatlock);
	if ((newval == CIOLIB_SCALING_INTERNAL) != internal_scaling) {
		internal_scaling = (newval == CIOLIB_SCALING_INTERNAL);
		w = vstat.winwidth;
		h = vstat.winheight;
		pthread_mutex_unlock(&vstatlock);
		sdl_user_func_ret(SDL_USEREVENT_SETVIDMODE, w, h);
	}
	else {
		pthread_mutex_unlock(&vstatlock);
	}
}