607 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			607 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
/*
 | 
						|
 * Mr. 4th Dimention - Allen Webster
 | 
						|
 *
 | 
						|
 * 14.11.2015
 | 
						|
 *
 | 
						|
 * Linux layer for project codename "4ed"
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
// TOP
 | 
						|
 | 
						|
#include "4ed_config.h"
 | 
						|
 | 
						|
#include "4ed_meta.h"
 | 
						|
 | 
						|
#define FCPP_FORBID_MALLOC
 | 
						|
 | 
						|
#include "4cpp_types.h"
 | 
						|
#define FCPP_STRING_IMPLEMENTATION
 | 
						|
#include "4coder_string.h"
 | 
						|
 | 
						|
#include "4ed_mem.cpp"
 | 
						|
#include "4ed_math.cpp"
 | 
						|
 | 
						|
#include "4coder_custom.h"
 | 
						|
#include "4ed_system.h"
 | 
						|
#include "4ed_rendering.h"
 | 
						|
#include "4ed.h"
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <memory.h>
 | 
						|
#include <math.h>
 | 
						|
#include <sys/ioctl.h>
 | 
						|
#include <sys/time.h>
 | 
						|
#include <sys/types.h>
 | 
						|
#include <sys/stat.h>
 | 
						|
#include <dirent.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <X11/Xlib.h>
 | 
						|
#include <GL/glx.h>
 | 
						|
#include <xmmintrin.h>
 | 
						|
#include <linux/fs.h>
 | 
						|
#include <X11/extensions/XInput2.h>
 | 
						|
#include <linux/input.h>
 | 
						|
#include <time.h>
 | 
						|
 | 
						|
#include "4ed_internal.h"
 | 
						|
#include "4ed_linux_keyboard.cpp"
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
void*
 | 
						|
LinuxGetMemory(i32 size){
 | 
						|
    // TODO(allen): Implement without stdlib.h
 | 
						|
    return (malloc(size));
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
LinuxFreeMemory(void *block){
 | 
						|
    // TODO(allen): Implement without stdlib.h
 | 
						|
    free(block);
 | 
						|
}
 | 
						|
 | 
						|
#if (defined(_BSD_SOURCE) || defined(_SVID_SOURCE))
 | 
						|
#define TimeBySt
 | 
						|
#endif
 | 
						|
#if (_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
 | 
						|
#define TimeBySt
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef TimeBySt
 | 
						|
#define nano_mtime_field st_mtim.tv_nsec
 | 
						|
#undef TimeBySt
 | 
						|
#else
 | 
						|
#define nano_mtime_field st_mtimensec
 | 
						|
#endif
 | 
						|
 | 
						|
Sys_File_Time_Stamp_Sig(system_file_time_stamp){
 | 
						|
    struct stat info;
 | 
						|
    i64 nanosecond_timestamp;
 | 
						|
    u64 result;
 | 
						|
    
 | 
						|
    stat(filename, &info);
 | 
						|
    nanosecond_timestamp = info.nano_mtime_field;
 | 
						|
    if (nanosecond_timestamp != 0){
 | 
						|
        result = (u64)(nanosecond_timestamp / 1000);
 | 
						|
    }
 | 
						|
    else{
 | 
						|
        result = (u64)(info.st_mtime * 1000000);
 | 
						|
    }
 | 
						|
 | 
						|
    return(result);
 | 
						|
}
 | 
						|
 | 
						|
Sys_Time_Sig(system_time){
 | 
						|
    struct timespec spec;
 | 
						|
    u64 result;
 | 
						|
    
 | 
						|
    clock_gettime(CLOCK_MONOTONIC, &spec);
 | 
						|
    result = (spec.tv_sec * 1000000) + (spec.tv_nsec / 1000);
 | 
						|
 | 
						|
    return(result);
 | 
						|
}
 | 
						|
 | 
						|
Sys_Set_File_List_Sig(system_set_file_list){
 | 
						|
    DIR *d;
 | 
						|
    struct dirent *entry;
 | 
						|
    char *fname, *cursor, *cursor_start;
 | 
						|
    File_Info *info_ptr;
 | 
						|
    i32 count, file_count, size, required_size;
 | 
						|
    
 | 
						|
    terminate_with_null(&directory);
 | 
						|
    d = opendir(directory.str);
 | 
						|
    if (d){
 | 
						|
        count = 0;
 | 
						|
        for (entry = readdir(d);
 | 
						|
             entry != 0;
 | 
						|
             entry = readdir(d)){
 | 
						|
            fname = entry->d_name;
 | 
						|
            ++file_count;            
 | 
						|
            for (size = 0; fname[size]; ++size);
 | 
						|
            count += size + 1;
 | 
						|
        }
 | 
						|
        closedir(d);
 | 
						|
 | 
						|
        required_size = count + file_count * sizeof(File_Info);
 | 
						|
        if (file_list->block_size < required_size){
 | 
						|
            if (file_list->block){
 | 
						|
                LinuxFreeMemory(file_list->block);
 | 
						|
            }
 | 
						|
            file_list->block = LinuxGetMemory(required_size);
 | 
						|
        }
 | 
						|
        
 | 
						|
        file_list->infos = (File_Info*)file_list->block;
 | 
						|
        cursor = (char*)(file_list->infos + file_count);
 | 
						|
        
 | 
						|
        d = opendir(directory.str);
 | 
						|
        if (d){
 | 
						|
            info_ptr = file_list->infos;
 | 
						|
            for (entry = readdir(d);
 | 
						|
                 entry != 0;
 | 
						|
                 entry = readdir(d), ++info_ptr){
 | 
						|
                fname = entry->d_name;
 | 
						|
                cursor_start = cursor;
 | 
						|
                for (; *fname; ) *cursor++ = *fname++;
 | 
						|
                *cursor++ = 0;
 | 
						|
                
 | 
						|
                info_ptr->folder = 0;
 | 
						|
                info_ptr->filename.str = cursor_start;
 | 
						|
                info_ptr->filename.size = (i32)(cursor - cursor_start);
 | 
						|
                info_ptr->filename.memory_size = info_ptr->filename.size + 1;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        closedir(d);
 | 
						|
    }
 | 
						|
    closedir(d);
 | 
						|
}
 | 
						|
 | 
						|
Sys_Post_Clipboard_Sig(system_post_clipboard){
 | 
						|
    // TODO(allen): Implement
 | 
						|
    AllowLocal(str);
 | 
						|
}
 | 
						|
 | 
						|
// NOTE(allen): Thanks to Casey for providing the linux OpenGL launcher.
 | 
						|
static bool ctxErrorOccurred = false;
 | 
						|
static int XInput2OpCode = 0;
 | 
						|
internal int
 | 
						|
ctxErrorHandler( Display *dpy, XErrorEvent *ev )
 | 
						|
{
 | 
						|
    ctxErrorOccurred = true;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
internal GLXContext
 | 
						|
InitializeOpenGLContext(Display *XDisplay, Window XWindow, GLXFBConfig &bestFbc, b32 &IsLegacy)
 | 
						|
{
 | 
						|
    IsLegacy = false;
 | 
						|
    
 | 
						|
    typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
 | 
						|
    const char *glxExts = glXQueryExtensionsString(XDisplay, DefaultScreen(XDisplay));
 | 
						|
    
 | 
						|
    glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
 | 
						|
    glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
 | 
						|
        glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
 | 
						|
 
 | 
						|
    GLXContext ctx = 0;
 | 
						|
    ctxErrorOccurred = false;
 | 
						|
    int (*oldHandler)(Display*, XErrorEvent*) =
 | 
						|
        XSetErrorHandler(&ctxErrorHandler);
 | 
						|
    if (!glXCreateContextAttribsARB)
 | 
						|
    {
 | 
						|
        printf( "glXCreateContextAttribsARB() not found"
 | 
						|
                " ... using old-style GLX context\n" );
 | 
						|
        ctx = glXCreateNewContext( XDisplay, bestFbc, GLX_RGBA_TYPE, 0, True );
 | 
						|
    } 
 | 
						|
    else
 | 
						|
    {
 | 
						|
        int context_attribs[] =
 | 
						|
        {
 | 
						|
            GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
 | 
						|
            GLX_CONTEXT_MINOR_VERSION_ARB, 3,
 | 
						|
            //GLX_CONTEXT_FLAGS_ARB        , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
 | 
						|
            None
 | 
						|
        };
 | 
						|
 | 
						|
        printf("\nAttribs: %d %d %d %d %d\n",
 | 
						|
               context_attribs[0],
 | 
						|
               context_attribs[1],
 | 
						|
               context_attribs[2],
 | 
						|
               context_attribs[3],
 | 
						|
               context_attribs[4]);
 | 
						|
 
 | 
						|
        printf( "Creating context\n" );
 | 
						|
        ctx = glXCreateContextAttribsARB( XDisplay, bestFbc, 0,
 | 
						|
                                          True, context_attribs );
 | 
						|
 
 | 
						|
        XSync( XDisplay, False );
 | 
						|
        if ( !ctxErrorOccurred && ctx )
 | 
						|
        {
 | 
						|
            printf( "Created GL 4.3 context\n" );
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            ctxErrorOccurred = false;
 | 
						|
 | 
						|
            context_attribs[1] = 4;
 | 
						|
            context_attribs[3] = 0;
 | 
						|
 
 | 
						|
            printf( "Creating context\n" );
 | 
						|
            ctx = glXCreateContextAttribsARB( XDisplay, bestFbc, 0,
 | 
						|
                                              True, context_attribs );
 | 
						|
 
 | 
						|
            XSync( XDisplay, False );
 | 
						|
 | 
						|
            if ( !ctxErrorOccurred && ctx )
 | 
						|
            {
 | 
						|
                printf( "Created GL 4.0 context\n" );
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                context_attribs[1] = 1;
 | 
						|
                context_attribs[3] = 0;
 | 
						|
 
 | 
						|
                ctxErrorOccurred = false;
 | 
						|
 
 | 
						|
                printf( "Failed to create GL 4.0 context"
 | 
						|
                        " ... using old-style GLX context\n" );
 | 
						|
                ctx = glXCreateContextAttribsARB( XDisplay, bestFbc, 0, 
 | 
						|
                                                  True, context_attribs );
 | 
						|
 | 
						|
                IsLegacy = true;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 
 | 
						|
    XSync( XDisplay, False );
 | 
						|
    XSetErrorHandler( oldHandler );
 | 
						|
 
 | 
						|
    if ( ctxErrorOccurred || !ctx )
 | 
						|
    {
 | 
						|
        printf( "Failed to create an OpenGL context\n" );
 | 
						|
        exit(1);
 | 
						|
    }
 | 
						|
 
 | 
						|
    if ( ! glXIsDirect ( XDisplay, ctx ) )
 | 
						|
    {
 | 
						|
        printf( "Indirect GLX rendering context obtained\n" );
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        printf( "Direct GLX rendering context obtained\n" );
 | 
						|
    }
 | 
						|
  
 | 
						|
    printf( "Making context current\n" );
 | 
						|
    glXMakeCurrent( XDisplay, XWindow, ctx );
 | 
						|
 | 
						|
    GLint n;
 | 
						|
    char *Vendor = (char *)glGetString(GL_VENDOR);
 | 
						|
    char *Renderer = (char *)glGetString(GL_RENDERER);
 | 
						|
    char *Version = (char *)glGetString(GL_VERSION);
 | 
						|
    char *Extensions = (char *)glGetString(GL_EXTENSIONS);
 | 
						|
 | 
						|
    printf("GL_VENDOR: %s\n", Vendor);
 | 
						|
    printf("GL_RENDERER: %s\n", Renderer);
 | 
						|
    printf("GL_VERSION: %s\n", Version);
 | 
						|
    printf("GL_EXTENSIONS: %s\n", Extensions);
 | 
						|
 | 
						|
    return(ctx);
 | 
						|
}
 | 
						|
 | 
						|
internal b32
 | 
						|
GLXSupportsModernContexts(Display *XDisplay)
 | 
						|
{
 | 
						|
    b32 Result = false;
 | 
						|
    
 | 
						|
    int GLXMajor, GLXMinor;
 | 
						|
 | 
						|
    char *XVendor = ServerVendor(XDisplay);
 | 
						|
    printf("XWindows vendor: %s\n", XVendor);
 | 
						|
    if(glXQueryVersion(XDisplay, &GLXMajor, &GLXMinor))
 | 
						|
    {
 | 
						|
        printf("GLX version %d.%d\n", GLXMajor, GLXMinor);
 | 
						|
        if(((GLXMajor == 1 ) && (GLXMinor >= 3)) ||
 | 
						|
           (GLXMajor > 1))
 | 
						|
        {
 | 
						|
            Result = true;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return(Result);
 | 
						|
}
 | 
						|
 | 
						|
typedef struct glx_config_result{
 | 
						|
    b32 Found;
 | 
						|
    GLXFBConfig BestConfig;
 | 
						|
    XVisualInfo BestInfo;
 | 
						|
} glx_config_result;
 | 
						|
 | 
						|
internal glx_config_result
 | 
						|
ChooseGLXConfig(Display *XDisplay, int XScreenIndex)
 | 
						|
{
 | 
						|
    glx_config_result Result = {0};
 | 
						|
    
 | 
						|
    int DesiredAttributes[] =
 | 
						|
    {
 | 
						|
        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 ConfigCount;
 | 
						|
        GLXFBConfig *Configs = glXChooseFBConfig(XDisplay,
 | 
						|
                                                 XScreenIndex,
 | 
						|
                                                 DesiredAttributes,
 | 
						|
                                                 &ConfigCount);
 | 
						|
 | 
						|
#if 0
 | 
						|
        int DiffValues[GLXValueCount];
 | 
						|
#endif
 | 
						|
        {for(int ConfigIndex = 0;
 | 
						|
             ConfigIndex < ConfigCount;
 | 
						|
             ++ConfigIndex)
 | 
						|
        {
 | 
						|
            GLXFBConfig &Config = Configs[ConfigIndex];
 | 
						|
            XVisualInfo *VisualInfo = glXGetVisualFromFBConfig(XDisplay, Config);
 | 
						|
 | 
						|
#if 0
 | 
						|
            printf("  Option %d:\n", ConfigIndex);
 | 
						|
            printf("    Depth: %d\n", VisualInfo->depth);
 | 
						|
            printf("    Bits per channel: %d\n", VisualInfo->bits_per_rgb);
 | 
						|
            printf("    Mask: R%06x G%06x B%06x\n",
 | 
						|
                   (uint32)VisualInfo->red_mask,
 | 
						|
                   (uint32)VisualInfo->green_mask,
 | 
						|
                   (uint32)VisualInfo->blue_mask);
 | 
						|
            printf("    Class: %d\n", VisualInfo->c_class);
 | 
						|
#endif
 | 
						|
            
 | 
						|
#if 0
 | 
						|
            {for(int ValueIndex = 0;
 | 
						|
                 ValueIndex < GLXValueCount;
 | 
						|
                 ++ValueIndex)
 | 
						|
            {
 | 
						|
                glx_value_info &ValueInfo = GLXValues[ValueIndex];
 | 
						|
                int Value;
 | 
						|
                glXGetFBConfigAttrib(XDisplay, Config, ValueInfo.ID, &Value);
 | 
						|
                if(DiffValues[ValueIndex] != Value)
 | 
						|
                {
 | 
						|
                    printf("    %s: %d\n", ValueInfo.Name, Value);
 | 
						|
                    DiffValues[ValueIndex] = Value;
 | 
						|
                }
 | 
						|
            }}
 | 
						|
#endif
 | 
						|
            
 | 
						|
            // TODO(casey): How the hell are you supposed to pick a config here??
 | 
						|
            if(ConfigIndex == 0)
 | 
						|
            {
 | 
						|
                Result.Found = true;
 | 
						|
                Result.BestConfig = Config;
 | 
						|
                Result.BestInfo = *VisualInfo;
 | 
						|
            }
 | 
						|
                        
 | 
						|
            XFree(VisualInfo);
 | 
						|
        }}
 | 
						|
                    
 | 
						|
        XFree(Configs);
 | 
						|
    }
 | 
						|
 | 
						|
    return(Result);
 | 
						|
}
 | 
						|
 | 
						|
internal void
 | 
						|
InitializeXInput(Display *dpy, Window XWindow)
 | 
						|
{
 | 
						|
    int event, error;
 | 
						|
    if(XQueryExtension(dpy, "XInputExtension", &XInput2OpCode, &event, &error))
 | 
						|
    {
 | 
						|
        int major = 2, minor = 0;
 | 
						|
        if(XIQueryVersion(dpy, &major, &minor) != BadRequest)
 | 
						|
        {
 | 
						|
            printf("XInput initialized");
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            printf("XI2 not available. Server supports %d.%d\n", major, minor);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        printf("X Input extension not available.\n");
 | 
						|
    }
 | 
						|
 | 
						|
    /*
 | 
						|
      TODO(casey): So, this is all one big clusterfuck I guess.
 | 
						|
 | 
						|
      The problem here is that you want to be able to get input
 | 
						|
      from all possible devices that could be a mouse or keyboard
 | 
						|
      (or gamepad, or whatever).  So you'd like to be able to
 | 
						|
      register events for XIAllDevices, so that when a new
 | 
						|
      input device is connected, you will start receiving
 | 
						|
      input from it automatically, without having to periodically
 | 
						|
      poll XIQueryDevice to see if a new device has appeared.
 | 
						|
 | 
						|
      UNFORTUNATELY, this is not actually possible in Linux because
 | 
						|
      there was a bug in Xorg (as of early 2013, it is still not
 | 
						|
      fixed in most distributions people are using, AFAICT) which
 | 
						|
      makes the XServer return an error if you actually try to
 | 
						|
      do this :(
 | 
						|
 | 
						|
      But EVENTUALLY, if that shit gets fixed, then that is
 | 
						|
      the way this should work.
 | 
						|
    */
 | 
						|
 | 
						|
