C and xlib: Crash in XPending() in a very simple program - c

I'm a beginner with xlib. I tried to program an Xwindow application using select() based on this example: how to quit the blocking of xlib's XNextEvent.
But the code mentioned above crashes in the XPending function. So I tried to isolate the problem and on my system even this from my point of view very simple example crashes on line 28. Due to several tests I assume is crashes internally by calling XFlush(). At the line marked with "// <- CRASH" I think XPending should return 0. Is that correct?
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
Display *dis;
Window win;
int x11_fd;
fd_set in_fds;
struct timeval tv;
XKeyEvent ev;
int main() {
dis = XOpenDisplay(NULL);
win = XCreateSimpleWindow(dis, RootWindow(dis, 0), 1, 1, 256, 256, \
0, BlackPixel (dis, 0), BlackPixel(dis, 0));
XSelectInput(dis, win,
KeyPressMask | KeyReleaseMask );
XMapWindow(dis, win);
XFlush(dis);
printf("Xpending: %d\n",XPending(dis));
printf("Xpending: %d\n",XPending(dis));
XPeekEvent(dis, (XEvent*) &ev);
printf("type: %d button: 0x%X state: 0x%x\n",ev.type, ev.keycode, ev.state);
int j = XPending(dis); // <- CRASH
printf("XPending: %d\n",j);
return 0;
}
Is this a bug or have I mistaken a major concept in xlib?

XKeyEvent is bigger in bytes than XEvent
when you receive a bigger event, the ev variable will overflow.
using malloc, you actualy get more bytes than you asked, solving the problem.
better solution will be using a XEvent ev;
XEvent ev;
...
XNextEvent( & ev );
...
printf( "%d\n", ev.xkey.keycode
);

I have solved the issue. Although I don't understand why it works:
Instead of using a global ev variable I declared it inside the main function body:
XKeyEvent *ev = (XKeyEvent*) malloc(sizeof(XKeyEvent));
and adapted its pointer nature to the program.

Related

Simulating button hold doesn't work as expected

#include <windows.h>
#define VK_W 0x57
int main()
{
keybd_event(VK_W, 0, 0, 0); // Press down the key
Sleep(3000);
keybd_event(VK_W, 0, KEYEVENTF_KEYUP, 0); // Release the key
}
This code is supposed to hold down a key for 3 seconds, and upon further checking through https://drakeirving.github.io/MultiKeyDisplay/ it does hold it for 3 second, but the default behaviour isn't present. The default behaviour I want is for it to repeatedly send the key when I hold it down (like what happens when I hold it down physically). This doesn't happen here, because when I open Notepad, it doesn't repeat the key.
I even tried simulating scancodes to see if it has an effect, but to no avail.
#include <windows.h>
#define VK_W 0x57
int main()
{
keybd_event(0,
MapVirtualKey(VK_W, MAPVK_VK_TO_VSC),
KEYEVENTF_SCANCODE | 0,
0);
Sleep(3000);
keybd_event(0,
MapVirtualKey(VK_W, MAPVK_VK_TO_VSC),
KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP,
0);
}
How do I simulate holding the key so that it behaves the same way as when I hold it down physically?

Linux framebuffer not updating when using KD_GRAPHICS

I've been trying to do some old-school drawing on the Linux framebuffer. I'm aware this is not the "modern" way to do things but exploring it out of curiosity. I am confused that my screen does not seem to update as expected when using KD_GRAPHICS mode.
Running the following program from the console to paint the screen white, the framebuffer will display a section of white on the screen, then stop updating for the duration of the sleep(), then briefly flash white before returning to KD_TEXT mode. If I comment out the KDSETMODE changes, then the framebuffer is painted white immediately except for the cursor being visible (which I don't want) and stays white for the expected 5 seconds. Can someone enlighten me why I am not seeing screen updates with KD_GRAPHCIS?
Machine is running Ubuntu 20.04 with a 5.13.0-52-generic kernel.
#include <linux/fb.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/kd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <unistd.h>
uint32_t pixel_color(uint8_t r, uint8_t g, uint8_t b, struct fb_var_screeninfo *vinfo)
{
return (r<<vinfo->red.offset) | (g<<vinfo->green.offset) | (b<<vinfo->blue.offset);
}
int main()
{
ioctl(0,KDSETMODE,KD_GRAPHICS);
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;
int fb_fd = open("/dev/fb0",O_RDWR);
ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo);
ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo);
long screensize = vinfo.yres_virtual * finfo.line_length;
uint8_t *fbp = mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, (off_t)0);
int x,y;
for (x=0;x<vinfo.xres;x++)
for (y=0;y<vinfo.yres;y++)
{
long location = x * (vinfo.bits_per_pixel/8) + y * finfo.line_length;
*((uint32_t*)(fbp + location)) = pixel_color(0xFF,0xFF,0xFF, &vinfo);
}
sleep(5);
ioctl(0,KDSETMODE,KD_TEXT);
return 0;
}

