I tried create window with gl 3.3 context, but it's eating cpu and lagging when I try to resize it.
My Code:
#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glxext.h>
#include <GL/glext.h>
struct _WGelWindowX11{
Display *XDspl;
Window XWin;
Colormap XCMap;
GLXContext glContext;
};
typedef struct _WGelWindowX11 WGelWindowX11;
#define WGEL_WINDOWX11(obj) ((WGelWindowX11*)obj)
int aiAttr[]={
GLX_X_RENDERABLE, True,
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_DOUBLEBUFFER, True,
None
};
int aiAttrGL[]={
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
None
};
void *WGelWindowNew(void){
WGelWindowX11 *Result=malloc(sizeof(WGelWindowX11));
Result->XDspl=XOpenDisplay(NULL);
if (!Result->XDspl){
perror("Cannot open display.\n");
return NULL;
}
//Gettin' matchin' framebuffer configuration
int iFBCount;
GLXFBConfig *pFBConf=glXChooseFBConfig(Result->XDspl, DefaultScreen(Result->XDspl), aiAttr, &iFBCount);
if(!pFBConf){
perror("Cannot get FBConfig.\n");
return NULL;
}
int iBestFBC=-1, iWorstFBC=-1, iBestNSampl=-1, iWorstNSampl=999,iSamplBuff, iSampl, i;
for(i=0; i<iFBCount; i++){
XVisualInfo *vi=glXGetVisualFromFBConfig(Result->XDspl, pFBConf[i]);
if (vi){
glXGetFBConfigAttrib(Result->XDspl, pFBConf[i], GLX_SAMPLE_BUFFERS, &iSamplBuff);
glXGetFBConfigAttrib(Result->XDspl, pFBConf[i], GLX_SAMPLES, &iSampl);
if (iBestFBC<0 || iSamplBuff && iSampl>iBestNSampl) iBestFBC=i, iBestNSampl=iSampl;
if (iWorstFBC<0 || !iSamplBuff || iSampl<iWorstNSampl) iWorstFBC=i, iWorstNSampl=iSampl;
}
XFree(vi);
}
GLXFBConfig FBConfBest=pFBConf[iBestFBC];
XFree(pFBConf);
XVisualInfo *XVslnfo=glXGetVisualFromFBConfig(Result->XDspl, FBConfBest);
XSetWindowAttributes XWinAttr;
Result->XCMap=XCreateColormap(Result->XDspl, RootWindow(Result->XDspl, XVslnfo->screen), XVslnfo->visual, AllocNone);
XWinAttr.colormap=Result->XCMap;
XWinAttr.background_pixmap=None;
XWinAttr.border_pixel=0;
XWinAttr.event_mask=StructureNotifyMask|ExposureMask|KeyPressMask;
Atom wmDeleteMessage=XInternAtom(Result->XDspl, "WM_DELETE_WINDOW", FALSE);
Result->XWin=XCreateWindow(Result->XDspl, RootWindow(Result->XDspl, XVslnfo->screen), 0, 0, 300, 300, 0, XVslnfo->depth, InputOutput, XVslnfo->visual, CWBorderPixel|CWColormap|CWEventMask, &XWinAttr);
if(!Result->XWin){
perror("Cannot create window.\n");
return NULL;
}
XFree(XVslnfo);
XStoreName(Result->XDspl, Result->XWin, "WGel Window" );
XSetWMProtocols(Result->XDspl, Result->XWin, &wmDeleteMessage, 1);
XMapWindow(Result->XDspl, Result->XWin);
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs=(PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((GLubyte*)"glXCreateContextAttribsARB");
Result->glContext=glXCreateContextAttribs(Result->XDspl, FBConfBest, 0, True, aiAttrGL);
if(!Result->glContext){
perror("Cannot create GL 3.3 context\n");
return NULL;
}
glXMakeCurrent(Result->XDspl, Result->XWin, Result->glContext);
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
return (void*)Result;}
Display *WGelX11GetDisplay(ptr window){
return WGEL_WINDOWX11(window)->XDspl;}
Window *WGelX11GetWindow(ptr window){
return &(WGEL_WINDOWX11(window)->XWin);
}
int main(void){
ptr frmMain=WGelWindowNew();
Display *dpy=WGelX11GetDisplay(frmMain);
XEvent e;
while(XNextEvent(dpy, &e)>=0){
if ((!XPending(dpy))&&(e.type==Expose)){
glClear(GL_COLOR_BUFFER_BIT);
glXSwapBuffers(dpy, *WGelX11GetWindow(frmMain));
}
if (e.type==ClientMessage){
XDestroyWindow(dpy, e.xclient.window);
break;
}
}
XCloseDisplay(dpy);
return EXIT_SUCCESS;}
GTK+ windows are not lagging that hard when I resize them, so I suppose there should be a way to get rid of that lagging.
Firstly, you have to ignore all Expose event and handle only the last one.
You can do like :
XNextEvent(dpy, &e);
switch (e.type)
{
case Expose:
/* Unless this is the last contiguous expose,
* don’t draw the window */
if (e.xexpose.count == 0)
{
// DRAW THINGS
}
break;
case ClientMessage:
XDestroyWindow(dpy, e.xclient.window);
break;
default:
break;
}
For better handling of Resizing, you have to catch the ConfigureNotify event.
Probably the same reason as I wrote about here: Is there a way to change ConfigureNotify event frequency in X11?
The basic fix: do not repaint at every resize event, your mouse generates events a lot faster than you can repaint the screen.
Related
I'm having trouble getting my image to display using SDL. I've checked the file path, made sure the image dimensions are compatible with the window size, and verified that the image is not NULL, but it still won't show up. I've been trying to debug this for hours and I'm at a loss. Can someone please take a look at my code and help me figure out what I'm missing? Here's the relevant code:
game.c:
#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "header/game.h"
#include "header/constant.h"
SDL_Rect position, positionPlayer;
// Game.c
void game(/*SDL_Window* window, */SDL_Renderer* renderer){
SDL_Texture *bomber[4]={NULL};
SDL_Texture *bomberCurrent=NULL;
positionPlayer.x=33;
positionPlayer.y=33;
SDL_Event event;
int runningGame=1;
int i=0/*, j=0*/;
bomber[DOWN]=IMG_LoadTexture(renderer,"playerPink1.png");
if (!bomber[DOWN]) {
printf("Error loading image: %s\n", SDL_GetError());
return;
}
int w, h;
SDL_QueryTexture(bomber[DOWN], NULL, NULL, &w, &h);
if (w > 952 || h > 442) {
printf("Error: Image size is larger than window size\n");
return;
}
bomberCurrent = bomber[DOWN];
while(runningGame){
SDL_WaitEvent(&event); // Bloque l'exécution du programme jusqu
while(SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
runningGame = 0;
}
}
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
position.x=positionPlayer.x*TAILLE_BLOC;
position.y=positionPlayer.y*TAILLE_BLOC;
SDL_RenderCopy(renderer,bomberCurrent,NULL,&position);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
for(i=0;i<4;i++){
SDL_DestroyTexture(bomber[i]);
}
}
game.h:
#ifndef CONSTANT_H_INCLUDED
#define CONSTANT_H_INCLUDED
#define TAILLE_BLOC 34
enum{UP,DOWN,LEFT,RIGHT};
enum{VIDE,WALL,BOMBER};
#endif
main.c:
#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "header/game.h"
int main(){
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Texture *menu = NULL;
SDL_Event event;
SDL_Surface *icon;
int runningGame=1;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("Etna Bomber", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 952, 442, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, 0);
icon = IMG_Load("src/favicon.bmp");
SDL_SetWindowIcon(window, icon);
menu = IMG_LoadTexture(renderer, "src/menu.png");
SDL_FreeSurface(icon);
while(runningGame){
SDL_WaitEvent(&event);
switch(event.type){
case SDL_QUIT:
runningGame=0;
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym) {
case SDLK_ESCAPE:
runningGame=0;
break;
case SDLK_SPACE:
game(/*window,*/renderer);
default:
break;
}
break;
}
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, menu, NULL, NULL);
SDL_RenderPresent(renderer);
}
SDL_DestroyTexture(menu);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;
}
constant.h:
#ifndef CONSTANT_H_INCLUDED
#define CONSTANT_H_INCLUDED
#define TAILLE_BLOC 34
enum{UP,DOWN,LEFT,RIGHT};
enum{VIDE,WALL,BOMBER};
#endif
I tried using the SDL_QueryTexture function to check if the dimensions of the image were compatible with the dimensions of the window, and also verified that the image was not NULL after loading it using IMG_LoadTexture. I was expecting the image to be displayed on the window at the specified position, but it is not showing up. I also tried various other methods such as checking the file path and making sure the image is in the correct format, but the problem persists.
when i start the code i get warning: incorrect audio format
i figured out its related to the mp3 file.
whats the problem and how can i fix it?
i already tried to convert the mp3 to a wav file but that also didnt work.
is it possible that 3mb of mp3 is to big? shouldnt be?
Edit: when i let it run without of mp3 the wav files will run just fine
with mp3 the programm will start but no sound at all
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h>
static const int width = 800;
static const int height = 600;
int main(int argc, char **argv)
{
// Initialize SDL video and audio systems
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
// Initialize SDL mixer
Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 3, 2048);
// Load audio files
Mix_Music *backgroundSound = Mix_LoadMUS("portfolio.mp3");
Mix_Chunk *jumpEffect = Mix_LoadWAV("JumpEffect.wav");
Mix_Chunk *laserEffect = Mix_LoadWAV("LaserEffect.wav");
//Mix_Chunk *musicEffect = Mix_LoadWAV("portfolio2.wav");
// Create a SDL window
SDL_Window *window = SDL_CreateWindow("Hello, SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL);
// Create a renderer (accelerated and in sync with the display refresh rate)
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
// Start the background music
Mix_PlayMusic(backgroundSound, -1);
bool running = true;
SDL_Event event;
while(running)
{
// Process events
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
running = false;
}
else if(event.type == SDL_KEYDOWN)
{
// Press "1" and play jump effect
if(event.key.keysym.sym == SDLK_1)
{
Mix_PlayChannel(-1, jumpEffect, 0);
}
// Press "2" and play laser effect
else if(event.key.keysym.sym == SDLK_2)
{
Mix_PlayChannel(-1, laserEffect, 0);
}
}
}
// Clear screen
SDL_RenderClear(renderer);
// Draw
// Show what was drawn
SDL_RenderPresent(renderer);
}
// Release resources
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
Mix_FreeMusic(backgroundSound);
Mix_FreeChunk(jumpEffect);
Mix_FreeChunk(laserEffect);
//Mix_FreeChunk(music);
Mix_CloseAudio();
SDL_Quit();
return 0;
}
I can only get events after the window has moved, not while it is moving.
I want to get moving events in real time. Please,what should I do?
#include <X11/X.h>
#include <X11/Xlib.h>
#include <stdio.h>
int main(int argv, char **agrc)
{
Display *dpy = XOpenDisplay(NULL);
Window w = XCreateSimpleWindow(dpy, RootWindow(dpy, DefaultScreen(dpy)), 10, 10, 800, 400, 1, BlackPixel(dpy, DefaultScreen(dpy)), WhitePixel(dpy, DefaultScreen(dpy)));
XSelectInput(dpy, w, StructureNotifyMask);
XMapWindow(dpy, w);
XEvent event;
for (;;)
{
XNextEvent(dpy, &event);
if(event.type == ConfigureNotify)
{
XConfigureEvent x = event.xconfigure;
printf("config[%d]{%d,%d,%d,%d}\n", x.window, x.x, x.y, x.width, x.height);
}
}
XDestroyWindow(dpy, w);
XCloseDisplay(dpy);
return 0;
}
I would like to open a "dock type" window without its title bar with x11 in C and I want to capture a key press (Ctrl-q) to close it. The actual code does not capture the key presses to the active window as they are all sent and printed in the terminal. Almost all the Ctrl key presses are somehow not detected. The only key presses that actually work on the opened window are Ctrl-c. I am aware of the _MOTIF_WM_HINTS property but it has the disadvantage to display a window icon in the panel to show a new opened window.
How can I have a "dock type" window while not losing the ability to detect key presses to the active window?
Here is the code basically copied from two other posts here and here
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
int main(int argc, char **argv)
{
Display *dpy = XOpenDisplay(0);
int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
200, 100, 0, blackColor, blackColor);
//Tell X Server to send MapNotify events
XSelectInput(dpy, w, StructureNotifyMask | KeyPressMask);
Atom window_type = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
long value = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
XChangeProperty(dpy, w, window_type, 4, 32,
PropModeReplace,
(unsigned char *)&value, 1);
//Make window appear
XMapWindow(dpy, w);
//Graphics Context
GC gc = XCreateGC(dpy, w, 0, 0);
//Set white color for drawing
XSetForeground(dpy, gc, whiteColor);
//Wait for the MapNotify event
for(;;) {
XEvent e;
XNextEvent(dpy, &e);
if (e.type == MapNotify) {
break;
}
}
//Draw the line
XDrawLine(dpy, w, gc, 10, 60, 180, 20);
//Send the "DrawLine" request to the server
XFlush(dpy);
char text[255];
XEvent e;
KeySym key;
int numKeys = 0;
for(;;) {
XNextEvent(dpy, &e);
if(e.type == KeyPress) {
if((numKeys = XLookupString(&e.xkey, text, 255, &key, 0))) {
if(e.xkey.state == ControlMask && key == XK_q) {
printf("CTRL-Q\n");
break;
}
}
}
}
if (dpy && gc) XFreeGC(dpy, gc);
if (dpy && w) XDestroyWindow(dpy, w);
if (dpy) XCloseDisplay(dpy);
return 0;
}
Compiled with:
gcc main.c -L/usr/X11R6/lib -lX11 -lm && ./a.out
I've also looked at the _NET_WM_STRUT_PARTIAL property but I haven't been succesful at implementing it.
I am designing an app that having the ID of an X11 window to draw a rectangle.
The problem I have is that I can not draw nothing in the window.
Code
One obvious error is that you did not select ExposureMask in call to XSelectInput, so you will not receive Expose event you are waiting for.
Other possible problem is not setting foreground drawing color of the GC by XSetForegroundColor, default is black. And using default gc of screen may fail if the window has different color depth or different visual. Other important GC attributes issubwindow_mode (whether to draw over child windows).
Still, after I did those changes, the program only works for me (draws a rectangle) on root window and xev, but not for xterm, no expose events.
This is my fixed version:
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main (int argc, char *argv[]){
Window win;
Display *display;
XEvent e;
display = XOpenDisplay(NULL);
if(display==NULL){
fprintf(stderr,"Cannot open Display\n");
exit(1);
}
int s = DefaultScreen(display);
//unsigned long *id = (unsigned long*)(argv[1]);
sscanf(argv[1], "0x%x", &win);
if(!XSelectInput(display,win,StructureNotifyMask | ExposureMask)){
fprintf(stderr,"Cannot select Display\n");
return -1;
}
if(!XMapWindow(display,win)){
fprintf(stderr,"Cannot map Display\n");
return -1;
}
XGCValues gcv;
gcv.subwindow_mode = IncludeInferiors;
GC gc = XCreateGC(display, win, GCSubwindowMode,
&gcv);
XSetForeground(display, gc, 0xff00ff00);
XSetPlaneMask(display, gc, 0xffffffff);
while (1) {
puts("waiting for event\n");
XNextEvent(display, &e);
puts("got event\n");
if (e.type == Expose) {
printf("drawing\n");
XFillRectangle(display, win, gc, 20, 20, 100, 100);
}
if (e.type == KeyPress)
break;
}
return 0;
}