GtkEntryCompletion without user input? - c

Hopefully this is an easy question to answer! I am trying to use GtkEntryCompletion (a la the example here) but while this code works I can't seem to get the GtkEntry to present the autocomplete results when I set the text of the field programatically. What I am trying to accomplish is a semi pre-filled text entry that is already presenting the user with some autocomplete options.
To set the text I have tried using the functions gtk_entry_set_text(...), gtk_entry_buffer_insert_text(...) and even gtk_entry_buffer_emit_inserted_text(...) but to no avail. Is there a way to do this in such a way as to act like regular user input and display the suggestions?

I think you need to call gtk_entry_completion_complete after setting the text.
EDIT
Sorry #Tylter, but wow, this is way more difficult than I imagined. The only way I can figure out how to do it is to actually send the keypress event to the window.
gtk_widget_grab_focus(entry);
GdkEvent new_event;
new_event.key.type = GDK_KEY_PRESS;
new_event.key.window = gtk_widget_get_parent_window(entry);
new_event.key.send_event = TRUE;
new_event.key.time = GDK_CURRENT_TIME;
new_event.key.keyval = 0x053; // capital S
new_event.key.state = GDK_KEY_PRESS_MASK;
new_event.key.length = 0;
new_event.key.string = 0;
new_event.key.hardware_keycode = 0;
new_event.key.group = 0;
gdk_event_put((gpointer)&new_event);
EDIT 2
Are you using a GtkDialog for your pop-up? I coded this up really quick and it seems to work. Here you would be creating the dialog in a button click event:
static void click_event( GtkWidget *widget,
gpointer data )
{
GtkWidget* window = gtk_dialog_new ();
completion = create_completion();
entry = gtk_entry_new();
gtk_entry_set_completion(GTK_ENTRY(entry), completion);
// add entry to dialog
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
entry, TRUE, TRUE, 0);
gtk_widget_show(entry);
gtk_widget_show(window); // you must show the window before sending the keypress event
gtk_widget_grab_focus(entry);
GdkEvent new_event;
new_event.key.type = GDK_KEY_PRESS;
new_event.key.window = gtk_widget_get_parent_window(entry);
new_event.key.send_event = TRUE;
new_event.key.time = GDK_CURRENT_TIME;
new_event.key.keyval = 0x053; // capital S
new_event.key.state = GDK_KEY_PRESS_MASK;
new_event.key.length = 0;
new_event.key.string = 0;
new_event.key.hardware_keycode = 0;
new_event.key.group = 0;
gdk_event_put((gpointer)&new_event);
}
The only gotcha I saw with this is that your must show the dialog window before sending the keypress event.

Related

making selectable the text of a GtkStatusbar

I have a statusbar, and I want to have its text being selectable (e.g. copy and pastable), on Linux/Debian, with GTK3 (3.21.5 on Debian/Sid). The label of the statusbar is the label field of its private data, and there is no direct API to access it.
I was able to code (in C99) the following, which is working:
mom_cmdstatusbar = // some global variable
gtk_statusbar_new ();
{
GtkWidget *statmsgarea =
gtk_statusbar_get_message_area (GTK_STATUSBAR (mom_cmdstatusbar));
MOM_ASSERTPRINTF (GTK_IS_CONTAINER (statmsgarea), "bad statmsgarea#%p",
statmsgarea);
GList *lischs = gtk_container_get_children (GTK_CONTAINER (statmsgarea));
for (GList * l = lischs; l != NULL; l = l->next)
{
GtkWidget *chwidg = l->data;
MOM_ASSERTPRINTF (GTK_IS_WIDGET (chwidg), "bad chwidg#%p", chwidg);
if (GTK_IS_LABEL (chwidg))
gtk_label_set_selectable (GTK_LABEL(chwidg), true);
}
g_list_free (lischs), lischs = NULL;
}
This does work, but is there a better or simpler way to do that? Getting the list of children inside the message area of the GtkStatusbar and testing each of them smells bad. It looks like some GtkWidget* gtk_statusbar_get_label (GtkStatusbar*); function is missing in in the GTK3 API.
PS. FWIW, the code is GPLv3+, on github in file gui.c on commit 58feb1d9473c34aca.. of the expjs branch. More details & motivation about that software project on this & that questions.
If there's no direct API to access the internal child, then that is probably on purpose, so that the GTK developers can keep their options open to reorganize the internal layout of the widget in future versions.

GTK in C language: Replace a image from event box