c - creating threads & joining them in a for loop

So basically I'm making a simulator in c for vehicles entering in and out of cell phone tower zones. I'm trying to add code in simulator.c that makes the function spawn a new thread for each cell tower as well as one thread to handle the display. The simulator program should continue up until all 7 cell tower threads have completed, and the cell tower threads should continue until they receive a shutdown request. The display thread runs indefinitely but gets killed when the simulator process completes. I'm having trouble understanding what parameters I'm supposed to use to create and join the threads. I posted below what I have so far in the simulator.c program. My attempt is trying to loop the statements to make 7 threads for 7 cell towers. I'm not sure if my first parameter for pthread_create is correct and I'm not really sure what my 4th parameter is supposed to be. I know I'm supposed to pass in some sort of argument but I'm not sure what. Also I'm not too sure what the requirements mean for "the cell tower threads should continue until they receive a shutdown request." Each cell tower thread is supposed to call handleIncomingRequests() from cellTower.c and the display thread should call showSimulation() from display.c
Any help would be really appreciated. I watched some videos online about threading in c but I'm still a little confused as to how they work. I posted below the files I felt were only related to this question, but if anyone wants me to post every file for this entire program I don't mind.
simulator.c:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "simulator.h"
#include "display.c"
#include "cellTower.c"
int main() {
City ottawa;
// Cell tower data
short xLocations[7] = {100, 400, 650, 640, 400, 120, 200};
short yLocations[7] = {100, 200, 150, 450, 500, 350, 500};
short cellRadii[7] = {110, 200, 150, 180, 160, 120, 100};
int cellColors[7] = {0xFF8822 /*Orange*/, 0xFF2222 /*Red*/, 0xFFFF44 /*Yellow*/,
0x22FF22 /*Green*/, 0xAA66FF /*Purple*/, 0x0099FF /*Blue*/,
0x999999 /*LightGray*/};
// Set up the Cell Towers with the above data ... and no connected vehicles to begin
ottawa.numTowers = 7;
for (int i=0; i<ottawa.numTowers; i++) {
ottawa.towers[i].online = 1;
ottawa.towers[i].id = (unsigned char)i;
ottawa.towers[i].x = xLocations[i];
ottawa.towers[i].y = yLocations[i];
ottawa.towers[i].radius = cellRadii[i];
ottawa.towers[i].color = cellColors[i];
ottawa.towers[i].numConnectedVehicles = 0;
for (int j=0; j<MAX_CONNECTIONS; j++)
ottawa.towers[i].connectedVehicles[j].connected = 0;
}
// Remove the line of code below. Add code to spawn the necessary threads and
// wait for their completion before exiting gracefully with some kind of message
pthread_t cellTowers[ottawa.numTowers];
int i;
for(i = 0; i < ottawa.numTowers; i++){
pthread_create(cellTowers[i], NULL, handleIncomingRequests, "");
pthread_join(cellTowers[i], NULL);
}
pthread_t displayTower;
pthread_create(&displayTower, NULL, showSimulation, "");
}
simulator.h:
#define VEHICLE_SPEED 3 // Forward pixels per movement
#define VEHICLE_TURN_ANGLE 5 // degrees to turn for each vehicle movement
#define NUM_TOWERS 7 // Number of cell towers within the city borders
#define SERVER_IP "127.0.0.1" // IP address of simulator server
#define SERVER_PORT 6000 // PORT of the simulator server
// Command codes sent from client to server
#define SHUTDOWN 1
#define CONNECT 2
#define UPDATE 3
// Command codes sent from server to client
#define YES 5
#define NO 6
#define NOT_OK_BOUNDARY 7
#define NOT_OK_COLLIDE 8
typedef struct {
int x;
int y;
int direction;
char towerID;
} Vehicle;
typedef struct {
int x;
int y;
char connected;
} ConnectedVehicle;
typedef struct {
char online; // 0 = no, 1 = yes
char id;
short x;
short y;
short radius;
int color;
ConnectedVehicle connectedVehicles[MAX_CONNECTIONS];
short numConnectedVehicles;
} CellTower;
typedef struct {
CellTower towers[NUM_TOWERS];
short numTowers;
} City;
cellTower.c:
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
void *handleIncomingRequests(void *ct) {
CellTower *tower = ct;
}
display.c:
#include <unistd.h>
#include <X11/Xlib.h>
//Display-related variables
Display *display;
Window win;
GC gc;
// Initialize and open the simulator window with size CITY_WIDTH x CITY_HEIGHT.
void initializeWindow() {
// Open connection to X server
display = XOpenDisplay(NULL);
// Create a simple window, set the title and get the graphics context then
// make is visible and get ready to draw
win = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0,
CITY_WIDTH, CITY_HEIGHT, 0, 0x000000, 0xFFFFFF);
XStoreName(display, win, "Vehicle Simulator");
gc = XCreateGC(display, win, 0, NULL);
XMapWindow(display, win);
XFlush(display);
usleep(20000); // sleep for 20 milliseconds.
}
// Close the display window
void closeWindow() {
XFreeGC(display, gc);
XUnmapWindow(display, win);
XDestroyWindow(display, win);
XCloseDisplay(display);
}
// Redraw all the cell towers and all the vehicles that are connected to towers.
// This code should run in an infinite loop continuously drawing the city.
// Vehicles are drawn as circles with radius VEHICLE_RADIUS.
void *showSimulation(void *c) {
City *city = c;
// Open the window
initializeWindow();
// Now keep redrawing until someone kills the thread
while(1) {
// Erase the background
XSetForeground(display, gc, 0xFFFFFF);
XFillRectangle(display, win, gc, 0, 0, CITY_WIDTH, CITY_HEIGHT);
// Draw all the cell towers
for (int i=0; i<city->numTowers; i++) {
short r = city->towers[i].radius;
XSetForeground(display, gc, city->towers[i].color);
for (int b=-3;b<=3; b++)
XDrawArc(display, win, gc,
city->towers[i].x-r+b, city->towers[i].y-r+b,
2*(r-b), 2*(r-b), 0, 360*64);
}
// Draw all the vehicles within each cell tower's range
for (int t=0; t<city->numTowers; t++) {
for (int i=0; i<MAX_CONNECTIONS; i++) {
if (city->towers[t].connectedVehicles[i].connected) {
XSetForeground(display, gc, city->towers[t].color);
XFillArc(display, win, gc,
city->towers[t].connectedVehicles[i].x-VEHICLE_RADIUS,
city->towers[t].connectedVehicles[i].y-VEHICLE_RADIUS,
2*VEHICLE_RADIUS, 2*VEHICLE_RADIUS, 0, 360*64);
XSetForeground(display, gc, 0x000000); // draw a black border
XDrawArc(display, win, gc,
city->towers[t].connectedVehicles[i].x-VEHICLE_RADIUS,
city->towers[t].connectedVehicles[i].y-VEHICLE_RADIUS,
2*VEHICLE_RADIUS, 2*VEHICLE_RADIUS, 0, 360*64);
}
}
}
XFlush(display);
usleep(2000);
}
closeWindow();
pthread_exit(NULL);
}
Also if anyone has some useful resources for threading, that would also be appreciated!!!
There are a few problems here:
pthread_t cellTowers[ottawa.numTowers];
int i;
for(i = 0; i < ottawa.numTowers; i++){
pthread_create(cellTowers[i], NULL, handleIncomingRequests, "");
pthread_join(cellTowers[i], NULL);
}
pthread_create stores the thread-id that it creates in memory location pointed at by the first argument.
Therefore, the first argument should be &cellTowers[i] (or equivalently cellTowers + i), and not cellTowers[i] that you are passing.
Your compiler should warn you that you are passing in a value of the wrong type. If you have not turned on compiler warnings, do so now. For GCC, use -Wall -Wextra -Werror.
Whenever you observe this sequence:
pthread_create ...
pthread_join ...
with the same thread-id in both, you can immediately know that the program is broken. The pthread_join will wait for the thread to complete. Therefore, no additional threads will be created until the first thread exits.
The way most threaded programs work:
for (...) pthread_create... // create all worker threads
// possibly perform additional work in main thread
for (...) pthread_join... // wait for all threads to finish
Finally, getting to your question: what should the 4th parameter be?
Since handleIncomingRequests() expects the argument to be a pointer to CellTower, that's what the 4th argument should be (that argument is passed directly to your function).
In this program, the 4th argument should be &ottawa.towers[i] (or equivalently ottawa.towers + i).

