/* 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 "SXWindowTheme.h" #include "SXWindow.h" #include "priv.h" static CFTypeID SFWindowTypeID; static void window_died (void *inst) { } /* CoreFoundation runtime class for SFWindow. */ static CFRuntimeClass SFWindowRuntimeClass = { 0, /* version */ "SFWindow", /* Name of class. */ sizeof (struct SFWindow), /* Instance size. */ 0, /* Init function. */ window_died /* Final function. */ }; static void initialize_window_runtime (void) __attribute__ ((constructor)); /* Initialize runtime class for SFWindow. This has a "constructor" attribute so that is should be called at initialization time. */ static void initialize_window_runtime (void) { SFWindowTypeID = CFRuntimeRegisterClass (&SFWindowRuntimeClass); } /* Create a window that will live in TOPLAYER. LEVEL is just the for setting in the window structure. It is not used when creating the window. */ /* ??? release resources if we fail any step. */ SFWindowRef SXWindowCreate (SFLayerRef toplayer, GFRect frame_rect, char *title, SFWindowStyleMask style_mask, SFWindowLevel level) { unsigned int shadow_y_offset = 0, shadow_x_offset = 0; SXWindowThemeRef theme = SXWindowThemeCurrent (); float opacity = kSFSurfaceNormalTransparent; SFWindowRef window; void *raster_buffer; int rowstride; GFRect total_rect; if (! (style_mask & kSFNoShadowWindowMask)) { shadow_x_offset = 0; shadow_y_offset = 0; } window = (SFWindowRef) CFRuntimeCreateInstance (SFWindowTypeID); if (! window) return 0; /* Total rect contains both frame rect and shadow rect. */ total_rect = frame_rect; if (! (style_mask & kSFNoShadowWindowMask)) { total_rect.size.width += 2*SHADOW_WIDTH; total_rect.size.height += 2*SHADOW_HEIGHT; } window->style_mask = style_mask; window->frame_rect = frame_rect; /* Create layer for the whole window for fast map/unmap. */ window->window_layer = SFLayerCreate (toplayer, total_rect); if (! window->window_layer) return 0; /* Create shadow (if we should have any). */ if (! (style_mask & kSFNoShadowWindowMask)) { window->shadow_surface = SFSurfaceCreate (total_rect.size, 0.60); /* ??? */ SFLayerInsertSurface (window->window_layer, window->shadow_surface, GFPointMake (SHADOW_WIDTH/2, SHADOW_HEIGHT / 2)); /* ??? */ SFSurfaceMap (window->shadow_surface); } /* Create the surface for the WHOLE window (I don't know how many times I can point that out). We use the frame rectangle we got from the user. */ if (style_mask & kSFNotTransparentWindowMask) opacity = kSFSurfaceNotTransparent; window->window_surface = SFSurfaceCreate (frame_rect.size, opacity); if (! window->window_surface) return 0; SFLayerInsertSurface (window->window_layer, window->window_surface, GFPointMake (SHADOW_WIDTH, 0)); raster_buffer = window->window_surface->shmem.address; rowstride = frame_rect.size.width * 4; memset (raster_buffer, 0x0, frame_rect.size.width * frame_rect.size.height * 4); window->content_rect = SFWindowContentRectForFrameRect (frame_rect, style_mask); /* Create pixbufs. ??? samples and stuff here maaan! */ if (style_mask & kSFTitledWindowMask) { #if 1 window->pixbuf_titlebar = GFImageCreateWithData (raster_buffer, shadow_x_offset, shadow_y_offset, window->content_rect.size.width, theme->titlebar.height, 4, 8, rowstride, kGFImageAlphaSeparateLast); #else window->pixbuf_titlebar = GFImageCreateWithData (raster_buffer, shadow_x_offset, shadow_y_offset, window->content_rect.size.width, theme->titlebar.height, 4, 8, rowstride, kGFImageAlphaSeparateFirst); #endif /* ??? create from window->content_rect. */ window->pixbuf_content = GFImageCreateWithData (raster_buffer, shadow_x_offset, theme->titlebar.height + shadow_y_offset, window->content_rect.size.width, window->content_rect.size.height, 4, 8, rowstride, kGFImageAlphaSeparateLast); GFImageFill (window->pixbuf_content, 255, 255, 255, 255); } else { window->pixbuf_content = GFImageCreateWithData (raster_buffer, shadow_x_offset, shadow_y_offset, window->content_rect.size.width, window->content_rect.size.height, 4, 8, rowstride, kGFImageAlphaSeparateLast); } /* Create tracking areas for window. */ SXWindowThemeCreateTitlebarAreas (window); if (style_mask & kSFTitledWindowMask) SXWindowThemeDrawTitlebar (window->pixbuf_titlebar, false, window->content_rect.size.width, style_mask, title); if (! (style_mask & kSFNoShadowWindowMask)) SXWindowUpdateShadow (window); /* We can now map the surface - since the layer is still unmapped. */ SFSurfaceMap (window->window_surface); return window; } /* Called when shape of window has been changed. */ void SXWindowUpdateShadow (SFWindowRef window) { GFImageRef shadow_img, window_img, dst_img; if (window->style_mask & kSFNoShadowWindowMask) return; dst_img = SFSurfaceCreateImageReference (window->shadow_surface); shadow_img = GFImageCreate (GFImageWidth (dst_img) + 2 * SHADOW_WIDTH, GFImageHeight (dst_img) + 2 * SHADOW_HEIGHT, 4, 8, kGFImageAlphaSeparateLast); window_img = SFSurfaceCreateImageReference (window->window_surface); memset (shadow_img->pixels, 0, shadow_img->rowstride * GFImageHeight (shadow_img)); GFImageComposite (shadow_img, window_img, 2 * SHADOW_WIDTH/3, 2 * SHADOW_HEIGHT/3, GFImageWidth (window_img) + SHADOW_WIDTH/3, GFImageHeight (window_img) + SHADOW_HEIGHT/3); GFImageGaussianBlur (shadow_img, 10.0, 10.0); GFImageClearColors (shadow_img, 0); memset (dst_img->pixels, 0, dst_img->rowstride * GFImageHeight (dst_img)); GFImageComposite (dst_img, shadow_img, 0, 0, GFImageWidth (shadow_img), GFImageHeight (shadow_img)); }