/* Copyright (C) 2001 Johan Rydberg. All Rights Reserved. This file is part of Crust. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "SXServerConnection.h" #include "crust-client.h" #include #include #include "priv.h" /* Forward. */ SFSurfaceRef _SFSurfaceAllocate (void); CFTypeID _SFSurfaceTypeID; /* This is called when we lose all references to a layer instance. We destroy all resources. */ static void surface_died (void *instp) { SFSurfaceRef surface = instp; CFRelease (surface->track_array); if (surface->surface_port) mach_port_deallocate (mach_task_self (), surface->surface_port); } /* CoreFoundation runtime class for SFSurface. */ CFRuntimeClass _SFSurfaceRuntimeClass = { 0, /* version */ "SFSurface", /* Name of class. */ sizeof (struct SFSurface), /* Instance size. */ 0, /* Init function. */ surface_died /* Final function. */ }; static void initialize_surface_runtime (void) __attribute__ ((constructor)); /* Initialize runtime class for SFSurface. This has a "constructor" attribute so that is should be called at initialization time. */ static void initialize_surface_runtime (void) { _SFSurfaceTypeID = CFRuntimeRegisterClass (&_SFSurfaceRuntimeClass); } /* Internal function to allocate a new layer instance. */ SFSurfaceRef _SFSurfaceAllocate (void) { return (SFSurfaceRef) CFRuntimeCreateInstance (_SFSurfaceTypeID); } /* Create a new surface. SIZE is the size of the surface. OPACITY is the level of transparency. For surfaces that will be inserted into non transparent layers - OPACITY should be 1.0. */ SFSurfaceRef SFSurfaceCreate (GFSize size, float opacity) { mach_port_t server_port; SFSurfaceRef surface; int err; /* Get server port. */ server_port = SXGetServerConnection (); if (! server_port) return 0; surface = _SFSurfaceAllocate (); if (! surface) return 0; /* Create the real surface. */ err = _surface_create (server_port, (int) size.width, (int) size.height, 32, &surface->surface_port); if (err) return 0; /* ??? free instance. */ if (opacity != 1.0) _surface_set_opaque (surface->surface_port, (float) opacity); err = _surface_get_shmem (surface->surface_port, &surface->shmem.memobj, &surface->shmem.size); if (err) return 0; surface->shmem.address = 0; err = vm_map (mach_task_self (), (vm_offset_t *) &surface->shmem.address, round_page (surface->shmem.size), 0, 1, surface->shmem.memobj, 0, 0, VM_PROT_ALL, VM_PROT_ALL, VM_INHERIT_NONE); if (err) return 0; /* ??? deallocate memobj? */ surface->position.size = size; surface->opacity = opacity; surface->track_array = CFArrayCreate (0, 0); return surface; } void SFSurfaceSetOpacity (SFSurfaceRef surface, float opacity) { _surface_set_opaque (surface->surface_port, (float) opacity); } GFImageRef SFSurfaceCreateImageReference (SFSurfaceRef surface) { GFSize size = surface->position.size; void *raster_buffer; int rowstride; raster_buffer = surface->shmem.address; rowstride = size.width * 4; return GFImageCreateWithData (raster_buffer, 0, 0, size.width, size.height, 4, 8, rowstride, kGFImageAlphaSeparateLast); } GFImageRef SFSurfaceContentImage (SFSurfaceRef surface) { GFSize size = surface->position.size; void *raster_buffer; int rowstride; raster_buffer = surface->shmem.address; rowstride = size.width * 4; return GFImageCreateWithData (raster_buffer, 0, 0, size.width - 1, size.height - 1, 4, 8, rowstride, kGFImageAlphaSeparateLast); } void SFSurfaceSetEventMask (SFSurfaceRef surface, unsigned int mask) { mach_port_t port; int err, real_mask = 0; if (mask == surface->event_mask) return; if (surface->event_port == 0) { err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &port); if (err) return; _SFEventInsertPort (surface, port); } surface->event_mask = mask; surface->event_port = port; if (mask & kSFEventMouseEnteredMask) real_mask |= CRUST_EVENT_FOCUS_ENTER; if (mask & kSFEventMouseExitedMask) real_mask |= CRUST_EVENT_FOCUS_LEAVE; if (mask & kSFEventMouseMovedMask) real_mask |= CRUST_EVENT_MOUSE_MOVE; if (mask & kSFEventMouseDownMask) real_mask |= CRUST_EVENT_MOUSE_DOWN; if (mask & kSFEventMouseUpMask) real_mask |= CRUST_EVENT_MOUSE_UP; _surface_set_event_mask (surface->surface_port, port, real_mask); } /* Retain a reference to SURFACE. */ void SFSurfaceRetain (SFSurfaceRef surface) { CFRetain (surface); } /* Release a reference to SURFACE. */ void SFSurfaceRelease (SFSurfaceRef surface) { CFRelease (surface); } void SFSurfaceMap (SFSurfaceRef surface) { _surface_map (surface->surface_port); } void SFSurfaceUnmap (SFSurfaceRef surface) { _surface_unmap (surface->surface_port); } void SFSurfaceUpdateRegion (SFSurfaceRef surface, GFRect rect) { _surface_update (surface->surface_port, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); } /* Get a graphic context for SURFACE. */ GFContextRef SFSurfaceGetContext (SFSurfaceRef surface) { #if 0 GFColorSpaceRef colorspace = GFColorSpaceCreateDeviceRGB (); int rowstride = 4 * surface->position.size.width; GFContextRef context; context = GFBitmapContextCreate (surface->shmem.address, surface->position.size.width, surface->position.size.height, 8, rowstride, colorspace, kGFImageAlphaPremultipliedLast); GFColorSpaceRelease (colorspace); return context; #endif return 0; }