Using the gotoxy() function to center X coordinate

I want to write something using printf while also centering the x coordinate and y=0.
How can I center the x coordinate? For example someone might have their compiler window open in fullscreen and others might not? I want the text in the middle. Right now x is assigned a random value (50)
#include <stdio.h>
#include <conio.h>
int main()
{
gotoxy(50,0);
printf("Test");
return 0;
}
I'm just using an online compiler right now. onlinegdb.com Was thinking if there was a way to center the x so that it's the same in every compiler.
What is possible or not isn't determined by the compiler you are using, but by the platform and the ammount of code you are prepared to write.
Standard C has no idea of consoles, windows and other platform dependent stuff. If you want to get to know something about your consoles properties you have to ask the console/operating system. There are also libraries like ncurses for POSIX that allowes different terminals POSIX systems can run on to be treated uniformly.
An implementation of the ncurses-library that is available for DOS, OS/2, Win32, X11 and SDL is PDCurses. It can be used to write platform agnostic code.
But since you mentioned that your platform is windows, here is a solution that uses only the WinAPI:
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>
COORD get_console_dimensions(void)
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
COORD dimensions = { csbi.srWindow.Right - csbi.srWindow.Left,
csbi.srWindow.Bottom - csbi.srWindow.Top };
return dimensions;
}
COORD get_console_cursor_pos(void)
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
return csbi.dwCursorPosition;
}
void gotoxy(short x, short y)
{
COORD pos = { x, y };
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
void puts_centered(char const *str)
{
size_t length = strlen(str);
short x = (short)(get_console_dimensions().X - length) / 2;
gotoxy(x, get_console_cursor_pos().Y);
puts(str);
}
int main(void)
{
puts_centered("Hello, World!");
}
Using ncurses the same can be achieved (also works with PDCurses, include <curses.h> instead of <ncurses.h>):
#include <string.h>
#include <ncurses.h>
int main(void)
{
initscr();
int max_x = getmaxx(stdscr);
int y, x;
getyx(stdscr, y, x);
char const *str = "Hello, World!\n";
mvaddstr(y, (max_x - strlen(str)) / 2, str);
refresh();
// endwin(); // *)
}
Live: https://onlinegdb.com/HkIpXBUim
Please note that OnlineGDBs support for ncurses with its "terminal" is broken. getyx() won't tell the real width of its console.
*) Documentation says you should call endwin() before exiting your program. If you do so with OnlineGDB you won't get any visible output at all from OnlineGDB. Only if you click the "Copy output to clipboard"-button and view the copied text you'll see the ANSI escape sequences produced by ncurses.

