diff --git a/Sources/tools/Display/Display.cpp b/Sources/tools/Display/Display.cpp index a8bedf5..12c557e 100644 --- a/Sources/tools/Display/Display.cpp +++ b/Sources/tools/Display/Display.cpp @@ -127,7 +127,7 @@ cairo_font_face_t * Display::GetFont(bool bold, bool italic) #undef __class__ #define __class__ "DrawerManager" -#define megaplop mlkjmlk +//#define megaplop mlkjmlk /** * @brief DrawerManager constructor : generate a memoryDC where we can draw everything... * @@ -151,42 +151,25 @@ DrawerManager::DrawerManager(GtkWidget * widget, int32_t x, int32_t y) m_windows = widget->window; # endif -#ifdef megaplop - m_cairoWindows = gdk_cairo_create(m_windows); - - // create internal surface : - m_imageSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, x, y); - m_cairo = cairo_create(m_imageSurface); - - // copy current windows : - cairo_surface_t * drawable_surface = cairo_get_target(m_cairoWindows); - cairo_set_source_surface(m_cairo, drawable_surface, 0, 0); - cairo_paint(m_cairo); - - -// for Test only : this remove slowly the old line that is not rewritten - cairo_set_source_rgb(m_cairo, 0, 0, 0); - cairo_set_source_rgba(m_cairo, 1, 1, 1, 0.3); - cairo_paint(m_cairo); - - cairo_set_font_size(m_cairo, POLICE_SIZE); - m_dataToDisplay[0] = '\0'; + // Double buffer with previous copy management : + { + // Create the Cairo context from the current windows + cairo_t * cairoWindows = gdk_cairo_create(m_windows); + // inform that we nee a double buffer + GdkRectangle myRect = {0, 0, x, y}; + gdk_window_begin_paint_rect(m_windows, &myRect); + // Create the Cairo context from the double Buffer just created + m_cairo = gdk_cairo_create(m_windows); + // Copy the previous display data from the current display to the double buffer area: + cairo_surface_t * drawableSurface = cairo_get_target(cairoWindows); + cairo_set_source_surface(m_cairo, drawableSurface, 0, 0); + cairo_paint(m_cairo); + //cairo_surface_destroy(drawableSurface); + cairo_destroy(cairoWindows); + } cairo_scale(m_cairo, 1.0, 1.0); - cairo_scale(m_cairoWindows, 1.0, 1.0); - -#else - // start painting : we not use the automatic double buffered for internal optimisation, then we nee to work with this : - - /* - GdkRectangle myRect = {0, 0, 300, 300}; - gdk_window_begin_paint_rect(m_windows, &myRect); - */ - - // Create the Cairo Element - m_cairo = gdk_cairo_create(m_windows); - //cairo_translate(m_cairo, 0, 7); // for Test only : this remove slowly the old line that is not rewritten cairo_set_source_rgb(m_cairo, 0, 0, 0); cairo_set_source_rgba(m_cairo, 1, 1, 1, 0.3); @@ -195,14 +178,8 @@ DrawerManager::DrawerManager(GtkWidget * widget, int32_t x, int32_t y) cairo_set_font_size(m_cairo, POLICE_SIZE); m_dataToDisplay[0] = '\0'; - cairo_scale(m_cairo, 1.0, 1.0); - -#endif - m_nbElement = 0; - - // http://cairographics.org/FAQ/#clear_a_surface // http://gtk.developpez.com/faq/?page=gtkwidget#GTK_WIDGET_transparent //cairo_set_source_rgba(m_cairo, 1, 1, 1, 0); @@ -225,16 +202,10 @@ DrawerManager::DrawerManager(GtkWidget * widget, int32_t x, int32_t y) */ DrawerManager::~DrawerManager() { -#ifdef megaplop - cairo_set_source_surface(m_cairoWindows, m_imageSurface, 0, 0); - cairo_paint(m_cairoWindows); + // call the painting of the double buffer in the displayed current buffer + gdk_window_end_paint(m_windows); + // Destroy cairo context cairo_destroy(m_cairo); - cairo_destroy(m_cairoWindows); -#else - // fill the diplayed buffer ... - //gdk_window_end_paint(m_windows); - cairo_destroy(m_cairo); -#endif } diff --git a/Sources/tools/Display/Display.h b/Sources/tools/Display/Display.h index e8aa3ab..ce418e0 100644 --- a/Sources/tools/Display/Display.h +++ b/Sources/tools/Display/Display.h @@ -86,8 +86,6 @@ class DrawerManager { position_ts m_size; //!< Total size cairo_t * m_cairo; //!< Cairo Layout pointer GdkWindow * m_windows; //!< remember the current widget ==> for some internal problems - cairo_t * m_cairoWindows; //!< Cairo context - cairo_surface_t *m_imageSurface; }; diff --git a/test_transparence.c b/test_transparence.c index 2019271..903ad40 100644 --- a/test_transparence.c +++ b/test_transparence.c @@ -36,6 +36,9 @@ int main(int argc, char **argv) gtk_widget_set_app_paintable(window, TRUE); + // Remove double-buffering ==> in the current case we can not get the previous display... + gtk_widget_set_double_buffered(window, FALSE); + # if USE_GTK_VERSION_3_0 g_signal_connect(G_OBJECT(window), "draw", G_CALLBACK(expose), NULL); # elif USE_GTK_VERSION_2_0 @@ -60,17 +63,17 @@ int main(int argc, char **argv) &color); */ #endif - gtk_window_set_decorated(GTK_WINDOW(window), FALSE); - gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK); - g_signal_connect(G_OBJECT(window), "button-press-event", G_CALLBACK(clicked), NULL); + //gtk_window_set_decorated(GTK_WINDOW(window), FALSE); + //gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK); + /* //g_signal_connect(G_OBJECT(window), "button-press-event", G_CALLBACK(clicked), NULL); GtkWidget* fixed_container = gtk_fixed_new(); gtk_container_add(GTK_CONTAINER(window), fixed_container); GtkWidget* button = gtk_button_new_with_label("button1"); gtk_widget_set_size_request(button, 100, 100); gtk_container_add(GTK_CONTAINER(fixed_container), button); - - screen_changed(window, NULL, NULL); +*/ + //screen_changed(window, NULL, NULL); gtk_widget_show_all(window); gtk_main(); @@ -114,20 +117,36 @@ static void screen_changed(GtkWidget *widget, GdkScreen *old_screen, gpointer us static gboolean expose(GtkWidget *widget, GdkEventExpose *event, gpointer userdata) { - return FALSE; -# if USE_GTK_VERSION_3_0 - cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(widget)); -# elif USE_GTK_VERSION_2_0 - cairo_t *cr = gdk_cairo_create(widget->window); -# endif - if (TRUE == supports_alpha) - cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 0.3); /* transparent */ - else - cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); /* opaque white */ - /* draw the background */ - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_paint (cr); + //return FALSE; + GdkWindow * m_windows = NULL; +# if USE_GTK_VERSION_3_0 + m_windows = gtk_widget_get_window(widget); +# elif USE_GTK_VERSION_2_0 + m_windows = widget->window; +# endif + gtk_widget_shape_combine_mask(widget, NULL, 0, 0); + cairo_t *cr = gdk_cairo_create(m_windows); + + + + //if (TRUE == supports_alpha) { + cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 0.2); // transparent + /*} else { + cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); // opaque white + }*/ + /* draw the background */ + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + + /* draw a circle */ + int width, height; + gtk_window_get_size(GTK_WINDOW(widget), &width, &height); + + cairo_set_source_rgba(cr, 1, 0.2, 0.2, 0.6); + cairo_arc(cr, width / 2, height / 2, (width < height ? width : height) / 2 - 8 , 0, 2 * 3.14); + cairo_fill(cr); + cairo_stroke(cr); cairo_destroy(cr); diff --git a/test_transparence2.c b/test_transparence2.c new file mode 100644 index 0000000..396ef30 --- /dev/null +++ b/test_transparence2.c @@ -0,0 +1,292 @@ +/******************************************************************************* +**3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 +** 10 20 30 40 50 60 70 80 +** +** program: +** input_shape_test +** +** created: +** 19.2.2006 +** +** last change: +** 20.2.2006 +** +** author: +** Mirco "MacSlow" Mueller +** +** license: +** GPL +** +** notes: +** - this is a test I did to figure out how to use input-shapes (XShape 1.1) +** - opens a decoration-less and transparent gtk+-window and draws a red +** cross with a circle around it +** - only the parts drawn will be "draggable" +** - window can be dragged around with LMB-drag +** - window can be resized with MMB-drag (the input-shape also resizes!) +** - window can be exited with ESC or q +** - needs a compositing manager to run in order to look as intended +** - tested with xcompmgr and compiz +** - tested with gtk+-2.8.11 and gtk+-2.9.0 (CVS-head) +** +** bugs: +** - there are no size-checks done for the input-shape, so I don't know what +** will happen, if you make the window super large +** +** todo: +** - nothing +** +** compile with: +** gcc `pkg-config --cflags --libs gtk+-2.0` input_shape_test.c -o input_shape_test +** +*******************************************************************************/ + +#include +#include +#include +#if !GTK_CHECK_VERSION(2,9,0) +#include +#include +#include +#endif + +#define WIN_WIDTH 300 +#define WIN_HEIGHT 300 + +gint g_iCurrentWidth = WIN_WIDTH; +gint g_iCurrentHeight = WIN_HEIGHT; + +void update_input_shape (GtkWidget* pWindow, int iWidth, int iHeight); +void on_alpha_screen_changed (GtkWidget* pWidget, GdkScreen* pOldScreen, GtkWidget* pLabel); +void render (cairo_t* pCairoContext, gint iWidth, gint iHeight); +gboolean on_expose (GtkWidget* pWidget, GdkEventExpose* pExpose); +gboolean on_key_press (GtkWidget* pWidget, GdkEventKey* pKey, gpointer userData); +gboolean on_button_press (GtkWidget* pWidget, GdkEventButton* pButton, GdkWindowEdge edge); +gboolean on_configure (GtkWidget* pWidget, GdkEventConfigure* pEvent, gpointer data); +#if !GTK_CHECK_VERSION(2,9,0) +void do_shape_combine_mask (GdkWindow* window, GdkBitmap* mask, gint x, gint y); +#endif +void update_input_shape (GtkWidget* pWindow, int iWidth, int iHeight); + +void on_alpha_screen_changed (GtkWidget* pWidget, + GdkScreen* pOldScreen, + GtkWidget* pLabel) +{ + GdkScreen* pScreen = gtk_widget_get_screen (pWidget); + GdkColormap* pColormap = gdk_screen_get_rgba_colormap (pScreen); + + if (!pColormap) + pColormap = gdk_screen_get_rgb_colormap (pScreen); + + gtk_widget_set_colormap (pWidget, pColormap); +} + +void render (cairo_t* pCairoContext, gint iWidth, gint iHeight) +{ + cairo_scale (pCairoContext, (double) iWidth, (double) iHeight); + cairo_set_source_rgba (pCairoContext, 1.0f, 1.0f, 1.0f, 0.0f); + cairo_set_operator (pCairoContext, CAIRO_OPERATOR_SOURCE); + cairo_paint (pCairoContext); + cairo_set_source_rgba (pCairoContext, 1.0f, 0.0f, 0.0f, 0.75f); + cairo_set_line_width (pCairoContext, 0.1f); + cairo_move_to (pCairoContext, 0.15f, 0.15f); + cairo_line_to (pCairoContext, 0.85f, 0.85f); + cairo_move_to (pCairoContext, 0.85f, 0.15f); + cairo_line_to (pCairoContext, 0.15f, 0.85f); + cairo_stroke (pCairoContext); + cairo_arc (pCairoContext, 0.5f, 0.5f, 0.45f, 0.0f, M_PI/180.0f * 360.0f); + cairo_stroke (pCairoContext); +} + +gboolean on_expose (GtkWidget* pWidget, + GdkEventExpose* pExpose) +{ + gint iWidth; + gint iHeight; + cairo_t* pCairoContext = NULL; + + pCairoContext = gdk_cairo_create (pWidget->window); + if (!pCairoContext) + return FALSE; + + gtk_window_get_size (GTK_WINDOW (pWidget), &iWidth, &iHeight); + render (pCairoContext, iWidth, iHeight); + cairo_destroy (pCairoContext); + + return FALSE; +} + +gboolean on_configure (GtkWidget* pWidget, + GdkEventConfigure* pEvent, + gpointer userData) +{ + gint iNewWidth = pEvent->width; + gint iNewHeight = pEvent->height; + + if (iNewWidth != g_iCurrentWidth || iNewHeight != g_iCurrentHeight) + { + update_input_shape (pWidget, iNewWidth, iNewHeight); + g_iCurrentWidth = iNewWidth; + g_iCurrentHeight = iNewHeight; + } + + return FALSE; +} + +gboolean on_key_press (GtkWidget* pWidget, + GdkEventKey* pKey, + gpointer userData) +{ + gint iWidth; + gint iHeight; + + if (pKey->type == GDK_KEY_PRESS) + { + switch (pKey->keyval) + { + case GDK_Escape : + case GDK_q : + gtk_main_quit (); + break; + } + } + + return FALSE; +} + +gboolean on_button_press (GtkWidget* pWidget, + GdkEventButton* pButton, + GdkWindowEdge edge) +{ + if (pButton->type == GDK_BUTTON_PRESS) + { + if (pButton->button == 1) + gtk_window_begin_move_drag (GTK_WINDOW (gtk_widget_get_toplevel (pWidget)), + pButton->button, + pButton->x_root, + pButton->y_root, + pButton->time); + if (pButton->button == 2) + gtk_window_begin_resize_drag (GTK_WINDOW (gtk_widget_get_toplevel (pWidget)), + edge, + pButton->button, + pButton->x_root, + pButton->y_root, + pButton->time); + } + + return FALSE; +} + +#if !GTK_CHECK_VERSION(2,9,0) +/* this is piece by piece taken from gtk+ 2.9.0 (CVS-head with a patch applied +regarding XShape's input-masks) so people without gtk+ >= 2.9.0 can compile and +run input_shape_test.c */ +void do_shape_combine_mask (GdkWindow* window, + GdkBitmap* mask, + gint x, + gint y) +{ + Pixmap pixmap; + int ignore; + int maj; + int min; + + if (!XShapeQueryExtension (GDK_WINDOW_XDISPLAY (window), &ignore, &ignore)) + return; + + if (!XShapeQueryVersion (GDK_WINDOW_XDISPLAY (window), &maj, &min)) + return; + + /* for shaped input we need at least XShape 1.1 */ + if (maj != 1 && min < 1) + return; + + if (mask) + pixmap = GDK_DRAWABLE_XID (mask); + else + { + x = 0; + y = 0; + pixmap = None; + } + + XShapeCombineMask (GDK_WINDOW_XDISPLAY (window), + GDK_DRAWABLE_XID (window), + ShapeInput, + x, + y, + pixmap, + ShapeSet); +} +#endif + +void update_input_shape (GtkWidget* pWindow, int iWidth, int iHeight) +{ + static GdkBitmap* pShapeBitmap = NULL; + static cairo_t* pCairoContext = NULL; + + pShapeBitmap = (GdkBitmap*) gdk_pixmap_new (NULL, iWidth, iHeight, 1); + if (pShapeBitmap) + { + pCairoContext = gdk_cairo_create (pShapeBitmap); + if (cairo_status (pCairoContext) == CAIRO_STATUS_SUCCESS) + { + render (pCairoContext, iWidth, iHeight); + cairo_destroy (pCairoContext); +#if !GTK_CHECK_VERSION(2,9,0) + do_shape_combine_mask (pWindow->window, NULL, 0, 0); + do_shape_combine_mask (pWindow->window, pShapeBitmap, 0, 0); +#else + gtk_widget_input_shape_combine_mask (pWindow, NULL, 0, 0); + gtk_widget_input_shape_combine_mask (pWindow, pShapeBitmap, 0, 0); +#endif + } + g_object_unref ((gpointer) pShapeBitmap); + } +} + +int main (int argc, char** argv) +{ + GtkWidget* pWindow = NULL; + GdkBitmap* pShapeMaskBitmap = NULL; + + gtk_init (&argc, &argv); + + pWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); + on_alpha_screen_changed (pWindow, NULL, NULL); + gtk_widget_set_app_paintable (pWindow, TRUE); + gtk_window_set_decorated (GTK_WINDOW (pWindow), FALSE); + gtk_window_set_resizable (GTK_WINDOW (pWindow), TRUE); + gtk_window_set_title (GTK_WINDOW (pWindow), "gtk+/XShape 1.1 test"); + gtk_widget_set_size_request (pWindow, g_iCurrentWidth, g_iCurrentHeight); + gtk_widget_add_events (pWindow, GDK_BUTTON_PRESS_MASK); + gtk_widget_show (pWindow); + + g_signal_connect (G_OBJECT (pWindow), + "destroy", + G_CALLBACK (gtk_main_quit), + NULL); + g_signal_connect (G_OBJECT (pWindow), + "expose-event", + G_CALLBACK (on_expose), + NULL); + g_signal_connect (G_OBJECT (pWindow), + "configure-event", + G_CALLBACK (on_configure), + NULL); + g_signal_connect (G_OBJECT (pWindow), + "key-press-event", + G_CALLBACK (on_key_press), + NULL); + g_signal_connect (G_OBJECT (pWindow), + "button-press-event", + G_CALLBACK (on_button_press), + NULL); + + update_input_shape (pWindow, g_iCurrentWidth, g_iCurrentHeight); + + gtk_main (); + + return 0; +}