diff --git a/dlls/winemac.drv/Makefile.in b/dlls/winemac.drv/Makefile.in index e188058f1d9..467a59d23c7 100644 --- a/dlls/winemac.drv/Makefile.in +++ b/dlls/winemac.drv/Makefile.in @@ -1,5 +1,6 @@ MODULE = winemac.drv IMPORTS = user32 gdi32 advapi32 +EXTRALIBS = @APPLICATIONSERVICESLIB@ C_SRCS = \ gdi.c \ diff --git a/dlls/winemac.drv/gdi.c b/dlls/winemac.drv/gdi.c index 7cfd18d8a3a..176b5883787 100644 --- a/dlls/winemac.drv/gdi.c +++ b/dlls/winemac.drv/gdi.c @@ -21,13 +21,7 @@ #include "config.h" -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "wine/debug.h" -#include "wine/gdi_driver.h" +#include "macdrv.h" #include "winreg.h" WINE_DEFAULT_DEBUG_CHANNEL(macdrv); @@ -44,13 +38,176 @@ static inline MACDRV_PDEVICE *get_macdrv_dev(PHYSDEV dev) } +/* a few dynamic device caps */ +static CGRect desktop_rect; /* virtual desktop rectangle */ +static int log_pixels_x; /* pixels per logical inch in x direction */ +static int log_pixels_y; /* pixels per logical inch in y direction */ +static int horz_size; /* horz. size of screen in millimeters */ +static int vert_size; /* vert. size of screen in millimeters */ +static int horz_res; /* width in pixels of screen */ +static int vert_res; /* height in pixels of screen */ +static int desktop_horz_res; /* width in pixels of virtual desktop */ +static int desktop_vert_res; /* height in pixels of virtual desktop */ +static int bits_per_pixel; /* pixel depth of screen */ +static int palette_size; /* number of color entries in palette */ +static int device_data_valid; /* do the above variables have up-to-date values? */ + +static CRITICAL_SECTION device_data_section; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &device_data_section, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": device_data_section") } +}; +static CRITICAL_SECTION device_data_section = { &critsect_debug, -1, 0, 0, 0, 0 }; + + +static const WCHAR dpi_key_name[] = {'S','o','f','t','w','a','r','e','\\','F','o','n','t','s','\0'}; +static const WCHAR dpi_value_name[] = {'L','o','g','P','i','x','e','l','s','\0'}; + static const struct gdi_dc_funcs macdrv_funcs; +/****************************************************************************** + * get_dpi + * + * get the dpi from the registry + */ +static DWORD get_dpi(void) +{ + DWORD dpi = 0; + HKEY hkey; + + if (RegOpenKeyW(HKEY_CURRENT_CONFIG, dpi_key_name, &hkey) == ERROR_SUCCESS) + { + DWORD type, size, new_dpi; + + size = sizeof(new_dpi); + if (RegQueryValueExW(hkey, dpi_value_name, NULL, &type, (void *)&new_dpi, &size) == ERROR_SUCCESS) + { + if (type == REG_DWORD && new_dpi != 0) + dpi = new_dpi; + } + RegCloseKey(hkey); + } + return dpi; +} + + +/*********************************************************************** + * macdrv_get_desktop_rect + * + * Returns the rectangle encompassing all the screens. + */ +static CGRect macdrv_get_desktop_rect(void) +{ + CGRect ret; + CGDirectDisplayID displayIDs[32]; + uint32_t count, i; + + EnterCriticalSection(&device_data_section); + + if (!device_data_valid) + { + desktop_rect = CGRectNull; + if (CGGetActiveDisplayList(sizeof(displayIDs)/sizeof(displayIDs[0]), + displayIDs, &count) != kCGErrorSuccess || + !count) + { + displayIDs[0] = CGMainDisplayID(); + count = 1; + } + + for (i = 0; i < count; i++) + desktop_rect = CGRectUnion(desktop_rect, CGDisplayBounds(displayIDs[i])); + } + + ret = desktop_rect; + LeaveCriticalSection(&device_data_section); + + TRACE("%s\n", wine_dbgstr_cgrect(ret)); + + return ret; +} + + +/********************************************************************** + * device_init + * + * Perform initializations needed upon creation of the first device. + */ +static void device_init(void) +{ + CGDirectDisplayID mainDisplay = CGMainDisplayID(); + CGSize size_mm = CGDisplayScreenSize(mainDisplay); + CGDisplayModeRef mode = CGDisplayCopyDisplayMode(mainDisplay); + CGDirectPaletteRef palette; + + /* Initialize device caps */ + log_pixels_x = log_pixels_y = get_dpi(); + if (!log_pixels_x) + { + size_t width = CGDisplayPixelsWide(mainDisplay); + size_t height = CGDisplayPixelsHigh(mainDisplay); + log_pixels_x = MulDiv(width, 254, size_mm.width * 10); + log_pixels_y = MulDiv(height, 254, size_mm.height * 10); + } + + horz_size = size_mm.width; + vert_size = size_mm.height; + + bits_per_pixel = 32; + if (mode) + { + CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); + + horz_res = CGDisplayModeGetWidth(mode); + vert_res = CGDisplayModeGetHeight(mode); + + if (pixelEncoding) + { + if (CFEqual(pixelEncoding, CFSTR(IO32BitDirectPixels))) + bits_per_pixel = 32; + else if (CFEqual(pixelEncoding, CFSTR(IO16BitDirectPixels))) + bits_per_pixel = 16; + else if (CFEqual(pixelEncoding, CFSTR(IO8BitIndexedPixels))) + bits_per_pixel = 8; + CFRelease(pixelEncoding); + } + + CGDisplayModeRelease(mode); + } + else + { + horz_res = CGDisplayPixelsWide(mainDisplay); + vert_res = CGDisplayPixelsHigh(mainDisplay); + } + + macdrv_get_desktop_rect(); + desktop_horz_res = desktop_rect.size.width; + desktop_vert_res = desktop_rect.size.height; + + palette = CGPaletteCreateWithDisplay(mainDisplay); + if (palette) + { + palette_size = CGPaletteGetNumberOfSamples(palette); + CGPaletteRelease(palette); + } + else + palette_size = 0; + + device_data_valid = TRUE; +} + + static MACDRV_PDEVICE *create_mac_physdev(void) { MACDRV_PDEVICE *physDev; + EnterCriticalSection(&device_data_section); + if (!device_data_valid) device_init(); + LeaveCriticalSection(&device_data_section); + if (!(physDev = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physDev)))) return NULL; return physDev; @@ -107,6 +264,154 @@ static BOOL macdrv_DeleteDC(PHYSDEV dev) } +/*********************************************************************** + * GetDeviceCaps (MACDRV.@) + */ +static INT macdrv_GetDeviceCaps(PHYSDEV dev, INT cap) +{ + INT ret; + + EnterCriticalSection(&device_data_section); + + if (!device_data_valid) device_init(); + + switch(cap) + { + case DRIVERVERSION: + ret = 0x300; + break; + case TECHNOLOGY: + ret = DT_RASDISPLAY; + break; + case HORZSIZE: + ret = horz_size; + break; + case VERTSIZE: + ret = vert_size; + break; + case HORZRES: + ret = horz_res; + break; + case VERTRES: + ret = vert_res; + break; + case DESKTOPHORZRES: + ret = desktop_horz_res; + break; + case DESKTOPVERTRES: + ret = desktop_vert_res; + break; + case BITSPIXEL: + ret = bits_per_pixel; + break; + case PLANES: + ret = 1; + break; + case NUMBRUSHES: + ret = -1; + break; + case NUMPENS: + ret = -1; + break; + case NUMMARKERS: + ret = 0; + break; + case NUMFONTS: + ret = 0; + break; + case NUMCOLORS: + /* MSDN: Number of entries in the device's color table, if the device has + * a color depth of no more than 8 bits per pixel.For devices with greater + * color depths, -1 is returned. */ + ret = (bits_per_pixel > 8) ? -1 : (1 << bits_per_pixel); + break; + case PDEVICESIZE: + ret = sizeof(MACDRV_PDEVICE); + break; + case CURVECAPS: + ret = (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE | + CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT); + break; + case LINECAPS: + ret = (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE | + LC_STYLED | LC_WIDESTYLED | LC_INTERIORS); + break; + case POLYGONALCAPS: + ret = (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE | + PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS); + break; + case TEXTCAPS: + ret = (TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE | + TC_CR_ANY | TC_SF_X_YINDEP | TC_SA_DOUBLE | TC_SA_INTEGER | + TC_SA_CONTIN | TC_UA_ABLE | TC_SO_ABLE | TC_RA_ABLE | TC_VA_ABLE); + break; + case CLIPCAPS: + ret = CP_REGION; + break; + case COLORRES: + /* The observed correspondence between BITSPIXEL and COLORRES is: + * BITSPIXEL: 8 -> COLORRES: 18 + * BITSPIXEL: 16 -> COLORRES: 16 + * BITSPIXEL: 24 -> COLORRES: 24 + * (note that bits_per_pixel is never 24) + * BITSPIXEL: 32 -> COLORRES: 24 */ + ret = (bits_per_pixel <= 8) ? 18 : (bits_per_pixel == 32) ? 24 : bits_per_pixel; + break; + case RASTERCAPS: + ret = (RC_BITBLT | RC_BANDING | RC_SCALING | RC_BITMAP64 | RC_DI_BITMAP | + RC_DIBTODEV | RC_BIGFONT | RC_STRETCHBLT | RC_STRETCHDIB | RC_DEVBITS | + (palette_size ? RC_PALETTE : 0)); + break; + case SHADEBLENDCAPS: + ret = (SB_GRAD_RECT | SB_GRAD_TRI | SB_CONST_ALPHA | SB_PIXEL_ALPHA); + break; + case ASPECTX: + case ASPECTY: + ret = 36; + break; + case ASPECTXY: + ret = 51; + break; + case LOGPIXELSX: + ret = log_pixels_x; + break; + case LOGPIXELSY: + ret = log_pixels_y; + break; + case CAPS1: + FIXME("(%p): CAPS1 is unimplemented, will return 0\n", dev->hdc); + /* please see wingdi.h for the possible bit-flag values that need + to be returned. */ + ret = 0; + break; + case SIZEPALETTE: + ret = palette_size; + break; + case NUMRESERVED: + case PHYSICALWIDTH: + case PHYSICALHEIGHT: + case PHYSICALOFFSETX: + case PHYSICALOFFSETY: + case SCALINGFACTORX: + case SCALINGFACTORY: + case VREFRESH: + case BLTALIGNMENT: + ret = 0; + break; + default: + FIXME("(%p): unsupported capability %d, will return 0\n", dev->hdc, cap); + ret = 0; + goto done; + } + + TRACE("cap %d -> %d\n", cap, ret); + +done: + LeaveCriticalSection(&device_data_section); + return ret; +} + + static const struct gdi_dc_funcs macdrv_funcs = { NULL, /* pAbortDoc */ @@ -147,7 +452,7 @@ static const struct gdi_dc_funcs macdrv_funcs = NULL, /* pGetCharABCWidths */ NULL, /* pGetCharABCWidthsI */ NULL, /* pGetCharWidth */ - NULL, /* pGetDeviceCaps */ + macdrv_GetDeviceCaps, /* pGetDeviceCaps */ NULL, /* pGetDeviceGammaRamp */ NULL, /* pGetFontData */ NULL, /* pGetFontUnicodeRanges */ diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h new file mode 100644 index 00000000000..db0069b0234 --- /dev/null +++ b/dlls/winemac.drv/macdrv.h @@ -0,0 +1,101 @@ +/* + * MACDRV windowing driver + * + * Copyright 1996 Alexandre Julliard + * Copyright 1999 Patrik Stridvall + * Copyright 2011, 2012 Ken Thomases for CodeWeavers Inc. + * + * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_MACDRV_H +#define __WINE_MACDRV_H + +#ifndef __WINE_CONFIG_H +# error You must include config.h to use this header +#endif + +#define GetCurrentProcess MacGetCurrentProcess +#define GetCurrentThread MacGetCurrentThread +#define LoadResource MacLoadResource +#define AnimatePalette MacAnimatePalette +#define EqualRgn MacEqualRgn +#define FillRgn MacFillRgn +#define FrameRgn MacFrameRgn +#define GetPixel MacGetPixel +#define InvertRgn MacInvertRgn +#define LineTo MacLineTo +#define OffsetRgn MacOffsetRgn +#define PaintRgn MacPaintRgn +#define Polygon MacPolygon +#define ResizePalette MacResizePalette +#define SetRectRgn MacSetRectRgn +#define EqualRect MacEqualRect +#define FillRect MacFillRect +#define FrameRect MacFrameRect +#define GetCursor MacGetCursor +#define InvertRect MacInvertRect +#define OffsetRect MacOffsetRect +#define PtInRect MacPtInRect +#define SetCursor MacSetCursor +#define SetRect MacSetRect +#define ShowCursor MacShowCursor +#define UnionRect MacUnionRect + +#include + +#undef GetCurrentProcess +#undef GetCurrentThread +#undef LoadResource +#undef AnimatePalette +#undef EqualRgn +#undef FillRgn +#undef FrameRgn +#undef GetPixel +#undef InvertRgn +#undef LineTo +#undef OffsetRgn +#undef PaintRgn +#undef Polygon +#undef ResizePalette +#undef SetRectRgn +#undef EqualRect +#undef FillRect +#undef FrameRect +#undef GetCursor +#undef InvertRect +#undef OffsetRect +#undef PtInRect +#undef SetCursor +#undef SetRect +#undef ShowCursor +#undef UnionRect +#undef DPRINTF + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "wine/debug.h" +#include "wine/gdi_driver.h" + + +static inline const char *wine_dbgstr_cgrect(CGRect cgrect) +{ + return wine_dbg_sprintf("(%g,%g)-(%g,%g)", CGRectGetMinX(cgrect), CGRectGetMinY(cgrect), + CGRectGetMaxX(cgrect), CGRectGetMaxY(cgrect)); +} + + +#endif /* __WINE_MACDRV_H */