Rework PublishProduct to use MSI_IterateRecords.
[wine] / dlls / x11drv / init.c
1 /*
2  * X11 graphics driver initialisation functions
3  *
4  * Copyright 1996 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <stdarg.h>
24 #include <string.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "x11drv.h"
30 #include "x11font.h"
31 #include "ddrawi.h"
32 #include "wine/debug.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
35
36 Display *gdi_display;  /* display to use for all GDI functions */
37
38 /* a few dynamic device caps */
39 static int log_pixels_x;  /* pixels per logical inch in x direction */
40 static int log_pixels_y;  /* pixels per logical inch in y direction */
41 static int horz_size;     /* horz. size of screen in millimeters */
42 static int vert_size;     /* vert. size of screen in millimeters */
43 static int palette_size;
44 unsigned int text_caps = (TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE |
45                           TC_CR_ANY | TC_SA_DOUBLE | TC_SA_INTEGER |
46                           TC_SA_CONTIN | TC_UA_ABLE | TC_SO_ABLE | TC_RA_ABLE);
47                           /* X11R6 adds TC_SF_X_YINDEP, Xrender adds TC_VA_ABLE */
48
49
50 static const WCHAR dpi_key_name[] = {'S','o','f','t','w','a','r','e','\\','F','o','n','t','s','\0'};
51 static const WCHAR dpi_value_name[] = {'L','o','g','P','i','x','e','l','s','\0'};
52
53
54 /******************************************************************************
55  *      get_dpi
56  *
57  * get the dpi from the registry
58  */
59 static DWORD get_dpi( void )
60 {
61     DWORD dpi = 96;
62     HKEY hkey;
63
64     if (RegOpenKeyW(HKEY_CURRENT_CONFIG, dpi_key_name, &hkey) == ERROR_SUCCESS)
65     {
66         DWORD type, size, new_dpi;
67
68         size = sizeof(new_dpi);
69         if(RegQueryValueExW(hkey, dpi_value_name, NULL, &type, (void *)&new_dpi, &size) == ERROR_SUCCESS)
70         {
71             if(type == REG_DWORD && new_dpi != 0)
72                 dpi = new_dpi;
73         }
74         RegCloseKey(hkey);
75     }
76     return dpi;
77 }
78
79 /**********************************************************************
80  *           X11DRV_GDI_Initialize
81  */
82 void X11DRV_GDI_Initialize( Display *display )
83 {
84     gdi_display = display;
85
86     /* Initialize XRender */
87     X11DRV_XRender_Init();
88
89     palette_size = X11DRV_PALETTE_Init();
90
91     X11DRV_BITMAP_Init();
92
93     /* Initialize device caps */
94     log_pixels_x = log_pixels_y = get_dpi();
95     horz_size = MulDiv( screen_width, 254, log_pixels_x * 10 );
96     vert_size = MulDiv( screen_height, 254, log_pixels_y * 10 );
97
98     /* Initialize fonts and text caps */
99     X11DRV_FONT_Init(log_pixels_x, log_pixels_y);
100 }
101
102 /**********************************************************************
103  *           X11DRV_GDI_Finalize
104  */
105 void X11DRV_GDI_Finalize(void)
106 {
107     X11DRV_PALETTE_Cleanup();
108     XCloseDisplay( gdi_display );
109     gdi_display = NULL;
110 }
111
112 /**********************************************************************
113  *           X11DRV_CreateDC
114  */
115 BOOL X11DRV_CreateDC( HDC hdc, X11DRV_PDEVICE **pdev, LPCWSTR driver, LPCWSTR device,
116                       LPCWSTR output, const DEVMODEW* initData )
117 {
118     X11DRV_PDEVICE *physDev;
119
120     physDev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physDev) );
121     if (!physDev) return FALSE;
122
123     *pdev = physDev;
124     physDev->hdc = hdc;
125
126     if (GetObjectType( hdc ) == OBJ_MEMDC)
127     {
128         if (!BITMAP_stock_phys_bitmap.hbitmap)
129             BITMAP_stock_phys_bitmap.hbitmap = GetCurrentObject( hdc, OBJ_BITMAP );
130         physDev->bitmap    = &BITMAP_stock_phys_bitmap;
131         physDev->drawable  = BITMAP_stock_phys_bitmap.pixmap;
132         physDev->depth     = 1;
133     }
134     else
135     {
136         physDev->bitmap    = NULL;
137         physDev->drawable  = root_window;
138         physDev->depth     = screen_depth;
139     }
140     physDev->region = CreateRectRgn( 0, 0, 0, 0 );
141
142     wine_tsx11_lock();
143     physDev->gc = XCreateGC( gdi_display, physDev->drawable, 0, NULL );
144     XSetGraphicsExposures( gdi_display, physDev->gc, False );
145     XSetSubwindowMode( gdi_display, physDev->gc, IncludeInferiors );
146     XFlush( gdi_display );
147     wine_tsx11_unlock();
148     return TRUE;
149 }
150
151
152 /**********************************************************************
153  *           X11DRV_DeleteDC
154  */
155 BOOL X11DRV_DeleteDC( X11DRV_PDEVICE *physDev )
156 {
157     if(physDev->xrender)
158       X11DRV_XRender_DeleteDC( physDev );
159     DeleteObject( physDev->region );
160     wine_tsx11_lock();
161     XFreeGC( gdi_display, physDev->gc );
162     while (physDev->used_visuals-- > 0)
163         XFree(physDev->visuals[physDev->used_visuals]);
164     wine_tsx11_unlock();
165     HeapFree( GetProcessHeap(), 0, physDev );
166     return TRUE;
167 }
168
169
170 /***********************************************************************
171  *           GetDeviceCaps    (X11DRV.@)
172  */
173 INT X11DRV_GetDeviceCaps( X11DRV_PDEVICE *physDev, INT cap )
174 {
175     switch(cap)
176     {
177     case DRIVERVERSION:
178         return 0x300;
179     case TECHNOLOGY:
180         return DT_RASDISPLAY;
181     case HORZSIZE:
182         return horz_size;
183     case VERTSIZE:
184         return vert_size;
185     case HORZRES:
186         return screen_width;
187     case VERTRES:
188         return screen_height;
189     case BITSPIXEL:
190         return screen_depth;
191     case PLANES:
192         return 1;
193     case NUMBRUSHES:
194         return -1;
195     case NUMPENS:
196         return -1;
197     case NUMMARKERS:
198         return 0;
199     case NUMFONTS:
200         return 0;
201     case NUMCOLORS:
202         /* MSDN: Number of entries in the device's color table, if the device has
203          * a color depth of no more than 8 bits per pixel.For devices with greater
204          * color depths, -1 is returned. */
205         return (screen_depth > 8) ? -1 : (1 << screen_depth);
206     case PDEVICESIZE:
207         return sizeof(X11DRV_PDEVICE);
208     case CURVECAPS:
209         return (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
210                 CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
211     case LINECAPS:
212         return (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
213                 LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
214     case POLYGONALCAPS:
215         return (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
216                 PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
217     case TEXTCAPS:
218         return text_caps;
219     case CLIPCAPS:
220         return CP_REGION;
221     case RASTERCAPS:
222         return (RC_BITBLT | RC_BANDING | RC_SCALING | RC_BITMAP64 | RC_DI_BITMAP |
223                 RC_DIBTODEV | RC_BIGFONT | RC_STRETCHBLT | RC_STRETCHDIB | RC_DEVBITS |
224                 (palette_size ? RC_PALETTE : 0));
225     case ASPECTX:
226     case ASPECTY:
227         return 36;
228     case ASPECTXY:
229         return 51;
230     case LOGPIXELSX:
231         return log_pixels_x;
232     case LOGPIXELSY:
233         return log_pixels_y;
234     case CAPS1:
235         FIXME("(%p): CAPS1 is unimplemented, will return 0\n", physDev->hdc );
236         /* please see wingdi.h for the possible bit-flag values that need
237            to be returned. also, see
238            http://msdn.microsoft.com/library/ddkdoc/win95ddk/graphcnt_1m0p.htm */
239         return 0;
240     case SIZEPALETTE:
241         return palette_size;
242     case NUMRESERVED:
243     case COLORRES:
244     case PHYSICALWIDTH:
245     case PHYSICALHEIGHT:
246     case PHYSICALOFFSETX:
247     case PHYSICALOFFSETY:
248     case SCALINGFACTORX:
249     case SCALINGFACTORY:
250     case VREFRESH:
251     case DESKTOPVERTRES:
252     case DESKTOPHORZRES:
253     case BTLALIGNMENT:
254         return 0;
255     default:
256         FIXME("(%p): unsupported capability %d, will return 0\n", physDev->hdc, cap );
257         return 0;
258     }
259 }
260
261
262 /**********************************************************************
263  *           ExtEscape  (X11DRV.@)
264  */
265 INT X11DRV_ExtEscape( X11DRV_PDEVICE *physDev, INT escape, INT in_count, LPCVOID in_data,
266                       INT out_count, LPVOID out_data )
267 {
268     switch(escape)
269     {
270     case QUERYESCSUPPORT:
271         if (in_data)
272         {
273             switch (*(const INT *)in_data)
274             {
275             case DCICOMMAND:
276                 return DD_HAL_VERSION;
277             case X11DRV_ESCAPE:
278                 return TRUE;
279             }
280         }
281         break;
282
283     case DCICOMMAND:
284         if (in_data)
285         {
286             const DCICMD *lpCmd = in_data;
287             if (lpCmd->dwVersion != DD_VERSION) break;
288             return X11DRV_DCICommand(in_count, lpCmd, out_data);
289         }
290         break;
291
292     case X11DRV_ESCAPE:
293         if (in_data && in_count >= sizeof(enum x11drv_escape_codes))
294         {
295             switch(*(const enum x11drv_escape_codes *)in_data)
296             {
297             case X11DRV_GET_DISPLAY:
298                 if (out_count >= sizeof(Display *))
299                 {
300                     *(Display **)out_data = gdi_display;
301                     return TRUE;
302                 }
303                 break;
304             case X11DRV_GET_DRAWABLE:
305                 if (out_count >= sizeof(Drawable))
306                 {
307                     *(Drawable *)out_data = physDev->drawable;
308                     return TRUE;
309                 }
310                 break;
311             case X11DRV_GET_FONT:
312                 if (out_count >= sizeof(Font))
313                 {
314                     fontObject* pfo = XFONT_GetFontObject( physDev->font );
315                     if (pfo == NULL) return FALSE;
316                     *(Font *)out_data = pfo->fs->fid;
317                     return TRUE;
318                 }
319                 break;
320             case X11DRV_SET_DRAWABLE:
321                 if (in_count >= sizeof(struct x11drv_escape_set_drawable))
322                 {
323                     const struct x11drv_escape_set_drawable *data = (const struct x11drv_escape_set_drawable *)in_data;
324                     if(physDev->xrender) X11DRV_XRender_UpdateDrawable( physDev );
325                     physDev->org = data->org;
326                     physDev->drawable = data->drawable;
327                     physDev->drawable_org = data->drawable_org;
328                     wine_tsx11_lock();
329                     XSetSubwindowMode( gdi_display, physDev->gc, data->mode );
330                     wine_tsx11_unlock();
331                     return TRUE;
332                 }
333                 break;
334             case X11DRV_START_EXPOSURES:
335                 wine_tsx11_lock();
336                 XSetGraphicsExposures( gdi_display, physDev->gc, True );
337                 wine_tsx11_unlock();
338                 physDev->exposures = 0;
339                 return TRUE;
340             case X11DRV_END_EXPOSURES:
341                 if (out_count >= sizeof(HRGN))
342                 {
343                     HRGN hrgn = 0, tmp = 0;
344
345                     wine_tsx11_lock();
346                     XSetGraphicsExposures( gdi_display, physDev->gc, False );
347                     if (physDev->exposures)
348                     {
349                         for (;;)
350                         {
351                             XEvent event;
352
353                             XWindowEvent( gdi_display, physDev->drawable, ~0, &event );
354                             if (event.type == NoExpose) break;
355                             if (event.type == GraphicsExpose)
356                             {
357                                 int x = event.xgraphicsexpose.x - physDev->org.x;
358                                 int y = event.xgraphicsexpose.y - physDev->org.y;
359
360                                 TRACE( "got %d,%d %dx%d count %d\n", x, y,
361                                        event.xgraphicsexpose.width,
362                                        event.xgraphicsexpose.height,
363                                        event.xgraphicsexpose.count );
364
365                                 if (!tmp) tmp = CreateRectRgn( 0, 0, 0, 0 );
366                                 SetRectRgn( tmp, x, y,
367                                             x + event.xgraphicsexpose.width,
368                                             y + event.xgraphicsexpose.height );
369                                 if (hrgn) CombineRgn( hrgn, hrgn, tmp, RGN_OR );
370                                 else
371                                 {
372                                     hrgn = tmp;
373                                     tmp = 0;
374                                 }
375                                 if (!event.xgraphicsexpose.count) break;
376                             }
377                             else
378                             {
379                                 ERR( "got unexpected event %d\n", event.type );
380                                 break;
381                             }
382                         }
383                         if (tmp) DeleteObject( tmp );
384                     }
385                     wine_tsx11_unlock();
386                     *(HRGN *)out_data = hrgn;
387                     return TRUE;
388                 }
389                 break;
390             case X11DRV_GET_DCE:
391                 if (out_count >= sizeof(struct dce *))
392                 {
393                     *(struct dce **)out_data = physDev->dce;
394                     return TRUE;
395                 }
396                 break;
397             case X11DRV_SET_DCE:
398                 if (in_count >= sizeof(struct x11drv_escape_set_dce))
399                 {
400                     const struct x11drv_escape_set_dce *data = (const struct x11drv_escape_set_dce *)in_data;
401                     physDev->dce = data->dce;
402                     return TRUE;
403                 }
404                 break;
405             }
406         }
407         break;
408     }
409     return 0;
410 }