C++, ncurses: unable to display menu before a key is pressed - c++

With a friend I am working on a tetris like game within a terminal. We are using ncurses to manage it and we have different "views". For example a view manages the grid while the other manages the Menu. However we have a problem: when we start the game, we need to press a key in order to see it, otherwise the window is empty.
Here is the code ran when we create the menu (the constructor):
MenuScreen::MenuScreen()
{
if (has_colors())
{
use_default_colors();
start_color();
init_pair(WHITEONRED, COLOR_WHITE, COLOR_RED);
init_pair(WHITEONBLUE, COLOR_WHITE, COLOR_BLUE);
init_pair(REDONWHITE, COLOR_RED, COLOR_WHITE);
}
char *choices[] = /* The menu choices */
{
(char *)" Solo ",
(char *)" Bot ",
(char *)" Tetrix ",
(char *)" Quitter ",
NULL};
/* Calculate nchoices */
for (n_choices = 0; choices[n_choices]; n_choices++)
;
/* alloction of an iteam array for the menu */
my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
for (ssChoice = 0; ssChoice < n_choices; ++ssChoice)
my_items[ssChoice] = new_item(choices[ssChoice], NULL);
my_items[n_choices] = (ITEM *)NULL;
/* menu structure creation */
my_menu = new_menu((ITEM **)my_items);
/* symbole on the left of selected iteam*/
set_menu_mark(my_menu, "> ");
/* Windows Border cration */
wBorder = newwin(8, 40, LINES / 2 - 8 / 2, COLS / 2 - 40 / 2);
registerWindow(wBorder);
wattrset(wBorder, COLOR_PAIR(WHITEONRED));
windowsFilling(wBorder);
box(wBorder, 0, 0);
windowsBorderTitle(wBorder, " option ");
wUI = derwin(wBorder, 8 - 2, 40 - 2, 2, 2);
registerWindow(wUI);
set_menu_sub(my_menu, wUI);
set_menu_fore(my_menu, COLOR_PAIR(REDONWHITE));
set_menu_back(my_menu, COLOR_PAIR(WHITEONRED));
/* menu display */
post_menu(my_menu);
}
And when the next key is pressed:
void MenuScreen::next()
{
menu_driver(my_menu, REQ_DOWN_ITEM);
update();
}
And here is what update() contains:
void MenuScreen::update()
{
touchwin(wUI);
wrefresh(wUI);
touchwin(wBorder);
wrefresh(wBorder);
}
If we remove update() from the next() function, the menu is no longer displayed when we press the next key, so we tried to add a call to update() at the end of the constructor, but this didn't work. We have no idea what could cause this bug. Here is our entire source code:
https://github.com/Th0rgal/poyuterm/tree/22e2422930a29fbe83414e382fd566c3eac69366
EDIT: Here is a minimal reproducible example made by my friend:
To build it, copy paste it in a menu.cpp file and type: g++ menu.cpp -o menu -lncurses -l menu
#include <stdlib.h> /* calloc() */
#include <string.h> /* strlen() */
#include <ncurses.h>
#include <menu.h>
#include <curses.h>
#define WHITEONRED 10
#define WHITEONBLUE 20
#define WHITEONBLACK 30
#define BLACKONWHITE 40
#define REDONWHITE 50
void windowsBorderTitle(WINDOW *pwin, const char *title)
{
int x, maxy, maxx, stringsize;
getmaxyx(pwin, maxy, maxx);
stringsize = 4 + strlen(title);
x = (maxx - stringsize) / 2;
mvwaddch(pwin, 0, x, ACS_RTEE);
waddch(pwin, ' ');
waddstr(pwin, title);
waddch(pwin, ' ');
waddch(pwin, ACS_LTEE);
}
void windowsFilling(WINDOW *pwin)
{
int y, x, maxy, maxx;
getmaxyx(pwin, maxy, maxx);
for (y = 0; y < maxy; y++)
for (x = 0; x < maxx; x++)
mvwaddch(pwin, y, x, ' ');
}
int main(int argc, char const *argv[])
{
initscr(); /* start ncurses */
cbreak(); /* immediately acquire each keystroke */
noecho(); /* do not echo user keystrokes */
keypad(stdscr, TRUE); /* enable detection of function keys */
int c;
ITEM **my_items;
MENU *my_menu;
WINDOW *wUI;
WINDOW *wBorder;
int n_choices;
int ssChoice;
int my_choice = -1;
if (has_colors())
{
use_default_colors();
start_color();
init_pair(WHITEONRED, COLOR_WHITE, COLOR_RED);
init_pair(WHITEONBLUE, COLOR_WHITE, COLOR_BLUE);
init_pair(REDONWHITE, COLOR_RED, COLOR_WHITE);
}
char *choices[] = /* The menu choices */
{
(char *)" Solo ",
(char *)" Bot ",
(char *)" Tetrix ",
(char *)" Quitter ",
NULL};
for(n_choices=0; choices[n_choices]; n_choices++);
/* ALLOCATE ITEM ARRAY AND INDIVIDUAL ITEMS */
my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
for(ssChoice = 0; ssChoice < n_choices; ++ssChoice)
my_items[ssChoice] = new_item(choices[ssChoice], NULL);
my_items[n_choices] = (ITEM *)NULL;
/* CREATE THE MENU STRUCTURE */
my_menu = new_menu((ITEM **)my_items);
/* PUT > TO THE LEFT OF HIGHLIGHTED ITEM */
set_menu_mark(my_menu, "> ");
/* SET UP WINDOW FOR MENU'S BORDER */
wBorder = newwin(16, 40, 2, 20);
wattrset(wBorder, COLOR_PAIR(WHITEONRED) | WA_BOLD);
windowsFilling(wBorder);
box(wBorder, 0, 0);
windowsBorderTitle(wBorder, "Choose one");
/* SET UP WINDOW FOR THE MENU'S USER INTERFACE */
wUI = derwin(wBorder, 16-2, 40-2, 2, 2);
/* ASSOCIATE THESE WINDOWS WITH THE MENU */
set_menu_win(my_menu, wBorder);
set_menu_sub(my_menu, wUI);
/* MATCH MENU'S COLORS TO THAT OF ITS WINDOWS */
set_menu_fore(my_menu, COLOR_PAIR(REDONWHITE));
set_menu_back(my_menu, COLOR_PAIR(WHITEONRED) | WA_BOLD);
/* SET UP AN ENVIRONMENT CONDUCIVE TO MENUING */
keypad(wUI, TRUE); /* enable detection of function keys */
noecho(); /* user keystrokes don't echo */
curs_set(0); /* make cursor invisible */
/* DISPLAY THE MENU */
post_menu(my_menu);
touchwin(wBorder);
wrefresh(wBorder);
while(my_choice == -1)
{
touchwin(wBorder);
wrefresh(wBorder);
touchwin(wUI); /* refresh prior to getch() */
wrefresh(wUI); /* refresh prior to getch() */
c = getch();
switch(c)
{
case KEY_DOWN:
menu_driver(my_menu, REQ_DOWN_ITEM);
break;
case KEY_UP:
menu_driver(my_menu, REQ_UP_ITEM);
break;
case 10: /* Enter */
my_choice = item_index(current_item(my_menu));
pos_menu_cursor(my_menu);
break;
}
}
unpost_menu(my_menu);
for(ssChoice = 0; ssChoice < n_choices; ++ssChoice)
free_item(my_items[ssChoice]);
free_menu(my_menu);
delwin(wUI);
delwin(wBorder);
touchwin(stdscr);
wrefresh(stdscr);
endwin();
}

