Confused about GDKPixBuf/Cairo interaction
Hi, just joined the mailing list, been using GTK and related projects for a while now. Recently I've been developing a Game Boy emulator that uses GtkDrawingArea and GdkPixbuf to display the game screen. In addition to the game output I want to also be able to draw text and shapes on the display window, and Cairo seems to be the ideal way to draw shapes. I'm already using Cairo to copy the Pixbuf to the GtkDrawingArea, so that seems like a good sign that Cairo and GdkPixbuf should interact nicely. However, it doesn't look like they should be able to interact at all, as they don't seem to be able to agree on a pixel format: http://developer.gnome.org/gdk-pixbuf/stable/gdk-pixbuf-Image-Data-in-Memory.html#gdk-pixbuf-new-from-data Currently only RGB images with 8 bits per sample are supported. http://developer.gnome.org/gdk-pixbuf/stable/gdk-pixbuf-The-GdkPixbuf-Structure.html#image-data p[0] = red; p[1] = green; p[2] = blue; p[3] = alpha; That seems to suggest that GdkPixbuf supports only RGB (24-bit) and RGBA (32-bit). But... http://www.cairographics.org/manual/cairo-Image-Surfaces.html#cairo-format-t CAIRO_FORMAT_ARGB32 is ARGB (each pixel is a 32-bit quantity, with alpha in the upper 8 bits...). CAIRO_FORMAT_RGB24 is xRGB (each pixel is a 32-bit quantity, with the upper 8 bits unused...). Neither of those are RGB or RGBA. So, how can Cairo operate on a surface provided by GdkPixbuf? -- Sent from my Game Boy. ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: Confused about GDKPixBuf/Cairo interaction
Hi, Le 18/02/2013 11:10, Rena a écrit : Hi, just joined the mailing list, been using GTK and related projects for a while now. Recently I've been developing a Game Boy emulator that uses GtkDrawingArea and GdkPixbuf to display the game screen. In addition to the game output I want to also be able to draw text and shapes on the display window, and Cairo seems to be the ideal way to draw shapes. I'm already using Cairo to copy the Pixbuf to the GtkDrawingArea, so that seems like a good sign that Cairo and GdkPixbuf should interact nicely. However, it doesn't look like they should be able to interact at all, as they don't seem to be able to agree on a pixel format: http://developer.gnome.org/gdk-pixbuf/stable/gdk-pixbuf-Image-Data-in-Memory.html#gdk-pixbuf-new-from-data Currently only RGB images with 8 bits per sample are supported. http://developer.gnome.org/gdk-pixbuf/stable/gdk-pixbuf-The-GdkPixbuf-Structure.html#image-data p[0] = red; p[1] = green; p[2] = blue; p[3] = alpha; That seems to suggest that GdkPixbuf supports only RGB (24-bit) and RGBA (32-bit). But... http://www.cairographics.org/manual/cairo-Image-Surfaces.html#cairo-format-t CAIRO_FORMAT_ARGB32 is ARGB (each pixel is a 32-bit quantity, with alpha in the upper 8 bits...). CAIRO_FORMAT_RGB24 is xRGB (each pixel is a 32-bit quantity, with the upper 8 bits unused...). Neither of those are RGB or RGBA. So, how can Cairo operate on a surface provided by GdkPixbuf? I don't really get it. You say you already use Cairo to draw your pixbuf, but also that you can't see how to use a GdkPixbuf with Cairo? This seems contradictory to me. Anyway, what you want is gdk_cairo_set_source_pixbuf()[1] that does the appropriate conversions to create a Cairo pattern from a GdkPixbuf. Then you can use this pattern like any other Cairo pattern (e.g. cairo_paint()), and you're done. Hope it helps. Colomban [1] http://developer.gnome.org/gdk/stable/gdk-Cairo-Interaction.html#gdk-cairo-set-source-pixbuf ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: Confused about GDKPixBuf/Cairo interaction
Le 18/02/2013 14:50, Rena a écrit : On Mon, Feb 18, 2013 at 8:35 AM, Colomban Wendling lists@herbesfolles.org wrote: Hi, Le 18/02/2013 11:10, Rena a écrit : Hi, just joined the mailing list, been using GTK and related projects for a while now. Recently I've been developing a Game Boy emulator that uses GtkDrawingArea and GdkPixbuf to display the game screen. In addition to the game output I want to also be able to draw text and shapes on the display window, and Cairo seems to be the ideal way to draw shapes. I'm already using Cairo to copy the Pixbuf to the GtkDrawingArea, so that seems like a good sign that Cairo and GdkPixbuf should interact nicely. [...] I don't really get it. You say you already use Cairo to draw your pixbuf, but also that you can't see how to use a GdkPixbuf with Cairo? This seems contradictory to me. Anyway, what you want is gdk_cairo_set_source_pixbuf()[1] that does the appropriate conversions to create a Cairo pattern from a GdkPixbuf. Then you can use this pattern like any other Cairo pattern (e.g. cairo_paint()), and you're done. Well, in the GtkDrawingArea::draw signal, I receive a cairo_t* that Gdk has created for me, and draw my pixbuf to it: gboolean draw_callback(GtkWidget *widget, cairo_t *cairo) { gdk_cairo_set_source_pixbuf(cairo, pixbuf, 0, 0); cairo_paint(cairo); } but if I want to draw a shape on the pixbuf, I would need to create a cairo_t* of my own for that purpose, and I don't see how to create one that's compatible with the pixel format GdkPixbuf uses. i.e. I want the destination to be my pixbuf, not the source. First, you could very well draw directly on the Cairo context straight in the ::draw handler, give then you don't need caching for decent performances. E.g., just continue drawing stuff in the ::draw handler after you painted the pixbuf. But if you want to draw everything on your own surface and then paint that surface in the ::draw handler, just create a surface with whatever format you need, gdk_cairo_set_source_pixbuf() should be able to do the conversion. The other solution is to use cairo_surface_create_similar(), but this requires a surface to be similar to -- but there is no much reason for that other surface to have a format better suitable to your pixbuf. The Cairo context passed to the ::draw handler is appropriate to draw on the screen, not particularly to draw your pixbuf. But you can very well do this: def prepare_suraface(pix): # use whatever format you need, e.g. ARGB32 or RGB24 surface = Cairo.Surface(cairo.Format.ARGB32, pix.width, pix.height) cr = Cairo.Context(surface) Gdk.cairo_set_source_pixbuf(cr, pix, 0, 0) cr.pain() # and continue drawing stuff cr.move_to(0, 0) cr.line_to(pix.width, pix.height) cr.stroke() return surface and then your simply paint the created surface in your ::draw handler. Of course, doing this is only useful if you need caching the drawn surface, otherwise it'd be faster do directly perform the draws on the ::draw handler. Or maybe I got you wrong and you'd like to *draw* on your GdkPixbuf? I'm afraid this just isn't possible directly. If you really want to do that, you'll probably have to manually do some pixel conversion. You can create a Cairo surface of the pixbuf's size, draw on that, and then get the surface's pixels which you'd convert manually to the pixbuf format, and push those pixels to the pixbuf. But again, why would you need to draw specifically on a GdkPixbuf? Regards, Colomban ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: How to prevent windows to be raised at the top of the stack when clicked?
Hi, I made some more tests about the solutions that seem to be useable. It appears that they are not. Reminder: the problem is to let the application manage window stacking (z- order), instead of letting the Window manager do most of the job by itself. - The gtk_windows_set_transient_for() function works but : . It's not possible to change anything in the window stacking order without rebuilding the whole list from scratch . When the list reaches 16 windows and more, this operation takes exponentially more and more time. With 20 windows, it takes several seconds. With 25, the whole system hangs. - The gtk_window_restack() function works but : . When a window is clicked, it seems that the WM automatically send it to the frontmost position in the stack, without letting the application avoid that. . I couldn't find any way to prevent that behaviour from the WM by altering the .XDefault/.XResources file Could it be possible to bypass GTK and to access the X structures and events directly? If yes, is it a way to prevent it to bring automatically the clicked window to front ? Regards, Olivier ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
parsing bibtex using gscanner
Dear Friends, I am trying to parse a bibtex file using gscanner. The problem is that, due to many formats accepted by bibtex, it seems bit hard to parse it. What I mean is as long as the bibtex is of the form key=some value, then g_scanner_get_next_token can get the string. But it fails if it is in the format key={value}. I am attaching my code. Some help (outside using btparse/ bison )is needed. guint parse_entry (GScanner *scanner, GHashTable *table) { int tokount; /* Entry starts with @ */ g_scanner_get_next_token (scanner); if (scanner-token != '@') return G_TOKEN_ERROR; /* Now get identifier */ g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_IDENTIFIER) return G_TOKEN_ERROR; g_hash_table_insert (table, g_strdup (type), g_strdup (scanner-value.v_identifier)); /* Brace */ g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_LEFT_CURLY){ return G_TOKEN_ERROR;} else tokount += tokount; /* ID */ g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_IDENTIFIER) return G_TOKEN_ERROR; g_hash_table_insert (table, g_strdup (id), g_strdup (scanner-value.v_identifier)); while (TRUE) { char *key, *val; g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_COMMA) return G_TOKEN_ERROR; g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_IDENTIFIER) return G_TOKEN_ERROR; key = g_strdup (scanner-value.v_identifier); /*g_scanner_peek_next_token (scanner); if (scanner-token == G_TOKEN_LEFT_CURLY) tokount += tokount;*/ g_scanner_get_next_token (scanner); if (scanner-token != '=') { g_free (key); return G_TOKEN_ERROR; } g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_STRING) { g_free (key); return G_TOKEN_ERROR; } val = g_strdup (scanner-value.v_string); g_hash_table_insert(table, key, val); g_scanner_peek_next_token (scanner); if (scanner-next_token == G_TOKEN_RIGHT_CURLY) break; } g_scanner_get_next_token (scanner); return G_TOKEN_NONE; } ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: parsing bibtex using gscanner
Below is a minimal example. One can check the problem with key={some value} by changing, say, author = \Chowdhury, D.\,\n to author = {Chowdhury, D.},\n This can be compiled as gcc -Wall `pkg-config --cflags --libs gtk+-3.0` glex.c /*glex.c*/ #include glib.h #include string.h /* Test data */ static const gchar *ttest = @phdthesis{chow1983thesis,\n author = \Chowdhury, D.\,\n institution = \Department of Physics, IIT, Kanpur\,\n location = \Kanpur\,\n publisher = \Department of Physics, IIT, Kanpur\,\n school = \Department of Physics, IIT, Kanpur\,\n title = \{The Spin Glass Transition}\,\n year = \1983\\n }; static void output_entry (GHashTable *table) { GHashTableIter iter; char *key, *val; g_print (Citation entry:\n); g_hash_table_iter_init (iter, table); while (g_hash_table_iter_next (iter, (void **)key, (void **)val)) g_print ( %16s: %s\n, key, val); g_print (\n); } static guint parse_entry (GScanner *scanner, GHashTable *table) { /* Entry starts with @ */ g_scanner_get_next_token (scanner); if (scanner-token != '@') return G_TOKEN_ERROR; /* Now get identifier */ g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_IDENTIFIER) return G_TOKEN_ERROR; g_hash_table_insert (table, g_strdup (type), g_strdup (scanner-value.v_identifier)); /* Brace */ g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_LEFT_CURLY) return G_TOKEN_ERROR; /* ID */ g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_IDENTIFIER) return G_TOKEN_ERROR; g_hash_table_insert (table, g_strdup (id), g_strdup (scanner-value.v_identifier)); while (TRUE) { char *key, *val; g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_COMMA) return G_TOKEN_ERROR; g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_IDENTIFIER) return G_TOKEN_ERROR; key = g_strdup (scanner-value.v_identifier); g_scanner_get_next_token (scanner); if (scanner-token != '=') { g_free (key); return G_TOKEN_ERROR; } g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_STRING) { g_free (key); return G_TOKEN_ERROR; } val = g_strdup (scanner-value.v_string); g_hash_table_insert(table, key, val); g_scanner_peek_next_token (scanner); if (scanner-next_token == G_TOKEN_RIGHT_CURLY) break; } /* Eat last curly brace and return */ g_scanner_get_next_token (scanner); return G_TOKEN_NONE; } int main (intargc, char **argv) { GScanner *scanner; GHashTable *table; guint ret; scanner = g_scanner_new (NULL); g_scanner_input_text (scanner, ttest, strlen (ttest)); table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); do { g_hash_table_remove_all (table); ret = parse_entry (scanner, table); if (ret == G_TOKEN_ERROR) break; else output_entry (table); g_scanner_peek_next_token (scanner); } while (scanner-next_token != G_TOKEN_EOF scanner-next_token != G_TOKEN_ERROR); /* finsish parsing */ g_scanner_destroy (scanner); g_hash_table_destroy (table); return 0; } ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: parsing bibtex using gscanner
On Mon, Feb 18, 2013 at 05:15:56PM +, Rudra Banerjee wrote: I am trying to parse a bibtex file using gscanner. The problem is that, due to many formats accepted by bibtex, it seems bit hard to parse it. What I mean is as long as the bibtex is of the form key=some value, then g_scanner_get_next_token can get the string. But it fails if it is in the format key={value}. And it fails even before escaping literal TeX code using braces within entries or string macros have come to play... I am attaching my code. Some help (outside using btparse/ bison )is needed. Don't do it this way. GScanner is a lexical scanner, it just tokenizes the input but it does not help with grammar. The best approach to parse a grammar is, you know, using a parser. If you insist on writing one manually realise that you need to formally keep state, eg. the nesting level of braces at which you are now, etc. Construct the parser similarly you would if you did if you just wrote the BNF and let the parser be generared, e.g. write subroutines to parse balanced braces, string, etc. possibly recusrively calling each other. Attempting to write code for all the cases that can occur using sequences of hardcoded ifs will only result in buggy mess. You have been warned. Yeti ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: parsing bibtex using gscanner
I forget the acknowledgment: http://www.gtkforums.com/viewtopic.php?f=3t=178159 On Mon, 2013-02-18 at 18:00 +, Rudra Banerjee wrote: Below is a minimal example. One can check the problem with key={some value} by changing, say, author = \Chowdhury, D.\,\n to author = {Chowdhury, D.},\n This can be compiled as gcc -Wall `pkg-config --cflags --libs gtk+-3.0` glex.c /*glex.c*/ #include glib.h #include string.h /* Test data */ static const gchar *ttest = @phdthesis{chow1983thesis,\n author = \Chowdhury, D.\,\n institution = \Department of Physics, IIT, Kanpur\,\n location = \Kanpur\,\n publisher = \Department of Physics, IIT, Kanpur\,\n school = \Department of Physics, IIT, Kanpur\,\n title = \{The Spin Glass Transition}\,\n year = \1983\\n }; static void output_entry (GHashTable *table) { GHashTableIter iter; char *key, *val; g_print (Citation entry:\n); g_hash_table_iter_init (iter, table); while (g_hash_table_iter_next (iter, (void **)key, (void **)val)) g_print ( %16s: %s\n, key, val); g_print (\n); } static guint parse_entry (GScanner *scanner, GHashTable *table) { /* Entry starts with @ */ g_scanner_get_next_token (scanner); if (scanner-token != '@') return G_TOKEN_ERROR; /* Now get identifier */ g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_IDENTIFIER) return G_TOKEN_ERROR; g_hash_table_insert (table, g_strdup (type), g_strdup (scanner-value.v_identifier)); /* Brace */ g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_LEFT_CURLY) return G_TOKEN_ERROR; /* ID */ g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_IDENTIFIER) return G_TOKEN_ERROR; g_hash_table_insert (table, g_strdup (id), g_strdup (scanner-value.v_identifier)); while (TRUE) { char *key, *val; g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_COMMA) return G_TOKEN_ERROR; g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_IDENTIFIER) return G_TOKEN_ERROR; key = g_strdup (scanner-value.v_identifier); g_scanner_get_next_token (scanner); if (scanner-token != '=') { g_free (key); return G_TOKEN_ERROR; } g_scanner_get_next_token (scanner); if (scanner-token != G_TOKEN_STRING) { g_free (key); return G_TOKEN_ERROR; } val = g_strdup (scanner-value.v_string); g_hash_table_insert(table, key, val); g_scanner_peek_next_token (scanner); if (scanner-next_token == G_TOKEN_RIGHT_CURLY) break; } /* Eat last curly brace and return */ g_scanner_get_next_token (scanner); return G_TOKEN_NONE; } int main (intargc, char **argv) { GScanner *scanner; GHashTable *table; guint ret; scanner = g_scanner_new (NULL); g_scanner_input_text (scanner, ttest, strlen (ttest)); table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); do { g_hash_table_remove_all (table); ret = parse_entry (scanner, table); if (ret == G_TOKEN_ERROR) break; else output_entry (table); g_scanner_peek_next_token (scanner); } while (scanner-next_token != G_TOKEN_EOF scanner-next_token != G_TOKEN_ERROR); /* finsish parsing */ g_scanner_destroy (scanner); g_hash_table_destroy (table); return 0; } ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: parsing bibtex using gscanner
On Mon, 2013-02-18 at 19:02 +0100, David Nečas wrote: The best approach to parse a grammar is, you know, using a parser. So anything better then bison? ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: parsing bibtex using gscanner
On Mon, 2013-02-18 at 19:02 +0100, David Nečas wrote: The best approach to parse a grammar is, you know, using a parser. So is there any better option then bison? ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: How to prevent windows to be raised at the top of the stack when clicked?
Hi, On Thu, Feb 14, 2013 at 12:17 AM, Olivier Guillion - Myriad oliv...@myriad-online.com wrote: Hi, I'm struggling with this problem for several days now, and can't find any solution. I'm writing an application for Ubuntu using GTK in C language. This application manages various windows (floating palettes, documents, toolbars, etc), with a complex stacking (Z-order) strategy. I would want to manage the stacking myself, by calling gtk_window_restack appropriately. Warning, here be dragons. Applications don't have full control over their stacking order or stacking policy, except if they are override redirect and the window manager does not touch them at all. It works well, except for one thing : when a window is clicked, it seems to be automatically sent to front (top of the stack) by the system before my program receives any signal. For instance, if I put a breakpoint in the focus_in_event or button_press_event signal callback, the window has already been sent to top before the breakpoint is reached. Is there a way to prevent a clicked window from being automatically sent to top of the stack ? Any help would be greatly appreciated. There isn't really. You can set _NET_WM_STATE_BELOW to make the window manager put it on the same layer as all of the below windows [1]. The window manager will still freely raise any window within this layer. Then you can use WM_TRANSIENT_FOR in order to force ordering amongst your windows. That ordering won't be exclusive though - it is entirely possible that other windows can go in-between. The reason why the window is automatically raised is because the window manager has a passive grab on the parent window if its not on the top of the stack. This grab activates and prevents your application from receiving the first mouse click until the window manager has done what its wants to do, namely, place the window at the top of the stack. This is part of the reason why people want client side decorations. I'd suggest reconsidering the design of your application. There are very good reasons why window managers needs to manage the stacking order, allowing applications to override that behaviour generally results in trouble. [1] http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#STACKINGORDER Thank you, Olivier ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list -- Sam Spilsbury ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list