Fix regression with IE's Menu Bar.
[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 "x11drv.h"
29 #include "x11font.h"
30 #include "ddrawi.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
34
35 Display *gdi_display;  /* display to use for all GDI functions */
36
37 /* a few dynamic device caps */
38 static int log_pixels_x;  /* pixels per logical inch in x direction */
39 static int log_pixels_y;  /* pixels per logical inch in y direction */
40 static int horz_size;     /* horz. size of screen in millimeters */
41 static int vert_size;     /* vert. size of screen in millimeters */
42 static int palette_size;
43 unsigned int text_caps = (TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE |
44                           TC_CR_ANY | TC_SA_DOUBLE | TC_SA_INTEGER |
45                           TC_SA_CONTIN | TC_UA_ABLE | TC_SO_ABLE | TC_RA_ABLE);
46                           /* X11R6 adds TC_SF_X_YINDEP, Xrender adds TC_VA_ABLE */
47
48 /**********************************************************************
49  *           X11DRV_GDI_Initialize
50  */
51 void X11DRV_GDI_Initialize( Display *display )
52 {
53     gdi_display = display;
54
55     palette_size = X11DRV_PALETTE_Init();
56
57     X11DRV_BITMAP_Init();
58
59     /* Initialize XRender */
60     X11DRV_XRender_Init();
61
62     /* Initialize fonts and text caps */
63
64     log_pixels_x = log_pixels_y = 96;
65     X11DRV_FONT_Init( &log_pixels_x, &log_pixels_y );
66     horz_size = MulDiv( screen_width, 254, log_pixels_x * 10 );
67     vert_size = MulDiv( screen_height, 254, log_pixels_y * 10 );
68 }
69
70 /**********************************************************************
71  *           X11DRV_GDI_Finalize
72  */
73 void X11DRV_GDI_Finalize(void)
74 {
75     X11DRV_PALETTE_Cleanup();
76     XCloseDisplay( gdi_display );
77     gdi_display = NULL;
78 }
79
80 /**********************************************************************
81  *           X11DRV_CreateDC
82  */
83 BOOL X11DRV_CreateDC( HDC hdc, X11DRV_PDEVICE **pdev, LPCWSTR driver, LPCWSTR device,
84                       LPCWSTR output, const DEVMODEW* initData )
85 {
86     X11DRV_PDEVICE *physDev;
87
88     physDev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physDev) );
89     if (!physDev) return FALSE;
90
91     *pdev = physDev;
92     physDev->hdc = hdc;
93
94     if (GetObjectType( hdc ) == OBJ_MEMDC)
95     {
96         physDev->drawable  = BITMAP_stock_pixmap;
97         physDev->depth     = 1;
98     }
99     else
100     {
101         physDev->drawable  = root_window;
102         physDev->depth     = screen_depth;
103     }
104     physDev->region = CreateRectRgn( 0, 0, 0, 0 );
105
106     wine_tsx11_lock();
107     physDev->gc = XCreateGC( gdi_display, physDev->drawable, 0, NULL );
108     XSetGraphicsExposures( gdi_display, physDev->gc, False );
109     XSetSubwindowMode( gdi_display, physDev->gc, IncludeInferiors );
110     XFlush( gdi_display );
111     wine_tsx11_unlock();
112     return TRUE;
113 }
114
115
116 /**********************************************************************
117  *           X11DRV_DeleteDC
118  */
119 BOOL X11DRV_DeleteDC( X11DRV_PDEVICE *physDev )
120 {
121     if(physDev->xrender)
122       X11DRV_XRender_DeleteDC( physDev );
123     DeleteObject( physDev->region );
124     wine_tsx11_lock();
125     XFreeGC( gdi_display, physDev->gc );
126     while (physDev->used_visuals-- > 0)
127         XFree(physDev->visuals[physDev->used_visuals]);
128     wine_tsx11_unlock();
129     HeapFree( GetProcessHeap(), 0, physDev );
130     return TRUE;
131 }
132
133
134 /***********************************************************************
135  *           GetDeviceCaps    (X11DRV.@)
136  */
137 INT X11DRV_GetDeviceCaps( X11DRV_PDEVICE *physDev, INT cap )
138 {
139     switch(cap)
140     {
141     case DRIVERVERSION:
142         return 0x300;
143     case TECHNOLOGY:
144         return DT_RASDISPLAY;
145     case HORZSIZE:
146         return horz_size;
147     case VERTSIZE:
148         return vert_size;
149     case HORZRES:
150         return screen_width;
151     case VERTRES:
152         return screen_height;
153     case BITSPIXEL:
154         return screen_depth;
155     case PLANES:
156         return 1;
157     case NUMBRUSHES:
158         return -1;
159     case NUMPENS:
160         return -1;
161     case NUMMARKERS:
162         return 0;
163     case NUMFONTS:
164         return 0;
165     case NUMCOLORS:
166         /* MSDN: Number of entries in the device's color table, if the device has
167          * a color depth of no more than 8 bits per pixel.For devices with greater
168          * color depths, -1 is returned. */
169         return (screen_depth > 8) ? -1 : (1 << screen_depth);
170     case PDEVICESIZE:
171         return sizeof(X11DRV_PDEVICE);
172     case CURVECAPS:
173         return (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
174                 CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
175     case LINECAPS:
176         return (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
177                 LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
178     case POLYGONALCAPS:
179         return (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
180                 PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
181     case TEXTCAPS:
182         return text_caps;
183     case CLIPCAPS:
184         return CP_REGION;
185     case RASTERCAPS:
186         return (RC_BITBLT | RC_BANDING | RC_SCALING | RC_BITMAP64 | RC_DI_BITMAP |
187                 RC_DIBTODEV | RC_BIGFONT | RC_STRETCHBLT | RC_STRETCHDIB | RC_DEVBITS |
188                 (palette_size ? RC_PALETTE : 0));
189     case ASPECTX:
190     case ASPECTY:
191         return 36;
192     case ASPECTXY:
193         return 51;
194     case LOGPIXELSX:
195         return log_pixels_x;
196     case LOGPIXELSY:
197         return log_pixels_y;
198     case CAPS1:
199         FIXME("(%p): CAPS1 is unimplemented, will return 0\n", physDev->hdc );
200         /* please see wingdi.h for the possible bit-flag values that need
201            to be returned. also, see
202            http://msdn.microsoft.com/library/ddkdoc/win95ddk/graphcnt_1m0p.htm */
203         return 0;
204     case SIZEPALETTE:
205         return palette_size;
206     case NUMRESERVED:
207     case COLORRES:
208     case PHYSICALWIDTH:
209     case PHYSICALHEIGHT:
210     case PHYSICALOFFSETX:
211     case PHYSICALOFFSETY:
212     case SCALINGFACTORX:
213     case SCALINGFACTORY:
214     case VREFRESH:
215     case DESKTOPVERTRES:
216     case DESKTOPHORZRES:
217     case BTLALIGNMENT:
218         return 0;
219     default:
220         FIXME("(%p): unsupported capability %d, will return 0\n", physDev->hdc, cap );
221         return 0;
222     }
223 }
224
225
226 /**********************************************************************
227  *           ExtEscape  (X11DRV.@)
228  */
229 INT X11DRV_ExtEscape( X11DRV_PDEVICE *physDev, INT escape, INT in_count, LPCVOID in_data,
230                       INT out_count, LPVOID out_data )
231 {
232     switch(escape)
233     {
234     case QUERYESCSUPPORT:
235         if (in_data)
236         {
237             switch (*(INT *)in_data)
238             {
239             case DCICOMMAND:
240                 return DD_HAL_VERSION;
241             case X11DRV_ESCAPE:
242                 return TRUE;
243             }
244         }
245         break;
246
247     case DCICOMMAND:
248         if (in_data)
249         {
250             const DCICMD *lpCmd = in_data;
251             if (lpCmd->dwVersion != DD_VERSION) break;
252             return X11DRV_DCICommand(in_count, lpCmd, out_data);
253         }
254         break;
255
256     case X11DRV_ESCAPE:
257         if (in_data && in_count >= sizeof(enum x11drv_escape_codes))
258         {
259             switch(*(enum x11drv_escape_codes *)in_data)
260             {
261             case X11DRV_GET_DISPLAY:
262                 if (out_count >= sizeof(Display *))
263                 {
264                     *(Display **)out_data = gdi_display;
265                     return TRUE;
266                 }
267                 break;
268             case X11DRV_GET_DRAWABLE:
269                 if (out_count >= sizeof(Drawable))
270                 {
271                     *(Drawable *)out_data = physDev->drawable;
272                     return TRUE;
273                 }
274                 break;
275             case X11DRV_GET_FONT:
276                 if (out_count >= sizeof(Font))
277                 {
278                     fontObject* pfo = XFONT_GetFontObject( physDev->font );
279                     if (pfo == NULL) return FALSE;
280                     *(Font *)out_data = pfo->fs->fid;
281                     return TRUE;
282                 }
283                 break;
284             case X11DRV_SET_DRAWABLE:
285                 if (in_count >= sizeof(struct x11drv_escape_set_drawable))
286                 {
287                     struct x11drv_escape_set_drawable *data = (struct x11drv_escape_set_drawable *)in_data;
288                     if(physDev->xrender) X11DRV_XRender_UpdateDrawable( physDev );
289                     physDev->org = data->org;
290                     physDev->drawable = data->drawable;
291                     physDev->drawable_org = data->drawable_org;
292                     wine_tsx11_lock();
293                     XSetSubwindowMode( gdi_display, physDev->gc, data->mode );
294                     wine_tsx11_unlock();
295                     return TRUE;
296                 }
297                 break;
298             case X11DRV_START_EXPOSURES:
299                 wine_tsx11_lock();
300                 XSetGraphicsExposures( gdi_display, physDev->gc, True );
301                 wine_tsx11_unlock();
302                 physDev->exposures = 0;
303                 return TRUE;
304             case X11DRV_END_EXPOSURES:
305                 if (out_count >= sizeof(HRGN))
306                 {
307                     HRGN hrgn = 0, tmp = 0;
308
309                     wine_tsx11_lock();
310                     XSetGraphicsExposures( gdi_display, physDev->gc, False );
311                     if (physDev->exposures)
312                     {
313                         for (;;)
314                         {
315                             XEvent event;
316
317                             XWindowEvent( gdi_display, physDev->drawable, ~0, &event );
318                             if (event.type == NoExpose) break;
319                             if (event.type == GraphicsExpose)
320                             {
321                                 int x = event.xgraphicsexpose.x - physDev->org.x;
322                                 int y = event.xgraphicsexpose.y - physDev->org.y;
323
324                                 TRACE( "got %d,%d %dx%d count %d\n", x, y,
325                                        event.xgraphicsexpose.width,
326                                        event.xgraphicsexpose.height,
327                                        event.xgraphicsexpose.count );
328
329                                 if (!tmp) tmp = CreateRectRgn( 0, 0, 0, 0 );
330                                 SetRectRgn( tmp, x, y,
331                                             x + event.xgraphicsexpose.width,
332                                             y + event.xgraphicsexpose.height );
333                                 if (hrgn) CombineRgn( hrgn, hrgn, tmp, RGN_OR );
334                                 else
335                                 {
336                                     hrgn = tmp;
337                                     tmp = 0;
338                                 }
339                                 if (!event.xgraphicsexpose.count) break;
340                             }
341                             else
342                             {
343                                 ERR( "got unexpected event %d\n", event.type );
344                                 break;
345                             }
346                         }
347                         if (tmp) DeleteObject( tmp );
348                     }
349                     wine_tsx11_unlock();
350                     *(HRGN *)out_data = hrgn;
351                     return TRUE;
352                 }
353                 break;
354             }
355         }
356         break;
357     }
358     return 0;
359 }