glutTimerFunc() not limiting framerate

glutTimerFunc isnt making a delay it just loops forever. Like fxp. while(1).
Did I something wrong? Or is it a compatibility issue?
I am using arch linux x64 with gcc. And I've been kinda mixing 32 bit programs with 64 bit ones.
I am trying to make a program that checks for input whilst updating frames constantly under a delay
My includes are:
#include <GL/glut.h>
#include <GL/glu.h>
#include <stdio.h>
#include <string.h>
And my main functions are:
void timer(void)
{
glutPostRedisplay();
glutTimerFunc ( 30 , mainloop , 0 );
}
int main() {
loadconfiguration();
char *myargv [1];
int myargc=1;
myargv [0]=strdup ("./file");
glutInit(&myargc, myargv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowPosition(100, 100);
glutInitWindowSize(displayx, displayy);
printf("Making a window\n");
winIDMain = glutCreateWindow("GL Game");
mainloop();
}
void mainloop(void){
Initilize();
glutSetWindow (winIDMain);
glutDisplayFunc (render);
glutReshapeFunc (reshape);
glutKeyboardFunc (keyboard);
glutMouseFunc (mouse);
glutIdleFunc (timer);
glutMainLoop();
}
Don't worry other functions are clean :)
The code worked earlier I don't know why it doesn't work now.
Your mainloop should be called init. All it does is set glut callbacks. Rather than call glutPostRedisplay in the idle function, you should call it in a timer function. In other words, don't call glutIdleFunc(timer);. Instead, call timer() once yourself and have it add a timer to itself glutTimerFunc (30 , timer, 0);.
However, I would recommend doing the timing for a frame limiter yourself as it will be much more accurate. I wrote this answer for exactly that.

Resources