Can't set video mode for SDL screen on embedded device - c

I've been hacking away on an ARM based device (Freescale i.MX27 ADS) with a built-in screen for the past few days. The device is running a modified, minimal GNU/Linux system, with no window management or graphical server. By default, the device is only supposed to run the one application that came with it.
I've never done any graphical programming before, so this is a learning experience for me. I tried writing a simple SDL program to run on the device, which would read a bitmap, and display the image on the embedded device's screen.
The problem I'm having is that no matter what resolution, depth, or flags I try, the video mode always fails to apply, and I get nothing.
I know my code isn't the problem, but I'm going to post it anyway.
#include "SDL/SDL.h"
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define SCREEN_DEPTH 24
int main(int argc, char *argv[])
{
SDL_Surface *screen;
if(!SDL_Init(SDL_INIT_VIDEO))
{
printf("Unable to initialize SDL.\n");
return 1;
}
// It always fails right here
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_DEPTH, SDL_SWSURFACE);
if(screen == NULL)
{
printf("Unable to set video mode.\n");
return 1;
}
SDL_Surface* image;
SDL_Surface* temp;
temp = SDL_LoadBMP("hello.bmp");
if(temp == NULL)
{
printf("Unable to load bitmap.\n");
return 1;
}
image = SDL_DisplayFormat(temp);
SDL_FreeSurface(temp);
SDL_Rect src, dest;
src.x = 0;
src.y = 0;
src.w = image->w;
src.h = image->h;
dest.x = 100;
dest.y = 100;
dest.w = image->w;
dest.h = image->h;
SDL_BlitSurface(image, &src, screen, &dest);
printf("Program finished.\n\n");
return 0;
}
From what I can tell, the application that's supposed to run on this device uses Qtopia. Again, I'm new to graphics programming, so I have no idea how one should control graphical output in an embedded environment like this.
Any ideas?

My code was hiding the fact that the problem was with initializing SDL, not setting the video mode. SDL wasn't initializing because my embedded system has no X server, and no mouse. After setting SDL_NOMOUSE, the problem was resolved.

Related

How do I Monitor Mouse Movement Events in All Windows (Not Just One) on X11

