How to replace GDK_INCLUDE_INFERIORS? - c

Since most of the gdk_gc_* methods are deprecated in GTK+ 3, how does one paint on sub-windows using Cairo only? Below is a simple example of what I would like to achieve:
GdkWindow *tl_window = parent_widget->window;
GdkGC *gc = gdk_gc_new(tl_window1->window);
gdk_gc_set_subwindow(gc, GDK_INCLUDE_INFERIORS);
gdk_gc_set_exposures(gc, FALSE);
do_my_painting(tl_window, gc);
gdk_gc_unref(gc);
http://developer.gnome.org/gdk/stable/gdk-Graphics-Contexts.html#gdk-gc-set-subwindow says GDK_INCLUDE_INFERIORS will be used on sources. So I assume the trick is to create a source of the window and then ... well then ... I'm stuck.

Found a solution myself
GtkWidget *tl_window = gtk_widget_get_toplevel(widget);
cairo_t *cairo = gdk_cairo_create(gtk_widget_get_window(tl_window));
cairo_surface_t *source_surface = cairo_get_target(cairo);
cairo_t *cairo_new = cairo_create(source_surface);
cairo_set_source_surface(cairo, cairo_get_target(cairo_new), 0, 0);
do_my_painting(cairo_new);
cairo_paint(cairo);
cairo_destroy(cairo);
(do I mis a destroy of cairo_new here ?)
I also found the next link (did not test it) http://mail.gnome.org/archives/commits-list/2010-August/msg03385.html where they seem to use a pixmap instead of a surface.

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.

Implementation of gtk3's new Height-for-width Geometry Management method

In continuation of my previous question
Drag and drop on a fixed container changes its size
I followed the advice given from ergosys and read the info in the link he provided.
If I understood correctly, the new way of declaring
/* LEFT FRAME */
frame1= gtk_frame_new(NULL);
gtk_table_attach(GTK_TABLE(table), frame1, 0,14,0,49,GTK_SHRINK,GTK_SHRINK,0,0);
gtk_widget_set_size_request(frame1, 360,570);
is (ignore the height for the time being)
static void
my_widget_get_preferred_width (GtkWidget *widget,
gint *minimal_width,
gint *natural_width)
{
GtkRequisition requisition;
gtk_widget_get_requisition (widget, &requisition);
*minimal_width = *natural_width = requisition.width;
}
....
/* LEFT FRAME */
frame1= gtk_frame_new(NULL);
gtk_table_attach(GTK_TABLE(table), frame1, 0,14,0,49,GTK_SHRINK,GTK_SHRINK,0,0);
gint min_width=360;
gint nat_width=360;
GTK_WIDGET_GET_CLASS(frame1)->get_preferred_width=my_widget_get_preferred_width;
my_widget_get_preferred_width(frame1,&min_width,&nat_width);
It compiles OK, but, when run, it gives me this error:
(conky_companion:19700): Gtk-WARNING **: GtkFrame 0xa00e660: widget tried to gtk_widget_get_width inside GtkWidget ::get_width implementation. Should just invoke GTK_WIDGET_GET_CLASS(widget)->get_width directly rather than using gtk_widget_get_width
without ever drawing the window and it segfaults after a while.
What am I missing here?
Or, TL;DR, what is the equivalent of
gtk_widget_set_size_request(frame1, 360,570);
in gtk3?

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);

How to change the cursor to a watch in GTK for C?

I'm using the C-style GTK functions in C++ and I can't figure out how to set the cursor for the main window.
Use gdk_set_cursor()
(https://developer.gnome.org/gdk3/stable/gdk3-Windows.html#gdk-window-set-cursor)
on a GdkCursor created by gdk_cursor_new()
(https://developer.gnome.org/gdk3/stable/gdk3-Cursors.html)
Use gdk_window_set_cursor() on a GdkCursor created by gdk_cursor_new_from_name().
To get the GdkWindow of a GtkWindow you can use gtk_widget_get_window() because GtkWindow is a subclass of GtkWidget.
Note: this answer is an improvement over idefixs answer (important correction + link update + minor modification to make the answer complete + improved formatting) that was rejected as an edit.
Posting this because the comment about getting the GdkWndow went unanswered so far.
For most widgets, the GdkWindow can be retrieved as the window data field of the GtkWidget structure. The following code sets a cursor on a GtkWindow widget:
GtkWidget* win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GdkCursor* watchCursor = gdk_cursor_new(GDK_WATCH);
/* set watch cursor */
gdk_window_set_cursor(win->window, watchCursor);
/* return to normal */
gdk_window_set_cursor(win->window, NULL);
If you need to get to the GtkWindow ancestor from one of its child widgets, you can use:
GtkWidget* win = gtk_widget_get_ancestor(someWidget, GTK_TYPE_WINDOW);
My solution:
void gtkSetCursor(GdkCursorType cursorType) {
GdkScreen * screen = gdk_screen_get_default();
GdkWindow * win = gdk_screen_get_root_window(screen);
GdkCursor * cursor = gdk_cursor_new(cursorType); //http://developer.gimp.org/api/2.0/gdk/gdk-Cursors.html
gdk_window_set_cursor(win, cursor);
while (gtk_events_pending()) gtk_main_iteration();
}
...
gtkSetCursor(GDK_WATCH);
start your stuff here
...
end of your stuff
gtkSetCursor(GDK_LEFT_PTR);
jeff's answer didn't work for me (Gtk3). So here's my solution:
GdkWindow* win = gtk_widget_get_parent_window(widget);
GdkCursor* watchCursor = gdk_cursor_new(GDK_WATCH);
gdk_window_set_cursor(win, watchCursor);

How to stretch a bitmap in C and SDL?

I am making a game for my CS class and the sprites I have found online are too small. How do you 'stretch' a bitmap... make them bigger using SDL? (I need to increase there size 50%, there all the same size.) A snippet of example code would be appreciated.
This question does not specify SDL version, and even though SDL2 was not available when the question was written, an SDL2 answer would add completeness here i believe.
Unlike SDL1.2, scaling is possible in SDL2 using the API method SDL_RenderCopyEx. No additional libs besides the basic SDL2 lib are needed.
int SDL_RenderCopyEx(SDL_Renderer* renderer,
SDL_Texture* texture,
const SDL_Rect* srcrect,
const SDL_Rect* dstrect,
const double angle,
const SDL_Point* center,
const SDL_RendererFlip flip)
By setting the size of dstrect one can scale the texture to an integer number of pixels. It is also possible to rotate and flip the texture at the same time.
Reference: https://wiki.libsdl.org/SDL_RenderCopyEx
Create your textures as usual:
surface = IMG_Load(filePath);
texture = SDL_CreateTextureFromSurface(renderer, surface);
And when it's time to render it, call SDL_RenderCopyEx instead of SDL_RenderCopy
You're going to get a better looking result using software that is designed for this task. A good option is ImageMagick. It can be used from the command line or programatically.
For example, from the command line you just enter:
convert sprite.bmp -resize 150% bigsprite.bmp
If for some strange reason you want to write your own bilinear resize, this guy looks like he knows what he is doing.
have you tried?
SDL_Rect src, dest;
src.x = 0;
src.y = 0;
src.w = image->w;
src.h = image->h;
dest.x = 100;
dest.y = 100;
dest.w = image->w*1.5;
dest.h = image->h*1.5;
SDL_BlitSurface(image, &src, screen, &dest);
Use for stretch the undocumented function of SDL:
extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect);
Like:
SDL_SoftStretch(image, &src, screen, &dest);

Resources