I'm writing a Win32 console application that interacts with the mouse. I'm using ReadConsoleInput to get the window-relative mouse movements like so. Here's a simplified version of my problem:
int main(void)
{
HANDLE hStdin;
DWORD cNumRead;
INPUT_RECORD irInBuf[128];
hStdin = GetStdHandle(STD_INPUT_HANDLE);
SetConsoleMode(hStdin, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT);
while (1)
{
mouse_position_changed = 0;
ReadConsoleInput(hStdin, irInBuf, 128, &cNumRead);
/* input handler here: changes the cursor position if the mouse position changed;
clears screen if mouse position changed;
sets mouse_position_changed (self-explanatory).
(this part of the code is irrelevant to the quesiton at hand) */
if (!mouse_position_changed)
putchar('0');
}
}
(I've removed most of the code including error checks. This is a simple, watered-down version of what I'm doing; it's much larger-scale than making 0's run away from the cursor.)
I want the screen to be cleared and the cursor set to the mouse coordinates whenever the mouse is moved. This part is working.
I want 0 to be printed the screen whenever the mouse is not moved. This will have the effect of 0's running away from the mouse cursor. This is not working, because ReadConsoleInput will block until it receives input.
The 0 is not printed until more input is received. Unless the user continually hits the keyboard, nothing is printed because whenever the mouse is moved, the screen is cleared.
The problem
I would like the loop to continue even when no input is present. ReadConsoleInput waits for input to be read, which means that the loop will pause until the keyboard is hit, or the mouse is moved.
I'm looking for an alternative to ReadConsoleInput, or a way to make it non-blocking.
This is all documented in ReadConsoleInput. You can determine if there is a console input with GetNumberOfConsoleInputEvents. And you are able to to determine the type of console input events with PeekConsoleInput.
So GetNumberOfConsoleInputEvents is all you need.
You can also use WaitForSingleObject with the console handle to wait for a next available input. This is also documented in ReadConsoleInput
Related
I want to refresh the screen every one second. I'm implementing a chat with ncurses.
So far, I have the following function:
void print_chat(char *chat) {
mvprintw(1, 1, "RPC Chat");
move(2, 1);
for (int i=0; i<CHAT_WIDTH; i++) {
addch('_');
}
move(CHAT_HEIGHT + 3, 1);
for (int i=0; i<CHAT_WIDTH; i++) {
addch('_');
}
mvprintw(CHAT_HEIGHT + 5, 1, "Enter message: ");
}
Which prints the following screen:
In the main function I'd like to have a loop that refreshes the screen every 1 second, obtaining possible new messages from a server, and refreshes the screen in that interval so if any, new messages could be displayed. I also want to read users input while the refreshing goes on at the same time. Do I need threads?
My attempt so far in the main function:
while (1) {
print_chat(chat);
refresh();
sleep(1);
chat = read_chat_from_server();
/*char l = getch(); --> This would block the loop, waiting for input...
}
Do I need threads to achieve this? If so, would the thread be able to reprint the screen? Any other way to solve this problem?
The problem is that getch() is waiting for the user to press return.
You want to have a look at raw() and call it once before getting any input. By calling this function you can get characters from the user without him pressing return, pausing your program. Basically the console reads user input, prints each character as its being written, and when the user sends '\n', it returns that input to your program (See this answer).
You might want to look at noecho() too. Similar to raw(), lets you scan for user input (using getch()) without printing the characters on the screen. This is usually useful for letting your program handle how the characters are displayed.
Finally, it may be a good idea to call refresh() when something gets updated (e.g. check each second if you got a message, you sent one, etc.) and then call refresh(). If you still want to run it every second, maybe try nodelay(stdscr, 1), where stdscr is your default window:
The nodelay option causes getch to be a non-blocking call. If no input is ready, getch returns ERR. If disabled (bf is FALSE), getch waits until a key is pressed.
You need to call the timeout() function when you first initialize your program.
timeout(0) should cause getch() to not wait for user input.
I'm working on a library that creates transparent X windows and uses cairo to draw on them. There is an event loop implemented in the main thread, while the drawing operations take place in a separate thread within a loop. The latter looks like this
while (self->_running) {
PyGILState_Release(gstate);
usleep(1000); // Sleep 1 ms
gstate = PyGILState_Ensure();
if (self->_expiry <= gettime()) {
draw(self, args_tuple); // All the cairo code is in here
self->_expiry += interval;
interval = self->interval;
}
}
The event loop calls XNextEvent periodically to trap key/button presses only. The window is mapped before the new UI thread is started from the main thread.
When the interval between iterations on the UI thread (the self->inteval value above) is large (order of seconds), the window stays transparent on the first iteration of the loop, and it only gets painted on from the second iteration onward. Calling draw right before the while loop doesn't help, unless there is a pause of some milliseconds in between calls to draw. For example, if I put interval = 25 right before the while loop, then the second call to draw paints on the window in most of the executions of the application implementing this code.
Things that I have tried:
cairo_surface_flush and XFlush right after draw don't seem to work
Sending an Expose event doesn't seem to help either.
How can I make sure that my loop starts painting on the window from the first iteration?
What I'm missing is the ExposureMask flag in the call to XSelectInput. With this flag set, one then has to look for Expose events in the event loop with the following pattern:
switch (e.type) {
case Expose:
if (e.xexpose.count == 0) {
BaseCanvas__redraw(canvas);
}
return;
}
The redraw operation doesn't need to be the full set of draw operations. Having modified the cairo context, it is enough to repaint it on the destination with no more than this
void
BaseCanvas__redraw(BaseCanvas * self) {
cairo_save(self->context);
cairo_set_operator(self->context, CAIRO_OPERATOR_SOURCE);
cairo_paint(self->context);
cairo_restore(self->context);
}
To me it looks like you are mapping the window and then immediately starting a thread that tries to draw to the window. Thus, if you try to draw before the window manager actually made the window visible, your drawing goes nowhere. If the window manager wins the race and the window actually becomes visible before your draw, the drawing actually works.
Your own answer is not an answer to your question. The question is "why does it stay transparent in the first iteration?" while your answer is (basically) "Don't use threads, just do all drawing in the main loop".
(Of course, handling Expose events is the right thing to do, but that's not what the question asked.)
I'm coding a console editor in C. I'm using CodeLite Editor on Windows. I want to insert a newline ('\n') when the user presses Return (Enter) key. I want to accomplish this goal with getchar() function is that possible?
I need it because I want to increment the y axis variable.
Code I'm trying on :
int X = 0; // X-axis
int Y = 0; // Y-axis
char key = getchar();
if (key=='sth') // Here I want to perform my check
{
//Do Something
++Y;
}
Update :
If it has a code like : '\x45' for example post it in the comments plz!!!
If you are trying to implement an editor, you will quickly find that getchar() is not the way to interpret keyboard events. In this very simplistic example, where all you might do is wait for a single keystroke of input that either is or is not a newline, your program will work if you change 'sth' (an abbreviation for "something"?) to '\n'. However, as your editor becomes more complicated, you will want to have an actual event handler that can detect any sort of keyboard events and can asynchronously deal with them. getchar() is not the way to do that.
This answer from 7 years ago shows that (1) you can go a limited distance with getch() (and getchar()), but (2) a far larger number of people agree that it's no substitute for a real event handler: Detect Keyboard Event in C
I'm writing a cross-platform application that on certain condition takes control of all user input for a period of time.
On GNU/Linux I've used gtk+, which allows me to retrieve mouse and keyboard events such as movement or presses. That's something I need as my application responds to them. It has also a small graphical interfce created with gtk+.
I've been trying to grab mouse input on Windows without success as gtk does work well graphically, but does not grab user input. I've tried using BlockIntput() but it does not works as expected because:
I need administrator priviledges to run the application
I can't read mouse nor keyboard input
Is there a way to grab mouse and keyboard input on windows and still being able to read their inputs without administrative rights?
I finally found a solution that fits my requirements. One of Marc's links guided me to the use of hooks on Windows which I had already tried with no success, but I ended up implementing them for both keyboard and mouse grabbing.
My Windows code uses windows libraries and when I need to block input I create a thread which calls a function:
DWORD dwThread;
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MouseHooker, NULL, 0, &dwThread);
Then I install the hook:
DWORD WINAPI MouseHooker(LPVOID lpParameter) {
HINSTANCE hExe = GetModuleHandle(NULL);
//The thread's parameter is the first command line argument which is the path to our executable.
if (!hExe) //If it fails we will try to actually load ourselves as a library.
hExe = LoadLibrary((LPCSTR) lpParameter);
if (!hExe)
return 1;
//Install the hook as a low level mouse hook thats calls mouseEvent
hMouseHook = SetWindowsHookEx (WH_MOUSE_LL, (HOOKPROC)MouseEvent, hExe, 0);
...
UnhookWindowsHookEx(hMouseHook);
return 0;
}
And on each mouse event code gets called:
if (nCode == HC_ACTION && ...) { //HC_ACTION means we may process this event, we may add specific mouse events
//We block mouse input here and do our thing
}
//return CallNextHookEx(hKeyHook, nCode, wParam, lParam);
return 1;
So as we not continue with the hook chain input never gets processed and the workstation gets blocked.
The code runs on Windows 7 as expected. I kept using gtk+ on Windows as I can still generate my GUI and retrieve mouse inputs with gdk.
On GNU/Linux code works only using GTK+ libraries as I had no issues when grabbing input.
I am working on a GTK+ editor in C. I have added a feature of displaying the current line number and column number of the cursor position in the textview. Its working well. But the drawback is when I attempt to move the cursor with the arrow keys the line number and column number do not get updated. Below is my code for updating the line number and column number
update_statusbar(GtkTextBuffer *buffer,GtkStatusbar *statusbar)
{
gchar *msg;
gint row, col;
GtkTextIter iter;
gtk_statusbar_pop(statusbar, 0);
g_print("c");
gtk_text_buffer_get_iter_at_mark(buffer,
&iter, gtk_text_buffer_get_insert(buffer));
row = gtk_text_iter_get_line(&iter);
col = gtk_text_iter_get_line_offset(&iter);
msg = g_strdup_printf("Col %d Ln %d", col+1, row+1);
gtk_statusbar_push(statusbar, 0, msg);
g_free(msg);
}
int main ( int argc, char *argv[])
{
.
.
.
.
.
.
g_signal_connect(buffer, "changed", G_CALLBACK(update_statusbar), statusbar);
update_statusbar(buffer, GTK_STATUSBAR (statusbar));
}
I guess the problem is with "changed" signal. Since the cursor is moved with arrow keys, buffer doesn't get changed. So can anyone suggest me a better way to solve the problem .
Thanks in advance :).
The TextBuffer "cursor-position" property has the buffer offset of the insertion mark (aka cursor). The signal corresponding to this property changing is named "notify::cursor-position", and is a notify signal as defined in gobject.
There's a list of text buffer signals here and a list of general widget signals here.
The latter link has a signal called key-release-event which you will probably find interesting.
This is the probably the best way to do this job. Although the move_cursor signal on GtKTextView works well for key press. It does not respond to mouse click based cursor position change. Notify signal on GtKTextView works for mouse click but causes thread conflict while trying to update the buffer's insert position. So the best thing is to directly associate the signal "notify::cursor-position" to the buffer behind GtKTextView. No need to associate signal to GtKTextView.