1 | /* GDK - The GIMP Drawing Kit |
2 | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2 of the License, or (at your option) any later version. |
8 | * |
9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Lesser General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
16 | */ |
17 | |
18 | /* |
19 | * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS |
20 | * file for a list of people on the GTK+ Team. See the ChangeLog |
21 | * files for a list of changes. These files are distributed with |
22 | * GTK+ at ftp://ftp.gtk.org/pub/gtk/. |
23 | */ |
24 | |
25 | /* Uninstalled header defining types and functions internal to GDK */ |
26 | |
27 | #ifndef __GDK_INTERNALS_H__ |
28 | #define __GDK_INTERNALS_H__ |
29 | |
30 | #include <gio/gio.h> |
31 | #include "gdkwindowimpl.h" |
32 | #include "gdkdisplay.h" |
33 | #include "gdkprivate.h" |
34 | |
35 | G_BEGIN_DECLS |
36 | |
37 | /********************** |
38 | * General Facilities * |
39 | **********************/ |
40 | |
41 | /* Debugging support */ |
42 | |
43 | typedef struct _GdkColorInfo GdkColorInfo; |
44 | typedef struct _GdkEventFilter GdkEventFilter; |
45 | typedef struct _GdkClientFilter GdkClientFilter; |
46 | |
47 | typedef enum { |
48 | GDK_COLOR_WRITEABLE = 1 << 0 |
49 | } GdkColorInfoFlags; |
50 | |
51 | struct _GdkColorInfo |
52 | { |
53 | GdkColorInfoFlags flags; |
54 | guint ref_count; |
55 | }; |
56 | |
57 | typedef enum { |
58 | GDK_EVENT_FILTER_REMOVED = 1 << 0 |
59 | } GdkEventFilterFlags; |
60 | |
61 | struct _GdkEventFilter { |
62 | GdkFilterFunc function; |
63 | gpointer data; |
64 | GdkEventFilterFlags flags; |
65 | guint ref_count; |
66 | }; |
67 | |
68 | struct _GdkClientFilter { |
69 | GdkAtom type; |
70 | GdkFilterFunc function; |
71 | gpointer data; |
72 | }; |
73 | |
74 | typedef enum { |
75 | GDK_DEBUG_MISC = 1 << 0, |
76 | GDK_DEBUG_EVENTS = 1 << 1, |
77 | GDK_DEBUG_DND = 1 << 2, |
78 | GDK_DEBUG_XIM = 1 << 3, |
79 | GDK_DEBUG_NOGRABS = 1 << 4, |
80 | GDK_DEBUG_INPUT = 1 << 5, |
81 | GDK_DEBUG_CURSOR = 1 << 6, |
82 | GDK_DEBUG_MULTIHEAD = 1 << 7, |
83 | GDK_DEBUG_XINERAMA = 1 << 8, |
84 | GDK_DEBUG_DRAW = 1 << 9, |
85 | GDK_DEBUG_EVENTLOOP = 1 << 10, |
86 | GDK_DEBUG_FRAMES = 1 << 11, |
87 | GDK_DEBUG_SETTINGS = 1 << 12, |
88 | GDK_DEBUG_OPENGL = 1 << 13, |
89 | } GdkDebugFlag; |
90 | |
91 | typedef enum { |
92 | GDK_RENDERING_MODE_SIMILAR = 0, |
93 | GDK_RENDERING_MODE_IMAGE, |
94 | GDK_RENDERING_MODE_RECORDING |
95 | } GdkRenderingMode; |
96 | |
97 | typedef enum { |
98 | GDK_GL_DISABLE = 1 << 0, |
99 | GDK_GL_ALWAYS = 1 << 1, |
100 | GDK_GL_SOFTWARE_DRAW_GL = 1 << 2, |
101 | GDK_GL_SOFTWARE_DRAW_SURFACE = 1 << 3, |
102 | GDK_GL_TEXTURE_RECTANGLE = 1 << 4, |
103 | GDK_GL_LEGACY = 1 << 5, |
104 | GDK_GL_GLES = 1 << 6 |
105 | } GdkGLFlags; |
106 | |
107 | extern GList *_gdk_default_filters; |
108 | extern GdkWindow *_gdk_parent_root; |
109 | |
110 | extern guint _gdk_debug_flags; |
111 | extern guint _gdk_gl_flags; |
112 | extern GdkRenderingMode _gdk_rendering_mode; |
113 | extern gboolean _gdk_debug_updates; |
114 | |
115 | #ifdef G_ENABLE_DEBUG |
116 | |
117 | #define GDK_DEBUG_CHECK(type) G_UNLIKELY (_gdk_debug_flags & GDK_DEBUG_##type) |
118 | |
119 | #define GDK_NOTE(type,action) G_STMT_START { \ |
120 | if (GDK_DEBUG_CHECK (type)) \ |
121 | { action; }; } G_STMT_END |
122 | |
123 | #else /* !G_ENABLE_DEBUG */ |
124 | |
125 | #define GDK_DEBUG_CHECK(type) 0 |
126 | #define GDK_NOTE(type,action) |
127 | |
128 | #endif /* G_ENABLE_DEBUG */ |
129 | |
130 | /* Arg parsing */ |
131 | |
132 | typedef enum |
133 | { |
134 | GDK_ARG_STRING, |
135 | GDK_ARG_INT, |
136 | GDK_ARG_BOOL, |
137 | GDK_ARG_NOBOOL, |
138 | GDK_ARG_CALLBACK |
139 | } GdkArgType; |
140 | |
141 | typedef struct _GdkArgContext GdkArgContext; |
142 | typedef struct _GdkArgDesc GdkArgDesc; |
143 | |
144 | typedef void (*GdkArgFunc) (const char *name, const char *arg, gpointer data); |
145 | |
146 | struct _GdkArgContext |
147 | { |
148 | GPtrArray *tables; |
149 | gpointer cb_data; |
150 | }; |
151 | |
152 | struct _GdkArgDesc |
153 | { |
154 | const char *name; |
155 | GdkArgType type; |
156 | gpointer location; |
157 | GdkArgFunc callback; |
158 | }; |
159 | |
160 | /* Event handling */ |
161 | |
162 | typedef struct _GdkEventPrivate GdkEventPrivate; |
163 | |
164 | typedef enum |
165 | { |
166 | /* Following flag is set for events on the event queue during |
167 | * translation and cleared afterwards. |
168 | */ |
169 | GDK_EVENT_PENDING = 1 << 0, |
170 | |
171 | /* The following flag is set for: |
172 | * 1) touch events emulating pointer events |
173 | * 2) pointer events being emulated by a touch sequence. |
174 | */ |
175 | GDK_EVENT_POINTER_EMULATED = 1 << 1, |
176 | |
177 | /* When we are ready to draw a frame, we pause event delivery, |
178 | * mark all events in the queue with this flag, and deliver |
179 | * only those events until we finish the frame. |
180 | */ |
181 | GDK_EVENT_FLUSHED = 1 << 2 |
182 | } GdkEventFlags; |
183 | |
184 | struct _GdkEventPrivate |
185 | { |
186 | GdkEvent event; |
187 | guint flags; |
188 | GdkScreen *screen; |
189 | gpointer windowing_data; |
190 | GdkDevice *device; |
191 | GdkDevice *source_device; |
192 | GdkSeat *seat; |
193 | GdkDeviceTool *tool; |
194 | guint16 key_scancode; |
195 | }; |
196 | |
197 | typedef struct _GdkWindowPaint GdkWindowPaint; |
198 | |
199 | struct _GdkWindow |
200 | { |
201 | GObject parent_instance; |
202 | |
203 | GdkWindowImpl *impl; /* window-system-specific delegate object */ |
204 | |
205 | GdkWindow *parent; |
206 | GdkVisual *visual; |
207 | |
208 | gpointer user_data; |
209 | |
210 | gint x; |
211 | gint y; |
212 | |
213 | GdkEventMask event_mask; |
214 | guint8 window_type; |
215 | |
216 | guint8 depth; |
217 | guint8 resize_count; |
218 | |
219 | gint8 toplevel_window_type; |
220 | |
221 | GList *filters; |
222 | GList *children; |
223 | GList children_list_node; |
224 | GList *native_children; |
225 | |
226 | |
227 | cairo_pattern_t *background; |
228 | |
229 | /* The paint logic here is a bit complex because of our intermingling of |
230 | * cairo and GL. Let's first go over the cairo-alone case: |
231 | * |
232 | * 1) gdk_window_begin_paint_region() is called with an update region. If |
233 | * the backend wants it, we redirect drawing to a temporary surface |
234 | * sized the same as the update region and set `surface_needs_composite` |
235 | * to TRUE. Otherwise, we paint directly onto the real server-side window. |
236 | * |
237 | * 2) Things paint with cairo using gdk_cairo_create(). |
238 | * |
239 | * 3) When everything is painted, the user calls gdk_window_end_paint(). |
240 | * If there was a temporary surface, this is composited back onto the |
241 | * real backing surface in the appropriate places. |
242 | * |
243 | * This is similar to double buffering, except we only have partial surfaces |
244 | * of undefined contents, and instead of swapping between two buffers, we |
245 | * create a new temporary buffer every time. |
246 | * |
247 | * When we add GL to the mix, we have this instead: |
248 | * |
249 | * 1) gdk_window_begin_paint_region() is called with an update region like |
250 | * before. We always redirect cairo drawing to a temporary surface when |
251 | * GL is enabled. |
252 | * |
253 | * 2) Things paint with cairo using gdk_cairo_create(). Whenever |
254 | * something paints, it calls gdk_window_mark_paint_from_clip() to mark |
255 | * which regions it has painted in software. We'll learn what this does |
256 | * soon. |
257 | * |
258 | * 3) Something paints with GL and uses gdk_cairo_draw_from_gl() to |
259 | * composite back into the scene. We paint this onto the backing |
260 | * store for the window *immediately* by using GL, rather than |
261 | * painting to the temporary surface, and keep track of the area that |
262 | * we've painted in `flushed_region`. |
263 | * |
264 | * 4) Something paints using software again. It calls |
265 | * gdk_window_mark_paint_from_clip(), which subtracts the region it |
266 | * has painted from `flushed_region` and adds the region to |
267 | * `needs_blended_region`. |
268 | * |
269 | * 5) Something paints using GL again, using gdk_cairo_draw_from_gl(). |
270 | * It paints directly to the backing store, removes the region it |
271 | * painted from `needs_blended_region`, and adds to `flushed_region`. |
272 | * |
273 | * 6) gdk_window_end_paint() is called. It composites the temporary surface |
274 | * back to the window, using GL, except it doesn't bother copying |
275 | * `flushed_region`, and when it paints `needs_blended_region`, it also |
276 | * turns on GL blending. |
277 | * |
278 | * That means that at any point in time, we have three regions: |
279 | * |
280 | * * `region` - This is the original invalidated region and is never |
281 | * touched. |
282 | * |
283 | * * `flushed_region` - This is the portion of `region` that has GL |
284 | * contents that have been painted directly to the window, and |
285 | * doesn't have any cairo drawing painted over it. |
286 | * |
287 | * * `needs_blended_region` - This is the portion of `region` that |
288 | * GL contents that have part cairo drawing painted over it. |
289 | * gdk_window_end_paint() will draw this region using blending. |
290 | * |
291 | * `flushed_region` and `needs_blended_region` never intersect, and the |
292 | * rest of `region` that isn't covered by either is the "opaque region", |
293 | * which is any area of cairo drawing that didn't ever intersect with GL. |
294 | * We can paint these from GL without turning on blending. |
295 | **/ |
296 | |
297 | struct { |
298 | /* The temporary surface that we're painting to. This will be composited |
299 | * back into the window when we call end_paint. This is our poor-man's |
300 | * way of doing double buffering. */ |
301 | cairo_surface_t *surface; |
302 | |
303 | cairo_region_t *region; |
304 | cairo_region_t *flushed_region; |
305 | cairo_region_t *need_blend_region; |
306 | |
307 | gboolean surface_needs_composite; |
308 | gboolean use_gl; |
309 | } current_paint; |
310 | GdkGLContext *gl_paint_context; |
311 | |
312 | cairo_region_t *update_area; |
313 | guint update_freeze_count; |
314 | /* This is the update_area that was in effect when the current expose |
315 | started. It may be smaller than the expose area if we'e painting |
316 | more than we have to, but it represents the "true" damage. */ |
317 | cairo_region_t *active_update_area; |
318 | /* We store the old expose areas to support buffer-age optimizations */ |
319 | cairo_region_t *old_updated_area[2]; |
320 | |
321 | GdkWindowState old_state; |
322 | GdkWindowState state; |
323 | |
324 | guint8 alpha; |
325 | guint8 fullscreen_mode; |
326 | |
327 | guint input_only : 1; |
328 | guint pass_through : 1; |
329 | guint modal_hint : 1; |
330 | guint composited : 1; |
331 | guint has_alpha_background : 1; |
332 | |
333 | guint destroyed : 2; |
334 | |
335 | guint accept_focus : 1; |
336 | guint focus_on_map : 1; |
337 | guint shaped : 1; |
338 | guint support_multidevice : 1; |
339 | guint synthesize_crossing_event_queued : 1; |
340 | guint effective_visibility : 2; |
341 | guint visibility : 2; /* The visibility wrt the toplevel (i.e. based on clip_region) */ |
342 | guint native_visibility : 2; /* the native visibility of a impl windows */ |
343 | guint viewable : 1; /* mapped and all parents mapped */ |
344 | guint applied_shape : 1; |
345 | guint in_update : 1; |
346 | guint geometry_dirty : 1; |
347 | guint event_compression : 1; |
348 | guint frame_clock_events_paused : 1; |
349 | |
350 | /* The GdkWindow that has the impl, ref:ed if another window. |
351 | * This ref is required to keep the wrapper of the impl window alive |
352 | * for as long as any GdkWindow references the impl. */ |
353 | GdkWindow *impl_window; |
354 | |
355 | guint update_and_descendants_freeze_count; |
356 | |
357 | gint abs_x, abs_y; /* Absolute offset in impl */ |
358 | gint width, height; |
359 | |
360 | guint num_offscreen_children; |
361 | |
362 | /* The clip region is the part of the window, in window coordinates |
363 | that is fully or partially (i.e. semi transparently) visible in |
364 | the window hierarchy from the toplevel and down */ |
365 | cairo_region_t *clip_region; |
366 | |
367 | GdkCursor *cursor; |
368 | GHashTable *device_cursor; |
369 | |
370 | cairo_region_t *shape; |
371 | cairo_region_t *input_shape; |
372 | |
373 | GList *devices_inside; |
374 | GHashTable *device_events; |
375 | |
376 | GHashTable *source_event_masks; |
377 | gulong device_added_handler_id; |
378 | gulong device_changed_handler_id; |
379 | |
380 | GdkFrameClock *frame_clock; /* NULL to use from parent or default */ |
381 | GdkWindowInvalidateHandlerFunc invalidate_handler; |
382 | |
383 | GdkDrawingContext *drawing_context; |
384 | }; |
385 | |
386 | #define GDK_WINDOW_TYPE(d) ((((GdkWindow *)(d)))->window_type) |
387 | #define GDK_WINDOW_DESTROYED(d) (((GdkWindow *)(d))->destroyed) |
388 | |
389 | extern gchar *_gdk_display_name; |
390 | extern gint _gdk_screen_number; |
391 | extern gchar *_gdk_display_arg_name; |
392 | extern gboolean _gdk_disable_multidevice; |
393 | |
394 | GdkEvent* _gdk_event_unqueue (GdkDisplay *display); |
395 | |
396 | void _gdk_event_filter_unref (GdkWindow *window, |
397 | GdkEventFilter *filter); |
398 | |
399 | void gdk_event_set_pointer_emulated (GdkEvent *event, |
400 | gboolean emulated); |
401 | |
402 | void gdk_event_set_scancode (GdkEvent *event, |
403 | guint16 scancode); |
404 | |
405 | void gdk_event_set_seat (GdkEvent *event, |
406 | GdkSeat *seat); |
407 | |
408 | void _gdk_event_emit (GdkEvent *event); |
409 | GList* _gdk_event_queue_find_first (GdkDisplay *display); |
410 | void _gdk_event_queue_remove_link (GdkDisplay *display, |
411 | GList *node); |
412 | GList* _gdk_event_queue_append (GdkDisplay *display, |
413 | GdkEvent *event); |
414 | GList* _gdk_event_queue_insert_after (GdkDisplay *display, |
415 | GdkEvent *after_event, |
416 | GdkEvent *event); |
417 | GList* _gdk_event_queue_insert_before(GdkDisplay *display, |
418 | GdkEvent *after_event, |
419 | GdkEvent *event); |
420 | |
421 | void _gdk_event_queue_handle_motion_compression (GdkDisplay *display); |
422 | void _gdk_event_queue_flush (GdkDisplay *display); |
423 | |
424 | void _gdk_event_button_generate (GdkDisplay *display, |
425 | GdkEvent *event); |
426 | |
427 | void _gdk_windowing_event_data_copy (const GdkEvent *src, |
428 | GdkEvent *dst); |
429 | void _gdk_windowing_event_data_free (GdkEvent *event); |
430 | |
431 | void _gdk_set_window_state (GdkWindow *window, |
432 | GdkWindowState new_state); |
433 | |
434 | gboolean _gdk_cairo_surface_extents (cairo_surface_t *surface, |
435 | GdkRectangle *extents); |
436 | void gdk_gl_texture_from_surface (cairo_surface_t *surface, |
437 | cairo_region_t *region); |
438 | |
439 | typedef struct { |
440 | float x1, y1, x2, y2; |
441 | float u1, v1, u2, v2; |
442 | } GdkTexturedQuad; |
443 | |
444 | void gdk_gl_texture_quads (GdkGLContext *paint_context, |
445 | guint texture_target, |
446 | int n_quads, |
447 | GdkTexturedQuad *quads, |
448 | gboolean flip_colors); |
449 | |
450 | void gdk_cairo_surface_mark_as_direct (cairo_surface_t *surface, |
451 | GdkWindow *window); |
452 | cairo_region_t *gdk_cairo_region_from_clip (cairo_t *cr); |
453 | |
454 | void gdk_cairo_set_drawing_context (cairo_t *cr, |
455 | GdkDrawingContext *context); |
456 | |
457 | /************************************* |
458 | * Interfaces used by windowing code * |
459 | *************************************/ |
460 | |
461 | cairo_surface_t * |
462 | _gdk_window_ref_cairo_surface (GdkWindow *window); |
463 | |
464 | void _gdk_window_destroy (GdkWindow *window, |
465 | gboolean foreign_destroy); |
466 | void _gdk_window_clear_update_area (GdkWindow *window); |
467 | void _gdk_window_update_size (GdkWindow *window); |
468 | gboolean _gdk_window_update_viewable (GdkWindow *window); |
469 | GdkGLContext * gdk_window_get_paint_gl_context (GdkWindow *window, |
470 | GError **error); |
471 | void gdk_window_get_unscaled_size (GdkWindow *window, |
472 | int *unscaled_width, |
473 | int *unscaled_height); |
474 | |
475 | GdkDrawingContext *gdk_window_get_drawing_context (GdkWindow *window); |
476 | |
477 | cairo_region_t *gdk_window_get_current_paint_region (GdkWindow *window); |
478 | |
479 | void _gdk_window_process_updates_recurse (GdkWindow *window, |
480 | cairo_region_t *expose_region); |
481 | |
482 | void _gdk_screen_set_resolution (GdkScreen *screen, |
483 | gdouble dpi); |
484 | void _gdk_screen_close (GdkScreen *screen); |
485 | |
486 | /***************************************** |
487 | * Interfaces provided by windowing code * |
488 | *****************************************/ |
489 | |
490 | /* Font/string functions implemented in module-specific code */ |
491 | |
492 | void _gdk_cursor_destroy (GdkCursor *cursor); |
493 | |
494 | extern const GOptionEntry _gdk_windowing_args[]; |
495 | |
496 | void _gdk_windowing_got_event (GdkDisplay *display, |
497 | GList *event_link, |
498 | GdkEvent *event, |
499 | gulong serial); |
500 | |
501 | #define GDK_WINDOW_IS_MAPPED(window) (((window)->state & GDK_WINDOW_STATE_WITHDRAWN) == 0) |
502 | |
503 | void _gdk_window_invalidate_for_expose (GdkWindow *window, |
504 | cairo_region_t *region); |
505 | |
506 | GdkWindow * _gdk_window_find_child_at (GdkWindow *window, |
507 | double x, double y); |
508 | GdkWindow * _gdk_window_find_descendant_at (GdkWindow *toplevel, |
509 | double x, double y, |
510 | double *found_x, |
511 | double *found_y); |
512 | |
513 | GdkEvent * _gdk_make_event (GdkWindow *window, |
514 | GdkEventType type, |
515 | GdkEvent *event_in_queue, |
516 | gboolean before_event); |
517 | gboolean _gdk_window_event_parent_of (GdkWindow *parent, |
518 | GdkWindow *child); |
519 | |
520 | void _gdk_synthesize_crossing_events (GdkDisplay *display, |
521 | GdkWindow *src, |
522 | GdkWindow *dest, |
523 | GdkDevice *device, |
524 | GdkDevice *source_device, |
525 | GdkCrossingMode mode, |
526 | gdouble toplevel_x, |
527 | gdouble toplevel_y, |
528 | GdkModifierType mask, |
529 | guint32 time_, |
530 | GdkEvent *event_in_queue, |
531 | gulong serial, |
532 | gboolean non_linear); |
533 | void _gdk_display_set_window_under_pointer (GdkDisplay *display, |
534 | GdkDevice *device, |
535 | GdkWindow *window); |
536 | |
537 | |
538 | void _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window); |
539 | |
540 | gboolean _gdk_window_has_impl (GdkWindow *window); |
541 | GdkWindow * _gdk_window_get_impl_window (GdkWindow *window); |
542 | |
543 | /***************************** |
544 | * offscreen window routines * |
545 | *****************************/ |
546 | GType gdk_offscreen_window_get_type (void); |
547 | void _gdk_offscreen_window_new (GdkWindow *window, |
548 | GdkWindowAttr *attributes, |
549 | gint attributes_mask); |
550 | cairo_surface_t * _gdk_offscreen_window_create_surface (GdkWindow *window, |
551 | gint width, |
552 | gint height); |
553 | |
554 | G_END_DECLS |
555 | |
556 | #endif /* __GDK_INTERNALS_H__ */ |
557 | |