Implemented wxScreenDC the hard way
[wxWidgets.git] / src / gtk1 / dcscreen.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dcscreen.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "dcscreen.h"
12 #endif
13
14 #include "wx/dcscreen.h"
15 #include "wx/window.h"
16
17 //-----------------------------------------------------------------------------
18 // global data initialization
19 //-----------------------------------------------------------------------------
20
21 GdkWindow *wxScreenDC::sm_overlayWindow = (GdkWindow*) NULL;
22 int wxScreenDC::sm_overlayWindowX = 0;
23 int wxScreenDC::sm_overlayWindowY = 0;
24
25
26 //-----------------------------------------------------------------------------
27 // create X window
28 //-----------------------------------------------------------------------------
29
30 extern "C" {
31
32 #include "gdk/gdk.h"
33 #include "gdk/gdkprivate.h"
34 #include "gdk/gdkx.h"
35 #include <netinet/in.h>
36
37 int nevent_masks = 17;
38 int event_mask_table[19] =
39 {
40 ExposureMask,
41 PointerMotionMask,
42 PointerMotionHintMask,
43 ButtonMotionMask,
44 Button1MotionMask,
45 Button2MotionMask,
46 Button3MotionMask,
47 ButtonPressMask | OwnerGrabButtonMask,
48 ButtonReleaseMask | OwnerGrabButtonMask,
49 KeyPressMask,
50 KeyReleaseMask,
51 EnterWindowMask,
52 LeaveWindowMask,
53 FocusChangeMask,
54 StructureNotifyMask,
55 PropertyChangeMask,
56 VisibilityChangeMask,
57 0, /* PROXIMITY_IN */
58 0 /* PROXIMTY_OUT */
59 };
60
61 GdkWindow*
62 gdk_window_transparent_new ( GdkWindow *parent,
63 GdkWindowAttr *attributes,
64 gint attributes_mask)
65 {
66 GdkWindow *window;
67 GdkWindowPrivate *gprivate;
68 GdkWindowPrivate *parent_private;
69 GdkVisual *visual;
70 Display *parent_display;
71 Window xparent;
72 Visual *xvisual;
73 XSetWindowAttributes xattributes;
74 long xattributes_mask;
75 XSizeHints size_hints;
76 XWMHints wm_hints;
77 XClassHint *class_hint;
78 int x, y, depth;
79 unsigned int gclass;
80 char *title;
81 int i;
82
83 g_return_val_if_fail (attributes != NULL, NULL);
84
85 if (!parent)
86 parent = (GdkWindow*) &gdk_root_parent;
87
88 parent_private = (GdkWindowPrivate*) parent;
89 if (parent_private->destroyed)
90 return NULL;
91
92 xparent = parent_private->xwindow;
93 parent_display = parent_private->xdisplay;
94
95 gprivate = g_new (GdkWindowPrivate, 1);
96 window = (GdkWindow*) gprivate;
97
98 gprivate->parent = parent;
99
100 if (parent_private != &gdk_root_parent)
101 parent_private->children = g_list_prepend (parent_private->children, window);
102
103 gprivate->xdisplay = parent_display;
104 gprivate->destroyed = FALSE;
105 gprivate->resize_count = 0;
106 gprivate->ref_count = 1;
107 xattributes_mask = 0;
108
109 if (attributes_mask & GDK_WA_X)
110 x = attributes->x;
111 else
112 x = 0;
113
114 if (attributes_mask & GDK_WA_Y)
115 y = attributes->y;
116 else
117 y = 0;
118
119 gprivate->x = x;
120 gprivate->y = y;
121 gprivate->width = (attributes->width > 1) ? (attributes->width) : (1);
122 gprivate->height = (attributes->height > 1) ? (attributes->height) : (1);
123 gprivate->window_type = attributes->window_type;
124 gprivate->extension_events = FALSE;
125 gprivate->dnd_drag_data_type = None;
126 gprivate->dnd_drag_data_typesavail =
127 gprivate->dnd_drop_data_typesavail = NULL;
128 gprivate->dnd_drop_enabled = gprivate->dnd_drag_enabled =
129 gprivate->dnd_drag_accepted = gprivate->dnd_drag_datashow =
130 gprivate->dnd_drop_data_numtypesavail =
131 gprivate->dnd_drag_data_numtypesavail = 0;
132 gprivate->dnd_drag_eventmask = gprivate->dnd_drag_savedeventmask = 0;
133
134 gprivate->filters = NULL;
135 gprivate->children = NULL;
136
137 window->user_data = NULL;
138
139 if (attributes_mask & GDK_WA_VISUAL)
140 visual = attributes->visual;
141 else
142 visual = gdk_visual_get_system ();
143 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
144
145 xattributes.event_mask = StructureNotifyMask;
146 for (i = 0; i < nevent_masks; i++)
147 {
148 if (attributes->event_mask & (1 << (i + 1)))
149 xattributes.event_mask |= event_mask_table[i];
150 }
151
152 if (xattributes.event_mask)
153 xattributes_mask |= CWEventMask;
154
155 if(attributes_mask & GDK_WA_NOREDIR) {
156 xattributes.override_redirect =
157 (attributes->override_redirect == FALSE)?False:True;
158 xattributes_mask |= CWOverrideRedirect;
159 } else
160 xattributes.override_redirect = False;
161
162 gclass = InputOutput;
163 depth = visual->depth;
164
165 if (attributes_mask & GDK_WA_COLORMAP)
166 gprivate->colormap = attributes->colormap;
167 else
168 gprivate->colormap = gdk_colormap_get_system ();
169
170 xattributes.colormap = ((GdkColormapPrivate*) gprivate->colormap)->xcolormap;
171 xattributes_mask |= CWColormap;
172
173 xparent = gdk_root_window;
174
175 xattributes.save_under = True;
176 xattributes.override_redirect = True;
177 xattributes.cursor = None;
178 xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
179
180 gprivate->xwindow = XCreateWindow (gprivate->xdisplay, xparent,
181 x, y, gprivate->width, gprivate->height,
182 0, depth, gclass, xvisual,
183 xattributes_mask, &xattributes);
184 gdk_window_ref (window);
185 gdk_xid_table_insert (&gprivate->xwindow, window);
186
187 if (gprivate->colormap)
188 gdk_colormap_ref (gprivate->colormap);
189
190 XSetWMProtocols (gprivate->xdisplay, gprivate->xwindow, gdk_wm_window_protocols, 2);
191
192 size_hints.flags = PSize;
193 size_hints.width = gprivate->width;
194 size_hints.height = gprivate->height;
195
196 wm_hints.flags = InputHint | StateHint | WindowGroupHint;
197 wm_hints.window_group = gdk_leader_window;
198 wm_hints.input = True;
199 wm_hints.initial_state = NormalState;
200
201 /* FIXME: Is there any point in doing this? Do any WM's pay
202 * attention to PSize, and even if they do, is this the
203 * correct value???
204 */
205 XSetWMNormalHints (gprivate->xdisplay, gprivate->xwindow, &size_hints);
206
207 XSetWMHints (gprivate->xdisplay, gprivate->xwindow, &wm_hints);
208
209 if (attributes_mask & GDK_WA_TITLE)
210 title = attributes->title;
211 else
212 title = gdk_progname;
213
214 XmbSetWMProperties (gprivate->xdisplay, gprivate->xwindow,
215 title, title,
216 NULL, 0,
217 NULL, NULL, NULL);
218
219 if (attributes_mask & GDK_WA_WMCLASS)
220 {
221 class_hint = XAllocClassHint ();
222 class_hint->res_name = attributes->wmclass_name;
223 class_hint->res_class = attributes->wmclass_class;
224 XSetClassHint (gprivate->xdisplay, gprivate->xwindow, class_hint);
225 XFree (class_hint);
226 }
227
228 return window;
229 }
230
231 } // extern "C"
232
233 //-----------------------------------------------------------------------------
234 // wxScreenDC
235 //-----------------------------------------------------------------------------
236
237 IMPLEMENT_DYNAMIC_CLASS(wxScreenDC,wxPaintDC)
238
239 wxScreenDC::wxScreenDC(void)
240 {
241 m_ok = FALSE;
242 m_window = (GdkWindow *) NULL;
243 m_cmap = gdk_colormap_get_system();
244
245 if (sm_overlayWindow)
246 {
247 m_window = sm_overlayWindow;
248 m_deviceOriginX = - sm_overlayWindowX;
249 m_deviceOriginY = - sm_overlayWindowY;
250 }
251 else
252 m_window = GDK_ROOT_PARENT();
253
254 SetUpDC();
255
256 gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS );
257 gdk_gc_set_subwindow( m_brushGC, GDK_INCLUDE_INFERIORS );
258 gdk_gc_set_subwindow( m_textGC, GDK_INCLUDE_INFERIORS );
259 gdk_gc_set_subwindow( m_bgGC, GDK_INCLUDE_INFERIORS );
260 }
261
262 wxScreenDC::~wxScreenDC(void)
263 {
264 EndDrawingOnTop();
265 }
266
267 bool wxScreenDC::StartDrawingOnTop( wxWindow *window )
268 {
269 if (!window) return StartDrawingOnTop();
270
271 int x = 0;
272 int y = 0;
273 window->GetPosition( &x, &y );
274 int w = 0;
275 int h = 0;
276 window->GetSize( &w, &h );
277 window->ClientToScreen( &x, &y );
278
279 wxRectangle rect;
280 rect.x = x;
281 rect.y = y;
282 rect.width = 0;
283 rect.height = 0;
284
285 return StartDrawingOnTop( &rect );
286 }
287
288 bool wxScreenDC::StartDrawingOnTop( wxRectangle *rect )
289 {
290 int x = 0;
291 int y = 0;
292 int width = gdk_screen_width();
293 int height = gdk_screen_height();
294 if (rect)
295 {
296 x = rect->x;
297 y = rect->y;
298 width = rect->width;
299 height = rect->height;
300 }
301
302 sm_overlayWindowX = x;
303 sm_overlayWindowY = y;
304
305 GdkWindowAttr attr;
306 attr.x = x;
307 attr.y = y;
308 attr.width = width;
309 attr.height = height;
310 attr.override_redirect = TRUE;
311 attr.wclass = GDK_INPUT_OUTPUT;
312 attr.event_mask = 0;
313 attr.window_type = GDK_WINDOW_TEMP;
314
315 // GTK cannot set transparent backgrounds. :-(
316 sm_overlayWindow = gdk_window_transparent_new( NULL, &attr, GDK_WA_NOREDIR | GDK_WA_X | GDK_WA_Y );
317
318 if (sm_overlayWindow) gdk_window_show( sm_overlayWindow );
319
320 return (sm_overlayWindow);
321 }
322
323 bool wxScreenDC::EndDrawingOnTop(void)
324 {
325 if (sm_overlayWindow) gdk_window_destroy( sm_overlayWindow );
326
327 sm_overlayWindow = NULL;
328 sm_overlayWindowX = 0;
329 sm_overlayWindowY = 0;
330
331 return TRUE;
332 }
333