I want to use cairo to enhance gtkentry look. For this, I have connected a callback to 'expose-event'. In callback, I call gtkentry's original expose-event handler. After that, I create cairo context and draw some lines and destroy the cairo. I return 'TRUE' as return value of callback function so that expose-event does not propagate.
Now my problem is, I am drawing line from (0,0) to (100,100). But line appears only over the border areas of the gtkentry. The place where text is, it does not appear.
Please help.
Kind Regards
-Durgesh O Mishra
GtkEntry uses an additional GdkWindow for the text area. It is sort-of-private, but you could access it using the following code:
GDK_WINDOW (gdk_window_peek_children (GTK_WIDGET (entry)->window)->data);
So, you can pass this window to gdk_cairo_create().
If you have problems applying this to your code, paste the code — it's hard to guess what to do without having any way to test.
Related
I have an ellipse which is drew on a window. I want to show a message when the pointer is on it (on the ellipse). How I do it? Is there any event for shapes? Like WM_MOVE or WM_SIZE.
I use TDM-GCC and C language.
When you draw on a device context, all knowledge of what shape you draw is lost, and the system just retains the pixel by pixel information of that device context. So there is no way for the system to give you any information about the shapes that you draw because it knows nothing of those shapes.
In order to do what you want you need to keep track in your program of the high level logic of where your shapes are. Then when you handle mouse messages you can map them onto your own data structures that represent the shapes.
There are no events for mouse activity over drawings. You are expected to remember where you draw, and then map the mouse coordinates to the drawing coordinates yourself. To help with this, have a look at the PtInRegion() function. Create an elliptical HRGN via CreateEllipticRgn() or CreateEllipticRgnIndirect() that matches your drawing (in fact, you can use the same HRGN to help facilitate the drawing, see the FillRgn() function), and when you want to test if the mouse is currently inside the drawing, such as in a WM_MOUSEMOVE handler, you can use PtInRegion() for that.
I simply draw specific content in a GtkTextView in a 'draw' signal,
on a next signal emission I draw different things in GtkTextView.
In the next signal invocation, if there is nothing to be drawn it clears all the previous drawings, which is good.
But when it is about to draw the new content, it draws all the previous at once, not only the needed one. Which is no good.
I tried many things to prevent this behavior, every possible combination with cairo_save() and cairo_restore() don't seem to do it.
How can I make it not draw every previous drawing at once, but the new one only ?
The "draw" signal should be only used to change GtkTextView's constant appearance.
For what I want, this may work as requested:
void draw_on_textview (GtkWidget* textview)
{
cairo_t* cr = gdk_cairo_create(gtk_widget_get_window(textview));
// Do ALL the drawing AT ONCE here..
cairo_destroy(cr);
}
When content needs to be removed:
gtk_widget_queue_draw(textview);
However this is still slightly different than the appropriate approach. As #jcoppens stated, draw_layer must be used instead. So I don't count this as an answer but some possible approach that I could alternatively use if there is no one else to provide the better way.
I program my application in C using GTK+3 and cairo.
is there a way to draw a line on top of a Vertical GtkBox ?
the thing is that I need to mark an area with a line. the area is a row of a vertical GtkBox, which is not a GtkDrawingArea.
is that possible?
any information regarding the issue would be greatly appreciated.
I'm using glade in order to create the Gtk Vertical Box.
I connected a callback to the draw signal and I marked 'After' in glade which actually calls my callback after the basic drawing. which allows me to draw on top of the elements inside it.
as simple as that ;)
The Gtk+ 3 migration guide shows how the GdkEventExpose.region field can be used to provide a fine-grained area for re-rendering widgets. We already do something like this in Inkscape to avoid rendering excessive amounts of complicated stuff on our drawing canvas.
However, the example in the guide shows how to do this for the old Gtk+ 2 expose_event handler.
How do I do the equivalent in a new Gtk+ 3 draw handler, which receives a "ready-clipped" Cairo context as a parameter, rather than a GdkEventExpose?
I guess one possibility is to use cairo_copy_clip_rectangle_list on the "ready-clipped" cairo context to obtain a list of rectangles that make up the region to draw. Does anyone have any experience of using this? Does it seem like a sensible approach?
Yes, you should use cairo_copy_clip_rectangle_list() on the cairo_t that you get in your widget's ::draw() signal handler. See this commit for an example:
http://git.gnome.org/browse/vte/commit/?id=21a064ac8b5925108b0ab9bd6516664c8cd3e268
Since I have not much clue, I decided to check the source code. GDK emits a GDK_EXPOSE event on a window and creates the GdkEventExpose instance for this.
This event is then handled in gtk/gtkmain.c via gtk_widget_send_expose():
http://git.gnome.org/browse/gtk+/tree/gtk/gtkwidget.c?id=eecb9607a5c0ee38eadb446545beccd0922cb0b8#n6104
This function clips the cairo_t to GdkEventExpose.region, as you already learned in the docs.
This then calls _gtk_widget_draw_internal() which emits the actual draw signal:
http://git.gnome.org/browse/gtk+/tree/gtk/gtkwidget.c?id=eecb9607a5c0ee38eadb446545beccd0922cb0b8#n5726
As far as I can see, nothing here let's you access the clip region directly. In gtk_widget_send_expose() the GdkEvent is added as userdata to the cairo context. However, this is not accessible, because all the involved functions and variables are static. So you'll have to use cairo_copy_clip_rectangle_list().
However, this sounds quite inefficent. First gdk_cairo_region transforms the region into a number of calls to cairo_rectangle and then cairo transforms this from its internal representation into a cairo_rectangle_list_t (which may fail if the clip is, for some reason, not a region). If you see this being slow, it might make sense to have some shortcut for this added to gtk directly.
I've got a drawing area inside a scrolled window (with convenience viewport),
and this drawing area updates itself according to incoming motion-notify-events.
When I scroll the area though obviously no motion events are emitted,
but I wanted to work around this, and so tried to connect the drawing area's
"scroll-event" signal to the same motion-notify callback.
The problem I'm facing here is that this signal is emitted before the scrolled window
has update its viewport, so in the callback, I end up with pointer coordinates that were true just before scrolling, making it look like the drawing area is always "lagging a step behind" the actual pointer when scrolling while not moving the pointer itself.
I thought I could compensate for this by manually extracting the coordinates with gdk_window_get_pointer, but then I realized this cannot work as the pointer is technically still at its old position when the callback is commencing.
I also tried using g_signal_connect_after in hopes it would have the callback get called after the viewport was scrolled, but it didn't help.
My last hope would be to start a timer on scroll-events, and have the callback fire after a minimal amount of time, but this sounds realllly ugly, and I'd like to avoid that at any cost.
Any ideas as to how this could be realized?
Thanks in advance!
A solution would be to connect to the "value-changed" signal of the GtkScrolledWindow
adjustments.
Source: https://mail.gnome.org/archives/gtk-app-devel-list/2011-September/msg00014.html