Related

How do I get all the clipboard events provided by XCB?

I am currently working on a cross-host clipboard sharing tool that can share text, rich text, or files.
Based on what I've learned so far, I already know which X11 events need to be handled, but I can't listen to them.
My current code I can only catch events that select text.
how to get the clipboard change event caused by ctrl+c?
#include <QCoreApplication>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <xcb/xcb.h>
#include <xcb/xfixes.h>
/**
* Enumeration of standard X11 atom identifiers
*/
typedef enum std_x_atoms {
/** The TARGETS atom identifier **/
X_ATOM_TARGETS = 0,
/** The MULTIPLE atom identifier **/
X_ATOM_MULTIPLE,
/** The TIMESTAMP atom identifier **/
X_ATOM_TIMESTAMP,
/** The INCR atom identifier **/
X_ATOM_INCR,
/** The CLIPBOARD atom identifier **/
X_ATOM_CLIPBOARD,
/** The UTF8_STRING atom identifier **/
X_ATOM_UTF8_STRING,
X_ATOM_XCLIPD,
/** End marker sentinel **/
X_ATOM_END
} std_x_atoms;
/**
* Union to simplify getting interned atoms from XCB
*/
typedef union atom_c {
/** The atom **/
xcb_atom_t atom;
/** The cookie returned by xcb_intern_atom **/
xcb_intern_atom_cookie_t cookie;
} atom_c;
/**
* The standard atom names. These values should match the
* std_x_atoms enumeration.
*/
const char * const g_std_atom_names[X_ATOM_END] = {
"TARGETS", "MULTIPLE", "TIMESTAMP", "INCR",
"CLIPBOARD", "UTF8_STRING", "XCLIPD"
};
atom_c std_atoms[X_ATOM_END];
/**
* \brief Interns the list of atoms
*
* \param [in] xc The XCB connection.
* \param [out] atoms The location to store interned atoms.
* \param [in] atom_names The names of the atoms to intern.
* \param [in] number The number of atoms to intern.
* \return true iff all atoms were interned.
*/
static bool x11_intern_atoms(xcb_connection_t *xc, atom_c *atoms, const char * const *atom_names, int number) {
for (int i = 0; i < number; i++) {
atoms[i].cookie = xcb_intern_atom(xc, 0,
strlen(atom_names[i]), atom_names[i]);
}
for (int i = 0; i < number; i++) {
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xc,
atoms[i].cookie, NULL);
if (reply == NULL) {
return false;
}
atoms[i].atom = reply->atom;
free(reply); /* XCB: Do not use custom allocators */
}
return true;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
xcb_connection_t *c;
xcb_screen_t *screen;
xcb_window_t win;
xcb_generic_event_t *e;
uint32_t mask = 0;
uint32_t values[2];
/* Create the window */
c = xcb_connect (NULL, NULL);
screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
if (!x11_intern_atoms(c, std_atoms, g_std_atom_names, X_ATOM_END))
return 1;
// xcb_flush (c);
win = xcb_generate_id (c);
mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
values[0] = screen->white_pixel;
values[1] = XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY;;
xcb_create_window (c, /* Connection */
XCB_COPY_FROM_PARENT, /* depth */
win, /* window Id */
screen->root, /* parent window */
0, 0, /* x, y */
150, 150, /* width, height */
10, /* border_width */
XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */
screen->root_visual, /* visual */
mask, values); /* masks */
xcb_map_window (c, win);
xcb_flush (c);
// init xfixes
xcb_generic_error_t *error = 0;
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(c, &xcb_xfixes_id);
if (!reply || !reply->present) {
return -1;
}
xcb_xfixes_query_version_cookie_t xfixes_query_cookie = xcb_xfixes_query_version(c,
XCB_XFIXES_MAJOR_VERSION,
XCB_XFIXES_MINOR_VERSION);
xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (c,
xfixes_query_cookie, &error);
if (!xfixes_query || error || xfixes_query->major_version < 2) {
free(error);
}
free(xfixes_query);
// delivers request
mask = XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE
| XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY
| XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER;
xcb_xfixes_select_selection_input_checked(c, win, XCB_ATOM_NONE, mask);
xcb_flush(c);
// recevie events
uint response_type;
while (e = xcb_wait_for_event(c)) {
xcb_xfixes_selection_notify_event_t *notify_event = reinterpret_cast<xcb_xfixes_selection_notify_event_t *>(e);
printf("response_type = %d\n", response_type);
response_type = notify_event->response_type & ~0x80;
printf("response_type = %d\n", response_type);
if (response_type == reply->first_event + XCB_XFIXES_SELECTION_NOTIFY) {
printf("notify\n");
} else {
printf("code:%d\n", response_type);
}
}
return a.exec();
}

