gtk/gdk/directfb/gdkgeometry-directfb.c

255 lines
8.1 KiB
C

/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team.
*/
/*
* GTK+ DirectFB backend
* Copyright (C) 2001-2002 convergence integrated media GmbH
* Copyright (C) 2002-2004 convergence GmbH
* Written by Denis Oliver Kropp <dok@convergence.de> and
* Sven Neumann <sven@convergence.de>
*/
#include "config.h"
#include "gdk.h" /* For gdk_rectangle_intersect */
#include "gdkdirectfb.h"
#include "gdkprivate-directfb.h"
#include "gdkinternals.h"
void
_gdk_directfb_window_get_offsets (GdkWindow *window,
gint *x_offset,
gint *y_offset)
{
if (x_offset)
*x_offset = 0;
if (y_offset)
*y_offset = 0;
}
gboolean
_gdk_windowing_window_queue_antiexpose (GdkWindow *window,
cairo_region_t *area)
{
return FALSE;
}
/**
* gdk_window_scroll:
* @window: a #GdkWindow
* @dx: Amount to scroll in the X direction
* @dy: Amount to scroll in the Y direction
*
* Scroll the contents of its window, both pixels and children, by
* the given amount. Portions of the window that the scroll operation
* brings in from offscreen areas are invalidated.
**/
void
_gdk_directfb_window_scroll (GdkWindow *window,
gint dx,
gint dy)
{
GdkWindowObject *private;
GdkDrawableImplDirectFB *impl;
cairo_region_t *invalidate_region = NULL;
GList *list;
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
return;
private = GDK_WINDOW_OBJECT (window);
impl = GDK_DRAWABLE_IMPL_DIRECTFB (private->impl);
if (dx == 0 && dy == 0)
return;
/* Move the current invalid region */
if (private->update_area)
cairo_region_translate (private->update_area, dx, dy);
if (GDK_WINDOW_IS_MAPPED (window))
{
GdkRectangle clip_rect = { 0, 0, impl->width, impl->height };
GdkRectangle rect = { dx, dy, impl->width, impl->height };
invalidate_region = cairo_region_create_rectangle (&clip_rect);
if (gdk_rectangle_intersect (&rect, &clip_rect, &rect) &&
(!private->update_area ||
!cairo_region_contains_rectangle (private->update_area, &rect)))
{
cairo_region_t *region;
region = cairo_region_create_rectangle (&rect);
cairo_region_subtract (invalidate_region, region);
cairo_region_destroy (region);
if (impl->surface)
{
DFBRegion update = { rect.x, rect.y,
rect.x + rect.width - 1,
rect.y + rect.height - 1 };
impl->surface->SetClip (impl->surface, &update);
impl->surface->Blit (impl->surface, impl->surface, NULL, dx, dy);
impl->surface->SetClip (impl->surface, NULL);
impl->surface->Flip(impl->surface,&update,0);
}
}
}
for (list = private->children; list; list = list->next)
{
GdkWindowObject *obj = GDK_WINDOW_OBJECT (list->data);
GdkDrawableImplDirectFB *obj_impl = GDK_DRAWABLE_IMPL_DIRECTFB (obj->impl);
_gdk_directfb_move_resize_child (list->data,
obj->x + dx,
obj->y + dy,
obj_impl->width,
obj_impl->height);
}
_gdk_directfb_calc_abs (window);
if (invalidate_region)
{
gdk_window_invalidate_region (window, invalidate_region, TRUE);
cairo_region_destroy (invalidate_region);
}
}
/**
* gdk_window_move_region:
* @window: a #GdkWindow
* @region: The #cairo_region_t to move
* @dx: Amount to move in the X direction
* @dy: Amount to move in the Y direction
*
* Move the part of @window indicated by @region by @dy pixels in the Y
* direction and @dx pixels in the X direction. The portions of @region
* that not covered by the new position of @region are invalidated.
*
* Child windows are not moved.
*
* Since: 2.8
**/
void
_gdk_directfb_window_move_region (GdkWindow *window,
const cairo_region_t *region,
gint dx,
gint dy)
{
GdkWindowObject *private;
GdkDrawableImplDirectFB *impl;
cairo_region_t *window_clip;
cairo_region_t *src_region;
cairo_region_t *brought_in;
cairo_region_t *dest_region;
cairo_region_t *moving_invalid_region;
GdkRectangle dest_extents;
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (region != NULL);
if (GDK_WINDOW_DESTROYED (window))
return;
private = GDK_WINDOW_OBJECT (window);
impl = GDK_DRAWABLE_IMPL_DIRECTFB (private->impl);
if (dx == 0 && dy == 0)
return;
GdkRectangle clip_rect = { 0, 0, impl->width, impl->height };
window_clip = cairo_region_create_rectangle (&clip_rect);
/* compute source regions */
src_region = cairo_region_copy (region);
brought_in = cairo_region_copy (region);
cairo_region_intersect (src_region, window_clip);
cairo_region_subtract (brought_in, src_region);
cairo_region_translate (brought_in, dx, dy);
/* compute destination regions */
dest_region = cairo_region_copy (src_region);
cairo_region_translate (dest_region, dx, dy);
cairo_region_intersect (dest_region, window_clip);
cairo_region_get_extents (dest_region, &dest_extents);
cairo_region_destroy (window_clip);
/* calculating moving part of current invalid area */
moving_invalid_region = NULL;
if (private->update_area)
{
moving_invalid_region = cairo_region_copy (private->update_area);
cairo_region_intersect (moving_invalid_region, src_region);
cairo_region_translate (moving_invalid_region, dx, dy);
}
/* invalidate all of the src region */
gdk_window_invalidate_region (window, src_region, FALSE);
/* un-invalidate destination region */
if (private->update_area)
cairo_region_subtract (private->update_area, dest_region);
/* invalidate moving parts of existing update area */
if (moving_invalid_region)
{
gdk_window_invalidate_region (window, moving_invalid_region, FALSE);
cairo_region_destroy (moving_invalid_region);
}
/* invalidate area brought in from off-screen */
gdk_window_invalidate_region (window, brought_in, FALSE);
cairo_region_destroy (brought_in);
/* Actually do the moving */
if (impl->surface)
{
DFBRectangle source = { dest_extents.x - dx,
dest_extents.y - dy,
dest_extents.width,
dest_extents.height};
DFBRegion destination = { dest_extents.x,
dest_extents.y,
dest_extents.x+dest_extents.width-1,
dest_extents.y+dest_extents.height-1};
impl->surface->SetClip (impl->surface, &destination);
impl->surface->Blit (impl->surface, impl->surface,&source,dx,dy);
impl->surface->SetClip (impl->surface, NULL);
impl->surface->Flip(impl->surface,&destination,0);
}
cairo_region_destroy (src_region);
cairo_region_destroy (dest_region);
}