I'm trying write an X11 program to monitor all mouse movements on the desktop. The program should be able to receive a notification whenever the mouse is moved by the human user, or moved programmatically via XWarpPointer() by a robotic application. I know it should be possible by setting a PointerMotionMask via XSelectInput() and monitor MotionNotify, but I'm having troubles receiving mouse events from all windows, not just one.
Initially, I just tried to receive pointer motion events from the root window, in the following demo.
#include <stdio.h>
#include <X11/Xlib.h>
int main(int argc, char **argv)
{
Display *display;
Window root_window;
XEvent event;
display = XOpenDisplay(0);
root_window = XRootWindow(display, 0);
XSelectInput(display, root_window, PointerMotionMask);
while (1) {
XNextEvent(display, &event);
switch(event.type) {
case MotionNotify:
printf("x: %d y: %d\n", event.xmotion.x, event.xmotion.y );
break;
}
}
return 0;
}
But it doesn't receive any events, unless the mouse pointer is on an empty desktop background. It's clear that merely receiving events from the root window won't work. Then I tried a workaround: first, set SubstructureNotifyMask on the root window to monitor all CreateNotify events to catch all newly created windows, then call XSelectInput() to enable the PointerMotionMask on these windows.
#include <stdio.h>
#include <X11/Xlib.h>
int main(int argc, char **argv)
{
Display *display;
Window root_window;
XEvent event;
display = XOpenDisplay(0);
root_window = XRootWindow(display, 0);
XSelectInput(display, root_window, SubstructureNotifyMask);
while (1) {
XNextEvent(display, &event);
switch(event.type) {
case CreateNotify:
XSelectInput(display, event.xcreatewindow.window, PointerMotionMask);
break;
case MotionNotify:
printf("x: %d y: %d\n", event.xmotion.x, event.xmotion.y);
break;
}
}
return 0;
}
This approach is more successful, I started to receive some mouse events from new windows. Unfortunately, it still doesn't work in all portions inside a window - for example, it cannot receive mouse events from the console area in terminal emulators, but can receive events when the mouse is located around the title bar. It appears that a window can create more subwindows, so the mouse events won't be recorded.
Then I tried another workaround - set both SubstructureNotifyMask and PointerMotionMask in CreateNotify, so when a window creates a child window, SubstructureNotifyMask ensures more CreateNotify events will be received in a recursive manner, so all child windows will get PointerMotionMask as well.
#include <stdio.h>
#include <X11/Xlib.h>
int main(int argc, char **argv)
{
Display *display;
Window root_window;
XEvent event;
display = XOpenDisplay(0);
root_window = XRootWindow(display, 0);
XSelectInput(display, root_window, SubstructureNotifyMask);
while (1) {
XNextEvent(display, &event);
switch(event.type) {
case CreateNotify:
XSelectInput(display, event.xcreatewindow.window, SubstructureNotifyMask | PointerMotionMask);
break;
case MotionNotify:
printf("x: %d y: %d\n", event.xmotion.x, event.xmotion.y);
break;
}
}
return 0;
}
It works a bit better than the second example, but it's not reliable:
X is fully asynchronous, is it possible that the child window got created before we had a chance to XSelectInput()?
Sometimes it just reports a BadWindow error and crashes.
X event handling becomes messy - if the program already handles a lot of different X events, enabling SubstructureNotifyMask recursively will make many unrelated events delivered to other handlers, and it's a pain to add extra code to discriminate between wanted and unwanted events.
So, how do I monitor mouse movement events in all windows on X11?
After doing some research, especially reading the source code of Xeyes (I always fell the demo is stupid, but it helps a lot here!), I found:
Calling XSelectInput() on all the windows and subwindows is a futile attempt, you have to set a mask on every single window and child window ever created, it's not a robust solution, and not recommended.
Instead, it's better to just continuously pulling the mouse pointer from the X server explicitly via XQueryPointer(), rather than asking the X server to push MotionEvent to us.
One naive solution is simply setting up a timer by XtAppAddTimeOut() and calling XQueryPointer() periodically, it works, and indeed, it was what Xeyes did in the past! But it unnecessarily wastes CPU time. Nowadays, the best practice is to take advantage of XInputExtention 2.0. The workflow is:
Initialize XInput v2.0
Enable various masks via XISetMask() and XIEventMask() to receive XI_RawMotion events (or XI_Motion, see notes below) from XIAllMasterDevices (or XIAllDevices).
When a XI_RawMotion (or XI_Motion) event has been received, call XQueryPointer().
XQueryPointer() returns:
Mouse coordinates with respect to the root window.
The active window under the mouse cursor, if any.
Perform a XTranslateCoordinates() if we want relative coordinates with respect to the active window under the mouse cursor.
Demo
Here's a demo (save as mouse.c, compile with gcc mouse.c -o mouse -lX11 -lXi). However, it cannot detect XWarpPointer(), see notes below.
#include <stdio.h>
#include <assert.h>
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
int main(int argc, char **argv)
{
Display *display;
Window root_window;
/* Initialize (FIXME: no error checking). */
display = XOpenDisplay(0);
root_window = XRootWindow(display, 0);
/* check XInput */
int xi_opcode, event, error;
if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) {
fprintf(stderr, "Error: XInput extension is not supported!\n");
return 1;
}
/* Check XInput 2.0 */
int major = 2;
int minor = 0;
int retval = XIQueryVersion(display, &major, &minor);
if (retval != Success) {
fprintf(stderr, "Error: XInput 2.0 is not supported (ancient X11?)\n");
return 1;
}
/*
* Set mask to receive XI_RawMotion events. Because it's raw,
* XWarpPointer() events are not included, you can use XI_Motion
* instead.
*/
unsigned char mask_bytes[(XI_LASTEVENT + 7) / 8] = {0}; /* must be zeroed! */
XISetMask(mask_bytes, XI_RawMotion);
/* Set mask to receive events from all master devices */
XIEventMask evmasks[1];
/* You can use XIAllDevices for XWarpPointer() */
evmasks[0].deviceid = XIAllMasterDevices;
evmasks[0].mask_len = sizeof(mask_bytes);
evmasks[0].mask = mask_bytes;
XISelectEvents(display, root_window, evmasks, 1);
XEvent xevent;
while (1) {
XNextEvent(display, &xevent);
if (xevent.xcookie.type != GenericEvent || xevent.xcookie.extension != xi_opcode) {
/* not an XInput event */
continue;
}
XGetEventData(display, &xevent.xcookie);
if (xevent.xcookie.evtype != XI_RawMotion) {
/*
* Not an XI_RawMotion event (you may want to detect
* XI_Motion as well, see comments above).
*/
XFreeEventData(display, &xevent.xcookie);
continue;
}
XFreeEventData(display, &xevent.xcookie);
Window root_return, child_return;
int root_x_return, root_y_return;
int win_x_return, win_y_return;
unsigned int mask_return;
/*
* We need:
* child_return - the active window under the cursor
* win_{x,y}_return - pointer coordinate with respect to root window
*/
int retval = XQueryPointer(display, root_window, &root_return, &child_return,
&root_x_return, &root_y_return,
&win_x_return, &win_y_return,
&mask_return);
if (!retval) {
/* pointer is not in the same screen, ignore */
continue;
}
/* We used root window as its reference, so both should be the same */
assert(root_x_return == win_x_return);
assert(root_y_return == win_y_return);
printf("root: x %d y %d\n", root_x_return, root_y_return);
if (child_return) {
int local_x, local_y;
XTranslateCoordinates(display, root_window, child_return,
root_x_return, root_y_return,
&local_x, &local_y, &child_return);
printf("local: x %d y %d\n\n", local_x, local_y);
}
}
XCloseDisplay(display);
return 0;
}
Sample Output
root: x 631 y 334
local: x 140 y 251
root: x 628 y 338
local: x 137 y 255
root: x 619 y 343
local: x 128 y 260
XWarpPointer() Troubles
The demo above doesn't work if the pointer is moved via XWarpPointer() by a robotic application on newer systems after X.Org 1.10.4. This is intentional, see Bug 30068 on FreeDesktop.
In order to receive mouse events triggered by all mouse movements, including XWarpPointer(), change XI_RawMotion to XI_Motion, and change XIAllMasterDevices to XIAllDevices.
References
This demo lacks error checking and may contain bugs. If in doubts, please check the following authoritative references.
Tracking Cursor Position by Keith Packard, a real X expert, has been heavily involved in the development of X since the late 1980s, and responsible for many X extensions and technical papers.
Xeyes source code from X.Org.

