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.
Related
I'm having issues with my termbox program rendering the screen and handling keyboard events. Recently, I've finished a C and C++ class at my university. I wanted to demonstrate my knowledge by creating a basic Snake game. The first steps, I wanted to get a simple render loop going and have a block of text simply move leftward and exit the game upon reaching the 0th x-coordinate. The issue arises when continuing to the next render frame, because the game is running single-threaded the next frame won't be rendered until a new keyboard event is accepted. Ordinarily, I would expect the game to continue rendering regardless of events, new events affecting the new frame.
As for potential solutions, I thought about using multiple threads to run the game loop and handle keyboard events. But, I think this would be overkill for such a small problem, there are likely easier alternatives than having to manage multiple threads for a simple snake game.
As for the code, it's as simple as:
while (1)
{
tb_clear();
draw(gameState);
tb_present();
struct tb_event event;
tb_poll_event(&event);
if (event.ch == 'q')
break;
}
After digging through the header file a bit more I found a method which doesn't wait forever.
/* Wait for an event up to 'timeout' milliseconds and fill the 'event'
* structure with it, when the event is available. Returns the type of the
* event (one of TB_EVENT_* constants) or -1 if there was an error or 0 in case
* there were no event during 'timeout' period.
*/
SO_IMPORT int tb_peek_event(struct tb_event *event, int timeout);
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 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
I have a GTK program with a lot of buttons. When I press one of them, my program starts to displaying a buffer, line by line, in this way:
...
gchar * stuff = g_strdup_printf("Some text");
gtk_text_buffer_insert(buffer, &iter, stuff, -1);
g_free(stuff);
while (gtk_events_pending())
gtk_main_iteration();
...
Because I manage a lot of data, this method is very slow.
I want a second plane mode when some variable reach a high value (for example an int scndplane=1). My idea for this mode is a normal execution of the main program, but to display the buffer only at the end of the program (a kind of backbuffer).
Is there any efficient way to do it?
Thank you.
Why do not you simply make a method of this and then call it at the end of your program ?
If you press your button during the exexution, put a boolean at true.
Then at the end of your program, you will have something along the lines of:
if(isClicked)
displayBuffer();
I'm attempting to write a simple chat application in C using ncurses, both of which I am new to with a background in PHP. (Yes, I know. Thanks. I'll take that advice to heart. Please put down the guns.)
What I've attempted to do is create two windows, one for input and one for channel text, like so:
int termwidth = getmaxy(stdscr);
int termheight = getmaxx(stdscr);
WINDOW *channel = newwin(termwidth, termheight - 1, 0, 0);
scrollok(channel, TRUE);
WINDOW *input = newwin(termwidth, 1, termheight + 1, 0);
scrollok(input, TRUE);
and then set cursor position to input:
wmove(input, 0, 0);
in order to put typed input in the second window, which should occupy a single column at the bottom of the terminal, while output appears in the first window which fills the rest of the terminal's space.
Output appears to fill the top window (channel) properly, with the input cursor flashing in the proper place, but changing its size does not yield predictable results and typed input doesn't appear to be going into the input window at all.
The complete source is available here: http://pastebin.com/X8apHUgh
To sum up, I am asking why input is behaving unexpectedly, and why drawing the "channel" window is yielding strange results.
Oh, [expletive/deleted]! I'm an imbecile. It turns out my problem was twofold:
I had inadvertently mixed my X and Y assignments, and
I had also reversed the width and height parameters in the functions.
This meant that positioning worked properly, until I made certain assumptions for basic positioning math.
I should add that this is partly because I was conceiving terminal positioning in terms of X/Y position, where rows/cols is the paradigm in place. They are only partly equivalent.
slow clap for self