i am following an example in a book and i have a drawing function that draws lines. when i place it just before the event loop before XFlush() no lines are drawn but if i place it in the eventloop like below the lines are drawn.
while(1)
{
XNextEvent(display, &report);
if (report.type == Expose)
{
draw_lines(win1, gca, 300, 200);
}
}
can anyone explain to me why this is happening? thanks much. why does it matter whether i place the function in the event loop or not?
Something seems to have changed in xlib. Look at my answer to this question and the others it references.
You can do the draws and flush first, then wait for the expose event with:
/* catch expose events */
XSelectInput(display, win, ExposureMask);
/* wait for the expose event */
XEvent ev;
XNextEvent(display, &ev);
Related
So i have this simple code that draws a small window using X11
int main(int, char*[])
{
Display* display = XOpenDisplay(NULL);
Window window = XCreateSimpleWindow(
display, XDefaultRootWindow(display),
100, 100, 200, 200, 4, 0, 0);
XEvent event;
XMapWindow(display, window);
XSelectInput(display, window, KeyPressMask | ButtonPressMask | ExposureMask);
while (True) {
XNextEvent(display, &event);
}
return 0;
}
Everything works fine, the window its drawed without problems.
The thing is i really want to understand how X11 works so im reading the source code of the headers but im unable to find the difinition for XMapWindow() i need help.
This was the only similutede i could find in the Xlib.h header file.
extern int XMapWindow(
Display* /* display */,
Window /* w */
);
You can find the implementation of XMapWindow() in the libX11 sources, specifically in src/MapWindow.c:XMapWindow().
It boils down to some locking, and a _XGetRequest(dpy, X_MapWindow, SIZEOF(xResourceReq)) call. That is defined in src/XlibInt.c:_XGetRequest(), and as you can guess by the name, adds the X_MapWindow request to the request queue sent to the X server.
How the X server (which manages the actual display) acts on that, is up to that X server implementation.
I am a beginner at OpenGL and I am trying to create a game in which as background I have a raw image. When the game starts I display that image and I want to be able to click on it and to display another image afterwards. I tried using the function glutMouseFunc but when I try to run the program I receive a message which says that the program stopped working.
Here are some parts of my code: I have a global variable onMouse; if I click the mouse button the variable takes the value 1 and if it has the value 1 I try to load the second image.
int onMouse;
void mouseClicks(int button, int state, int x, int y) {
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
onMouse = 1;
}
}
And this is the main function:
//load first texture
texture = LoadTextureRAW( "2 Lock screen.raw", TRUE );
glutMouseFunc(mouseClicks);
if(onMouse == 1){
//load second texture
texture = LoadTextureRAW( "in_game.raw", TRUE );
}
What am I doing wrong?
EDIT I have made some changes to the code, but the background image still doesn't change. Here is the new main function:
glutCreateWindow("Game");
texture = LoadTextureRAW( "2 Lock screen.raw", 1 );
glutDisplayFunc(display);
glutMouseFunc(mouseClicks);
glutKeyboardFunc(key);
glutMainLoop();
if(onMouse == 1){
texture = LoadTextureRAW( "in_game.raw", 2 );
glutDisplayFunc(display);
}
And this is the display function in which I map the texture to a quad:
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
glClear( GL_COLOR_BUFFER_BIT );
// setup texture mapping
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, texture );
glPushMatrix();
glBegin( GL_QUADS );
glTexCoord2d(1.0,0.0); glVertex3d(1.0,1.0, 1.0);
glTexCoord2d(0.0,0.0); glVertex3d(-1.0,1.0,1.0);
glTexCoord2d(0.0,1.0); glVertex3d(-1.0,-1.0, -1.0);
glTexCoord2d(1.0,1.0); glVertex3d(1.0,-1.0, 1.0);
glEnd();
glPopMatrix();
glutSwapBuffers();
// free the texture
FreeTexture( texture );
You have the order wrong.
glutMouseFunc(mouseClicks);
Here you register the function to be called when the mouse is clicked.
if(onMouse == 1) {
You immediately check if the mouse had been clicked. It's impossible for the mouse to have been clicked in the brief period between these two lines, and glutMainLoop hasn't been entered yet so your program didn't even have a chance to listen for mouse events.
As for the crash, I can't help you debug it with just the code you have provided. Please try a debugger and find which line causes the crash.
What am I doing wrong?
You're expecting glutMouseFunc to wait for a mouse click. This is not how GLUT works (GLUT is not part of OpenGL BTW). Another callback to be registered is the drawing function (usually called display in GLUT based programs).
Once you enter the GLUT main loop (glutMainLoop() call) user events are processed and if a redisplay is requested the display function is called.
So here's what you do (in simplified pseudocode)
// Define bitmasks for mouse status, we assume mice have less than 17 buttons
#define MB_LEFT 0
#define MB_MIDDLE 1
#define MB_RIGHT 2
#define LMB_PRESSED (1<<0)
#define MMB_PRESSED (1<<1)
#define RMB_PRESSED (1<<2)
#define LMB_CLICKED (1<<16)
#define MMB_CLICKED (1<<17)
#define RMB_CLICKED (1<<18)
#define MB_PRESSED(state, button) (1<<(button))
#define MB_CLICKED(state, button) (1<<((button)+16)))
#define MB_MASK_PRESSED 0x0000ffffL
#define MB_MASK_CLICKED 0xffff0000L
uint32_t mouse_status = 0;
void onMouseButton(int button, int state, int x, int y)
{
int b;
switch(button) {
case GLUT_LEFT_BUTTON: b=MB_LEFT; break;
case GLUT_MIDDLE_BUTTON: b=MB_MIDDLE; break;
case GLUT_RIGHT_BUTTON: b=MB_RIGHT; break;
}
if(mouse_status & MB_PRESSED(b) && GLUT_UP == state) {
mouse_status |= MB_CLICKED(b);
}
if( !(mouse_status & MB_PRESSED(b)) && GLUT_DOWN == state) {
mouse_status = (mouse_status & ~(0L | MB_CLICKED(b))) | MB_PRESSED(b);
}
glutPostRedisplay();
}
void display(void)
{
if(mouse_status & MB_CLICKED(MB_LEFT)) {
/* do something */
…
/* clear the click flag */
mouse_status &= ~MB_MASK_CLICKED;
}
}
int main(…)
{
…
glutCreateWindow(…);
glutDisplayFunc(display);
glutMouseFunc(onMouseButton);
glutMainLoop();
}
You can of course use any other kind of structure you like to pass the mouse button status between program parts. I prefer bitmasks for such. Other people may prefer arrays (personally I don't like arrays for tasks like this, because they're not as easy to look at in a debugger than a simple bitfield).
glutMouseFunc registers a callback: a function to be called on specific events (here mouse events). These events are collected by glutMainLoop, which has not been called yet when you test onMouse.
Another thing, though I cannot tell for sure from the small code excerpt you provide, is that you'd better load the assets from the start of the programme, rather than wait for a user event to do it. Load them first, and simply change texture to whichever id correspond to the texture you wish to display then.
I want to create 2 windows in linux that I'll later draw in from a separate thread. I currently have a non-deterministic bug where the second window that I create sometimes doesn't get created (no errors though).
Here is the code.
static void create_x_window(Display *display, Window *win, int width, int height)
{
int screen_num = DefaultScreen(display);
unsigned long background = WhitePixel(display, screen_num);
unsigned long border = BlackPixel(display, screen_num);
*win = XCreateSimpleWindow(display, DefaultRootWindow(display), /* display, parent */
0,0, /* x, y */
width, height, /* width, height */
2, border, /* border width & colour */
background); /* background colour */
XSelectInput(display, *win, ButtonPressMask|StructureNotifyMask);
XMapWindow(display, *win);
}
int main(void) {
XInitThreads(); // prevent threaded XIO errors
local_display = XOpenDisplay(":0.0");
Window self_win, remote_win;
XEvent self_event, remote_event;
create_x_window(local_display, &remote_win, 640,480);
// this line flushes buffer and blocks so that the window doesn't crash for a reason i dont know yet
XNextEvent(local_display, &remote_event);
create_x_window(local_display, &self_win, 320, 240);
// this line flushes buffer and blocks so that the window doesn't crash for a reason i dont know yet
XNextEvent(local_display, &self_event);
while (1) {
}
return 0;
}
I don't really care for capturing input in the windows, but I found a tutorial that had XSelectInput and XNextEvent (in an event loop) and I was having trouble making this work without either.
It's not a bug, it's a feature. You left out the event loop.
Although you cleverly called XNextEvent twice, the X protocol is asynchronous so the server may still be setting up the actual window while you call XNextEvent, so there is nothing to do.
Tutorial here.
In my opengl program, I want to make the screen turn red when a user hits a certain key. In my my_keyboard function, I have the following:
void my_keyboard( unsigned char key, int x, int y ) {
int feedback_code=0;
if (key == 49) {
feedback_code=1;
}
if (feedback_code==1) {
flash_screen();
}
My flash_screen method is as follows:
void screen_flash() {
float mat[16];
glGetFloatv(GL_MODELVIEW_MATRIX,mat);
glColor3f(1.0f,0.0f,0.0f);
glBegin(GL_POLYGON);
glVertex2f(0.0f, 0.0f);
glVertex2f(0.0f, 640.0f);
glVertex2f(888.0f, 640.f);
glVertex2f(888.0f, 0.0f);
glEnd();
}
By the glGetFloatv call, I know that my transformation matrix is back at the lower left corner where it should be, at point (0,0). So the draw function should draw a red square 888x640px, the size of my window. When I run the program and hit the '1' key, however, I don't get a shape! I've used breakpoints and determined that the GlBegin-GlEnd statements DO run, they just don't seem to produce anything.
The only other shapes I have are done in my main display function, called before the main_loop starts.
What am I doing wrong?
It's a common newbie mistake. So here's the general rule: Never make OpenGL drawing calls from event handlers. Never!
When you want something on the screen happen in reaction to a input event, set some flag variables, and signal a redraw. Then in the drawing function draw according to the signal.
I have to monitor the X11 Clipboard.
For the moment, I request the ClipBoard Selection each 5 seconds, then I hash the text returned from clipboard and I compare it with the hash calculate from the last check. If hash are not the same, I analysis the text content and do some stuff...
I don't like my method. I'm from Windows, and with the winapi, it is the kernel that notify your program when the clipboard has changed, and it's more efficient!
I just want to know if it is possible that X11 can notify your program as winapi when the clipboard has changed ? What is the more efficient way to check clipboard modifications with X11 ?
Use XFixesSelectSelectionInput() from Xfixes extension and wait for XFixesSelectionNotify event.
Example:
// gcc -o xclipwatch xclipwatch.c -lX11 -lXfixes
...
#include <X11/extensions/Xfixes.h>
...
void WatchSelection(Display *display, Window window, const char *bufname)
{
int event_base, error_base;
XEvent event;
Atom bufid = XInternAtom(display, bufname, False);
assert( XFixesQueryExtension(display, &event_base, &error_base) );
XFixesSelectSelectionInput(display, DefaultRootWindow(display), bufid, XFixesSetSelectionOwnerNotifyMask);
while (True)
{
XNextEvent(display, &event);
if (event.type == event_base + XFixesSelectionNotify &&
((XFixesSelectionNotifyEvent*)&event)->selection == bufid)
{
if (!PrintSelection(display, window, bufname, "UTF8_STRING"))
PrintSelection(display, window, bufname, "STRING");
fflush(stdout);
}
}
}
...
This works both for bufname == "CLIPBOARD" and bufname == "PRIMARY" selection.
Also see PrintSelection() function in this answer.
Find window with selection using GetSelectionOwner (PRIMARY and CLIPBOARD)
get copy of selection by sending SelectionRequest, notify your application
watch for SelectionClear event
update window with selection using id from SelectionClear event, goto step 2
The accepted answer from x11user is a good one. But you probably want a non-blocking while loop, and for that you can take that answer, and adapt it like this.
// get the internal X11 event file descriptor
int x11fd = ConnectionNumber(display);
while(!shutdown)
{
if(!XPending(display)) {
// wait on the file descriptor
// you can use poll, epoll, select, eventfd, etc.
}
XNextEvent(display, &event);
// process the event
}