#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?
Related
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;
}
I was trying to write a basic program to print ā (a with overline) in C using curses and non-spacing characters. I have set the locale to en_US.UTF-8 and I am able to print international language characters using that. This code only prints a without overline. I am getting similar results with ncurses too. What else do I need to do to get ā on screen?
#include <curses.h>
#include <locale.h>
#include <wchar.h>
#include <assert.h>
int main() {
setlocale(LC_ALL, "");
initscr();
int s = 0x41; // represents 'a'
int ns = 0x0305; // represents COMBINING OVERLINE (a non-spacing character)
assert(wcwidth(ns) == 0);
wchar_t wstr[] = { s, ns, L'\0'};
cchar_t *cc;
int x = setcchar(cc, wstr, 0x00, 0, NULL);
assert(x == 0);
add_wch(cc);
refresh();
getch();
endwin();
return 0;
}
The curses calls need a pointer to data, not just a pointer.
It's okay to pass a null-terminated array for the wide-characters, but the pointer for the cchar_t data needs some repair.
Here's a fix for the program:
> diff -u foo.c.orig foo.c
--- foo.c.orig 2020-05-21 19:50:48.000000000 -0400
+++ foo.c 2020-05-21 19:51:46.799849136 -0400
## -3,7 +3,7 ##
#include <wchar.h>
#include <assert.h>
-int main() {
+int main(void) {
setlocale(LC_ALL, "");
initscr();
int s = 0x41; // represents 'a'
## -12,11 +12,11 ##
assert(wcwidth(ns) == 0);
wchar_t wstr[] = { s, ns, L'\0'};
- cchar_t *cc;
- int x = setcchar(cc, wstr, 0x00, 0, NULL);
+ cchar_t cc;
+ int x = setcchar(&cc, wstr, 0x00, 0, NULL);
assert(x == 0);
- add_wch(cc);
+ add_wch(&cc);
refresh();
getch();
That produces (on xterm) a "A" with an overbar:
(For what it's worth, 0x61 is "a", while 0x41 is "A").
Your code is basically correct aside from the declaration of cc. You'd be well-advised to hide the cursor, though; I think it is preventing you from seeing the overbar incorrectly rendered in the following character position.
I modified your code as follows:
#include <curses.h>
#include <locale.h>
#include <wchar.h>
#include <assert.h>
int main() {
setlocale(LC_ALL, "");
initscr();
int s = 0x41; // represents 'A'
int ns = 0x0305; // represents COMBINING OVERLINE (a non-spacing character)
assert(wcwidth(ns) == 0);
wchar_t wstr[] = { s, ns, L'\0'};
cchar_t cc; /* Changed *cc to cc */
int x = setcchar(&cc, wstr, 0x00, 0, NULL); /* Changed cc to &cc */
assert(x == 0);
set_curs(0); /* Added to hide the cursor */
add_wch(&cc); /* Changed cc to &cc */
refresh();
getch();
endwin();
return 0;
}
I tested on a kubuntu system, since that's what I have handy. The resulting program worked perfectly on xterm (which has ugly fonts) but not on konsole. On konsole, it rendered the overbar in the following character position, which is clearly a rendering bug since the overbar appears on top of the following character if there is one. After changing konsole's font to Liberation Mono, the test program worked perfectly.
The rendering bug is not going to be easy to track down because it is hard to reproduce, although from my experiments it seems to show up reliably when the font is DejaVu Sans Mono. Curiously, my system is set up to use non-spacing characters from DejaVu Sans Mono as substitutes in other fonts, such as Ubuntu Mono, and when these characters are used as substitutes, the spacing appears to be correct. However, Unicode rendering is sufficiently intricate that I cannot actually prove that the substitute characters really come from the configured font, and the rendering bug seems to come and go. It may depend on the font cache, although I can't prove that either.
If I had more to go on I'd file a bug report, and if I get motivated to look at this some more tomorrow, I might find something. Meanwhile, any information that other people can provide will undoubtedly be useful; at a minimum, that should include operating system and console emulator, with precise version numbers, and a list of fonts tried along with an indication whether they succeeded or not.
It's not necessary to use ncurses to see this bug, by the way. It's sufficient to test in your shell:
printf '\u0041\u0305\u000a'
will suffice. I found it interesting to test
printf '\u0041\u0305\u0321\u000a'
as well.
The system I tested it on:
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.4 LTS
Release: 18.04
Codename: bionic
$ konsole --version
konsole 17.12.3
$ # Fonts showing bug
$ otfinfo -v /usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf
Version 2.37
$ # Fonts not showing bug
$ otfinfo -v /usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf
Version 1.07.4
There are multiple issues here. First, you're storing the result of setcchar to random memory at an uninitialized pointer, cc. Whenever a function takes a pointer for output, you need to pass the address of an object where the result will be stored, not an uninitialized pointer variable. The output must be an array of sufficient length to store the number of characters in the input. I'm not sure what the null termination convention is so to be safe I'd use:
cchar_t cc[3];
int x = setcchar(cc, wstr, 0x00, 0, NULL);
Then, the add_wch function takes only a single character to add, and replaces or appends based on whether it's a spacing or non-spacing character. So you need to call it once for each character.
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).
I'm trying to get a curses program working with my terminal spanning my monitor. However, the x coordinate can't move past the 223rd column, instead it loops around. In the source, this seems to be due to them being defined as 8-bits, and having the position values start only after the first 32 values (i.e. x = raw_x - ' ').
Here's an example program from https://gist.github.com/sylt/93d3f7b77e7f3a881603 that demonstrates the issue when compiled with libncurses5. In it, if your cursor moves more than 233 columns to the right of the window, the x value will loop back over to 0 - ' ', i.e. -32
#include <curses.h>
#include <stdio.h>
int main()
{
initscr();
cbreak();
noecho();
// Enables keypad mode. This makes (at least for me) mouse events getting
// reported as KEY_MOUSE, instead as of random letters.
keypad(stdscr, TRUE);
// Don't mask any mouse events
mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);
printf("\033[?1003h\n"); // Makes the terminal report mouse movement events
for (;;) {
int c = wgetch(stdscr);
// Exit the program on new line fed
if (c == '\n')
break;
char buffer[512];
size_t max_size = sizeof(buffer);
if (c == ERR) {
snprintf(buffer, max_size, "Nothing happened.");
}
else if (c == KEY_MOUSE) {
MEVENT event;
if (getmouse(&event) == OK) {
snprintf(buffer, max_size, "Mouse at row=%d, column=%d bstate=0x%08lx",
event.y, event.x, event.bstate);
}
else {
snprintf(buffer, max_size, "Got bad mouse event.");
}
}
else {
snprintf(buffer, max_size, "Pressed key %d (%s)", c, keyname(c));
}
move(0, 0);
insertln();
addstr(buffer);
clrtoeol();
move(0, 0);
}
printf("\033[?1003l\n"); // Disable mouse movement events, as l = low
endwin();
return 0;
}
for the curious, you can build this with gcc file.c -lcurses
How do I workaround this? I can use vim in full-screen mode mode, and tmux mouse interactions also work. These both depend on ncurses, so it must be fixed somehow. I tried reading their source for hours and attempting samples of what I thought would work. I've also tried several printf() terminal modes, but none seem to enable this mode. How can I get my mouse event to hold more than 8 bits, and thus let the columns field hold values larger than 232?
That's a terminal-dependent feature (not an ncurses limitation as such). The original xterm protocol dating from the late 1980s encodes each ordinate in a byte, reserving the first 32 for control characters. That gives 256 - 32 = 223.
xterm introduced an experimental feature in 2010 to extend the range. There is an ncurses terminal description "xterm-1005" which uses that. Some criticized that, and xterm introduced an different feature in 2012. Again, there is a "xterm-1006" using that feature.
The descriptions in ncurses were added in 2014. ncurses 6 was released in 2015, and still supports (by compile-time options) the ABI 5 for ncurses 5. If your "ncurses5" is at least as new as the changes in 2014, the library supports SGR 1006 without change.
The reason for not making one of those part of the default "xterm" is that portability across the various xterm imitators is poor (as is their documentation), and that would only increase bug reports. But if you happen to be using one of the terminals (such as xterm...) which support the SGR 1006 feature, that's supported in the ncurses library.
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.