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);
}
Related
I am using windows 10 and sdl2. The SDL_INIT_GAMECONTROLLER flag must be initted or execution will not start. Here's some code from main (see the bottom comment at the gamecontroller init call):
SDL_Init(SDL_INIT_VIDEO);
int imgFlags = IMG_INIT_PNG;
if(!( IMG_Init(imgFlags) & imgFlags)) {
printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
return 0;
}
SDL_ShowCursor(SDL_DISABLE);
SDL_Window* window = NULL;
window = SDL_CreateWindow("Anica", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, W, H,
SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = NULL;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_InitSubSystem(SDL_INIT_AUDIO);
SDL_InitSubSystem(SDL_INIT_EVENTS);
SDL_InitSubSystem(SDL_INIT_TIMER);
// If this sub system is not initted execution stops. If it is initted
// execution works fine. It takes 2-3 seconds for this call to finish which
// is really slow.
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
The window open and hangs until the gamecontroller init call is done (2-3 seconds) if the gamecontroller subsystem is initted. Then everything works fine. If the gamecontroller subsystem is not initted the window opens and hangs indefinitely.
I am using windows 10 if that makes any difference.
My partner does not have this issue using the same code on windows 10, which is confusing to both of us.
Going from SDL 2.0.9 to 2.0.8 fixed the problem for me.
Thanks to the comments on the question for helping.
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:
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.
I'm trying to create window without borders (popup?) in xlib. I'm using this code:
#include <stdio.h>
#include <X11/Xlib.h>
int main( int argc, char **argv )
{
Display *display = NULL;
Window window;
XSetWindowAttributes attribs;
display = XOpenDisplay( NULL );
if( !display )
{
printf( "Cannot to open display." );
return 1;
}
attribs.override_redirect = 1;
window = XCreateWindow( display, RootWindow(display, 0), 20, 20, 400, 300, 0, CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attribs );
XSetWindowBackground( display, window, 0x00F0FF );
XClearWindow( display, window );
XMapWindow( display, window );
XFlush( display );
getchar( );
return 0;
}
It creating window without borders, but this window is always on top.
The question is: Why and what to do in xlib to display it as a normal window.
That's how override-redirect windows are meant to behave. They are designed for implementing pop-up menus and similar windows which are transient and stay above other windows.
If that's not what you want, do not use override-redirect flag. Instead, use WM hints. See here for the full list of hints. You want to tell your WM which window type you have (_NET_WM_WINDOW_TYPE_TOOLBAR etc), not how it's decorated. See here for a usage example.
If that's still not what you want, use the (somewhat outdated) Motif WM hints. See for example here.
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.