예제 #1
0
파일: mesh.c 프로젝트: FelixDeng/alsaplayer
static void meshscope(Window *win)
{
	Bool configured = FALSE;
	while (running) {
		while (XPending (meshscope_dpy)) {
			XEvent event;

			XNextEvent (meshscope_dpy, &event);
			switch (event.type) {
				case ConfigureNotify:
					glViewport (0, 0, event.xconfigure.width, event.xconfigure.height);
					configured = TRUE;
					break;
				case ButtonPress:
					mousepress(event);
					break;
				case ButtonRelease:
					mouserelease(event);
					break;
				case MotionNotify:
					mousemove(event);
					break;
				default:
					printf("event %x\n", event.type);
					break;
			}
		}
		drawMesh ();
		animate();
		dosleep (25000);
	}
}
예제 #2
0
void	gere_event(t_graph *g, int *cont, int i, int dec)
{
  Uint32	pause;
  Uint32	to;
  SDL_Event	event;

  pause = SDL_GetTicks();
  if (dec)
    set_cursor(g);
  to = SDL_GetTicks();
  while ((to - pause < 1 && *cont) || (i && *cont))
    {
      if (g->key)
	iterate(g);
      aff(g, i);
      while (SDL_PollEvent(&event))
	{
	  if (event.type == SDL_KEYDOWN)
	    keydown(g, event, cont);
	  if (event.type == SDL_KEYUP)
	    keyup(g, event);
	  if (event.type == SDL_MOUSEMOTION)
	    mousemove(g, event);
	}
      to = SDL_GetTicks();
    }
  if (i)
    *cont = -1;
}
예제 #3
0
파일: main.c 프로젝트: Aiur/Airtab
bool execCommand(Command *cmd) {
    double x, y;
    int key;
    if (strcmp(cmd->cmd, "mm") == 0) {
        x = strtod(cmd->arg1, NULL);
        y = strtod(cmd->arg2, NULL);
        mousemove(x, y);
        return true;
    } else if (strcmp(cmd->cmd, "kd") == 0) {
        key = (int) strtol(cmd->arg1, NULL, 10);
        keydown(key);
    } else if (strcmp(cmd->cmd, "ku") == 0) {
        key = (int)strtol(cmd->arg1, NULL, 10);
        keyup(key);
    } else if (strcmp(cmd->cmd, "md") == 0) {
        mousedown(cmd->arg1[0]);
    } else if (strcmp(cmd->cmd, "mu") == 0) {
        mouseup(cmd->arg1[0]);
    } else if (strcmp(cmd->cmd, "sy") == 0) {
        scrollY(strtod(cmd->arg1, NULL));
    } else if (strcmp(cmd->cmd, "sx") == 0) {
        scrollX(strtod(cmd->arg1, NULL));
    }
    
    return false;
}
예제 #4
0
    void injectMousePosition(float x, float y, bool immediate)
    {
        if (immediate)
        {
            float curr_x, curr_y;
            g3d_cursorpos(curr_x, curr_y);
            float xrel = x - curr_x;
            float yrel = y - curr_y;
            xrel *= max(screen->w, screen->h);
            yrel *= max(screen->w, screen->h);
//printf("curr: %f, %f\r\n", curr_x, curr_y);
//printf("next: %f, %f\r\n", x, y);
//printf("RELS: %f, %f       \r\n", xrel, yrel);
            if(!g3d_movecursor(0, 0))
            {
                mousemove(xrel, yrel);
                SDL_WarpMouse(screen->w / 2, screen->h / 2);
            }
            cursorx = x;
            cursory = y;
            return;
        }

/*
            float curr_x, curr_y;
            g3d_cursorpos(curr_x, curr_y);
            float xrel = x - curr_x;
            float yrel = y - curr_y;
            xrel *= 1000;
            yrel *= 1000;
printf("rels: %f, %f        %f,%f\r\n", xrel, yrel, x, curr_x);
            if(!g3d_movecursor(xrel, yrel))
                mousemove(xrel, yrel);
*/

        g3d_resetcursor(); // now at 0.5,0.5
        float curr_x, curr_y;
        float factor = 400;
        int iters = 0;
        do
        {
            g3d_cursorpos(curr_x, curr_y);
            //printf("A %d : (%f,%f) vs (%f,%f): %f,%f\r\n", iters, x, y, curr_x, curr_y, factor*(x - curr_x), factor*(y - curr_y));
            g3d_movecursor(factor*(x - curr_x), factor*(y - curr_y));
            iters++;
            //printf("B %d : (%f,%f) vs (%f,%f)\r\n", iters, x, y, curr_x, curr_y);
        } while (fabs(x-curr_x) + fabs(y-curr_y) > 0.005 && iters < 1000);
        assert(iters < 1000);
    }