Why do I receive key release event when key release is not in event mask. (xcb)

I am making a simple xcb application and I noticed that when XCB_EVENT_MASK_KEY_PRESS is in the event mask and XCB_EVENT_MASK_KEY_RELEASE is not in the event mask I still get XCB_KEY_RELEASE events in my event loop if I hold down a key so that it repeats the key press event. Surely if XCB_EVENT_MASK_KEY_RELEASE is not in the event mask I should never get an XCB_KEY_RELEASE event?
Minimum reproducible example:
Run and hold down a key for a few seconds so that the keypress event repeats. This causes the key release event despite XCB_EVENT__MASK_KEY_RELEASE not being in the event mask.
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <xcb/xcb.h>
/* notice that the event mask does not conatin XCB_EVENT_MASK_KEY_RLEASE */
const uint32_t EVENT_MASK
= XCB_EVENT_MASK_EXPOSURE
| XCB_EVENT_MASK_KEY_PRESS;
int main()
{
int screenNum;
xcb_connection_t* xcon = xcb_connect(NULL, &screenNum);
const xcb_setup_t* xsetup = xcb_get_setup(xcon);
xcb_screen_t* screen;
{
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xsetup);
for (int i = 0; i < screenNum; i++)
xcb_screen_next(&iter);
screen = iter.data;
}
xcb_window_t window = xcb_generate_id(xcon);
uint32_t winvals[] = { screen->white_pixel, EVENT_MASK };
xcb_create_window(
xcon,
XCB_COPY_FROM_PARENT,
window,
screen->root,
10, 10,
150, 150,
10,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, winvals);
xcb_map_window(xcon, window);
xcb_flush(xcon);
xcb_generic_event_t* event;
while ((event = xcb_wait_for_event(xcon))) {
switch (event->response_type & ~0x80) {
case XCB_EXPOSE: {
// TODO: draw something
xcb_flush(xcon);
break;
}
case XCB_KEY_PRESS: {
xcb_key_press_event_t* kp = (xcb_key_press_event_t*)event;
printf("key pressed: %u\n", kp->detail);
break;
}
case XCB_KEY_RELEASE: {
puts("KEY RELEASE EVENT?!");
break;
}
default: {
printf("unknown event. type = %u\n", event->response_type);
break;
}
}
free(event);
}
xcb_disconnect(xcon);
return 0;
}

