diff --git a/CMakeLists.txt b/CMakeLists.txt index f4ff43a..2cfc159 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,10 +21,11 @@ add_library(Airlib SHARED ) if(UNIX AND NOT APPLE) - target_link_libraries(Airlib PRIVATE X11) - target_link_libraries(Airlib PRIVATE pulse-simple) + find_package(GLUT REQUIRED) + find_package(OpenGL REQUIRED) + target_link_libraries(Airlib PRIVATE X11 OpenGL::GL GLUT::GLUT pulse-simple) elseif(WIN32) - target_link_libraries(Airlib winmm) + target_link_libraries(Airlib winmm) target_link_libraries(Airlib opengl32) target_link_libraries(Airlib gdi32 @@ -37,12 +38,9 @@ add_executable(Airlib_test main.c) # Link the Airlib library to the Airlib_test executable target_link_libraries(Airlib_test PRIVATE Airlib) + if (UNIX AND NOT APPLE) - target_link_libraries(Airlib_test PRIVATE X11) - target_link_libraries(Airlib_test - OpenGL::GL - GLUT::GLUT - ) + target_link_libraries(Airlib_test PRIVATE OpenGL::GL GLUT::GLUT X11) endif() #[[ diff --git a/include/video.h b/include/video.h index bf1022d..11b600c 100644 --- a/include/video.h +++ b/include/video.h @@ -4,6 +4,8 @@ /* X11 */ #ifdef __linux__ +#include + #define KEY_ESCAPE 9 #define KEY_SPACEBAR 65 #define KEY_UP 111 @@ -12,9 +14,8 @@ #define KEY_LEFT 113 static Display *d; -static Window w; static XEvent e; -static int s; +static int *s; static GC gc; void axCreateWindow(int width, int height); @@ -22,13 +23,13 @@ void axDrawRect(unsigned long color, int x, int y, int width, int height); void axClearWindow(); int axGetNextEvent(XEvent *event); void axCloseWindow(); -int axGetNextEvent(XEvent *event) +int axGetNextEvent(XEvent *event); #endif /* FreeGLUT (cross-platform) */ -typedef struct Window { +typedef struct CustomWindow { void (*create)(int width, int height, const char* title); void (*pollEvents)(void); void (*swapBuffers)(void); @@ -37,28 +38,9 @@ typedef struct Window { void (*drawButton)(float x, float y, float width, float height, const char* label); void (*destroy)(void); int (*isButtonClicked)(float x, float y, float width, float height); -} Window; +} CustomWindow; -Window* createWindowInstance(void); +CustomWindow* createWindowInstance(void); #endif -/* -Copyright (C) 2024 Ellouze Adam - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ diff --git a/main.c b/main.c index a384a01..d48f031 100644 --- a/main.c +++ b/main.c @@ -1,41 +1,28 @@ -#include #include +#include #include "include/video.h" -static const char* display_text = "yOU ARE A KING !"; - int main(int argc, char** argv) { - glutInit(&argc, argv); - glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); - - Window* window = createWindowInstance(); - window->create(800, 600, "Best game ever"); - - glClearColor(0.0f, 1.0f, 1.0f, 0.0f); + glutInit(&argc, argv); // Initialize FreeGLUT - while (!window->shouldClose()) { - window->pollEvents(); - glClear(GL_COLOR_BUFFER_BIT); + CustomWindow *win = createWindowInstance(); + win->create(800, 600, "Linux GLX Window"); - // Draw button background - glColor3f(0.0,0.0,0.0); - window->drawButton(-0.5f, -0.5f, 1.0f, 0.3f, "BUD"); + while (!win->shouldClose()) { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // Text - glColor3f(0.0f, 0.0f, 1.0f); - window->drawText(-0.2f, -0.4f, "Click Me"); + win->drawText(-0.5f, 0.0f, "Hello, Linux with GLX!"); + win->drawButton(-0.5f, -0.5f, 0.3f, 0.2f, "Click Me"); - // Draw header text in white - glColor3f(0.0f, 0.0f, 1.0f); - window->drawText(-0.8f, 0.8f, display_text); - - if (window->isButtonClicked(-0.5f, -0.5f, 1.0f, 0.3f)) { - display_text = "Hello GLUT!"; + if (win->isButtonClicked(-0.5f, -0.5f, 0.3f, 0.2f)) { + printf("Button was clicked!\n"); } - window->swapBuffers(); + win->swapBuffers(); + win->pollEvents(); } - window->destroy(); + win->destroy(); return 0; } + diff --git a/src/system/Windows/WIN_video.c b/src/system/Windows/WIN_video.c index d6916b9..0c9f9c7 100644 --- a/src/system/Windows/WIN_video.c +++ b/src/system/Windows/WIN_video.c @@ -1,3 +1,5 @@ +#ifdef _WIN32 + #include "../../../include/video.h" #include #include @@ -112,3 +114,5 @@ __declspec(dllexport) Window* createWindowInstance(void) { }; return &window; } + +#endif diff --git a/src/system/gnu_linux/linux_video.c b/src/system/gnu_linux/linux_video.c index c99c496..46ee8ee 100644 --- a/src/system/gnu_linux/linux_video.c +++ b/src/system/gnu_linux/linux_video.c @@ -1,85 +1,122 @@ #include "../../../include/video.h" #include #include +#include -/* X11 */ +#include +#include -#ifdef __linux__ +/* FreeGLUT (native) */ -#include +static Display *display; +static Window xWindow; +static GLXContext glContext; +static int shouldCloseFlag = 0; -static Display *d; -static Window w; -static XEvent e; -static int s; -static GC gc; +static void create(int width, int height, const char* title) { + display = XOpenDisplay(NULL); + if (display == NULL) { + fprintf(stderr, "Cannot open X display\n"); + exit(1); + } -void axCreateWindow(int width, int height) { - d = XOpenDisplay(NULL); - if (d == NULL) { - printf("Cannot open display\n"); + static int visual_attribs[] = { + GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None + }; + int screen = DefaultScreen(display); + XVisualInfo *vi = glXChooseVisual(display, screen, visual_attribs); + if (vi == NULL) { + fprintf(stderr, "No appropriate visual found\n"); exit(1); } - s = DefaultScreen(d); - w = XCreateSimpleWindow(d, RootWindow(d,s), 0, 0, width, height, 1, - BlackPixel(d,s), WhitePixel(d,s)); + Colormap cmap = XCreateColormap(display, RootWindow(display, screen), vi->visual, AllocNone); + XSetWindowAttributes swa; + swa.colormap = cmap; + swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask; - // Enable key press and expose events - XSelectInput(d, w, KeyPressMask | ExposureMask); + xWindow = XCreateWindow(display, RootWindow(display, screen), 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, + CWColormap | CWEventMask, &swa); + XMapWindow(display, xWindow); + XStoreName(display, xWindow, title); - // Create graphics context - gc = DefaultGC(d, s); + glContext = glXCreateContext(display, vi, NULL, GL_TRUE); + glXMakeCurrent(display, xWindow, glContext); - XMapWindow(d, w); - XFlush(d); + glEnable(GL_DEPTH_TEST); } -void axDrawRect(unsigned long color, int x, int y, int width, int height) { - XSetForeground(d, gc, color); - XFillRectangle(d, w, gc, x, y, width, height); - XFlush(d); +static void pollEvents(void) { + XEvent xev; + while (XPending(display) > 0) { + XNextEvent(display, &xev); + if (xev.type == ClientMessage || xev.type == KeyPress) { + shouldCloseFlag = 1; + } else if (xev.type == ButtonPress) { + // Add button click logic here + } + } } -void axClearWindow() { - XClearWindow(d, w); - XFlush(d); +static void swapBuffers(void) { + glXSwapBuffers(display, xWindow); } -int axGetNextEvent(XEvent *event) { - if (XPending(d)) { - XNextEvent(d, event); - return 1; - } - return 0; +static int shouldClose(void) { + return shouldCloseFlag; } -void axCloseWindow() { - XCloseDisplay(d); +static void drawText(float x, float y, const char* text) { + glRasterPos2f(x, y); + while (*text) { + glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *text); + text++; + } } -#endif - -/* FreeGLUT (cross-platform) */ +static void drawButton(float x, float y, float width, float height, const char* label) { + glBegin(GL_QUADS); + glVertex2f(x, y); + glVertex2f(x + width, y); + glVertex2f(x + width, y + height); + glVertex2f(x, y + height); + glEnd(); + drawText(x + width / 10.0f, y + height / 2.0f, label); +} +static int isButtonClicked(float x, float y, float width, float height) { + XEvent xev; + if (XPending(display) > 0) { + XNextEvent(display, &xev); + if (xev.type == ButtonPress) { + int mouseX = xev.xbutton.x; + int mouseY = xev.xbutton.y; + if (mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height) { + return 1; + } + } + } + return 0; +} +static void destroy(void) { + glXMakeCurrent(display, None, NULL); + glXDestroyContext(display, glContext); + XDestroyWindow(display, xWindow); + XCloseDisplay(display); +} -/* -Copyright (C) 2024 Ellouze Adam - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. +CustomWindow* createWindowInstance(void) { + static CustomWindow win = { + .create = create, + .pollEvents = pollEvents, + .swapBuffers = swapBuffers, + .shouldClose = shouldClose, + .drawText = drawText, + .drawButton = drawButton, + .destroy = destroy, + .isButtonClicked = isButtonClicked + }; + return &win; +} -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/