예제 #5
0
void ImageLabel::mouseMoveEvent(QMouseEvent* e){
	if (_mouseclick){
		if (e->buttons() & Qt::LeftButton) {
			endPos = e->pos();

			//int distance = (endPos - startPos).manhattanLength();
			//if (distance >= QApplication::startDragDistance()){
				_mousemove = true;
				emit mousemove(points[points.size()-1],endPos);
				emit mouserect(startPos, endPos);
				/*std::cout << "points:" << points[points.size() - 1].x() << "  " << points[points.size() - 1].y() << endl
					<< points[points.size() - 1].x() << "  " << points[points.size() - 1].y() << endl << endl;*/
				points.push_back(endPos);
				
			//}
			//_mouserelease = false;
		}
	}
	QLabel::mouseMoveEvent(e);
}
예제 #6
0
파일: 1.cpp 프로젝트: halfopen/data_struct
void main(void)
{
sta:
	reset();
	puts("\t\t\t\t说明:\n");
	puts("1、鼠标左键点击添加墙壁,右键取消添加");
	puts("2、双击左上角在S开始走迷宫");
	puts("3、按回车键走下一步\n");
	for(int i=0;i<10;i++)
	{	for(int j=0;j<10;j++)
				if(fkm[j][i]!=0)printf(" %2d ",fkm[j][i]);
				else printf("    ");
		puts("");

	}
	while(1)
	{	if(mousemove()==1)
		{	puts("迷宫:");
			for(int i=0;i<10;i++)
			{	for(int j=0;j<10;j++)
					if(fkm[j][i]!=0)printf(" %2d ",fkm[j][i]);
					else printf("    ");
					puts("");
			}
			if(mgpath(1,1,8,8))
			{	int ret;ret=MessageBox(NULL,"找到出口了,是否继续?","迷宫",MB_YESNO | MB_SYSTEMMODAL );
				if(ret==IDYES)goto sta;
				else break;
			}
			else
			{	int ret;ret=MessageBox(NULL,"没有找到出口,是否继续?","迷宫",MB_YESNO | MB_SYSTEMMODAL );
				if(ret==IDYES)goto sta;
				else break;
			}
		}
	}
	closegraph();                 /*图形结束*/
}
예제 #7
0
static void
handle_mouse_event(MOUSE_EVENT_RECORD mer)
{
    static DWORD lastclick = 0;
    static int clicks = 0;

    int onmode = FALSE;
    COORD current, first, latest;
    MARK lmbdn_mark;		/* left mouse button down here */
    int sel_pending = 0, state;
    DWORD thisclick;
    UINT clicktime = GetDoubleClickTime();

    buttondown = FALSE;
    for_ever {
	current = mer.dwMousePosition;
	switch (mer.dwEventFlags) {
	case 0:
	    state = mer.dwButtonState;
	    if (state == 0) {	/* button released */
		thisclick = GetTickCount();
		TRACE(("CLICK %d/%d\n", lastclick, thisclick));
		if (thisclick - lastclick < clicktime) {
		    clicks++;
		    TRACE(("MOUSE CLICKS %d\n", clicks));
		} else {
		    clicks = 0;
		}
		lastclick = thisclick;

		switch (clicks) {
		case 1:
		    on_double_click();
		    break;
		case 2:
		    on_triple_click();
		    break;
		}

		if (buttondown) {
		    int dummy;

		    halt_autoscroll_thread();

		    /* Finalize cursor position. */
		    (void) MouseClickSetPos(&current, &dummy);
		    if (!(onmode || sel_pending))
			sel_yank(0);
		}
		return;
	    }
	    if (state & FROM_LEFT_1ST_BUTTON_PRESSED) {
		if (MouseClickSetPos(&current, &onmode)) {
		    first = latest = current;
		    lmbdn_mark = DOT;
		    sel_pending = FALSE;
		    mouse_wp = row2window(latest.Y);
		    if (onmode) {
			buttondown = TRUE;
			sel_release();
			update(TRUE);
		    } else {
			HWND hwnd;

			(void) update(TRUE);	/* possible wdw change */
			buttondown = FALSE;	/* until all inits are successful */

			/* Capture mouse to console vile's window handle. */
			hwnd = GetVileWindow();
			(void) SetCapture(hwnd);

			/* Compute pixel height of each row on screen. */
			(void) GetClientRect(hwnd, &client_rect);
			row_height = client_rect.bottom / term.rows;

			/*
			 * Create mutex to ensure that main thread and worker
			 * thread don't update display at the same time.
			 */
			if ((hAsMutex = CreateMutex(0, FALSE, 0)) == NULL)
			    mlforce("[Can't create autoscroll mutex]");
			else {
			    /*
			     * Setup a worker thread to act as a pseudo
			     * timer that kicks off autoscroll when
			     * necessary.
			     */

			    if (_beginthread(autoscroll_thread,
					     0,
					     NULL) == (unsigned long) -1) {
				(void) CloseHandle(hAsMutex);
				mlforce("[Can't create autoscroll thread]");
			    } else
				sel_pending = buttondown = TRUE;
			}
			if (!buttondown)
			    (void) ReleaseCapture();
		    }
		}
	    } else if (state & FROM_LEFT_2ND_BUTTON_PRESSED) {
		if (MouseClickSetPos(&current, &onmode)
		    && !onmode) {
		    sel_yank(0);
		    sel_release();
		    paste_selection();
		    (void) update(TRUE);
		}
		return;
	    } else {
		if (MouseClickSetPos(&current, &onmode)
		    && onmode) {
		    sel_release();
		    update(TRUE);
		} else {
		    kbd_alarm();
		}
	    }
	    break;

	case MOUSE_MOVED:
	    if (!buttondown)
		return;
	    if (onmode) {
		/* on mode line, resize window (if possible). */

		if (!adjust_window(mouse_wp, &current, &latest)) {
		    /*
		     * left mouse button still down, but cursor moved off mode
		     * line.  Update latest to keep track of cursor in case
		     * it wanders back on the mode line.
		     */

		    latest = current;
		}
	    } else {
		mousemove(&sel_pending,
			  &first,
			  &current,
			  &lmbdn_mark,
			  (mer.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
		    );
	    }
	    break;

#ifdef MOUSE_WHEELED
	case MOUSE_WHEELED:
	    /*
	     * Trial and error experimentation shows that dwButtonState
	     * has its high bit set when the wheel moves back and not
	     * set otherwise.
	     */
	    mvupwind(TRUE, ((long) mer.dwButtonState < 0) ? -3 : 3);
	    update(TRUE);
	    return;
#endif /* MOUSE_WHEELED */
	}

	for_ever {
	    INPUT_RECORD ir;
	    DWORD nr;
	    int key;

	    if (!ReadConsoleInput(hConsoleInput, &ir, 1, &nr))
		imdying(0);
	    switch (ir.EventType) {
	    case KEY_EVENT:
		key = decode_key_event(&ir);
		if (key == ESC) {
		    if (buttondown)
			halt_autoscroll_thread();
		    sel_release();
		    (void) update(TRUE);
		    return;
		}
		continue;

	    case MOUSE_EVENT:
		mer = ir.Event.MouseEvent;
		break;
	    }
	    break;
	}
    }
}
예제 #8
0
//------------------------------------------------------------------
LRESULT CALLBACK WndMainProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int i, notif;
	Tsquare *t;

	switch(message){
		case WM_PAINT:
		{
			static PAINTSTRUCT ps;
			BeginPaint(hWnd, &ps);
			paint(ps.hdc, &ps.rcPaint);
			EndPaint(hWnd, &ps);
		}
			break;
		case WM_LBUTTONDOWN:
			lbutton(lParam);
			break;
		case WM_RBUTTONDOWN:
			rbutton(lParam);
			break;
		case WM_LBUTTONUP:
			if(inserting){
				ReleaseCapture();
				inserting=false;
				insertGroup();
				resetSolution();
			}
			break;
		case WM_MOUSEMOVE:
			if(inserting){
				t= hitTest(lParam);
				if(t && t!=insSquares[insLen-1] && insLen<Nsymbol){
					insSquares[insLen++]=t;
				}
			}
#ifdef _DEBUGM
			mousemove(lParam);
#endif
			break;

		case WM_TIMER:
			if(!IsIconic(hWin)){
				playtime++;
				statusTime();
				checkShowErr(false);
			}
			break;
		case WM_KEYDOWN:
			key(wParam);
			break;
		case WM_GETMINMAXINFO:
		{
			LPMINMAXINFO lpmm = (LPMINMAXINFO)lParam;
			lpmm->ptMinTrackSize.x = 250;
			lpmm->ptMinTrackSize.y = 200+toolH;
			break;
		}
		case WM_SIZE:
			width=LOWORD(lParam);
			height=HIWORD(lParam);
			SendMessage(toolbar, TB_AUTOSIZE, 0, 0);
			SendMessage(statusbar, WM_SIZE, 0, 0);
			onMoved();
			invalidate();
			break;
		case WM_MOVE:
			onMoved();
			break;
		case WM_CLOSE:
			SendMessage(hWin, WM_COMMAND, ID_EXIT, 0);
			break;
		case WM_QUERYENDSESSION:
			writeini();
			return TRUE;
		case WM_DESTROY:
			PostQuitMessage(0);
			break;

		case WM_COMMAND:
			notif=HIWORD(wParam);
			wParam=LOWORD(wParam);
			if(setLang(wParam)) break;
			if(wParam>=ID_SYMBOL && wParam<unsigned(ID_SYMBOL+size)){
				select(wParam-ID_SYMBOL);
				break;
			}
			if(wParam>=ID_SIZE+4 && wParam<=ID_SIZE+Msize){
				if(askNew()) break;
				size=wParam-ID_SIZE;
				newGameFormat();
				numButtons();
				break;
			}
			if(wParam>=ID_MULTI && wParam<ID_MULTI+sizeA(gameTypeA)-1){
				if(askNew()) break;
				gameType=wParam-ID_MULTI;
				newGameFormat();
				break;
			}

			switch(wParam){
				case ID_CLEAR:
					noScore=true;
					init(false);
					invalidate();
					break;
				case ID_CLEAR_ALL:
					noScore=true;
					initSquare(false);
					invalidate();
					break;
				case ID_EDITOR:
					if(!editor){
						if((undoPos==0 || done==Nsquare) && isGenerated()){
							initSquare(false);
						}
						editor=true;
						playtime=0;
						noScore=true;
						editorChanged();
					}
					break;
				case ID_EDITOR_END:
					if(editor){
						endEditor();
						editor=false;
						editorChanged();
					}
					break;
				case ID_SOLVE:
				case ID_SOLVE1:
					if(testTotal()) break;
					noScore=true;
					if(done<Nsquare){
						waitOn();
#ifdef _DEBUG
						DWORD time=getTickCount();
#endif
						Nsolution=0;
						curSolution=-1; //find all solutions (up to Msolution)
						undoAllPos=undoPos;
						if(wParam==ID_SOLVE1) resolve1(); else resolve();
						freeGroups();
#ifdef _DEBUG
						status(4, _T("%d ms"), getTickCount()-time);
#endif
						waitOff();
					}
					if(Nsolution>0){
						i=curSolution;
						curSolution++;
						if(curSolution>=Nsolution) curSolution=0;
						if(Nsolution>1){
							if(i<0){
								status(4, _T("%d %s"), Nsolution, lng(662, "solutions"));
							}
							else{
								status(4, _T("%d/%d"), curSolution+1, Nsolution);
							}
						}
						rdSolution();
					}
					else{ //easy solution (without recurse) or not solvable
						curSolution=0;
						status(4, _T(""));
					}
					checkErr();
					invalidate();
					break;
				case ID_CHEAT:
					noScore=true;
					if(errTime<0){
						waitOn();
						hint();
						waitOff();
					}
					checkShowErr(true);
					break;
				case ID_UNDO:
					undo();
					checkErr();
					break;
				case ID_REDO:
					redo();
					checkErr();
					break;
				case ID_UNDO_SYMBOL:
					undoSymbol();
					checkErr();
					break;
				case ID_REDO_SYMBOL:
					redoSymbol();
					checkErr();
					break;
				case ID_UNDO_ALL:
					undoAll();
					checkErr();
					break;
				case ID_REDO_ALL:
					while(redo());
					checkErr();
					break;
				case ID_DEL:
					select(-1);
					break;
				case ID_INS:
					select(-2);
					break;
				case ID_SIGN:
					select(-3);
					break;
				case ID_CONS:
					select(-4);
					break;
				case ID_EVEN:
					select(-5);
					break;
				case ID_EXIT:
					writeini();
					DestroyWindow(hWin);
					break;
				case ID_DIAGONAL:
					if(askNew()) break;
					diag=!diag;
					newGameFormat();
					break;
				case ID_SYMETRIC:
					if(askNew()) break;
					symetric=!symetric;
					newGameFormat();
					break;
				case ID_LEVEL:
					if(DialogBox(inst, MAKEINTRESOURCE(IDD_LEVEL), hWnd, (DLGPROC)LevelProc)){
						if(!editor) newGame();
					}
					break;
				case ID_SHOWERR:
					DialogBox(inst, MAKEINTRESOURCE(IDD_ERRTIME), hWnd, (DLGPROC)ShowErrProc);
					break;
				case ID_KILLER:
					if(askNew()) break;
					killer=!killer;
					newGameFormat();
					numButtons();
					break;
				case ID_GREATER:
					if(askNew()) break;
					greater=!greater;
					newGameFormat();
					break;
				case ID_CONSECUTIVE:
					if(askNew()) break;
					consecutive=!consecutive;
					newGameFormat();
					if(selectedNum==-4 && !consecutive) select(-1);
					break;
				case ID_ODDEVEN:
					if(askNew()) break;
					oddeven=!oddeven;
					newGameFormat();
					if(selectedNum==-5 && !oddeven) select(-1);
					break;
				case ID_DIGITS:
				case ID_LETTERS:
				case ID_COLORS:
					symbol0=wParam-350;
					checkMenus();
					invalidate();
					numButtons();
					break;
				case ID_NEWGAME:
					if(editor) SendMessage(hWnd, WM_COMMAND, ID_EDITOR_END, 0);
					else newGame();
					break;
				case ID_DELINI:
					delreg=true;
					break;
				case ID_DELHISCORE:
					if(MessageBox(hWnd,
						lng(799, "Do you really want to delete all hiscores ?"), title,
						MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDYES){
						for(TscoreTab *tab=score; tab;){
							TscoreTab *t1= tab->next;
							delete tab;
							tab=t1;
						}
						score=0;
						writeScore();
					}
					break;
				case ID_BEST_SCORES:
					DialogBox(inst, MAKEINTRESOURCE(IDD_HISCORE), hWnd, (DLGPROC)ScoreProc);
					break;
				case ID_COLORDLG:
					DialogBox(inst, MAKEINTRESOURCE(IDD_COLORS), hWin, (DLGPROC)ColorProc);
					break;
				case ID_ABOUT:
					DialogBox(inst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)AboutProc);
					break;
				case ID_HELP_README:
				{
					TCHAR *buf=(TCHAR*)_alloca(2*MAX_PATH);
					getExeDir(buf, lng(13, "readme.txt"));
					if(ShellExecute(0, _T("open"), buf, 0, 0, SW_SHOWNORMAL)==(HINSTANCE)ERROR_FILE_NOT_FOUND){
						msglng(730, "Cannot open %s", buf);
					}
				}
					break;
				case ID_WRBMP:
					if(saveFileDlg(&bmpOfn, hWnd, 0)){
						wrBmp(bmpFn, bmpOfn.nFilterIndex);
					}
					break;
				case ID_SAVE:
					if(saveFileDlg(&gameOfn, hWnd, OFN_OVERWRITEPROMPT)){
						save(gameFn);
					}
					break;
				case ID_OPEN:
					if(openFileDlg(&gameOfn, hWnd, OFN_FILEMUSTEXIST|OFN_HIDEREADONLY)){
						open(gameFn);
						checkErr();
					}
					break;
				case ID_CLEAR_GRP:
					resetSolution();
					for(i=0; i<Ngroup; i++){
						delGroup(&group[i]);
					}
					invalidate();
					break;
				case ID_CLEAR_SGN:
				case ID_CLEAR_CONS:
					resetSolution();
					for(i=0; i<Nboard; i++){
						if(wParam==ID_CLEAR_SGN){
							putSign(0, &board[i], 0);
							putSign(0, &board[i], 1);
						}
						if(wParam==ID_CLEAR_CONS){
							putCons(false, &board[i], 0);
							putCons(false, &board[i], 1);
						}
					}
					invalidate();
					break;
				case ID_MARKS:
					noScore=true;
					showMarks();
					break;
				case ID_DELMARKS:
					delAllMarks();
					break;
				case ID_PDF:
					if(askNew()) break;
					DialogBox(inst, MAKEINTRESOURCE(IDD_PDF), hWnd, (DLGPROC)PdfProc);
					numButtons();
					break;
			}
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}
예제 #9
0
int main(int argc, char **argv){
    bool want_gl_debugging = false;
    bool want_msaa = false; // doesn't currently work, probably needs extension
    if(argc == 2 && (strncmp(argv[1], "debug_gl", 9) == 0)){
	want_gl_debugging = true;
    }
    START_TIMER(SDL_initialization_and_GL_context_creation);
    if(SDL_Init(SDL_INIT_EVERYTHING) == 1){
	printf("SDL failed to initialize: %s\n", SDL_GetError());
	return 1;
    }
    get_controller();
    SDL_Window *win = SDL_CreateWindow("SDL2/GL4.3", 0, 0, 1280, 720, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);    

    SDL_SetWindowGrab(win, SDL_TRUE);
    
    if(win == NULL){
	printf("SDL failed to create window: %s\n", SDL_GetError());
	return 1;
    }
    if(want_msaa){
	printf("setting msaa\n");
	if(SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 4) != 0){
	    printf("failed to set MULTISAMPLEBUFFERS\n");
	}
	if(SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 16) != 0){
	    printf("failed to set MULTISAMPLESAMPLES\n");
	}
	glEnable(GL_MULTISAMPLE);
    }
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
    if(want_gl_debugging){
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
    }
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); // it looks like we always get a core context anyway.
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    
    SDL_GLContext glcontext = SDL_GL_CreateContext(win);
    if(glcontext == NULL){
	printf("SDL failed to create context: %s\n", SDL_GetError());
	return 1;
    }

    int loaded_gl = ogl_LoadFunctions();
    if(!loaded_gl){
	printf("Failed to load OpenGL entry points.\n");
	return 1;
    }
    int context_flags;
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &context_flags);
    bool have_debug_context = (context_flags & SDL_GL_CONTEXT_DEBUG_FLAG) == SDL_GL_CONTEXT_DEBUG_FLAG;
    
    printf("OpenGL vendor: " TERMCOLOR_HIGHLIGHT "'%s'\n" TERMCOLOR_DEFAULT, glGetString(GL_VENDOR));
    printf("OpenGL renderer: " TERMCOLOR_HIGHLIGHT "'%s'\n" TERMCOLOR_DEFAULT, glGetString(GL_RENDERER));
    printf("OpenGL version: " TERMCOLOR_HIGHLIGHT "'%s'\n" TERMCOLOR_DEFAULT, glGetString(GL_VERSION));
    printf("GLSL version: " TERMCOLOR_HIGHLIGHT "'%s'\n" TERMCOLOR_DEFAULT, glGetString(GL_SHADING_LANGUAGE_VERSION));
    printf("Debug context: " TERMCOLOR_BOLD "%s" TERMCOLOR_DEFAULT "\n", have_debug_context ? "yes" : "no");
    int profile_flags;
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_flags);
    printf("Core context: " TERMCOLOR_BOLD "%s" TERMCOLOR_DEFAULT "\n", (profile_flags & SDL_GL_CONTEXT_PROFILE_CORE) != 0 ? "yes" : "no");

    if(have_debug_context && want_gl_debugging){
	printf(TERMCOLOR_HIGHLIGHT "We have debug extensions & context, installing debug callbacks..." TERMCOLOR_DEFAULT "\n");
	glDebugMessageCallback(debug_callback, stderr);
	glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
	glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
    }
    else {
	const char *reason = NULL;
	if(!want_gl_debugging)
	    reason = "debugging not requested (use 'debug_gl command line argument)";
	else if(!have_debug_context)
	    reason = "could not acquire debug context";
	else
	    reason = "unknown";
	printf(TERMCOLOR_ERROR "Not installing GL debug hooks. Reason: %s" TERMCOLOR_DEFAULT "\n", reason);
    }
    STOP_TIMER_AND_PRINT(SDL_initialization_and_GL_context_creation);
    START_TIMER(user_init);
    init(WINDOW_WIDTH, WINDOW_HEIGHT);
    STOP_TIMER_AND_PRINT(user_init);
    START_TIMER(total_renderloop_runtime);
    bool continue_loop = true;
    while(continue_loop){
        continue_loop = render(win);
	SDL_Event e;
	while(SDL_PollEvent(&e)){
	    if(e.type == SDL_QUIT){
		printf("received SDL_QUIT\n");
		goto exiting;
	    }
	    else if(e.type == SDL_MOUSEMOTION){
	      mousemove(e.motion.xrel, e.motion.yrel);
	      //SDL_WarpMouseInWindow(win, WINDOW_WIDTH/2, WINDOW_HEIGHT/2);
	      //printf("relative movement: %d, %d\n", e.motion.xrel, e.motion.yrel);
	    }
	    else if(e.type == SDL_WINDOWEVENT && e.window.event == SDL_WINDOWEVENT_RESIZED){
		resize(e.window.data1, e.window.data2);
	    }
	}
    }
    exiting:
    STOP_TIMER_AND_PRINT(total_renderloop_runtime);

    quit();
    
    SDL_GL_DeleteContext(glcontext);
    SDL_Quit();
    return 0;
}