I'm trying replace a image from event_box but doesn't work.
When the user click in a Event box, I try remove the image from the event box and add another, but when I run just remove the image and not add another.
void selecFichas(GtkWidget *casillaAtril, gpointer data){
int i;
for(i = 0; i < LETRAS; i++)
if(casillaAtril == atrilJugador1[i]){
Element = i;
break;
}
gtk_container_remove(GTK_CONTAINER(atrilJugador1[Element]), fichasABC[coordImagen[Element][0]][coordImagen[Element][1]]);
gtk_container_add(GTK_CONTAINER(atrilJugador1[Element]), casillasAtriles[Element]);
}
Have you made sure to call gtk_widget_show() on the image that you added?
You can open up the GTK Inspector with Ctrl+D or Ctrl+I and check whether the new image is actually in there or not, and whether it is visible or not.

GtkButton to emit GDK_KEY_PRESS

I'm attempting to attach to a toolbar button a signal associated with a keystroke supported by GtkTextView (CTRL+a, CTRL+x, etc) using the following widget structure, signal connect, and callback:
typedef struct
{
GtkWidget *window;
GtkWidget *text_view;
}EditorWidgets;
//...
g_signal_connect(cut, "clicked", G_CALLBACK(cut_button_press), editor_widgets);
//...
static void cut_button_press(GtkWidget *button, EditorWidgets *editor_widgets)
{
UNUSED(button);
GdkEvent *event = gdk_event_new(GDK_KEY_PRESS);
event->key.window = gtk_widget_get_window(editor_widgets->window);
event->key.send_event = FALSE;
event->key.time = 0;
event->key.state = GDK_CONTROL_MASK;
event->key.keyval = GDK_KEY_x;
event->key.string = g_strdup("x");
event->key.length = strlen(event->key.string);
gtk_main_do_event(event);
gdk_event_free(event);
}
When run, GDK complains with the following:
(ex1:7856): Gdk-WARNING **: Event with type 8 not holding a GdkDevice. It is most likely synthesized outside Gdk/GTK+
Which lets me know I've created the signal improperly (I assume). However, there's very little out there about having buttons emit GDK signals, so I'm at a loss for what's missing here.
As a secondary question, I remember reading somewhere that there was a GDK #define for TIME_NOW or something, but I couldn't find it again. Any hints there?
1.use "key-press-event" instead of clicked, clicked was associated with mouse pointer and keyboard enter key, something like (in python):
def on_key_press (self, widget, event):
if event.keyval == 120:
print ('test')
2.GDK_CURRENT_TIME, define at Gdk.Event class

Gtk+ delayed white screen (flash plugin + NPAPI)