#if 0
 | 
						|
    int DeviceCount;
 | 
						|
    XIDeviceInfo *DeviceInfo = XIQueryDevice(dpy, XIAllDevices, &DeviceCount);
 | 
						|
    {for(int32x DeviceIndex = 0;
 | 
						|
         DeviceIndex < DeviceCount;
 | 
						|
         ++DeviceIndex)
 | 
						|
    {
 | 
						|
        XIDeviceInfo *Device = DeviceInfo + DeviceIndex;
 | 
						|
        printf("Device %d: %s\n", Device->deviceid, Device->name);
 | 
						|
    }}
 | 
						|
    XIFreeDeviceInfo(DeviceInfo);
 | 
						|
#endif
 | 
						|
    
 | 
						|
    XIEventMask Mask = {0};
 | 
						|
    Mask.deviceid = XIAllDevices;
 | 
						|
    Mask.mask_len = XIMaskLen(XI_RawMotion);
 | 
						|
    size_t MaskSize = Mask.mask_len * sizeof(char unsigned);
 | 
						|
    Mask.mask = (char unsigned *)alloca(MaskSize);
 | 
						|
    memset(Mask.mask, 0, MaskSize);
 | 
						|
    if(Mask.mask)
 | 
						|
    {
 | 
						|
        XISetMask(Mask.mask, XI_ButtonPress);
 | 
						|
        XISetMask(Mask.mask, XI_ButtonRelease);
 | 
						|
        XISetMask(Mask.mask, XI_KeyPress);
 | 
						|
        XISetMask(Mask.mask, XI_KeyRelease);
 | 
						|
        XISetMask(Mask.mask, XI_Motion);
 | 
						|
        XISetMask(Mask.mask, XI_DeviceChanged);
 | 
						|
        XISetMask(Mask.mask, XI_Enter);
 | 
						|
        XISetMask(Mask.mask, XI_Leave);
 | 
						|
        XISetMask(Mask.mask, XI_FocusIn);
 | 
						|
        XISetMask(Mask.mask, XI_FocusOut);
 | 
						|
        XISetMask(Mask.mask, XI_HierarchyChanged);
 | 
						|
        XISetMask(Mask.mask, XI_PropertyEvent);
 | 
						|
        XISelectEvents(dpy, XWindow, &Mask, 1);
 | 
						|
        XSync(dpy, False);
 | 
						|
 | 
						|
        Mask.deviceid = XIAllMasterDevices;
 | 
						|
        memset(Mask.mask, 0, MaskSize);
 | 
						|
        XISetMask(Mask.mask, XI_RawKeyPress);
 | 
						|
        XISetMask(Mask.mask, XI_RawKeyRelease);
 | 
						|
        XISetMask(Mask.mask, XI_RawButtonPress);
 | 
						|
        XISetMask(Mask.mask, XI_RawButtonRelease);
 | 
						|
        XISetMask(Mask.mask, XI_RawMotion);
 | 
						|
        XISelectEvents(dpy, DefaultRootWindow(dpy), &Mask, 1);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
main(int ArgCount, char **Args)
 | 
						|
{
 | 
						|
    Display *XDisplay = XOpenDisplay(0);
 | 
						|
    if(XDisplay && GLXSupportsModernContexts(XDisplay))
 | 
						|
    {
 | 
						|
        int XScreenCount = ScreenCount(XDisplay);
 | 
						|
        for(int XScreenIndex = 0;
 | 
						|
            XScreenIndex < XScreenCount;
 | 
						|
            ++XScreenIndex)
 | 
						|
        {                
 | 
						|
            Screen *XScreen = ScreenOfDisplay(XDisplay, XScreenIndex);
 | 
						|
                
 | 
						|
            int WinWidth = WidthOfScreen(XScreen);
 | 
						|
            int WinHeight = HeightOfScreen(XScreen);
 | 
						|
                                
 | 
						|
            glx_config_result Config = ChooseGLXConfig(XDisplay, XScreenIndex);
 | 
						|
            if(Config.Found)
 | 
						|
            {
 | 
						|
                Colormap cmap;
 | 
						|
                XSetWindowAttributes swa;
 | 
						|
                swa.colormap = cmap = XCreateColormap(XDisplay,
 | 
						|
                                                      RootWindow(XDisplay, Config.BestInfo.screen ), 
 | 
						|
                                                      Config.BestInfo.visual, AllocNone);
 | 
						|
                swa.background_pixmap = None;
 | 
						|
                swa.border_pixel = 0;
 | 
						|
                swa.event_mask = StructureNotifyMask;
 | 
						|
 
 | 
						|
                Window XWindow = XCreateWindow(XDisplay,
 | 
						|
                                               RootWindow(XDisplay, Config.BestInfo.screen),
 | 
						|
                                               0, 0, WinWidth, WinHeight,
 | 
						|
                                               0, Config.BestInfo.depth, InputOutput, 
 | 
						|
                                               Config.BestInfo.visual, 
 | 
						|
                                               CWBorderPixel|CWColormap|CWEventMask, &swa );
 | 
						|
                if(XWindow)
 | 
						|
                {
 | 
						|
                    XStoreName(XDisplay, XWindow, "4coder");
 | 
						|
                    XMapWindow(XDisplay, XWindow);
 | 
						|
 | 
						|
                    InitializeXInput(XDisplay, XWindow);
 | 
						|
 | 
						|
                    b32 IsLegacy = false;
 | 
						|
                    GLXContext GLContext =
 | 
						|
                        InitializeOpenGLContext(XDisplay, XWindow, Config.BestConfig, IsLegacy);
 | 
						|
 | 
						|
                    XWindowAttributes WinAttribs;
 | 
						|
                    if(XGetWindowAttributes(XDisplay, XWindow, &WinAttribs))
 | 
						|
                    {
 | 
						|
                        WinWidth = WinAttribs.width;
 | 
						|
                        WinHeight = WinAttribs.height;
 | 
						|
                    }
 | 
						|
                    
 | 
						|
                    XRaiseWindow(XDisplay, XWindow);
 | 
						|
                    XSync(XDisplay, False);
 | 
						|
 | 
						|
                    for(;;)
 | 
						|
                    {
 | 
						|
                        while(XPending(XDisplay))
 | 
						|
                        {
 | 
						|
                            XEvent Event;                    
 | 
						|
                            XNextEvent(XDisplay, &Event);
 | 
						|
 | 
						|
                            if((Event.xcookie.type == GenericEvent) &&
 | 
						|
                               (Event.xcookie.extension == XInput2OpCode) &&
 | 
						|
                               XGetEventData(XDisplay, &Event.xcookie))
 | 
						|
                            {
 | 
						|
                                switch(Event.xcookie.evtype)
 | 
						|
                                {
 | 
						|
                                    case XI_Motion:
 | 
						|
                                    {
 | 
						|
                                        Window root_return, child_return;
 | 
						|
                                        int root_x_return, root_y_return;
 | 
						|
                                        int MouseX, MouseY;
 | 
						|
                                        unsigned int mask_return;
 | 
						|
                                        XQueryPointer(XDisplay,
 | 
						|
                                                      XWindow,
 | 
						|
                                                      &root_return, &child_return,
 | 
						|
                                                      &root_x_return, &root_y_return,
 | 
						|
                                                      &MouseX, &MouseY,
 | 
						|
                                                      &mask_return);
 | 
						|
                                    } break;
 | 
						|
 | 
						|
                                    case XI_ButtonPress:
 | 
						|
                                    case XI_ButtonRelease:
 | 
						|
                                    {
 | 
						|
                                        b32 Down = (Event.xcookie.evtype == XI_ButtonPress);
 | 
						|
                                        XIDeviceEvent *DevEvent = (XIDeviceEvent *)Event.xcookie.data;
 | 
						|
                                        int Button = DevEvent->detail;
 | 
						|
                                    } break;
 | 
						|
 | 
						|
                                    case XI_KeyPress:
 | 
						|
                                    case XI_KeyRelease:
 | 
						|
                                    {
 | 
						|
                                        b32 Down = (Event.xcookie.evtype == XI_KeyPress); 
 | 
						|
                                        XIDeviceEvent *DevEvent = (XIDeviceEvent *)Event.xcookie.data;
 | 
						|
                                        int VK = DevEvent->detail;
 | 
						|
                                    } break;
 | 
						|
                                }
 | 
						|
 | 
						|
                                XFreeEventData(XDisplay, &Event.xcookie);
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                        
 | 
						|
                        // Draw some stuff here?
 | 
						|
                        
 | 
						|
                        glXSwapBuffers(XDisplay, XWindow);                    
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
// BOTTOM
 | 
						|
 |