SDL2 CreateTextureFromSurface slow down

im doing a graphic interface in SDL2 but if i create the renderer with the flags SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC i get a notable slowdown in comparation with the flag SDL_RENDERER_SOFTWARE what i think shouldn't be possible.
I can't use SDL_RENDERER_SOFTWARE because i need enable VSYNC for avoid the tearing and i need double buffer for that.
Actually i realize that the bottleneck is with the function SDL_CreateTextureFromSurface().
Like my code is pretty big i'll try to explain it instead of past everything here:
Initialize SDL and create a SDL_Surface named screen_surface with SDL_CreateRGBSurface with the same size than my window where ill blit any other surface.
I draw a big square in the middle of that surface with SDL_FillRect and draw a rack inside that square using two times SDL_FillRect for draw two squares, one 2 pixels more big than the next one and like that simulate a empty square (i know i can do the same with SDL_RenderDrawRect but i think is more optimal draw in a surface instead of the Render) for every cell of the rack until i have 4096 cells;
now using SDL_TTF i write info in each cell for that i use TTF_RenderUTF8_Blended for get a surface for each cell and i use SDL_BlitSurface for 'fusion' this surfaces with the screen_surface
And finally i want to go through the big square illuminating the cells that are being cheked for that i use SDL_FillRect for draw a little square that travel throught the rack.
Finally i use the SDL_CreateTextureFromSurface for transform screen_surface in screen_texture followed for SDL_RenderCopy and SDL_RenderPresent
This five steps are inside of the main while with the event management and following the recomendations in the SDL_API i do SDL_RenderClear each loop for redraw everything another time.
Said all this how i said at the begining i realise that the bottleneck is step 5 independent from the another steps because if i take the steps 2 and 3 and i do them before the while leaving inside the while only the creation of the rack illumination on a black window (cause im not drawing anything) i get the same slowdown. Only if i manage to draw things without use textures the velocity increase notably.
There are my questions:
Why could this happening? Teorically use double buffering shouldn't be faster than use Software Renderer?
There is any form to simulate vsync in Software Renderer?
Can i Render a Surface without build a Texture?
PD: I have read a bunch of post around the internet and im gonna answer some typical questions: i reutilize the screen_surface, i can't reutilize the surface that TTF returns, im creating and destroying the texture each loop (cause i think i can not reutilize it).
I let here my code
int main(int ac, char **av)
{
t_data data;
init_data(&data) /* initialize SDL */
ft_ini_font(data); /* Initialize TTF */
ft_ini_interface(data);
main_loop(&data);
ft_quit_graphics(data); /* Close SDL and TTF */
free(data);
return (0);
}
void main_loop(t_data *data)
{
while (data->running)
{
events(data);
SDL_BlitSurface(data->rack_surface, NULL, data->screen_surface, &(SDL_Rect){data->rack_x, data->rack_y, data->rack_w, data->rack_h}); /* Insert the rack in the screen_surface */
ft_write_info(data);
ft_illum_celd(data);
set_back_to_front(data);
}
}
void ft_ini_interface(t_data *data)
{
data->screen_surface = SDL_CreateRGBSurface(0, data->w, data->h, 32, RED_MASK, GREEN_MASK, BLUE_MASK, ALPHA_MASK)
...
/* stuff for calculate rack dims */
...
data->rack_surface = generate_rack_surface(data);
}
void generate_rack_surface(t_data *data)
{
int i;
int j;
int k;
data->rack_surface = SDL_CreateRGBSurface(0, data->rack_w, data->rack_h, 32, RED_MASK, GREEN_MASK, BLUE_MASK, ALPHA_MASK);
SDL_FillRect(Graph->rack, NULL, 0x3D3D33FF);
...
/* ini i, j, k for drawn the rack properly */
...
while (all cells not drawn)
{
if (k && !i)
{
data->celd_y += Graph->data->celd_h - 1;
data->celd_x = 0;
k--;
}
SDL_FillRect(data->rack, &(SDL_Rect){data->celd_x - 1, data->celd_y - 1, data->celd_w + 2, data->celd_h + 2}, 0x1C1C15FF))
SDL_FillRect(data->rack, &(SDL_Rect){data->celd_x, data->celd_y, data->celd_w, data->celd_h}, 0x3D3D33FF)
data->celd_x += data->celd_w - 1;
i--;
}
}
void ft_write_info(t_data *data)
{
SDL_Color color;
char *info;
while (all info not written)
{
color = take_color(); /*take the color of the info (only 4 ifs) */
info = take_info(data); /*take info from a source using malloc*/
surf_byte = TTF_RenderUTF8_Blended(data->font, info, color);
...
/*stuf for take the correct possition in the rack */
...
SDL_BlitSurface(surf_byte, NULL, Graph->screen.screen, &(SDL_Rect){data->info_x, data->info_y, data->celd.w, data->celd.h});
SDL_FreeSurface(surf_byte);
free(info);
}
void ft_illum_celd(t_data *data)
{
int color;
SDL_Rect illum;
illum = next_illum(data) /* return a SDL_Rect with the position of the info being read */
SDL_FillRect(data->screen_surface, &pc, color);
}
void set_back_to_front(t_data *data)
{
SDL_Texture *texture;
texture = SDL_CreateTextureFromSurface(data->Renderer, data->screen_surface);
SDL_RenderCopy(data->Renderer, texture, NULL, NULL);
SDL_DestroyTexture(texture);
SDL_RenderPresent(data->Renderer);
SDL_RenderClear(data->Renderer);
}

X11 Why I can't draw any text?

I'm trying to learn X11. It's very hard to me, because I don't have experience with window applications on Linux.
I wrote some simple code and I can't resolve this not visible text problem.
Everything is working good probably, when I was trying to draw rectangle with DrawRectangle function it was working.
Here is the code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
int main()
{
Display* myDisplay;
Window myWindow;
int myScreen;
GC myGC;
XEvent myEvent;
unsigned long black, white;
char* hello = "Hello world!";
XFontStruct* myFont;
if((myDisplay = XOpenDisplay(NULL)) == NULL)
{
puts("Error in conneting to X Server!");
return -1;
}
myScreen = DefaultScreen(myDisplay);
black = BlackPixel(myDisplay, myScreen);
white = WhitePixel(myDisplay, myScreen);
myWindow = XCreateSimpleWindow(myDisplay, RootWindow(myDisplay, myScreen), 0, 0, 640, 320, 5, black, white);
XSelectInput(myDisplay, myWindow, ExposureMask);
XClearWindow(myDisplay, myWindow);
XMapWindow(myDisplay, myWindow);
myGC = XCreateGC(myDisplay, myWindow, 0, 0);
XSetForeground(myDisplay, myGC, black);
XSetBackground(myDisplay, myGC, white);
myFont = XLoadQueryFont(myDisplay, "-Misc-Fixed-Medium-R-Normal--7-70-75-75-C-50-ISO10646-1");
XSetFont(myDisplay, myGC, myFont->fid);
while(1)
{
XNextEvent(myDisplay, &myEvent);
if(myEvent.type == Expose)
{
XClearWindow(myDisplay, myWindow);
// HERE I DONT KNOW WHY IT DOESNT WORK!
XDrawString(myDisplay, myWindow, myGC, 0, 0, hello, strlen(hello));
}
}
XFreeGC(myDisplay, myGC);
XDestroyWindow(myDisplay, myWindow);
XCloseDisplay(myDisplay);
return 0;
}
Thank you for help!
Your font path argument to XLoadQueryFont is wrong (on my Linux/Debian desktop). Check with the xlsfonts command the right ones (they are all lowercases).
With
myFont = XLoadQueryFont
(myDisplay,
"-misc-fixed-medium-r-normal--9-90-75-75-c-60-iso10646-1");
it could work better. Try also with "lucidasanstypewriter-bold-14"
And most importantly the coordinates passed to XDrawString are wrong. Remember that they are the coordinates of the baseline of your text. And x=0, y=0 is the top left corner of the window, and y is growing downwards and x is growing to the right. Hence your text is drawn off-window, above its top. So y should be positive and more than the font height.
Try
XDrawString (myDisplay, myWindow, myGC, 15, 20, hello,
strlen (hello));
As I commented, you need to handle a lot more events.
I don't have experience with window applications on Linux.
And to learn about GUI programming, I strongly recommend first using some toolkit like GTK or Qt or perhaps SDL.
Raw X11 programming is too hard (and by the time you'll learn it is will be obsolete, e.g. by Wayland), in particular because an X11 application needs to be ICCCM & EWMH compliant. Notice that the entire X11 documentation requires nearly ten thousand pages.
See also https://tronche.com/gui/x/xlib/
BTW, most Linux GUI applications are drawing pixmap client side and sending it to the X11 server. Read about compositing window managers. Drawing requests like XDrawString are no more used anymore in practice. Recent font related libraries like libfontconfig, libXft, etc are working on the client side.

SDL TTF - Line wrapping & changing height of wrapped lines?

I've been programming a small text adventure game using SDL2 recently and have come across an issue with line wrapping. I am using TTF_RenderText_Blended_Wrapped() to render my strings, and this gives me some nicely wrapped lines. But The line height is an issue, the lines seem squished together, and letters like 'jqg' overlap with letters like 'tli'.
Does anyone know if there is a way to change the line height? TTF_RenderText_Blended_Wrapped() still isn't even in the documentation for SDL_ttf. Should I just write my own text wrapping function?
The font size is 16pt, styling is TTF_STYLE_BOLD, and the font can be found here. The code below should reproduce the error, there is almost no error checking though, use at your own risk. Here is the output of the code:
#include <stdio.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
int main(int argc, char *argv[]) {
SDL_Window *gui;
SDL_Surface *screen, *text;
SDL_Event ev;
TTF_Font *font;
int running = 1;
const char *SAMPLETEXT = "This is an example of my problem, for most lines it works fine, albeit it looks a bit tight. But for any letters that \"hang\" below the line, there is a chance of overlapping with the letters below. This isn\'t the end of the world, but I think it makes for rather cluttered text.\n\nNotice the p and k on line 1/2, and the g/t on 2/3 and 3/4.";
// init SDL/TTF
SDL_Init(SDL_INIT_EVERYTHING);
TTF_Init();
// Open and set up font
font = TTF_OpenFont("Anonymous.ttf", 16);
if(font == NULL) {
fprintf(stderr, "Error: font could not be opened.\n");
return 0;
}
TTF_SetFontStyle(font, TTF_STYLE_BOLD);
// Create GUI
gui = SDL_CreateWindow("Example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
640, 480, SDL_WINDOW_SHOWN);
// Grab GUI surface
screen = SDL_GetWindowSurface(gui);
// Clear screen black
SDL_FillRect(screen, NULL, 0);
// Draw some text to screen
SDL_Color color = {0xff, 0xff, 0xff, 0xff};
text = TTF_RenderText_Blended_Wrapped(font, SAMPLETEXT, color, screen->w);
SDL_BlitSurface(text, NULL, screen, NULL);
while(running) { // Main loop
while(SDL_PollEvent(&ev)) {
switch(ev.type){
case SDL_QUIT:
running = 0;
break;
}
}
SDL_UpdateWindowSurface(gui); // Refresh window
SDL_Delay(20); // Delay loop
}
// Destroy resources and quit
TTF_CloseFont(font);
TTF_Quit();
SDL_FreeSurface(text);
SDL_DestroyWindow(gui);
SDL_Quit();
return 0;
}
The easiest solution is to find a font that doesn't have that issue. The FreeMono font has more spacing:
From looking at the source code for TTF_RenderUTF8_Blended_Wrapped, which is called by TTF_RenderText_Blended_Wrapped, there is no configurable way to set the spacing between the lines. See const int lineSpace = 2; on line 1893.
However, even though lineSpace is set to 2, it is not being used when computing the address of each pixel to render. This is effectively setting the line spacing to 0. I reported this as a bug in the SDL_ttf library: https://bugzilla.libsdl.org/show_bug.cgi?id=3679
I was able to fix the issue in SDL_ttf 2.0.14 with the following change:
--- a/SDL_ttf.c Fri Jan 27 17:54:34 2017 -0800
+++ b/SDL_ttf.c Thu Jun 22 16:54:38 2017 -0700
## -1996,7 +1996,7 ##
return(NULL);
}
- rowSize = textbuf->pitch/4 * height;
+ rowSize = textbuf->pitch/4 * (height + lineSpace);
/* Adding bound checking to avoid all kinds of memory corruption errors
that may occur. */
With the above patch applied, your example program shows the correct line spacing with the Anonymous font:

Border/Titlebar not properly displaying in SDL OSX

I was just following lazyfoo's SDL tutorial and I ran the sample code as shown here:
#include <SDL2/SDL.h>
#include <stdio.h>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
int main( int argc, char* args[] )
{
//The window we'll be rendering to
SDL_Window* window = NULL;
//The surface contained by the window
SDL_Surface* screenSurface = NULL;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "Failed to initialise SDL! SDL_Error: %s\n", SDL_GetError() );
}
else
{
//Create window
window = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( window == NULL )
{
printf( "Failed to create window! SDL_Error: %s\n", SDL_GetError() );
}
else
{
//Get window surface
screenSurface = SDL_GetWindowSurface( window );
//Fill the surface white
SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 255, 0, 0 ) );
//Update the surface
SDL_UpdateWindowSurface( window );
//Wait two seconds
SDL_Delay( 2000 );
}
}
//Destroy window
SDL_DestroyWindow( window );
//Quit SDL subsystems
SDL_Quit();
return 0;
}
But for some reason no real border or title bar is being shown, it just displays a white screen. I tried using
SDL_SetWindowBordered but it did nothing. Next I set the background colour to red and from this image you can see there is a titlebar but there is no close or minimize button.
Does anyone know why this is happening. Is it just me or is it a problem with mac's?
Since getting rid of SDL_Delay seemed to help, I will try to elaborate a little. If we look at the code of SDL_Delay we can see that it basically does two things:
if nanosleep() can be utilized, it does sleep for a time interval;
else, it runs in an infinite while loop, checking how much time has passed # each iteration, and breaking out of the loop after enough time has passed.
Now, I must say that I have never personally coded for osx, so I do not know how exactly does it draw it's windows. However I can assume that for some reason SDL_Delay in your code gets called (and effectively blocks the thread it's called from) before the OS manages to draw the header of the window, and after the delay finishes you immediately destroy the window yourself, thus the header is never properly drawn.
I know that the answer is already solved, but for anyone who wants a simple solution.
Example:
SDL_Delay(4000);
would turn into
for(int i = 0; i < 4000; i++){
SDL_PumpEvents();
SDL_Delay(1);
}
Actually this has nothing to do with SDL_Delay() at all.
I tested it out, and it seems that on OSX the title-bar only updates each time the events are polled or pumped.
This means that SDL_Delay() blocks the title-bar rendering process if it prevents you from pumping events.
To fix this just call SDL_PumpEvents() every millisecond or so:
for(int i = 0; i < time_to_sleep; i++){
SDL_PumpEvents();
SDL_Delay(1);
}

Resources