2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
20 #define GDK_ENABLE_BROKEN
26 #include <gdk/gdkkeysyms.h>
27 #include <locale.h> /* For WIN32 */
28 #if !defined(GDK_Book) || !defined(GDK_Calendar)
29 #include <X11/XF86keysym.h>
48 #include "navit/font/freetype/font_freetype.h"
52 #define GDK_Book XF86XK_Book
55 #define GDK_Calendar XF86XK_Calendar
59 struct graphics_priv {
60 GdkEventButton button_event;
65 GdkDrawable *drawable;
66 GdkDrawable *background;
68 GdkColormap *colormap;
78 int overlay_autodisabled;
81 struct graphics_priv *parent;
82 struct graphics_priv *overlays;
83 struct graphics_priv *next;
84 struct graphics_gc_priv *background_gc;
85 enum draw_mode_num mode;
86 struct callback_list *cbl;
87 struct font_freetype_methods freetype_methods;
90 struct timeval button_press[8];
91 struct timeval button_release[8];
98 struct graphics_gc_priv {
101 struct graphics_priv *gr;
105 struct graphics_image_priv {
111 static GHashTable *hImageData; /*hastable for uncompressed image data*/
112 static int hImageDataCount;
113 static struct graphics_image_priv image_error;
116 graphics_destroy_image(gpointer data)
118 struct graphics_image_priv *priv = (struct graphics_image_priv*)data;
120 if (priv == &image_error)
124 g_object_unref(priv->pixbuf);
129 graphics_destroy(struct graphics_priv *gr)
131 dbg(0,"enter parent %p\n",gr->parent);
133 dbg(0,"enter win %p\n",gr->win);
135 gtk_widget_destroy(gr->win);
136 dbg(0,"widget %p\n",gr->widget);
138 gtk_widget_destroy(gr->widget);
139 g_free(gr->window_title);
141 dbg(0,"hImageDataCount %d\n",hImageDataCount);
142 if (!--hImageDataCount)
143 g_hash_table_destroy(hImageData);
148 gc_destroy(struct graphics_gc_priv *gc)
150 g_object_unref(gc->gc);
155 gc_set_linewidth(struct graphics_gc_priv *gc, int w)
157 gdk_gc_set_line_attributes(gc->gc, w, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
161 gc_set_dashes(struct graphics_gc_priv *gc, int w, int offset, unsigned char *dash_list, int n)
163 gdk_gc_set_dashes(gc->gc, offset, (gint8 *)dash_list, n);
164 gdk_gc_set_line_attributes(gc->gc, w, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND);
168 gc_set_color(struct graphics_gc_priv *gc, struct color *c, int fg)
175 gdk_colormap_alloc_color(gc->gr->colormap, &gdkc, FALSE, TRUE);
176 gdk_colormap_query_color(gc->gr->colormap, gdkc.pixel, &gdkc);
179 gdk_gc_set_foreground(gc->gc, &gdkc);
181 gdk_gc_set_background(gc->gc, &gdkc);
185 gc_set_foreground(struct graphics_gc_priv *gc, struct color *c)
187 gc_set_color(gc, c, 1);
191 gc_set_background(struct graphics_gc_priv *gc, struct color *c)
193 gc_set_color(gc, c, 0);
197 gc_set_stipple(struct graphics_gc_priv *gc, struct graphics_image_priv *img)
199 char data[2]={0x2,0x1};
200 gdk_gc_set_fill(gc->gc, GDK_STIPPLED);
201 gc->pixmap=gdk_bitmap_create_from_data(gc->gr->widget->window, data, 2, 2);
202 gdk_gc_set_stipple(gc->gc, gc->pixmap);
205 static struct graphics_gc_methods gc_methods = {
214 static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth)
216 struct graphics_gc_priv *gc=g_new(struct graphics_gc_priv, 1);
219 gc->gc=gdk_gc_new(gr->widget->window);
225 static struct graphics_image_priv *
226 image_new(struct graphics_priv *gr, struct graphics_image_methods *meth, char *name, int *w, int *h, struct point *hot, int rotation)
229 struct graphics_image_priv *ret;
232 char* hash_key = g_strdup_printf("%s_%d_%d_%d",name,*w,*h,rotation);
234 //check if image already exists in hashmap
235 struct graphics_image_priv *curr_elem = g_hash_table_lookup(hImageData, hash_key);
236 if(curr_elem == &image_error) {
237 //found but couldn't be loaded
242 //found and OK -> use hashtable entry
246 hot->x = curr_elem->w / 2 - 1;
247 hot->y = curr_elem->h / 2 - 1;
248 ret=g_new0(struct graphics_image_priv, 1);
250 g_object_ref(ret->pixbuf);
254 if (*w == -1 && *h == -1)
255 pixbuf=gdk_pixbuf_new_from_file(name, NULL);
257 pixbuf=gdk_pixbuf_new_from_file_at_size(name, *w, *h, NULL);
260 g_hash_table_insert(hImageData, g_strdup(hash_key), &image_error);
277 g_hash_table_insert(hImageData, g_strdup(hash_key), &image_error);
282 tmp=gdk_pixbuf_rotate_simple(pixbuf, rotation);
285 g_hash_table_insert(hImageData, g_strdup(hash_key), &image_error);
287 g_object_unref(pixbuf);
291 g_object_unref(pixbuf);
295 ret=g_new0(struct graphics_image_priv, 1);
297 ret->w=gdk_pixbuf_get_width(pixbuf);
298 ret->h=gdk_pixbuf_get_height(pixbuf);
302 option=gdk_pixbuf_get_option(pixbuf, "x_hot");
307 option=gdk_pixbuf_get_option(pixbuf, "y_hot");
313 struct graphics_image_priv *cached = g_new0(struct graphics_image_priv, 1);
315 g_hash_table_insert(hImageData, g_strdup(hash_key), cached);
316 g_object_ref(pixbuf);
323 image_free(struct graphics_priv *gr, struct graphics_image_priv *priv)
325 g_object_unref(priv->pixbuf);
330 draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
332 if (gr->mode == draw_mode_begin || gr->mode == draw_mode_end)
333 gdk_draw_lines(gr->drawable, gc->gc, (GdkPoint *)p, count);
334 if (gr->mode == draw_mode_end || gr->mode == draw_mode_cursor)
335 gdk_draw_lines(gr->widget->window, gc->gc, (GdkPoint *)p, count);
339 draw_polygon(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
341 if (gr->mode == draw_mode_begin || gr->mode == draw_mode_end)
342 gdk_draw_polygon(gr->drawable, gc->gc, TRUE, (GdkPoint *)p, count);
343 if (gr->mode == draw_mode_end || gr->mode == draw_mode_cursor)
344 gdk_draw_polygon(gr->widget->window, gc->gc, TRUE, (GdkPoint *)p, count);
348 draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h)
350 gdk_draw_rectangle(gr->drawable, gc->gc, TRUE, p->x, p->y, w, h);
354 draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int r)
356 if (gr->mode == draw_mode_begin || gr->mode == draw_mode_end)
357 gdk_draw_arc(gr->drawable, gc->gc, FALSE, p->x-r/2, p->y-r/2, r, r, 0, 64*360);
358 if (gr->mode == draw_mode_end || gr->mode == draw_mode_cursor)
359 gdk_draw_arc(gr->widget->window, gc->gc, FALSE, p->x-r/2, p->y-r/2, r, r, 0, 64*360);
363 display_text_draw(struct font_freetype_text *text, struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, int color, struct point *p)
366 struct font_freetype_glyph *g, **gp;
367 unsigned char *shadow,*glyph;
368 struct color transparent={0x0,0x0,0x0,0x0};
369 struct color white={0xffff,0xffff,0xffff,0xffff};
378 if (g->w && g->h && bg ) {
381 shadow=g_malloc(stride*(g->h+2));
382 if (gr->freetype_methods.get_shadow(g, shadow, 8, stride, &white, &transparent))
383 gdk_draw_gray_image(gr->drawable, bg->gc, ((x+g->x)>>6)-1, ((y+g->y)>>6)-1, g->w+2, g->h+2, GDK_RGB_DITHER_NONE, shadow, stride);
387 shadow=g_malloc(stride*(g->h+2));
388 gr->freetype_methods.get_shadow(g, shadow, 24, stride, &bg->c, &transparent);
389 gdk_draw_rgb_image(gr->drawable, fg->gc, ((x+g->x)>>6)-1, ((y+g->y)>>6)-1, g->w+2, g->h+2, GDK_RGB_DITHER_NONE, shadow, stride);
395 shadow=malloc(stride*(g->h+2));
397 gr->freetype_methods.get_shadow(g, shadow, 1, stride);
398 image=gdk_image_new_bitmap(gdk_visual_get_system(),shadow,g->w+2, g->h+2);
399 gdk_draw_image(gr->drawable, bg->gc, image, 0, 0, ((x+g->x)>>6)-1, ((y+g->y)>>6)-1, g->w+2, g->h+2);
400 g_object_unref(image);
418 glyph=g_malloc(stride*g->h);
419 gr->freetype_methods.get_glyph(g, glyph, 8, stride, &fg->c, &bg->c, &transparent);
420 gdk_draw_gray_image(gr->drawable, bg->gc, (x+g->x)>>6, (y+g->y)>>6, g->w, g->h, GDK_RGB_DITHER_NONE, glyph, g->w);
424 glyph=g_malloc(stride*g->h);
425 gr->freetype_methods.get_glyph(g, glyph, 24, stride, &fg->c, bg?&bg->c:&transparent, &transparent);
426 gdk_draw_rgb_image(gr->drawable, fg->gc, (x+g->x)>>6, (y+g->y)>>6, g->w, g->h, GDK_RGB_DITHER_NONE, glyph, stride);
429 gdk_draw_gray_image(gr->drawable, fg->gc, (x+g->x)>>6, (y+g->y)>>6, g->w, g->h, GDK_RGB_DITHER_NONE, g->pixmap, g->w);
437 draw_text(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *font, char *text, struct point *p, int dx, int dy)
439 struct font_freetype_text *t;
444 dbg(0,"no font, returning\n");
447 #if 0 /* Temporarily disabled because it destroys text rendering of overlays and in gui internal in some places */
449 This needs an improvement, no one checks if the strings are visible
451 if (p->x > gr->width-50 || p->y > gr->height-50) {
454 if (p->x < -50 || p->y < -50) {
460 if (COLOR_IS_BLACK(fg->c) && COLOR_IS_WHITE(bg->c)) {
461 gdk_gc_set_function(fg->gc, GDK_AND_INVERT);
462 gdk_gc_set_function(bg->gc, GDK_OR);
463 } else if (COLOR_IS_WHITE(fg->c) && COLOR_IS_BLACK(bg->c)) {
464 gdk_gc_set_function(fg->gc, GDK_OR);
465 gdk_gc_set_function(bg->gc, GDK_AND_INVERT);
467 gdk_gc_set_function(fg->gc, GDK_OR);
468 gdk_gc_set_function(bg->gc, GDK_AND_INVERT);
472 gdk_gc_set_function(fg->gc, GDK_OR);
475 t=gr->freetype_methods.text_new(text, (struct font_freetype_font *)font, dx, dy);
476 display_text_draw(t, gr, fg, bg, color, p);
477 gr->freetype_methods.text_destroy(t);
478 gdk_gc_set_function(fg->gc, GDK_COPY);
480 gdk_gc_set_function(bg->gc, GDK_COPY);
485 gr->freetype_methods.get_text_bbox(gr, font, text, dx, dy, pnt, 1);
486 for (i = 0 ; i < 4 ; i++) {
491 gdk_draw_lines(gr->drawable, fg->gc, (GdkPoint *)pnt, 5);
497 draw_image(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img)
499 gdk_draw_pixbuf(gr->drawable, fg->gc, img->pixbuf, 0, 0, p->x, p->y,
500 img->w, img->h, GDK_RGB_DITHER_NONE, 0, 0);
505 draw_image_warp(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, int count, char *data)
509 dbg(1,"draw_image_warp data=%s\n", data);
510 image = imlib_load_image(data);
511 imlib_context_set_display(gdk_x11_drawable_get_xdisplay(gr->widget->window));
512 imlib_context_set_colormap(gdk_x11_colormap_get_xcolormap(gtk_widget_get_colormap(gr->widget)));
513 imlib_context_set_visual(gdk_x11_visual_get_xvisual(gtk_widget_get_visual(gr->widget)));
514 imlib_context_set_drawable(gdk_x11_drawable_get_xid(gr->drawable));
515 imlib_context_set_image(image);
516 w = imlib_image_get_width();
517 h = imlib_image_get_height();
521 imlib_render_image_on_drawable_skewed(0, 0, w, h, p[0].x, p[0].y, p[1].x-p[0].x, p[1].y-p[0].y, p[2].x-p[0].x, p[2].y-p[0].y);
526 imlib_render_image_on_drawable_skewed(0, 0, w, h, p[0].x, p[0].y, p[1].x-p[0].x, 0, 0, p[1].y-p[0].y);
532 imlib_render_image_on_drawable_skewed(0, 0, w, h, p[0].x-w/2, p[0].y-h/2, w, 0, 0, h);
539 overlay_rect(struct graphics_priv *parent, struct graphics_priv *overlay, int clean, GdkRectangle *r)
542 r->x=overlay->pclean.x;
543 r->y=overlay->pclean.y;
548 r->width=overlay->width;
549 r->height=overlay->height;
550 if (!overlay->wraparound)
553 r->x += parent->width;
555 r->y += parent->height;
557 r->width += parent->width;
559 r->height += parent->height;
563 overlay_draw(struct graphics_priv *parent, struct graphics_priv *overlay, GdkRectangle *re, GdkPixmap *pixmap, GdkGC *gc)
565 GdkPixbuf *pixbuf,*pixbuf2;
566 guchar *pixels1, *pixels2, *p1, *p2, r=0, g=0, b=0, a=0;
568 int rowstride1,rowstride2;
569 int n_channels1,n_channels2;
571 struct graphics_gc_priv *bg=overlay->background_gc;
579 if (parent->overlay_disabled || overlay->overlay_disabled || overlay->overlay_autodisabled)
581 dbg(1,"r->x=%d r->y=%d r->width=%d r->height=%d\n", re->x, re->y, re->width, re->height);
582 overlay_rect(parent, overlay, 0, &or);
583 dbg(1,"or.x=%d or.y=%d or.width=%d or.height=%d\n", or.x, or.y, or.width, or.height);
584 if (! gdk_rectangle_intersect(re, &or, &ir))
588 pixbuf=gdk_pixbuf_get_from_drawable(NULL, overlay->drawable, NULL, 0, 0, 0, 0, or.width, or.height);
589 pixbuf2=gdk_pixbuf_new(gdk_pixbuf_get_colorspace(pixbuf), TRUE, gdk_pixbuf_get_bits_per_sample(pixbuf),
590 or.width, or.height);
591 rowstride1 = gdk_pixbuf_get_rowstride (pixbuf);
592 rowstride2 = gdk_pixbuf_get_rowstride (pixbuf2);
593 pixels1=gdk_pixbuf_get_pixels (pixbuf);
594 pixels2=gdk_pixbuf_get_pixels (pixbuf2);
595 n_channels1 = gdk_pixbuf_get_n_channels (pixbuf);
596 n_channels2 = gdk_pixbuf_get_n_channels (pixbuf2);
597 for (y = 0 ; y < or.height ; y++) {
598 for (x = 0 ; x < or.width ; x++) {
599 p1 = pixels1 + y * rowstride1 + x * n_channels1;
600 p2 = pixels2 + y * rowstride2 + x * n_channels2;
604 if (bg && p1[0] == r && p1[1] == g && p1[2] == b)
610 gdk_draw_pixbuf(pixmap, gc, pixbuf2, 0, 0, or.x, or.y, or.width, or.height, GDK_RGB_DITHER_NONE, 0, 0);
611 g_object_unref(pixbuf);
612 g_object_unref(pixbuf2);
616 draw_restore(struct graphics_priv *gr, struct point *p, int w, int h)
618 GtkWidget *widget=gr->widget;
619 gdk_draw_drawable(widget->window,
620 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
622 p->x, p->y, p->x, p->y, w, h);
627 draw_drag(struct graphics_priv *gr, struct point *p)
643 background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc)
645 gr->background_gc=gc;
649 gtk_drawing_area_draw(struct graphics_priv *gr, GdkRectangle *r)
652 GtkWidget *widget=gr->widget;
653 GdkGC *gc=widget->style->fg_gc[GTK_WIDGET_STATE(widget)];
654 struct graphics_priv *overlay;
658 pixmap = gdk_pixmap_new(widget->window, r->width, r->height, -1);
659 if ((gr->p.x || gr->p.y) && gr->background_gc)
660 gdk_draw_rectangle(pixmap, gr->background_gc->gc, TRUE, 0, 0, r->width, r->height);
661 gdk_draw_drawable(pixmap, gc, gr->drawable, r->x, r->y, gr->p.x, gr->p.y, r->width, r->height);
662 overlay=gr->overlays;
664 overlay_draw(gr,overlay,r,pixmap,gc);
665 overlay=overlay->next;
667 gdk_draw_drawable(widget->window, gc, pixmap, 0, 0, r->x, r->y, r->width, r->height);
668 g_object_unref(pixmap);
672 draw_mode(struct graphics_priv *gr, enum draw_mode_num mode)
675 struct graphics_priv *overlay;
677 if (mode == draw_mode_begin) {
678 if (! gr->parent && gr->background_gc)
679 gdk_draw_rectangle(gr->drawable, gr->background_gc->gc, TRUE, 0, 0, gr->width, gr->height);
682 if (mode == draw_mode_end && gr->mode != draw_mode_cursor) {
685 overlay_rect(gr->parent, gr, 1, &r);
686 gtk_drawing_area_draw(gr->parent, &r);
689 overlay_rect(gr->parent, gr, 0, &r);
690 gtk_drawing_area_draw(gr->parent, &r);
696 gtk_drawing_area_draw(gr, &r);
697 overlay=gr->overlays;
700 overlay=overlay->next;
710 configure(GtkWidget * widget, GdkEventConfigure * event, gpointer user_data)
712 struct graphics_priv *gra=user_data;
715 if (gra->drawable != NULL) {
716 g_object_unref(gra->drawable);
718 if(gra->background_ready && gra->background != NULL) {
719 g_object_unref(gra->background);
720 gra->background_ready = 0;
723 dbg(1,"window=%d\n", GDK_WINDOW_XID(widget->window));
725 gra->width=widget->allocation.width;
726 gra->height=widget->allocation.height;
727 gra->drawable = gdk_pixmap_new(widget->window, gra->width, gra->height, -1);
728 callback_list_call_attr_2(gra->cbl, attr_resize, GINT_TO_POINTER(gra->width), GINT_TO_POINTER(gra->height));
733 expose(GtkWidget * widget, GdkEventExpose * event, gpointer user_data)
735 struct graphics_priv *gra=user_data;
739 configure(widget, NULL, user_data);
740 gtk_drawing_area_draw(gra, &event->area);
742 gdk_draw_drawable(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
743 gra->drawable, event->area.x, event->area.y,
744 event->area.x, event->area.y,
745 event->area.width, event->area.height);
753 button_timeout(gpointer user_data)
756 struct container *co=user_data;
757 int x=co->gra->gra->button_event.x;
758 int y=co->gra->gra->button_event.y;
759 int button=co->gra->gra->button_event.button;
761 co->gra->gra->button_timeout=0;
762 popup(co, x, y, button);
770 tv_delta(struct timeval *old, struct timeval *new)
772 if (new->tv_sec-old->tv_sec >= INT_MAX/1000)
774 return (new->tv_sec-old->tv_sec)*1000+(new->tv_usec-old->tv_usec)/1000;
778 button_press(GtkWidget * widget, GdkEventButton * event, gpointer user_data)
780 struct graphics_priv *this=user_data;
785 gettimeofday(&tv, &tz);
787 if (event->button < 8) {
788 if (tv_delta(&this->button_press[event->button], &tv) < this->timeout)
790 this->button_press[event->button]= tv;
791 this->button_release[event->button].tv_sec=0;
792 this->button_release[event->button].tv_usec=0;
796 callback_list_call_attr_3(this->cbl, attr_button, GINT_TO_POINTER(1), GINT_TO_POINTER(event->button), (void *)&p);
801 button_release(GtkWidget * widget, GdkEventButton * event, gpointer user_data)
803 struct graphics_priv *this=user_data;
808 gettimeofday(&tv, &tz);
810 if (event->button < 8) {
811 if (tv_delta(&this->button_release[event->button], &tv) < this->timeout)
813 this->button_release[event->button]= tv;
814 this->button_press[event->button].tv_sec=0;
815 this->button_press[event->button].tv_usec=0;
819 callback_list_call_attr_3(this->cbl, attr_button, GINT_TO_POINTER(0), GINT_TO_POINTER(event->button), (void *)&p);
826 scroll(GtkWidget * widget, GdkEventScroll * event, gpointer user_data)
828 struct graphics_priv *this=user_data;
834 switch (event->direction) {
838 case GDK_SCROLL_DOWN:
846 callback_list_call_attr_3(this->cbl, attr_button, GINT_TO_POINTER(1), GINT_TO_POINTER(button), (void *)&p);
847 callback_list_call_attr_3(this->cbl, attr_button, GINT_TO_POINTER(0), GINT_TO_POINTER(button), (void *)&p);
853 motion_notify(GtkWidget * widget, GdkEventMotion * event, gpointer user_data)
855 struct graphics_priv *this=user_data;
860 callback_list_call_attr_1(this->cbl, attr_motion, (void *)&p);
865 * * Exit navit (X pressed)
866 * * @param widget active widget
867 * * @param event the event (delete_event)
868 * * @param user_data Pointer to private data structure
872 delete(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
874 struct graphics_priv *this=user_data;
875 dbg(0,"enter this->win=%p\n",this->win);
876 if (this->delay & 2) {
880 callback_list_call_attr_0(this->cbl, attr_window_closed);
886 keypress(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
888 struct graphics_priv *this=user_data;
891 ucode=gdk_keyval_to_unicode(event->keyval);
892 len=g_unichar_to_utf8(ucode, key);
895 switch (event->keyval) {
901 key[0]=NAVIT_KEY_DOWN;
905 key[0]=NAVIT_KEY_LEFT;
909 key[0]=NAVIT_KEY_RIGHT;
913 key[0]=NAVIT_KEY_BACKSPACE;
921 key[0]=NAVIT_KEY_DELETE;
925 key[0]=NAVIT_KEY_BACK;
930 key[0]=NAVIT_KEY_RETURN;
937 key[0]=NAVIT_KEY_ZOOM_IN;
944 key[0]=NAVIT_KEY_ZOOM_OUT;
949 callback_list_call_attr_1(this->cbl, attr_keypress, (void *)key);
951 dbg(0,"keyval 0x%x\n", event->keyval);
956 static struct graphics_priv *graphics_gtk_drawing_area_new_helper(struct graphics_methods *meth);
959 overlay_disable(struct graphics_priv *gr, int disabled)
961 if (!gr->overlay_disabled != !disabled) {
962 gr->overlay_disabled=disabled;
965 overlay_rect(gr->parent, gr, 0, &r);
966 gtk_drawing_area_draw(gr->parent, &r);
972 overlay_resize(struct graphics_priv *this, struct point *p, int w, int h, int alpha, int wraparound)
974 //do not dereference parent for non overlay osds
995 if (this->width != w2) {
1000 if (this->height != h2) {
1005 this->a = alpha >> 8;
1006 this->wraparound = wraparound;
1009 // Set the drawables to the right sizes
1010 g_object_unref(this->drawable);
1011 g_object_unref(this->background);
1013 this->drawable=gdk_pixmap_new(this->parent->widget->window, w2, h2, -1);
1014 this->background=gdk_pixmap_new(this->parent->widget->window, w2, h2, -1);
1016 if ((w == 0) || (h == 0)) {
1017 this->overlay_autodisabled = 1;
1019 this->overlay_autodisabled = 0;
1022 callback_list_call_attr_2(this->cbl, attr_resize, GINT_TO_POINTER(this->width), GINT_TO_POINTER(this->height));
1027 get_data_window(struct graphics_priv *this, unsigned int xid)
1030 this->win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1032 this->win = gtk_plug_new(xid);
1033 if (!gtk_widget_get_parent(this->widget))
1034 gtk_widget_ref(this->widget);
1035 gtk_window_set_default_size(GTK_WINDOW(this->win), this->win_w, this->win_h);
1036 dbg(1,"h= %i, w= %i\n",this->win_h, this->win_w);
1037 gtk_window_set_title(GTK_WINDOW(this->win), this->window_title);
1038 gtk_window_set_wmclass (GTK_WINDOW (this->win), "navit", this->window_title);
1039 gtk_widget_realize(this->win);
1040 if (gtk_widget_get_parent(this->widget))
1041 gtk_widget_reparent(this->widget, this->win);
1043 gtk_container_add(GTK_CONTAINER(this->win), this->widget);
1044 gtk_widget_show_all(this->win);
1045 GTK_WIDGET_SET_FLAGS (this->widget, GTK_CAN_FOCUS);
1046 gtk_widget_set_sensitive(this->widget, TRUE);
1047 gtk_widget_grab_focus(this->widget);
1048 g_signal_connect(G_OBJECT(this->widget), "key-press-event", G_CALLBACK(keypress), this);
1049 g_signal_connect(G_OBJECT(this->win), "delete_event", G_CALLBACK(delete), this);
1053 set_attr(struct graphics_priv *gr, struct attr *attr)
1056 switch (attr->type) {
1058 get_data_window(gr, attr->u.num);
1065 static struct graphics_priv *
1066 overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h, int alpha, int wraparound)
1069 struct graphics_priv *this=graphics_gtk_drawing_area_new_helper(meth);
1070 this->colormap=gr->colormap;
1071 this->widget=gr->widget;
1077 /* If either height or width is 0, we set it to 1 to avoid warnings, and
1078 * disable the overlay. */
1091 this->background=gdk_pixmap_new(gr->widget->window, w2, h2, -1);
1092 this->drawable=gdk_pixmap_new(gr->widget->window, w2, h2, -1);
1094 if ((w == 0) || (h == 0)) {
1095 this->overlay_autodisabled = 1;
1097 this->overlay_autodisabled = 0;
1100 this->next=gr->overlays;
1102 this->wraparound=wraparound;
1107 static int gtk_argc;
1108 static char **gtk_argv={NULL};
1112 graphics_gtk_drawing_area_fullscreen(struct window *w, int on)
1114 struct graphics_priv *gr=w->priv;
1116 gtk_window_fullscreen(GTK_WINDOW(gr->win));
1118 gtk_window_unfullscreen(GTK_WINDOW(gr->win));
1123 graphics_gtk_drawing_area_disable_suspend(struct window *w)
1125 struct graphics_priv *gr=w->priv;
1129 kill(gr->pid, SIGWINCH);
1131 dbg(1, "failed to kill() under Windows\n");
1137 get_data(struct graphics_priv *this, char const *type)
1140 if (!strcmp(type,"gtk_widget"))
1141 return this->widget;
1143 if (!strcmp(type,"xwindow_id"))
1144 return (void *)GDK_WINDOW_XID(this->win ? this->win->window : this->widget->window);
1146 if (!strcmp(type,"window")) {
1147 char *cp = getenv("NAVIT_XID");
1150 xid = strtol(cp, NULL, 0);
1151 if (!(this->delay & 1))
1152 get_data_window(this, xid);
1153 this->window.fullscreen=graphics_gtk_drawing_area_fullscreen;
1154 this->window.disable_suspend=graphics_gtk_drawing_area_disable_suspend;
1155 this->window.priv=this;
1156 #if !defined(_WIN32) && !defined(__CEGCC__)
1157 f=popen("pidof /usr/bin/ipaq-sleep","r");
1159 fscanf(f,"%d",&this->pid);
1160 dbg(1,"ipaq_sleep pid=%d\n", this->pid);
1164 return &this->window;
1169 static struct graphics_methods graphics_methods = {
1185 NULL, /* font_new */
1192 NULL, /* get_text_bbox */
1198 static struct graphics_priv *
1199 graphics_gtk_drawing_area_new_helper(struct graphics_methods *meth)
1201 struct font_priv * (*font_freetype_new)(void *meth);
1202 font_freetype_new=plugin_get_font_type("freetype");
1203 if (!font_freetype_new)
1205 struct graphics_priv *this=g_new0(struct graphics_priv,1);
1206 font_freetype_new(&this->freetype_methods);
1207 *meth=graphics_methods;
1208 meth->font_new=(struct graphics_font_priv *(*)(struct graphics_priv *, struct graphics_font_methods *, char *, int, int))this->freetype_methods.font_new;
1209 meth->get_text_bbox=this->freetype_methods.get_text_bbox;
1214 static struct graphics_priv *
1215 graphics_gtk_drawing_area_new(struct navit *nav, struct graphics_methods *meth, struct attr **attrs, struct callback_list *cbl)
1221 if (! event_request_system("glib","graphics_gtk_drawing_area_new"))
1224 draw=gtk_drawing_area_new();
1225 struct graphics_priv *this=graphics_gtk_drawing_area_new_helper(meth);
1229 if ((attr=attr_search(attrs, NULL, attr_w)))
1230 this->win_w=attr->u.num;
1232 if ((attr=attr_search(attrs, NULL, attr_h)))
1233 this->win_h=attr->u.num;
1235 if ((attr=attr_search(attrs, NULL, attr_timeout)))
1236 this->timeout=attr->u.num;
1238 if ((attr=attr_search(attrs, NULL, attr_delay)))
1239 this->delay=attr->u.num;
1240 if ((attr=attr_search(attrs, NULL, attr_window_title)))
1241 this->window_title=g_strdup(attr->u.str);
1243 this->window_title=g_strdup("Navit");
1245 this->colormap=gdk_colormap_new(gdk_visual_get_system(),FALSE);
1246 gtk_widget_set_events(draw, GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK|GDK_KEY_PRESS_MASK);
1247 g_signal_connect(G_OBJECT(draw), "expose_event", G_CALLBACK(expose), this);
1248 g_signal_connect(G_OBJECT(draw), "configure_event", G_CALLBACK(configure), this);
1249 g_signal_connect(G_OBJECT(draw), "button_press_event", G_CALLBACK(button_press), this);
1250 g_signal_connect(G_OBJECT(draw), "button_release_event", G_CALLBACK(button_release), this);
1251 g_signal_connect(G_OBJECT(draw), "scroll_event", G_CALLBACK(scroll), this);
1252 g_signal_connect(G_OBJECT(draw), "motion_notify_event", G_CALLBACK(motion_notify), this);
1253 g_signal_connect(G_OBJECT(draw), "delete_event", G_CALLBACK(delete), nav);
1255 for (i = 0; i < 8; i++) {
1256 this->button_press[i].tv_sec = 0;
1257 this->button_press[i].tv_usec = 0;
1258 this->button_release[i].tv_sec = 0;
1259 this->button_release[i].tv_usec = 0;
1262 //create hash table for uncompressed image data
1263 if (!hImageDataCount++)
1264 hImageData = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, graphics_destroy_image);
1272 gtk_init(>k_argc, >k_argv);
1274 #ifdef HAVE_API_WIN32
1275 setlocale(LC_NUMERIC, "C"); /* WIN32 gtk resets LC_NUMERIC */
1277 plugin_register_graphics_type("gtk_drawing_area", graphics_gtk_drawing_area_new);