How to have gtk control+c to be handled, or not? - c

I'm using pygtk, and would like to handle control+c sometimes to do a special copy action, but other times to let gtk handle it. For example, I'd like to put an object on my clipboard if it is available, or just let control+c be used in the normal fashion in a text entry.
Currently I have an ActionGroup associated with "c" but that always eats the keystroke, even if I return False. If I remove the ActionGroup, it always works in the text areas. If I add the ActionGroup, it always handles it, and copy doesn't work in the text areas.
What is the proper manner to have control+c appear in the menu, handle the keystroke sometimes, but other times, let it fall to a text widget?

I don't know if this is the "proper" way, but here is how I do it. I pass the application window as the user data parameter to the action callback. Then I find out which widget is focused in the window, and I pass the copy command on to that widget if that makes sense to do (i.e. the focused widget is a text entry like you say). If that doesn't make sense, then I copy from the window's 'default' text view.
void
action_copy(GtkAction *action, gpointer user_data)
{
GtkWidget *widget = gtk_window_get_focus(GTK_WINDOW(user_data));
/* What actually happens depends on the type of widget that is focused */
if(WEBKIT_IS_WEB_VIEW(widget))
webkit_web_view_copy_clipboard(WEBKIT_WEB_VIEW(widget));
else if((GTK_IS_LABEL(widget) && gtk_label_get_selectable(GTK_LABEL(widget)))
|| GTK_IS_ENTRY(widget) || GTK_IS_TEXT_VIEW(widget))
g_signal_emit_by_name(widget, "copy-clipboard", NULL);
else
g_signal_emit_by_name(/* ...default text view... */, "copy-clipboard", NULL);
}
(Obtaining the default text view is actually done by calling a get_default_view() method on my application class, which is a subclass of GtkWindow; but I didn't want to complicate matters here.)

Related

Initialization of GtkApplication - Should I use GObject's "init" or GtkApplication's "startup"?

I'm trying to create a GTK-3 Application and in the initialization process I want to check if the GSetting's value is set, otherwise I want to show a "startup" dialog which will be only on the first run visible.
The GObject's has a _init suffix which can be used for the class initialization. In that case the MyGtkApplication will be constructed, which is based on GtkApplication. The GtkApplication has the startup-thing which can be used for the initialization too.
In that example, I still need to implement the _init function for GApplicationClass.
GApplicationClass *gapp_class;
gapp_class = G_APPLICATION_CLASS (class);
gapp_class->startup = app_startup;
// This must be always implemented, because the MyGtkApplication is "GtkApplication"-based class.
void app_init(MyGtkApplication *app) {
// Check and show the modal dialog if key does not exist?
}
// This will overwrite the GApplicatio's "startup".
void app_startup(GApplication *app) {
// Check and show the modal dialog if key does not exist?
}
Currently app_init does not have a body.
What is the difference and which one should I use?
Regards,
TheAifam5.
init is basically the constructor of the GApplication object. Use it for initializing the object's private data and putting it into a consistent state.
startup is invoked when the application starts. In particular, after you have called g_application_run() and the main event loop is started, and the application has checked that it is the only instance running. You don't want to show dialog boxes before then, so startup is the right place to do that.

g_signal_connect & g_signal_connect_swapped [duplicate]

According to GObject reference
g_signal_connect_swapped(instance, detailed_signal, c_handler, data); connects a GCallback function to a signal for a particular object. The instance on which the signal is emitted and data will be swapped when calling the handler.
I don't quite get what this means. Does this mean that the data will point to the object pointed to byinstance and instance will point to the object that was pointed to by data or am I making a mistake here?
If former is the case then what is the logic behind this?
You understand correctly.
This allows you to do tricks like the following: You have a button (let's call it button), that is supposed to hide another widget (let's call it textview) when pressed.
You can then do
g_signal_connect_swapped(button, 'clicked', G_CALLBACK(gtk_widget_hide), textview);
to achieve that. When the button is pressed, it generates the 'clicked' signal, and the callback is called with textview as the first argument, and button as the second. In this case the callback is gtk_widget_hide() which only takes one argument, so the second argument is ignored, because that's the way the C calling convention works.
It's the same as the following, but shorter.
static void
on_button_clicked(GtkButton *button, GtkWidget *textview)
{
gtk_widget_hide(textview);
}
...elsewhere...
g_signal_connect(button, 'clicked', G_CALLBACK(on_button_clicked), textview);
Basically it saves you from having to write an extra function if you hand-code your interface. Of course, there may be some far more practical use that I've never understood.

Animated window icon

I have seen a rare amount of programs, having animated window icons.
From a distant vantage point, this could be rather beneficially isn't it..
I took the rudder in the process of inventing one function to do so.
It does what you probably thought of and using Sleep() to simulate intervals after each "frame".
I don't have to say that using WinAPI in major programs is a bad idea as well as the fact that the program will freeze until the function terminates.
Back on track. I am looking for a possibility to avoid this behavior.
It is understandable, hence no one wants a non-functional but take a note WITH ANIMATED ICON program.
You are probably calling your function from the Main Event Loop. This is the thread where all sort of GUI events are handled, including mouse clicks and key presses. If you call Sleep from within this thread, all these processing tasks will be pending and your program will freeze.
To avoid this behavior, use g_timeout_add. This function will call a function at regular intervals from within the Main Event Loop (so no need to do it yourself). You need to define a function like this:
// define this function somewhere
gboolean animate(gpointer user_data) {
// cast user_data to appropriate type
// supposing you have a AnimationParameters class with everything you need...
AnimationParameters* animParams = (AnimationParameters*)user_data;
// update animation
// ...
return TRUE; // return TRUE to call function again, FALSE to stop
}
Elsewhere in your code, to start the animation:
AnimationParameters* animationParameters = new AnimationParameters(...);
g_timeout_add (30, // call every 30 milliseconds
animate,
animationParameters);
Hope it helps.

Get monitor number widget is on in gtk 2

So there is an application I would like to patch. It uses GtkWidget as its topmost container. I would like to do what follows, check number of screens, if it is >2 then check the width of the screen the app is executed on (focus is on screen). I could use Xinerama but first I would like to try native Gtk things. What I do is:
num_monitors = gdk_screen_get_n_monitors (screen);
Then I found a function gdk_screen_get_monitor_at_window(screen, ?window?) but it takes screen and GtkWindow as its argument. Unfortunately I have no window, only widget. I tried to get window by gtk_widget_get_parent_window(widget) or gtk_widget_get_window(widget) these always result in giving me GDK_IS_WINDOW (widget) failed. On the other hand gtk_widget_get_has_window(window) returns 1.
How can I determine screen the app was run on ? I need it to set width hints right.
You're probably failing to get the window because the widget isn't realized and/or mapped, yet. You'll get NULL from gtk_widget_get_window() if it isn't.
The return value from gtk_widget_get_has_window() is probably static; a particular class of widget either always has a window, or never has one.
Try forcing the widget to be realized with gtk_widget_realize(), before extracting the window. If that fails, also try to map it.
You might want to investigate this from the other end, i.e. decide which screen you want/expect the widget to use, and look up that screen's info, without starting from the widget itself.
The window must be actually shown before the function returns you the correct screen the window resides on. This makes your window manager apply its placement policy. To ensure the widget is shown you can use gtk_main_iteration(), calling it until there are no more pending events.
Example code:
#include <stdio.h>
#include <gtk/gtk.h>
int main(int argc, char** argv)
{
gtk_init(&argc, &argv);
GtkWidget*const widget=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_show(widget);
while(gtk_events_pending())
gtk_main_iteration();
GdkWindow*const window=gtk_widget_get_window(widget);
GdkScreen*const screen=gdk_window_get_screen(window);
const int monitor=gdk_screen_get_monitor_at_window(screen,window);
printf("Monitor number: %d\n",monitor);
}

g_signal delays (C, GTK+)

I've got a little GTK-Application with two buttons (A, B) and a drawing area (C).
When I click on A, C's size should be recalculated and set with gtk_widget_set_size_request(). This will cause an expose-event, whose handler will calculate some data. Further, the click on A will emit a clicked signal at B, whose handler needs the data calculated by C's expose-event.
In fact everything works fine, but the expose-event delays somehow, and the clicked handler is called before and the data (you may guess it) is missing.
a_handler() {
new_size = calculate_size();
gtk_widget_set_size_request(C, new_size); //Will cause expose-event
g_signal_emit_by_name(B, "clicked");
}
b_handler() {
calculate_something(data); //Error
}
c_handler() {
draw_something();
data = calcluate_data();
}
What can I do?
Gtk (and most other GUI toolkits) does the painting and event handling all in one thread. Therefore when the expose event is emitted, it goes into a queue and will be handled only after a_handler returns.
The best approach in my opinion would be to move the calculation somewhere else, if there is not some good reason to tie it into GUI drawing. For example, there could be a separate method calculate_data that is called both from b_handler and c_handler.
The next best way is to call gdk_window_process_updates to force the expose event to be handled immediately:
http://developer.gnome.org/gdk/stable/gdk-Windows.html#gdk-window-process-updates
The ugly fix is typically to add calls to gtk_main_iteration(), for instance between the call to gtk_widget_set_size_request() and the signal-emission.

Resources