How deep is mouse in Rectangle C++ & SDL2 (Position flickers between two positions)

I am creating a program, and I have a rectangle. Basically, I am creating a custom window inside the SDL2 window, which is a Rect, with another Rect being its toolbar. I am struggling for hours trying to figure how to detect how deep is the mouse within the Rect, but I am failing every time. The most obvious equation for me was int deep = mousePos.x - x, but it flickers between two positions every time I move my mouse. I then have tried a LOT of other calculations, but none of them worked. Either they flickered between two positions with descending values, or they were completely static and didn't move, or always moved a lot in a specific direction. I have visually represented the calculations, which were mostly correct, but the flickering between two positions is always ruining it. Thanks for any help. I am providing source code, too.
SOURCE:
//
// main.cpp
// Open
//
// Created by Fildom on 28.12.2021.
//
// Library includes
#include <SDL2/SDL.h>
#include <stdio.h>
bool isdown = false;
// Screen rendering helper
void on_render(SDL_Window* window, SDL_Renderer* renderer);
// Concatenation (probably not spelt correctly but idrc) for easier use
const char * concat(const char * one, const char * two) {
char * buffer = new char[strlen(one) + strlen(two) + 1];
strcpy(buffer, one);
strcat(buffer, two);
return buffer;
}
// Main method, required for performing application run
int main(int argc, const char * argv[]) {
SDL_Renderer *renderer = NULL; // Initialize the renderer
SDL_Event event = { 0 }; // Create a null event
SDL_Window *win = NULL; // Initialize a window
int exit = 0; // If exit is 1, win closes
// Window pre-modifiers
const char * appName = "test";
// SDL VIDEO mode initialization and error check
if(SDL_Init(SDL_INIT_VIDEO) == -1) {
printf("SDL_Init() failed with \"%s.\"", SDL_GetError());
return 1;
}
// Create the window and load it into a previously defined variable
win = SDL_CreateWindow(concat(appName, " - Initialization in progress"), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
// Window creation was unsuccessfull
if(!win) {
printf("SDL_CreateWindow() failed with \"%s.\"", SDL_GetError());
return -1;
}
// Creating renderer
renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
// If renderer failed to load...
if(!renderer) {
printf("SDL_CreateRenderer() failed with \"%s.\"", SDL_GetError());
return -1;
}
// Everything has gone OK, thus the window can be renamed
SDL_SetWindowTitle(win, appName);
// Game loop, as said previously, false = 0, true = 1.
// while !exit |
// while not exit <- |
// while exit is 0 (false) <-
while (!exit) {
// Event loop
if (SDL_WaitEvent(&event)) {
// Event types
switch(event.type) {
case SDL_QUIT:
exit = 1; // Exit = 1, thus app is being exitted
break;
case SDL_KEYDOWN:
if(event.key.keysym.sym == SDLK_ESCAPE) exit = 1; // If ESC is pressed
break;
case SDL_MOUSEBUTTONUP:
isdown = false;
break;
case SDL_MOUSEBUTTONDOWN:
isdown = true;
break;
case SDL_MOUSEMOTION:
break;
case SDL_WINDOWEVENT:
switch(event.window.event) {
case SDL_WINDOWEVENT_CLOSE: // macOS and/or other OSes rely on right click + Quit to fully exit out of an application. This makes it easier by just hitting the close button.
exit = 1;
break;
}
break;
default: break;
}
}
// Render the screen
on_render(win, renderer);
// Swap buffers to display
SDL_RenderPresent(renderer);
}
// Cleanup
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
class Window {
public:
int x, y, w, h;
SDL_Color winc, wintc;
bool draggable;
int titleh;
Window(int wx, int wy, int ww, int wh, SDL_Color window_color = {255, 255, 255, 255}, SDL_Color window_title_color = {200, 200, 200, 255}) {
x = wx;
y = wy;
w = ww;
h = wh;
winc = window_color;
wintc = window_title_color;
draggable = true;
titleh = 50;
}
int tx, ty = 0;
void Render(SDL_Renderer* renderer) {
SDL_Rect _t;
_t.x = x;
_t.y = y;
_t.w = w;
_t.h = h;
SDL_Rect title;
title.x = x;
title.y = y;
title.w = w;
title.h = titleh;
SDL_SetRenderDrawColor(renderer, winc.r, winc.g, winc.b, winc.a);
SDL_RenderFillRect(renderer, &_t);
SDL_SetRenderDrawColor(renderer, wintc.r, wintc.g, wintc.b, wintc.a);
SDL_RenderFillRect(renderer, &title);
int mx, my;
SDL_PumpEvents();
SDL_GetMouseState(&mx, &my);
SDL_Point ms;
ms.x = mx;
ms.y = my;
if (SDL_PointInRect(&ms, &title) and isdown) {
x = mx - tx;
y = my - ty;
tx = x;
ty = y;
}
}
};
Window test1 = Window(200, 100, 300, 200);
void on_render(SDL_Window* window, SDL_Renderer* renderer) {
SDL_Rect wind = { 0 };
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_GetWindowSize(window, &wind.w, &wind.h);
test1.Render(renderer);
}
I ended up doing it in a different way. Instead of using mousePosition.x and y, I used relative X and Y which worked out perfectly.
code for that is
mousePosition.relX and mousePosition.relY;

NCURSES skips menu option

Picture below shows what I see when program starts:
That is correct, however when I press right arrow key selector skips middle menu option and renames last one:
Here's my code. To compile it run g++ <source_file> -lmenu -lncurses
#include <ncurses.h>
#include <menu.h>
#include <vector>
#include <string>
#include <cstdlib>
int main()
{
// # Initialize curses
initscr();
start_color();
cbreak();
noecho();
curs_set(0);
keypad(stdscr, TRUE);
init_pair(1, COLOR_RED, COLOR_BLACK);
// # Setup menu
std::vector<std::string> menuChoices;
menuChoices.push_back(" < CREATE > ");
menuChoices.push_back(" < VERIFY > ");
menuChoices.push_back(" < EXIT > ");
ITEM **menuItems = (ITEM **)calloc(menuChoices.size() + 1, sizeof(ITEM *));
for (unsigned int i = 0; i < menuChoices.size(); i++)
menuItems[i] = new_item(menuChoices[i].c_str(), menuChoices[i].c_str());
menuItems[menuChoices.size()] = (ITEM *)NULL;
MENU *menu = new_menu((ITEM **)menuItems);
set_menu_mark(menu, NULL);
set_menu_format(menu, 1, menuChoices.size());
menu_opts_off(menu, O_SHOWDESC);
// # Setup window
const int windowHeight = 6;
const int windowWidth = 70;
WINDOW *window = newwin(windowHeight, windowWidth, (LINES - windowHeight) / 2, (COLS - windowWidth) / 2);
keypad(window, TRUE);
box(window, 0, 0);
set_menu_win(menu, window);
set_menu_sub(menu, derwin(window, 1, 38, windowHeight - 1, (windowWidth - 38) / 2));
// # Post the menu
post_menu(menu);
wrefresh(window);
int keyPressed;
while ((keyPressed = wgetch(window))) {
switch (keyPressed) {
case KEY_RIGHT:
menu_driver(menu, REQ_RIGHT_ITEM);
break;
case KEY_LEFT:
menu_driver(menu, REQ_LEFT_ITEM);
break;
}
wrefresh(window);
}
// # Unpost and free all the memory taken up
unpost_menu(menu);
for (unsigned int i = 0; i < menuChoices.size() + 1; i++)
free_item(menuItems[i]);
free_menu(menu);
endwin();
return 0;
}
How can I fix it?
The problem is that the program makes these calls in the wrong order:
set_menu_format(menu, 1, menuChoices.size());
menu_opts_off(menu, O_SHOWDESC);
The menu_opts_off call changes the width of menu items; the set_menu_format call needs to know the width of the menu items. Reversing the order of the calls makes the program work as intended.

When i compile acode i have this error cannot open file X11/Xlib.h in c++

/* Sequential Mandelbrot program mandelbrot.c */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#define X_RESN 800 /* x resolution */
#define Y_RESN 800 /* y resolution */
typedef struct complextype
{ float real, imag;
} Compl;
int main (int argc, char *argv[])
{ Window win; /* window initialization */
unsigned
int width, height, /* window size */
x, y, /* window position */
border_width, /* border width in pixels */
display_width,
display_height, /* size of screen */
screen; /* which screen */
char *window_name = "Mandelbrot Set", *display_name = NULL;
GC gc;
unsigned long valuemask = 0;
XGCValues values;
Display *display;
XSizeHints size_hints;
Pixmap bitmap;
XPoint points[800];
FILE *fp, *fopen ();
char str[100];
XSetWindowAttributes attr[1];
/* Mandlebrot variables */
int i, j, k;
Compl z, c;
float lengthsq, temp;
/* connect to Xserver */
if ( (display = XOpenDisplay (display_name)) == NULL )
{ fprintf (stderr, "drawon: cannot connect to X server %s\n",
XDisplayName (display_name) );
exit (-1);
}
/* get screen size */
screen = DefaultScreen (display);
display_width = DisplayWidth (display, screen);
display_height = DisplayHeight (display, screen);
/* set window size */
width = X_RESN;
height = Y_RESN;
/* set window position */
x = 0;
y = 0;
/* create opaque window */
border_width = 4;
win = XCreateSimpleWindow(display, RootWindow (display, screen),
x, y, width, height, border_width,
BlackPixel (display, screen), WhitePixel (display, screen));
size_hints.flags = USPosition|USSize;
size_hints.x = x;
size_hints.y = y;
size_hints.width = width;
size_hints.height = height;
size_hints.min_width = 300;
size_hints.min_height = 300;
XSetNormalHints (display, win, &size_hints);
XStoreName(display, win, window_name);
/* create graphics context */
gc = XCreateGC (display, win, valuemask, &values);
XSetBackground (display, gc, WhitePixel (display, screen));
XSetForeground (display, gc, BlackPixel (display, screen));
XSetLineAttributes (display,gc,1,LineSolid,CapRound,JoinRound);
attr[0].backing_store = Always;
attr[0].backing_planes = 1;
attr[0].backing_pixel = BlackPixel(display, screen);
XChangeWindowAttributes(display, win,
CWBackingStore | CWBackingPlanes | CWBackingPixel, attr);
XMapWindow (display, win);
XSync(display, 0);
/* Calculate and draw points */
for(i=0; i < X_RESN; i++)
{ for(j=0; j < Y_RESN; j++)
{ z.real = z.imag = 0.0; /* 800x800 scale factors */
c.real = ((float) j - 400.0)/200.0;
c.imag = ((float) i - 400.0)/200.0;
k = 0;
do
{ /* iterate for pixel color */
temp = z.real*z.real - z.imag*z.imag + c.real;
z.imag = 2.0*z.real*z.imag + c.imag;
z.real = temp;
lengthsq = z.real*z.real+z.imag*z.imag;
k++;
} while (lengthsq < 4.0 && k < 100);
if (k == 100) XDrawPoint (display, win, gc, j, i);
} }
XFlush (display);
sleep (30);
/* Program Finished */
}
Open up a command prompt and run the two commands:
find / -type f - name Xlib.h
find / -type d - name X11
That should help you locate that file and/or directory so you can see whether it's available.
If it is available (e.g., it's found at /usr/include/X_stuff/X11/Xlib.h), make sure your compiler command references it, like:
g++ -I/usr/include/X_stuff ...
If it's not there, install it.
Either you forgot to install the X development packages, or the directory containing the headers was not added to the includedir list.