mirror of
https://github.com/ZoiteChat/zoitechat.git
synced 2026-03-20 12:40:18 +00:00
- Added Cairo-based window snapshot conversion (with unpremultiplication) for drag icons and updated drag rendering to use the new helper instead of drawable capture.
- Updated GtkXText to track the draw window and use a pixmap-to-surface helper for Cairo contexts, avoiding drawable references in the struct and rendering flow. - Added a Cairo helper for capturing window-backed surfaces and used it when blitting during scrolling, fixing the build break from the removed drawable helper.
This commit is contained in:
@@ -91,6 +91,88 @@ mg_set_source_color (cairo_t *cr, const GdkColor *color)
|
|||||||
color->blue / 65535.0, 1.0);
|
color->blue / 65535.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
#define MG_CAIRO_BLUE 0
|
||||||
|
#define MG_CAIRO_GREEN 1
|
||||||
|
#define MG_CAIRO_RED 2
|
||||||
|
#define MG_CAIRO_ALPHA 3
|
||||||
|
#else
|
||||||
|
#define MG_CAIRO_ALPHA 0
|
||||||
|
#define MG_CAIRO_RED 1
|
||||||
|
#define MG_CAIRO_GREEN 2
|
||||||
|
#define MG_CAIRO_BLUE 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
mg_unpremultiply_pixel (const guchar *src, guchar *dest)
|
||||||
|
{
|
||||||
|
guchar alpha = src[MG_CAIRO_ALPHA];
|
||||||
|
guchar red = src[MG_CAIRO_RED];
|
||||||
|
guchar green = src[MG_CAIRO_GREEN];
|
||||||
|
guchar blue = src[MG_CAIRO_BLUE];
|
||||||
|
|
||||||
|
if (alpha == 0)
|
||||||
|
{
|
||||||
|
dest[0] = 0;
|
||||||
|
dest[1] = 0;
|
||||||
|
dest[2] = 0;
|
||||||
|
dest[3] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest[0] = (guchar)((red * 255 + alpha / 2) / alpha);
|
||||||
|
dest[1] = (guchar)((green * 255 + alpha / 2) / alpha);
|
||||||
|
dest[2] = (guchar)((blue * 255 + alpha / 2) / alpha);
|
||||||
|
dest[3] = alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkPixbuf *
|
||||||
|
mg_pixbuf_from_window (GdkWindow *window, int width, int height)
|
||||||
|
{
|
||||||
|
cairo_surface_t *surface;
|
||||||
|
cairo_t *cr;
|
||||||
|
GdkPixbuf *pixbuf;
|
||||||
|
guchar *surface_data;
|
||||||
|
guchar *dest;
|
||||||
|
int surface_stride;
|
||||||
|
int dest_stride;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
|
||||||
|
cr = cairo_create (surface);
|
||||||
|
gdk_cairo_set_source_window (cr, window, 0.0, 0.0);
|
||||||
|
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||||
|
cairo_paint (cr);
|
||||||
|
cairo_destroy (cr);
|
||||||
|
|
||||||
|
cairo_surface_flush (surface);
|
||||||
|
|
||||||
|
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
|
||||||
|
surface_data = cairo_image_surface_get_data (surface);
|
||||||
|
surface_stride = cairo_image_surface_get_stride (surface);
|
||||||
|
dest = gdk_pixbuf_get_pixels (pixbuf);
|
||||||
|
dest_stride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||||
|
|
||||||
|
for (y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
const guchar *src_row = surface_data + (y * surface_stride);
|
||||||
|
guchar *dest_row = dest + (y * dest_stride);
|
||||||
|
|
||||||
|
for (x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
const guchar *src = src_row + (x * 4);
|
||||||
|
guchar *dst = dest_row + (x * 4);
|
||||||
|
|
||||||
|
mg_unpremultiply_pixel (src, dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_surface_destroy (surface);
|
||||||
|
|
||||||
|
return pixbuf;
|
||||||
|
}
|
||||||
|
|
||||||
static void mg_create_entry (session *sess, GtkWidget *box);
|
static void mg_create_entry (session *sess, GtkWidget *box);
|
||||||
static void mg_create_search (session *sess, GtkWidget *box);
|
static void mg_create_search (session *sess, GtkWidget *box);
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
@@ -4062,18 +4144,18 @@ gboolean
|
|||||||
mg_drag_begin_cb (GtkWidget *widget, GdkDragContext *context, gpointer userdata)
|
mg_drag_begin_cb (GtkWidget *widget, GdkDragContext *context, gpointer userdata)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
GdkColormap *cmap;
|
|
||||||
GdkPixbuf *pix, *pix2;
|
GdkPixbuf *pix, *pix2;
|
||||||
|
GdkWindow *window;
|
||||||
|
|
||||||
/* ignore file drops */
|
/* ignore file drops */
|
||||||
if (!mg_is_gui_target (context))
|
if (!mg_is_gui_target (context))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
cmap = gtk_widget_get_colormap (widget);
|
window = gtk_widget_get_window (widget);
|
||||||
width = gdk_window_get_width (gtk_widget_get_window (widget));
|
width = gdk_window_get_width (window);
|
||||||
height = gdk_window_get_height (gtk_widget_get_window (widget));
|
height = gdk_window_get_height (window);
|
||||||
|
|
||||||
pix = gdk_pixbuf_get_from_drawable (NULL, gtk_widget_get_window (widget), cmap, 0, 0, 0, 0, width, height);
|
pix = mg_pixbuf_from_window (window, width, height);
|
||||||
pix2 = gdk_pixbuf_scale_simple (pix, width * 4 / 5, height / 2, GDK_INTERP_HYPER);
|
pix2 = gdk_pixbuf_scale_simple (pix, width * 4 / 5, height / 2, GDK_INTERP_HYPER);
|
||||||
g_object_unref (pix);
|
g_object_unref (pix);
|
||||||
|
|
||||||
@@ -4128,7 +4210,7 @@ mg_drag_motion_cb (GtkWidget *widget, GdkDragContext *context, int x, int y, gui
|
|||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
int half, width, height;
|
int half, width, height;
|
||||||
int ox, oy;
|
int ox, oy;
|
||||||
GdkDrawable *draw;
|
GdkWindow *window;
|
||||||
GtkAllocation allocation;
|
GtkAllocation allocation;
|
||||||
|
|
||||||
/* ignore file drops */
|
/* ignore file drops */
|
||||||
@@ -4142,20 +4224,20 @@ mg_drag_motion_cb (GtkWidget *widget, GdkDragContext *context, int x, int y, gui
|
|||||||
oy = allocation.y;
|
oy = allocation.y;
|
||||||
width = allocation.width;
|
width = allocation.width;
|
||||||
height = allocation.height;
|
height = allocation.height;
|
||||||
draw = gtk_widget_get_window (widget);
|
window = gtk_widget_get_window (widget);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ox = oy = 0;
|
ox = oy = 0;
|
||||||
width = gdk_window_get_width (gtk_widget_get_window (widget));
|
window = gtk_widget_get_window (widget);
|
||||||
height = gdk_window_get_height (gtk_widget_get_window (widget));
|
width = gdk_window_get_width (window);
|
||||||
draw = gtk_widget_get_window (widget);
|
height = gdk_window_get_height (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
col.red = rand() % 0xffff;
|
col.red = rand() % 0xffff;
|
||||||
col.green = rand() % 0xffff;
|
col.green = rand() % 0xffff;
|
||||||
col.blue = rand() % 0xffff;
|
col.blue = rand() % 0xffff;
|
||||||
cr = gdk_cairo_create (draw);
|
cr = gdk_cairo_create (window);
|
||||||
cairo_set_operator (cr, CAIRO_OPERATOR_XOR);
|
cairo_set_operator (cr, CAIRO_OPERATOR_XOR);
|
||||||
mg_set_source_color (cr, &col);
|
mg_set_source_color (cr, &col);
|
||||||
cairo_set_line_width (cr, 1.0);
|
cairo_set_line_width (cr, 1.0);
|
||||||
|
|||||||
@@ -158,9 +158,20 @@ xtext_set_source_color (cairo_t *cr, GdkColor *color, gdouble alpha)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static cairo_surface_t *
|
static cairo_surface_t *
|
||||||
xtext_surface_from_drawable (GdkDrawable *drawable)
|
xtext_surface_from_pixmap (GdkPixmap *pixmap)
|
||||||
{
|
{
|
||||||
cairo_t *cr = gdk_cairo_create (drawable);
|
cairo_t *cr = gdk_cairo_create (pixmap);
|
||||||
|
cairo_surface_t *surface = cairo_surface_reference (cairo_get_target (cr));
|
||||||
|
|
||||||
|
cairo_destroy (cr);
|
||||||
|
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cairo_surface_t *
|
||||||
|
xtext_surface_from_window (GdkWindow *window)
|
||||||
|
{
|
||||||
|
cairo_t *cr = gdk_cairo_create (window);
|
||||||
cairo_surface_t *surface = cairo_surface_reference (cairo_get_target (cr));
|
cairo_surface_t *surface = cairo_surface_reference (cairo_get_target (cr));
|
||||||
|
|
||||||
cairo_destroy (cr);
|
cairo_destroy (cr);
|
||||||
@@ -174,7 +185,7 @@ xtext_create_context (GtkXText *xtext)
|
|||||||
if (xtext->draw_surface)
|
if (xtext->draw_surface)
|
||||||
return cairo_create (xtext->draw_surface);
|
return cairo_create (xtext->draw_surface);
|
||||||
|
|
||||||
return gdk_cairo_create (xtext->draw_buf);
|
return gdk_cairo_create (xtext->draw_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@@ -215,7 +226,7 @@ xtext_draw_bg_offset (GtkXText *xtext, int x, int y, int width, int height, int
|
|||||||
|
|
||||||
if (xtext->pixmap)
|
if (xtext->pixmap)
|
||||||
{
|
{
|
||||||
cairo_surface_t *surface = xtext_surface_from_drawable (xtext->pixmap);
|
cairo_surface_t *surface = xtext_surface_from_pixmap (xtext->pixmap);
|
||||||
|
|
||||||
cairo_set_source_surface (cr, surface, tile_x, tile_y);
|
cairo_set_source_surface (cr, surface, tile_x, tile_y);
|
||||||
cairo_surface_destroy (surface);
|
cairo_surface_destroy (surface);
|
||||||
@@ -487,6 +498,7 @@ static void
|
|||||||
gtk_xtext_init (GtkXText * xtext)
|
gtk_xtext_init (GtkXText * xtext)
|
||||||
{
|
{
|
||||||
xtext->pixmap = NULL;
|
xtext->pixmap = NULL;
|
||||||
|
xtext->draw_window = NULL;
|
||||||
xtext->draw_surface = NULL;
|
xtext->draw_surface = NULL;
|
||||||
xtext->io_tag = 0;
|
xtext->io_tag = 0;
|
||||||
xtext->add_io_tag = 0;
|
xtext->add_io_tag = 0;
|
||||||
@@ -758,7 +770,7 @@ gtk_xtext_realize (GtkWidget * widget)
|
|||||||
xtext_set_bg (xtext, XTEXT_BG);
|
xtext_set_bg (xtext, XTEXT_BG);
|
||||||
|
|
||||||
/* draw directly to window */
|
/* draw directly to window */
|
||||||
xtext->draw_buf = widget->window;
|
xtext->draw_window = widget->window;
|
||||||
|
|
||||||
if (xtext->pixmap)
|
if (xtext->pixmap)
|
||||||
{
|
{
|
||||||
@@ -3877,7 +3889,7 @@ gtk_xtext_render_page (GtkXText * xtext)
|
|||||||
cr = xtext_create_context (xtext);
|
cr = xtext_create_context (xtext);
|
||||||
cairo_save (cr);
|
cairo_save (cr);
|
||||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||||
surface = xtext_surface_from_drawable (GTK_WIDGET (xtext)->window);
|
surface = xtext_surface_from_window (GTK_WIDGET (xtext)->window);
|
||||||
cairo_set_source_surface (cr, surface, dest_x - src_x, dest_y - src_y);
|
cairo_set_source_surface (cr, surface, dest_x - src_x, dest_y - src_y);
|
||||||
cairo_surface_destroy (surface);
|
cairo_surface_destroy (surface);
|
||||||
cairo_rectangle (cr, dest_x, dest_y, width, copy_height);
|
cairo_rectangle (cr, dest_x, dest_y, width, copy_height);
|
||||||
@@ -3898,7 +3910,7 @@ gtk_xtext_render_page (GtkXText * xtext)
|
|||||||
cr = xtext_create_context (xtext);
|
cr = xtext_create_context (xtext);
|
||||||
cairo_save (cr);
|
cairo_save (cr);
|
||||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||||
surface = xtext_surface_from_drawable (GTK_WIDGET (xtext)->window);
|
surface = xtext_surface_from_window (GTK_WIDGET (xtext)->window);
|
||||||
cairo_set_source_surface (cr, surface, dest_x - src_x, dest_y - src_y);
|
cairo_set_source_surface (cr, surface, dest_x - src_x, dest_y - src_y);
|
||||||
cairo_surface_destroy (surface);
|
cairo_surface_destroy (surface);
|
||||||
cairo_rectangle (cr, dest_x, dest_y, width, copy_height);
|
cairo_rectangle (cr, dest_x, dest_y, width, copy_height);
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ struct _GtkXText
|
|||||||
|
|
||||||
GtkAdjustment *adj;
|
GtkAdjustment *adj;
|
||||||
GdkPixmap *pixmap; /* 0 = use palette[19] */
|
GdkPixmap *pixmap; /* 0 = use palette[19] */
|
||||||
GdkDrawable *draw_buf; /* points to ->window */
|
GdkWindow *draw_window; /* points to ->window */
|
||||||
cairo_surface_t *draw_surface; /* temporary surface for offscreen draws */
|
cairo_surface_t *draw_surface; /* temporary surface for offscreen draws */
|
||||||
GdkCursor *hand_cursor;
|
GdkCursor *hand_cursor;
|
||||||
GdkCursor *resize_cursor;
|
GdkCursor *resize_cursor;
|
||||||
|
|||||||
Reference in New Issue
Block a user