added windowKeyPressed and windowKeyReleased
This commit is contained in:
parent
98af446a2f
commit
14342c8c9f
|
@ -0,0 +1,7 @@
|
|||
lib/
|
||||
main
|
||||
main.exe
|
||||
valgrind-out.txt
|
||||
*.o
|
||||
sample/
|
||||
other/
|
12
Makefile
12
Makefile
|
@ -1,4 +1,4 @@
|
|||
FLAGS=-fPIC --shared
|
||||
FLAGS=-fPIC --shared -Wall -Wextra
|
||||
|
||||
LINUX_FILES=src/openwindow.c deps/lib/glad_linux.a
|
||||
|
||||
|
@ -11,7 +11,7 @@ all: libopenwindow.so libopenwindow.dll
|
|||
|
||||
libopenwindow.so: glad_linux.a
|
||||
mkdir -p ${OUTPUT}
|
||||
gcc ${FLAGS} -o ${OUTPUT}libopenwindow.so ${LINUX_FILES}
|
||||
gcc ${FLAGS} -o ${OUTPUT}libopenwindow.so ${LINUX_FILES} -lX11 -lGLX -lOpenGL
|
||||
|
||||
libopenwindow.dll: glad_windows.a
|
||||
mkdir -p ${OUTPUT}
|
||||
|
@ -21,9 +21,9 @@ GLAD_FLAGS=-fPIC -c
|
|||
GLAD_FILES=deps/src/glad.c
|
||||
|
||||
glad_linux.a: deps/src/glad.c
|
||||
gcc ${GLAD_FLAGS} -o deps/src/glad_linux.o ${GLAD_FILES}
|
||||
ar rcs deps/lib/glad_linux.a deps/src/glad_linux.o
|
||||
gcc ${GLAD_FLAGS} -o deps/lib/glad_linux.o ${GLAD_FILES}
|
||||
ar rcs deps/lib/glad_linux.a deps/lib/glad_linux.o
|
||||
|
||||
glad_windows.a: deps/src/glad.c
|
||||
x86_64-w64-mingw32-gcc ${GLAD_FLAGS} -o deps/src/glad_windows.o ${GLAD_FILES}
|
||||
ar rcs deps/lib/glad_windows.a deps/src/glad_windows.o
|
||||
x86_64-w64-mingw32-gcc ${GLAD_FLAGS} -o deps/lib/glad_windows.o ${GLAD_FILES}
|
||||
ar rcs deps/lib/glad_windows.a deps/lib/glad_windows.o
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
The glad source code:
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2022 David Herberth
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
The Khronos Specifications:
|
||||
|
||||
Copyright (c) 2013-2020 The Khronos Group Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
The EGL Specification and various headers:
|
||||
|
||||
Copyright (c) 2007-2016 The Khronos Group Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and/or associated documentation files (the
|
||||
"Materials"), to deal in the Materials without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
permit persons to whom the Materials are furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Materials.
|
||||
|
||||
THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
Binary file not shown.
Binary file not shown.
77
main.c
77
main.c
|
@ -1,81 +1,34 @@
|
|||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "deps/include/glad/glad.h"
|
||||
#include "GL/gl.h"
|
||||
|
||||
#include "src/openwindow.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <X11/keysym.h>
|
||||
|
||||
#define Window X11Window
|
||||
#include <X11/Xlib.h>
|
||||
#undef Window
|
||||
|
||||
void xevent(Window * w, XEvent xev) {
|
||||
switch (xev.type)
|
||||
{
|
||||
case MotionNotify:
|
||||
printf("motion: %d %d\n", xev.xbutton.x, xev.xbutton.y);
|
||||
break;
|
||||
case KeyRelease:
|
||||
printf("release (%s)\n", XKeysymToString(XLookupKeysym(&xev.xkey, 0)));
|
||||
break;
|
||||
case KeyPress:
|
||||
if (XLookupKeysym(&xev.xkey, 0) == XK_Escape) w->close = true;
|
||||
printf("keypress (%s)\n", XKeysymToString(XLookupKeysym(&xev.xkey, 0)));
|
||||
break;
|
||||
case ButtonPress:
|
||||
printf("BPress: state = %d, button = %d, x = %d, y = %d\n", xev.xbutton.state, xev.xbutton.button, xev.xbutton.x, xev.xbutton.y);
|
||||
printf("Type=%d\n", (int)xev.xbutton.type);
|
||||
break;
|
||||
case ButtonRelease:
|
||||
printf("BRelease: state = %d, button = %d, x = %d, y = %d\n", xev.xbutton.state, xev.xbutton.button, xev.xbutton.x, xev.xbutton.y);
|
||||
printf("Type=%d\n", (int)xev.xbutton.type);
|
||||
break;
|
||||
default:
|
||||
printf("Unknown event!\n");
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
const char * fss =
|
||||
"#version 330 core\n"
|
||||
"precision mediump float;"
|
||||
"out vec4 FragColor;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" FragColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
|
||||
"}";
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Window w = openWindow("Window", 800, 600);
|
||||
Window * w = openWindow("Window", 800, 600);
|
||||
|
||||
// TODO: do this
|
||||
#ifndef _WIN32
|
||||
windowSetEventHandler(&w, xevent);
|
||||
#endif // _WIN32
|
||||
while (!windowKeyPressed(w, WINDOW_KEY_ESC)) {
|
||||
windowHandleEvents(w);
|
||||
|
||||
while (!w.close)
|
||||
{
|
||||
windowHandleEvents(&w);
|
||||
if (windowKeyPressed(w, WINDOW_KEY_A))
|
||||
printf("A is being pressed\n");
|
||||
|
||||
glClearColor(0.1f, 0.2f, 0.3f, 1.0f);
|
||||
if (windowKeyReleased(w, WINDOW_KEY_A))
|
||||
printf("A is being released\n");
|
||||
|
||||
glClearColor(0.1, 0.2, 0.3, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glViewport(0, 0, 800, 600);
|
||||
|
||||
glColor3f(1.0, 0, 0);
|
||||
glBegin(GL_TRIANGLES);
|
||||
glColor3f(1.0f, 0.0f, 0.0f);
|
||||
glVertex2f(-0.5, -0.5);
|
||||
glColor3f(0.0f, 1.0f, 0.0f);
|
||||
glVertex2f(0.5, -0.5);
|
||||
glColor3f(0.0f, 0.0f, 1.0f);
|
||||
glVertex2f(0.0, 0.5);
|
||||
glEnd();
|
||||
glFlush();
|
||||
|
||||
windowDraw(w);
|
||||
}
|
||||
|
|
BIN
sample/x11
BIN
sample/x11
Binary file not shown.
256
sample/x11.c
256
sample/x11.c
|
@ -1,256 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glx.h>
|
||||
|
||||
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
|
||||
|
||||
// Helper to check for extension string presence. Adapted from:
|
||||
// http://www.opengl.org/resources/features/OGLextensions/
|
||||
static bool isExtensionSupported(const char *extList, const char *extension)
|
||||
{
|
||||
const char *start;
|
||||
const char *where, *terminator;
|
||||
|
||||
/* Extension names should not have spaces. */
|
||||
where = strchr(extension, ' ');
|
||||
if (where || *extension == '\0')
|
||||
return false;
|
||||
|
||||
/* It takes a bit of care to be fool-proof about parsing the
|
||||
OpenGL extensions string. Don't be fooled by sub-strings,
|
||||
etc. */
|
||||
for (start=extList;;) {
|
||||
where = strstr(start, extension);
|
||||
|
||||
if (!where)
|
||||
break;
|
||||
|
||||
terminator = where + strlen(extension);
|
||||
|
||||
if ( where == start || *(where - 1) == ' ' )
|
||||
if ( *terminator == ' ' || *terminator == '\0' )
|
||||
return true;
|
||||
|
||||
start = terminator;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
Display *display = XOpenDisplay(NULL);
|
||||
|
||||
if (!display)
|
||||
{
|
||||
printf("Failed to open X display\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Get a matching FB config
|
||||
static int visual_attribs[] =
|
||||
{
|
||||
GLX_X_RENDERABLE , True,
|
||||
GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
|
||||
GLX_RENDER_TYPE , GLX_RGBA_BIT,
|
||||
GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
|
||||
GLX_RED_SIZE , 8,
|
||||
GLX_GREEN_SIZE , 8,
|
||||
GLX_BLUE_SIZE , 8,
|
||||
GLX_ALPHA_SIZE , 8,
|
||||
GLX_DEPTH_SIZE , 24,
|
||||
GLX_STENCIL_SIZE , 8,
|
||||
GLX_DOUBLEBUFFER , True,
|
||||
//GLX_SAMPLE_BUFFERS , 1,
|
||||
//GLX_SAMPLES , 4,
|
||||
None
|
||||
};
|
||||
|
||||
int glx_major, glx_minor;
|
||||
|
||||
// FBConfigs were added in GLX version 1.3.
|
||||
if ( !glXQueryVersion( display, &glx_major, &glx_minor ) ||
|
||||
( ( glx_major == 1 ) && ( glx_minor < 3 ) ) || ( glx_major < 1 ) )
|
||||
{
|
||||
printf("Invalid GLX version");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf( "Getting matching framebuffer configs\n" );
|
||||
int fbcount;
|
||||
GLXFBConfig* fbc = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount);
|
||||
if (!fbc)
|
||||
{
|
||||
printf( "Failed to retrieve a framebuffer config\n" );
|
||||
exit(1);
|
||||
}
|
||||
printf( "Found %d matching FB configs.\n", fbcount );
|
||||
|
||||
// Pick the FB config/visual with the most samples per pixel
|
||||
printf( "Getting XVisualInfos\n" );
|
||||
int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999;
|
||||
|
||||
int i;
|
||||
for (i=0; i<fbcount; ++i)
|
||||
{
|
||||
XVisualInfo *vi = glXGetVisualFromFBConfig( display, fbc[i] );
|
||||
if ( vi )
|
||||
{
|
||||
int samp_buf, samples;
|
||||
glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf );
|
||||
glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLES , &samples );
|
||||
|
||||
printf( " Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d,"
|
||||
" SAMPLES = %d\n",
|
||||
i, vi -> visualid, samp_buf, samples );
|
||||
|
||||
if ( best_fbc < 0 || samp_buf && samples > best_num_samp )
|
||||
best_fbc = i, best_num_samp = samples;
|
||||
if ( worst_fbc < 0 || !samp_buf || samples < worst_num_samp )
|
||||
worst_fbc = i, worst_num_samp = samples;
|
||||
}
|
||||
XFree( vi );
|
||||
}
|
||||
|
||||
GLXFBConfig bestFbc = fbc[ best_fbc ];
|
||||
|
||||
// Be sure to free the FBConfig list allocated by glXChooseFBConfig()
|
||||
XFree( fbc );
|
||||
|
||||
// Get a visual
|
||||
XVisualInfo *vi = glXGetVisualFromFBConfig( display, bestFbc );
|
||||
printf( "Chosen visual ID = 0x%x\n", vi->visualid );
|
||||
|
||||
printf( "Creating colormap\n" );
|
||||
XSetWindowAttributes swa;
|
||||
Colormap cmap;
|
||||
swa.colormap = cmap = XCreateColormap( display,
|
||||
RootWindow( display, vi->screen ),
|
||||
vi->visual, AllocNone );
|
||||
swa.background_pixmap = None ;
|
||||
swa.border_pixel = 0;
|
||||
swa.event_mask = StructureNotifyMask;
|
||||
|
||||
printf( "Creating window\n" );
|
||||
Window win = XCreateWindow( display, RootWindow( display, vi->screen ),
|
||||
0, 0, 100, 100, 0, vi->depth, InputOutput,
|
||||
vi->visual,
|
||||
CWBorderPixel|CWColormap|CWEventMask, &swa );
|
||||
if ( !win )
|
||||
{
|
||||
printf( "Failed to create window.\n" );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Done with the visual info data
|
||||
XFree( vi );
|
||||
|
||||
XStoreName( display, win, "GL 3.0 Window" );
|
||||
|
||||
printf( "Mapping window\n" );
|
||||
XMapWindow( display, win );
|
||||
|
||||
// Get the default screen's GLX extension list
|
||||
//const char *glxExts = glXQueryExtensionsString( display,
|
||||
// DefaultScreen( display ) );
|
||||
|
||||
// NOTE: It is not necessary to create or make current to a context before
|
||||
// calling glXGetProcAddressARB
|
||||
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
|
||||
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
|
||||
glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
|
||||
|
||||
GLXContext ctx = 0;
|
||||
|
||||
// Install an X error handler so the application won't exit if GL 3.0
|
||||
// context allocation fails.
|
||||
//
|
||||
// Note this error handler is global. All display connections in all threads
|
||||
// of a process use the same error handler, so be sure to guard against other
|
||||
// threads issuing X commands while this code is running.
|
||||
//ctxErrorOccurred = false;
|
||||
//int (*oldHandler)(Display*, XErrorEvent*) =
|
||||
// XSetErrorHandler(&ctxErrorHandler);
|
||||
|
||||
// Check for the GLX_ARB_create_context extension string and the function.
|
||||
// If either is not present, use GLX 1.3 context creation method.
|
||||
//if ( !isExtensionSupported( glxExts, "GLX_ARB_create_context" ) ||
|
||||
// !glXCreateContextAttribsARB )
|
||||
//{
|
||||
// printf( "glXCreateContextAttribsARB() not found"
|
||||
// " ... using old-style GLX context\n" );
|
||||
// ctx = glXCreateNewContext( display, bestFbc, GLX_RGBA_TYPE, 0, True );
|
||||
//} else
|
||||
//{
|
||||
int context_attribs[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
|
||||
//GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
|
||||
None
|
||||
};
|
||||
|
||||
printf( "Creating context\n" );
|
||||
ctx = glXCreateContextAttribsARB( display, bestFbc, 0,
|
||||
True, context_attribs );
|
||||
|
||||
// Sync to ensure any errors generated are processed.
|
||||
//XSync( display, False );
|
||||
//if (ctxErrorOccurred && !ctx)
|
||||
//{
|
||||
// context_attribs[1] = 1;
|
||||
// context_attribs[3] = 0;
|
||||
|
||||
// ctxErrorOccurred = false;
|
||||
|
||||
// printf( "Failed to create GL 3.0 context"
|
||||
// " ... using old-style GLX context\n" );
|
||||
// ctx = glXCreateContextAttribsARB( display, bestFbc, 0,
|
||||
// True, context_attribs );
|
||||
//}
|
||||
//}
|
||||
|
||||
//XSync( display, False );
|
||||
//XSetErrorHandler( oldHandler );
|
||||
|
||||
//if ( ctxErrorOccurred || !ctx )
|
||||
//{
|
||||
// printf( "Failed to create an OpenGL context\n" );
|
||||
// exit(1);
|
||||
//}
|
||||
|
||||
printf( "Making context current\n" );
|
||||
glXMakeCurrent( display, win, ctx );
|
||||
|
||||
const GLubyte * v = glGetString(GL_VERSION);
|
||||
printf("%s\n", v);
|
||||
|
||||
glClearColor( 0, 0.5, 1, 1 );
|
||||
glClear( GL_COLOR_BUFFER_BIT );
|
||||
glXSwapBuffers ( display, win );
|
||||
|
||||
sleep( 1 );
|
||||
|
||||
glClearColor ( 1, 0.5, 0, 1 );
|
||||
glClear ( GL_COLOR_BUFFER_BIT );
|
||||
glXSwapBuffers ( display, win );
|
||||
|
||||
sleep( 1 );
|
||||
|
||||
glXMakeCurrent( display, 0, 0 );
|
||||
glXDestroyContext( display, ctx );
|
||||
|
||||
XDestroyWindow( display, win );
|
||||
XFreeColormap( display, cmap );
|
||||
XCloseDisplay( display );
|
||||
|
||||
return 0;
|
||||
}
|
202
src/openwindow.c
202
src/openwindow.c
|
@ -1,6 +1,9 @@
|
|||
// TODO: Add all the error handling to the glx part
|
||||
|
||||
#include "openwindow.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int initOpenGL() {
|
||||
if (getOpenGLProcs() == 0) return -1;
|
||||
|
@ -10,10 +13,34 @@ int initOpenGL() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define OPENWINDOW_OPENGL_VERSSION_MAJOR 3
|
||||
#define OPENWINDOW_OPENGL_VERSSION_MINOR 0
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
|
||||
|
||||
void windowDefaultEventHandler(Window * w, XEvent xev) {
|
||||
switch (xev.type)
|
||||
{
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
XQueryKeymap(w->x.display, w->io.current);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void windowEventHandler(Window * w, XEvent event) {
|
||||
if (w->eventHandler == NULL) {
|
||||
windowDefaultEventHandler(w, event);
|
||||
}
|
||||
else {
|
||||
w->eventHandler(w, event);
|
||||
}
|
||||
}
|
||||
|
||||
bool checkGLXVersion(Window window) {
|
||||
int glx_major, glx_minor;
|
||||
|
||||
|
@ -85,9 +112,9 @@ int initGLX(Window * window)
|
|||
glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
|
||||
|
||||
int context_attribs[] = {
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 6,
|
||||
GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, OPENWINDOW_OPENGL_VERSSION_MAJOR,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, OPENWINDOW_OPENGL_VERSSION_MINOR,
|
||||
GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
None
|
||||
};
|
||||
window->glx.context = glXCreateContextAttribsARB(window->x.display, window->glx.config, 0, True, context_attribs);
|
||||
|
@ -97,6 +124,7 @@ int initGLX(Window * window)
|
|||
|
||||
int init(Window * window, const char * name, size_t width, size_t height) {
|
||||
window->x.display = XOpenDisplay(NULL);
|
||||
|
||||
if (window->x.display == NULL) {
|
||||
fprintf(stderr, "Failed to open xdisplay!\n");
|
||||
return -1;
|
||||
|
@ -155,10 +183,11 @@ int init(Window * window, const char * name, size_t width, size_t height) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
Window openWindow(const char * name, size_t width, size_t height) {
|
||||
Window w = {0};
|
||||
Window * openWindow(const char * name, size_t width, size_t height) {
|
||||
Window * w = calloc(1, sizeof(Window));
|
||||
w->fps = WINDOW_DEFAULT_FPS;
|
||||
|
||||
if (init(&w, name, width, height) < 0) {
|
||||
if (init(w, name, width, height) < 0) {
|
||||
fprintf(stderr, "Failed to initialize window: X11 error!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -171,34 +200,65 @@ Window openWindow(const char * name, size_t width, size_t height) {
|
|||
return w;
|
||||
}
|
||||
|
||||
void windowDraw(Window window) {
|
||||
glXSwapBuffers(window.x.display, window.x.window);
|
||||
void windowSetFps(Window * window, uint32_t fps) {
|
||||
window->fps = fps;
|
||||
}
|
||||
|
||||
void windowDraw(Window * window) {
|
||||
glXSwapBuffers(window->x.display, window->x.window);
|
||||
usleep(1 / window->fps);
|
||||
}
|
||||
|
||||
void windowSetEventHandler(Window * window, WindowEventHandler handler) {
|
||||
window->eventHandler = handler;
|
||||
}
|
||||
|
||||
void windowHandleEvents(Window * window) {
|
||||
if (window->eventHandler == NULL) {
|
||||
fprintf(stderr, "Window event handler is not defined. Use `setEventHandler' to set it!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XEvent xev;
|
||||
|
||||
if (XPending(window->x.display))
|
||||
if (XCheckWindowEvent(window->x.display, window->x.window, window->x.eventMask, &xev))
|
||||
window->eventHandler(window, xev);
|
||||
void resetIOState(Window * window) {
|
||||
memcpy(window->io.last, window->io.current, WINDOW_KEY_COUNT);
|
||||
}
|
||||
|
||||
void closeWindow(Window window) {
|
||||
glXMakeCurrent(window.x.display, None, None);
|
||||
glXDestroyContext(window.x.display, window.glx.context);
|
||||
void windowHandleEvents(Window * window) {
|
||||
XEvent xev = {0};
|
||||
|
||||
XFreeColormap(window.x.display, window.x.cmap);
|
||||
XDestroyWindow(window.x.display, window.x.window);
|
||||
XCloseDisplay(window.x.display);
|
||||
resetIOState(window);
|
||||
|
||||
while (XPending(window->x.display)) {
|
||||
if (XCheckWindowEvent(window->x.display, window->x.window, window->x.eventMask, &xev)) {
|
||||
if (window->eventHandler != NULL) {
|
||||
window->eventHandler(window, xev);
|
||||
} else {
|
||||
windowEventHandler(window, xev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void closeWindow(Window * window) {
|
||||
glXMakeCurrent(window->x.display, None, None);
|
||||
glXDestroyContext(window->x.display, window->glx.context);
|
||||
|
||||
XFreeColormap(window->x.display, window->x.cmap);
|
||||
XDestroyWindow(window->x.display, window->x.window);
|
||||
XCloseDisplay(window->x.display);
|
||||
free(window);
|
||||
}
|
||||
|
||||
bool windowKeyPressed(Window * window, char * key) {
|
||||
KeySym keysym = XStringToKeysym(key);
|
||||
if (keysym == NoSymbol) return false;
|
||||
|
||||
KeyCode keycode = XKeysymToKeycode(window->x.display, keysym);
|
||||
|
||||
return window->io.current[keycode / 8] & (1 << (keycode % 8));
|
||||
}
|
||||
|
||||
bool windowKeyReleased(Window * window, char * key) {
|
||||
KeySym keysym = XStringToKeysym(key);
|
||||
if (keysym == NoSymbol) return false;
|
||||
|
||||
KeyCode keycode = XKeysymToKeycode(window->x.display, keysym);
|
||||
|
||||
return (window->io.last[keycode / 8] & (1 << (keycode % 8))) && !(window->io.current[keycode / 8] & (1 << (keycode % 8)));
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -206,22 +266,37 @@ void closeWindow(Window window) {
|
|||
#include <windows.h>
|
||||
#include <GL/wgl.h>
|
||||
|
||||
//TODO: Change this every time we open a window
|
||||
#define WND_CLASS_NAME "OpenWindowWndClass"
|
||||
|
||||
LRESULT CALLBACK wndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
Window * window = (Window *)(LONG_PTR)GetWindowLong(hwnd, GWLP_USERDATA);
|
||||
void windowDefaultEventHandler(Window * window, unsigned int event, WPARAM wParam, LPARAM lParam) {
|
||||
(void) wParam;
|
||||
(void) lParam;
|
||||
|
||||
switch (msg)
|
||||
switch (event)
|
||||
{
|
||||
case WM_KEYDOWN:
|
||||
{
|
||||
if (wParam == VK_ESCAPE) window->close = true;
|
||||
case WM_KEYUP:
|
||||
GetKeyboardState(window->io.current);
|
||||
break;
|
||||
case WM_TIMER:
|
||||
InvalidateRect(window->wgl.window, NULL, FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK windowEventHandler(HWND hwnd, unsigned int event, WPARAM wParam, LPARAM lParam) {
|
||||
Window * window = (Window *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
if (window == NULL) goto uninit;
|
||||
|
||||
if (window->eventHandler == NULL) {
|
||||
windowDefaultEventHandler(window, event, wParam, lParam);
|
||||
} else {
|
||||
window->eventHandler(window, event, wParam, lParam);
|
||||
}
|
||||
|
||||
return (DefWindowProc(hwnd, msg, wParam, lParam));
|
||||
uninit:
|
||||
return (DefWindowProc(hwnd, event, wParam, lParam));
|
||||
}
|
||||
|
||||
int init(Window * window, const char * title, size_t width, size_t height) {
|
||||
|
@ -230,7 +305,7 @@ int init(Window * window, const char * title, size_t width, size_t height) {
|
|||
|
||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||
wcex.style = CS_CLASSDC;
|
||||
wcex.lpfnWndProc = wndProc;
|
||||
wcex.lpfnWndProc = windowEventHandler;
|
||||
wcex.cbClsExtra = 0;
|
||||
wcex.cbWndExtra = 0;
|
||||
wcex.hInstance = window->wgl.instance;
|
||||
|
@ -254,14 +329,17 @@ int init(Window * window, const char * title, size_t width, size_t height) {
|
|||
NULL,
|
||||
NULL,
|
||||
window->wgl.instance,
|
||||
window
|
||||
NULL
|
||||
);
|
||||
|
||||
if (window->wgl.window == NULL) return -1;
|
||||
if (window->wgl.window == NULL) {
|
||||
fprintf(stderr, "Failed to create window!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ShowWindow(window->wgl.window, SW_SHOW);
|
||||
|
||||
SetWindowLong(window->wgl.window, GWLP_USERDATA, (LONG_PTR)window);
|
||||
SetWindowLongPtr(window->wgl.window, GWLP_USERDATA, (LONG_PTR)window);
|
||||
|
||||
window->wgl.display = GetDC(window->wgl.window);
|
||||
PIXELFORMATDESCRIPTOR pfd = {0};
|
||||
|
@ -300,12 +378,12 @@ int init(Window * window, const char * title, size_t width, size_t height) {
|
|||
|
||||
if (!wglMakeCurrent(window->wgl.display, tempContext)) return -1;
|
||||
|
||||
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
|
||||
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)(void *)wglGetProcAddress("wglCreateContextAttribsARB");
|
||||
if (wglCreateContextAttribsARB == NULL) return -1;
|
||||
|
||||
int attribs[] = {
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, 6,
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, OPENWINDOW_OPENGL_VERSSION_MAJOR,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, OPENWINDOW_OPENGL_VERSSION_MINOR,
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
0
|
||||
};
|
||||
|
@ -321,13 +399,16 @@ int init(Window * window, const char * title, size_t width, size_t height) {
|
|||
|
||||
wglMakeCurrent(window->wgl.display, window->wgl.context);
|
||||
|
||||
SetTimer(window->wgl.window, 1, (1 / window->fps) * 1000, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Window openWindow(const char * name, size_t width, size_t height) {
|
||||
Window w = {0};
|
||||
Window * openWindow(const char * name, size_t width, size_t height) {
|
||||
Window * w = calloc(1, sizeof(Window));
|
||||
w->fps = WINDOW_DEFAULT_FPS;
|
||||
|
||||
if (init(&w, name, width, height) < 0) {
|
||||
if (init(w, name, width, height) < 0) {
|
||||
fprintf(stderr, "Failed to initialize wgl!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -340,24 +421,45 @@ Window openWindow(const char * name, size_t width, size_t height) {
|
|||
return w;
|
||||
}
|
||||
|
||||
void windowDraw(Window window) {
|
||||
SwapBuffers(window.wgl.display);
|
||||
void windowDraw(Window * window) {
|
||||
SwapBuffers(window->wgl.display);
|
||||
}
|
||||
|
||||
void windowSetEventHandler(Window * window, WindowEventHandler handler) {
|
||||
window->eventHandler = handler;
|
||||
}
|
||||
|
||||
void resetIOState(Window * window) {
|
||||
memcpy(window->io.last, window->io.current, WINDOW_KEY_COUNT);
|
||||
}
|
||||
|
||||
void windowHandleEvents(Window * window) {
|
||||
MSG msg;
|
||||
(void) window;
|
||||
|
||||
resetIOState(window);
|
||||
|
||||
MSG msg = {0};
|
||||
GetMessage(&msg, NULL, 0, 0);
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
void closeWindow(Window window) {
|
||||
void closeWindow(Window * window) {
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(window.wgl.context);
|
||||
ReleaseDC(window.wgl.window, window.wgl.display);
|
||||
wglDeleteContext(window->wgl.context);
|
||||
ReleaseDC(window->wgl.window, window->wgl.display);
|
||||
|
||||
DestroyWindow(window.wgl.window);
|
||||
UnregisterClass(WND_CLASS_NAME, window.wgl.instance);
|
||||
DestroyWindow(window->wgl.window);
|
||||
UnregisterClass(WND_CLASS_NAME, window->wgl.instance);
|
||||
free(window);
|
||||
}
|
||||
|
||||
bool windowKeyPressed(Window * window, int key) {
|
||||
return window->io.current[key] & 0x80;
|
||||
}
|
||||
|
||||
bool windowKeyReleased(Window * window, int key) {
|
||||
return (window->io.last[key] & 0x80) && !(window->io.current[key] & 0x80);
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
|
115
src/openwindow.h
115
src/openwindow.h
|
@ -1,11 +1,18 @@
|
|||
#ifndef _OPEN_WINDOW_H_
|
||||
#define _OPEN_WINDOW_H_
|
||||
|
||||
#define WINDOW_DEFAULT_FPS 60
|
||||
|
||||
#define WINDOW_KEY_COUNT 256
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../deps/include/glad/glad.h"
|
||||
int gladLoadGL(void);
|
||||
|
||||
#include "GL/gl.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
|
@ -28,21 +35,53 @@ typedef struct {
|
|||
long eventMask;
|
||||
} X11;
|
||||
|
||||
typedef struct {
|
||||
char current[WINDOW_KEY_COUNT];
|
||||
char last[WINDOW_KEY_COUNT];
|
||||
} WindowIOState;
|
||||
|
||||
typedef struct Window Window;
|
||||
typedef void(* WindowEventHandler)(Window * w, XEvent xev);
|
||||
typedef void(* WindowEventHandler)(Window * window, XEvent event);
|
||||
|
||||
typedef struct Window {
|
||||
WindowIOState io;
|
||||
GLX glx;
|
||||
X11 x;
|
||||
WindowEventHandler eventHandler;
|
||||
bool close;
|
||||
uint32_t fps;
|
||||
} Window;
|
||||
|
||||
Window openWindow(const char * name, size_t width, size_t height);
|
||||
void windowDraw(Window window);
|
||||
void windowSetEventHandler(Window * window, WindowEventHandler handler);
|
||||
void windowHandleEvents(Window * window);
|
||||
void closeWindow(Window w);
|
||||
#define WINDOW_KEY_Q ("q")
|
||||
#define WINDOW_KEY_W ("w")
|
||||
#define WINDOW_KEY_E ("e")
|
||||
#define WINDOW_KEY_R ("r")
|
||||
#define WINDOW_KEY_T ("t")
|
||||
#define WINDOW_KEY_Y ("y")
|
||||
#define WINDOW_KEY_U ("u")
|
||||
#define WINDOW_KEY_I ("i")
|
||||
#define WINDOW_KEY_O ("o")
|
||||
#define WINDOW_KEY_P ("p")
|
||||
#define WINDOW_KEY_A ("a")
|
||||
#define WINDOW_KEY_S ("s")
|
||||
#define WINDOW_KEY_D ("d")
|
||||
#define WINDOW_KEY_F ("f")
|
||||
#define WINDOW_KEY_G ("g")
|
||||
#define WINDOW_KEY_H ("h")
|
||||
#define WINDOW_KEY_J ("j")
|
||||
#define WINDOW_KEY_K ("k")
|
||||
#define WINDOW_KEY_L ("l")
|
||||
#define WINDOW_KEY_Z ("z")
|
||||
#define WINDOW_KEY_X ("x")
|
||||
#define WINDOW_KEY_C ("c")
|
||||
#define WINDOW_KEY_V ("v")
|
||||
#define WINDOW_KEY_B ("b")
|
||||
#define WINDOW_KEY_N ("n")
|
||||
#define WINDOW_KEY_M ("m")
|
||||
|
||||
#define WINDOW_KEY_ESC ("Escape")
|
||||
|
||||
bool windowKeyPressed(Window * window, char * key);
|
||||
bool windowKeyReleased(Window * window, char * key);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -55,24 +94,66 @@ typedef struct {
|
|||
HGLRC context;
|
||||
} WGL;
|
||||
|
||||
typedef struct {
|
||||
BYTE current[WINDOW_KEY_COUNT];
|
||||
BYTE last[WINDOW_KEY_COUNT];
|
||||
} WindowIOState;
|
||||
|
||||
typedef struct Window Window;
|
||||
typedef void(* WindowEventHandler)(Window * window, unsigned int event, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
typedef struct Window {
|
||||
WindowIOState io;
|
||||
WGL wgl;
|
||||
//WindowEventHandler eventHandler;
|
||||
bool close;
|
||||
WindowEventHandler eventHandler;
|
||||
uint32_t fps;
|
||||
} Window;
|
||||
|
||||
Window openWindow(const char * name, size_t width, size_t height);
|
||||
void windowDraw(Window window);
|
||||
void windowHandleEvents(Window * window);
|
||||
void closeWindow(Window w);
|
||||
#define WINDOW_KEY_Q ('Q')
|
||||
#define WINDOW_KEY_W ('W')
|
||||
#define WINDOW_KEY_E ('E')
|
||||
#define WINDOW_KEY_R ('R')
|
||||
#define WINDOW_KEY_T ('T')
|
||||
#define WINDOW_KEY_Y ('Y')
|
||||
#define WINDOW_KEY_U ('U')
|
||||
#define WINDOW_KEY_I ('I')
|
||||
#define WINDOW_KEY_O ('O')
|
||||
#define WINDOW_KEY_P ('P')
|
||||
#define WINDOW_KEY_A ('A')
|
||||
#define WINDOW_KEY_S ('S')
|
||||
#define WINDOW_KEY_D ('D')
|
||||
#define WINDOW_KEY_F ('F')
|
||||
#define WINDOW_KEY_G ('G')
|
||||
#define WINDOW_KEY_H ('H')
|
||||
#define WINDOW_KEY_J ('J')
|
||||
#define WINDOW_KEY_K ('K')
|
||||
#define WINDOW_KEY_L ('L')
|
||||
#define WINDOW_KEY_Z ('Z')
|
||||
#define WINDOW_KEY_X ('X')
|
||||
#define WINDOW_KEY_C ('C')
|
||||
#define WINDOW_KEY_V ('V')
|
||||
#define WINDOW_KEY_B ('B')
|
||||
#define WINDOW_KEY_N ('N')
|
||||
#define WINDOW_KEY_M ('M')
|
||||
|
||||
#define WINDOW_KEY_ESC (VK_ESCAPE)
|
||||
|
||||
bool windowKeyPressed(Window * window, int key);
|
||||
bool windowKeyReleased(Window * window, int key);
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
// depends on glad
|
||||
Window * openWindow(const char * name, size_t width, size_t height);
|
||||
void windowSetFps(Window * window, uint32_t fps);
|
||||
void windowDraw(Window * window);
|
||||
void windowSetEventHandler(Window * window, WindowEventHandler handler);
|
||||
void windowHandleEvents(Window * window);
|
||||
void closeWindow(Window * window);
|
||||
|
||||
typedef enum {
|
||||
WindowKeyPress = 0,
|
||||
} WindowEvent;
|
||||
|
||||
int getOpenGLProcs(void);
|
||||
|
||||
#endif // _OPEN_WINDOW_H_
|
||||
|
||||
// TODO: Add all the error handling to the glx
|
||||
|
|
Loading…
Reference in New Issue