>>55142
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/extensions/xf86vmode.h> //libxxf86vm-dev libXxf86vm.a
#include <GL/glx.h>
#include <GL/gl.h>
#include <X11/X.h>
#include <X11/keysym.h>
#include "../Common/ErrorLog.h"
static int snglBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 16, None};
static int dblBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None};
Display *dpy;
Window win;
XVisualInfo *vi;
Colormap cmap;
XSetWindowAttributes swa;
GLXContext cx;
XF86VidModeModeInfo desktopMode;
int screen;
bool doubleBuffer = true;
bool fullscreen = false;
void fatalError(const char *message)
{
fprintf(stderr, "main: %s\n", message);
Log(LOG_ERROR,"Fatal error: %s\n", message);
exit(1);
}
void InitGL()
{
int dummy;
dpy = XOpenDisplay(NULL);
if (dpy == NULL)
fatalError("could not open display");
if(!glXQueryExtension(dpy, &dummy, &dummy))
fatalError("X server has no OpenGL GLX extension");
vi = glXChooseVisual(dpy, DefaultScreen(dpy), dblBuf);
if (vi == NULL)
{
vi = glXChooseVisual(dpy, DefaultScreen(dpy), snglBuf);
if (vi == NULL) fatalError("no RGB visual with double buffer");
doubleBuffer = GL_FALSE;
Log(LOG_ERROR,"Error: unable to set double buffer\n");
}
if(vi->c_class != TrueColor)
fatalError("TrueColor visual required for this program");
cx = glXCreateContext(dpy, vi,None,GL_TRUE);
if (cx == NULL)
fatalError("could not create rendering context");
cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
swa.colormap = cmap;
swa.border_pixel = 0;
swa.event_mask = KeyPressMask | ExposureMask
| KeyReleaseMask | StructureNotifyMask;
}
typedef struct{
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long inputMode;
unsigned long status;
} Hints;
bool InitFullScreen(int &width,int &height)
{
InitGL();
XF86VidModeModeInfo **modes;
int modeNum, bestMode;
int vmMajor, vmMinor;
bestMode = -1;
screen = DefaultScreen(dpy);
XF86VidModeQueryVersion(dpy, &vmMajor, &vmMinor);
Log(LOG_NORMAL,"XF86 VideoMode extension version %d.%d\n", vmMajor, vmMinor);
XF86VidModeGetAllModeLines(dpy, screen, &modeNum, &modes);
desktopMode = *modes[0];
for (int i = 0; i < modeNum; i++)
{
if ((modes[i]->hdisplay == width) && (modes[i]->vdisplay == height))
bestMode = i;
}
if(bestMode==-1)
{
Log(LOG_WARNING,"Unable to change resolution. Aviable modes:\n");
LogInc();
for (int i = 0; i < modeNum; i++)
Log(LOG_NORMAL,"%dx%d\n", modes[i]->hdisplay, modes[i]->vdisplay);
LogDec();
bestMode=0;
Log(LOG_WARNING,"Chosen resolution %dx%d\n\n", modes[bestMode]->hdisplay, modes[bestMode]->vdisplay);
}
XF86VidModeSwitchToMode(dpy, screen, modes[bestMode]);
XF86VidModeSetViewPort(dpy, screen, 0, 0);
fullscreen=GL_TRUE;
width = modes[bestMode]->hdisplay;
height = modes[bestMode]->vdisplay;
XFree(modes);
win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0,
width, height, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask |CWOverrideRedirect, &swa);
XSizeHints *size_hints;
size_hints=XAllocSizeHints();
if(size_hints!=NULL)
{
size_hints->flags= USPosition | PAspect | PMinSize | PMaxSize;
size_hints->min_width=width;
size_hints->min_height=height;
size_hints->max_width=width;
size_hints->max_height=height;
XSetWMNormalHints(dpy,
win,
size_hints
);
}
Hints hints;
Atom property;
hints.flags = 2; // Specify that we're changing the window decorations.
hints.decorations = 0; // 0 (false) means that window decorations should go bye-bye.
property = XInternAtom(dpy,"_MOTIF_WM_HINTS",true);
XChangeProperty(dpy,win,property,property,32,PropModeReplace,(unsigned char *)&hints,5);
glXMakeCurrent(dpy, win, cx);
XMapWindow(dpy, win);
XGrabPointer(dpy,win,True,0,GrabModeAsync,GrabModeAsync,win,0L,CurrentTime);
XGrabKeyboard(dpy,win,False,GrabModeAsync,GrabModeAsync,CurrentTime);
//Hide cursor
Cursor invisibleCursor;
Pixmap bitmapNoData;
XColor black;
static char noData[] = { 0,0,0,0,0,0,0,0 };
black.red = black.green = black.blue = 0;
bitmapNoData = XCreateBitmapFromData(dpy, win, noData, 8, 8);
invisibleCursor = XCreatePixmapCursor(dpy, bitmapNoData, bitmapNoData,
&black, &black, 0, 0);
XDefineCursor(dpy,win, invisibleCursor);
XFreeCursor(dpy, invisibleCursor);
return true;
}
bool InitWindowed(int x,int y,int width,int height)
{
InitGL();
win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), x, y,
width, height, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask, &swa);
XSetStandardProperties(dpy, win, APP_NAME, APP_NAME, None,
0, 0, NULL);
XSizeHints *size_hints;
size_hints=XAllocSizeHints();
if(size_hints!=NULL)
{
size_hints->flags= USPosition | PAspect | PMinSize | PMaxSize;
size_hints->min_width=width;
size_hints->min_height=height;
size_hints->max_width=width;
size_hints->max_height=height;
XSetWMNormalHints(dpy,
win,
size_hints
);
}
glXMakeCurrent(dpy, win, cx);
XMapWindow(dpy, win);
return true;
}
void ReleaseGL()
{
if( cx )
{
if( !glXMakeCurrent(dpy, None, NULL))
{
printf("Could not release drawing context.\n");
}
glXDestroyContext(dpy, cx);
cx = NULL;
}
if( fullscreen )
{
XF86VidModeSwitchToMode(dpy, screen, &desktopMode);
XF86VidModeSetViewPort(dpy, screen, 0, 0);
XUndefineCursor(dpy, win);
}
XCloseDisplay(dpy);
}
bool DispatchMessages()
{
XEvent event;
while(XPending(dpy))
{
XNextEvent(dpy, &event);
switch (event.type)
{
case KeyPress:
{
KeySym key=XLookupKeysym(&event.xkey, 0);
if(key == (KeySym)XK_Escape)
return false;
ButtonDown(key);
}
break;
case KeyRelease:
{
bool is_retriggered = false;
if (XEventsQueued(dpy, QueuedAfterReading))
{
XEvent nev;
XPeekEvent(dpy, &nev);
if (nev.type == KeyPress &&
nev.xkey.keycode == event.xkey.keycode) //&& nev.xkey.time == event.xkey.time
{
// Key wasn’t actually released
is_retriggered=true;
// delete retriggered KeyPress event
XNextEvent (dpy, &event);
}
}
if(!is_retriggered)
{
KeySym key=XLookupKeysym(&event.xkey, 0);
ButtonUp(key);
}
}
break;
}
}
return true;
}
void UpdateFrame()
{
// if (doubleBuffer)
glXSwapBuffers(dpy, win);/* buffer swap does implicit glFlush */
// else
// glFlush(); /* explicit flush for single buffered case */
}