I created an standalone application which run compiled flash (.swf) on a gtk+ UI with NPAPI. When my video runs, there's a small time where there's a white screen (maybe 1 or 2 sec). It's kind of annoying and I am wondering if I can do something to get rid of it.. by going with Xlib for example (native). Is it possible? I guess it is, but I'm pretty new to this stuff and only ran my first application ("hello world"). I'm pretty sure it's very low level and demands considerable amount of time to do the same thing. I could provide the code if necessary.
1) What could be possibly causing the white screen delay (before loading my flash) in gtk+?
2) How difficult could it be to implement a window in native Xlib to render flash? For example, for setting up NPWindow...
Gtk++ (would look something like this)
static NPWindow *
npwindow_construct (GtkWidget *widget) {
NPWindow *npwindow;
NPSetWindowCallbackStruct *ws_info = NULL;
GdkWindow *parent_win = widget->window;
GtkWidget *socketWidget = gtk_socket_new();
gtk_widget_set_parent_window(socketWidget, parent_win);
gtk_widget_set_uposition(socketWidget, xPosition, yPosition);
g_signal_connect(socketWidget, "plug_removed", G_CALLBACK(plug_removed_cb), NULL);
g_signal_connect(socketWidget, "unrealize", G_CALLBACK(socket_unrealize_cb), NULL);
g_signal_connect(socketWidget, "destroy", G_CALLBACK(gtk_widget_destroyed), &socketWidget);
gpointer user_data = NULL;
gdk_window_get_user_data(parent_win, &user_data);
GtkContainer *container = GTK_CONTAINER(user_data);
gtk_container_add(container, socketWidget);
gtk_widget_realize(socketWidget);
GtkAllocation new_allocation;
new_allocation.x = 0;
new_allocation.y = 0;
new_allocation.width = WINDOW_XSIZE;
new_allocation.height = WINDOW_YSIZE;
gtk_widget_size_allocate(socketWidget, &new_allocation);
gtk_widget_show(socketWidget);
gdk_flush();
GdkNativeWindow ww = gtk_socket_get_id(GTK_SOCKET(socketWidget));
GdkWindow *w = gdk_window_lookup(ww);
npwindow = malloc (sizeof (NPWindow));
npwindow->window = (void*)(unsigned long)ww;
npwindow->x = 0;
npwindow->y = 0;
npwindow->width = WINDOW_XSIZE;
npwindow->height = WINDOW_YSIZE;
ws_info = malloc(sizeof (NPSetWindowCallbackStruct));
ws_info->type = NP_SETWINDOW;
ws_info->display = GDK_WINDOW_XDISPLAY(w);
ws_info->colormap = GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(w));
GdkVisual* gdkVisual = gdk_drawable_get_visual(w);
ws_info->visual = GDK_VISUAL_XVISUAL(gdkVisual);
ws_info->depth = gdkVisual->depth;
npwindow->ws_info = ws_info;
npwindow->type = NPWindowTypeWindow;
return npwindow;
}
3) What is the difference between Xlib and Xt?
Any advice or fix is appreciated.
thank you.
EDIT: I tried to embed Xlib within my gtk components. So, create a simple window (XCreateSimpleWindow) within my main GdkWindow (widget->window). I'm kind of lost on how to do this... Because, gtk_socket_new() creates a process which enable gtk component to reach (enable to be "feed") data from my npapi plugin. So, how do I populate (code) the NPWindow?
GtkWidget *socketWidget = gtk_drawing_area_new ();
gtk_drawing_area_size (socketWidget , WINDOW_XSIZE, WINDOW_YSIZE);
gtk_widget_realize (socketWidget);
XCreateSimpleWindow (GDK_WINDOW_XDISPLAY (parent_win), GDK_WINDOW_XWINDOW (parent_win), 0, 0, WINDOW_XSIZE, WINDOW_YSIZE, 0, 0);

Remove GTK+ container children, repopulate it, then refresh

I'm into a problem with a GTK+ C application. I have a container that, when starting the application, contains a button. During the running an user interation must cause this widget to contain more of them.
I need to write a function that removes all the "old" inner buttons, then adds all the ones from a list and finally refresh the view. This is what I'm writing but some parts are missing (TODOs)
void refresh_sequence_panel()
{
GSList* iterator = NULL;
GtkWidget* button;
// TODO: Here the container must be empty
// Now add all the buttons
for (iterator = steps; iterator; iterator = iterator->next) {
button = gtk_button_new_from_stock(GTK_STOCK_ADD);
gtk_widget_set_size_request(button, SEQ_BUTTON_W, SEQ_BUTTON_H);
gtk_box_pack_start(GTK_BOX(sequence_panel), button, FALSE, FALSE, 5);
handler_id = g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(seq_popup), GTK_BOX(sequence_panel));
}
// TODO: Now refresh the view, so I can see the changes...
}
Hope that someone can help, thanks!
Removing all children:
GList *children, *iter;
children = gtk_container_get_children(GTK_CONTAINER(container));
for(iter = children; iter != NULL; iter = g_list_next(iter))
gtk_widget_destroy(GTK_WIDGET(iter->data));
g_list_free(children);
Note that the above just deletes each child widget directly, rather than asking the container to remove it (with gtk_container_remove()), this is recommended by the documentation and matches what you intend, so it's fine in my opinion.
There's no point in "refreshing the view", as long as you actually add and show the newly built widgets to the container. GTK+ is event-based, and adding children to a container makes the container realize it needs to refresh its visual appearance automatically.
One-liner:
gtk_container_foreach (GTK_CONTAINER (container), (void*) gtk_widget_destroy, NULL);
Here is the method that I followed. Because I am using gtkmm on c++
Gtk::Box_Helpers::BoxList *childList = &vboxImgLst->children();
Box_Helpers::BoxList::iterator start = childList->begin();
Box_Helpers::BoxList::iterator end = childList->end();
childList->erase(start, end);
where vboxImgLst is,
VBox *vboxImgLst;
Hope this will help to someone who are using gtkmm and c++.
Thanks
This one worked for me (it's a variation of unwind's answer):
Glib::ListHandle<Widget*> childList = this->get_children();
Glib::ListHandle<Widget*>::iterator it = childList.begin();
while (it != childList.end()) {
remove(*(*it));
it++;
}
(GTKMM 2.4)

Resources