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
35G_BEGIN_DECLS
36
37/**********************
38 * General Facilities *
39 **********************/
40
41/* Debugging support */
42
43typedef struct _GdkColorInfo GdkColorInfo;
44typedef struct _GdkEventFilter GdkEventFilter;
45typedef struct _GdkClientFilter GdkClientFilter;
46
47typedef enum {
48 GDK_COLOR_WRITEABLE = 1 << 0
49} GdkColorInfoFlags;
50
51struct _GdkColorInfo
52{
53 GdkColorInfoFlags flags;
54 guint ref_count;
55};
56
57typedef enum {
58 GDK_EVENT_FILTER_REMOVED = 1 << 0
59} GdkEventFilterFlags;
60
61struct _GdkEventFilter {
62 GdkFilterFunc function;
63 gpointer data;
64 GdkEventFilterFlags flags;
65 guint ref_count;
66};
67
68struct _GdkClientFilter {
69 GdkAtom type;
70 GdkFilterFunc function;
71 gpointer data;
72};
73
74typedef 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
91typedef enum {
92 GDK_RENDERING_MODE_SIMILAR = 0,
93 GDK_RENDERING_MODE_IMAGE,
94 GDK_RENDERING_MODE_RECORDING
95} GdkRenderingMode;
96
97typedef 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
107extern GList *_gdk_default_filters;
108extern GdkWindow *_gdk_parent_root;
109
110extern guint _gdk_debug_flags;
111extern guint _gdk_gl_flags;
112extern GdkRenderingMode _gdk_rendering_mode;
113extern 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
132typedef 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
141typedef struct _GdkArgContext GdkArgContext;
142typedef struct _GdkArgDesc GdkArgDesc;
143
144typedef void (*GdkArgFunc) (const char *name, const char *arg, gpointer data);
145
146struct _GdkArgContext
147{
148 GPtrArray *tables;
149 gpointer cb_data;
150};
151
152struct _GdkArgDesc
153{
154 const char *name;
155 GdkArgType type;
156 gpointer location;
157 GdkArgFunc callback;
158};
159
160/* Event handling */
161
162typedef struct _GdkEventPrivate GdkEventPrivate;
163
164typedef 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
184struct _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
197typedef struct _GdkWindowPaint GdkWindowPaint;
198
199struct _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
389extern gchar *_gdk_display_name;
390extern gint _gdk_screen_number;
391extern gchar *_gdk_display_arg_name;
392extern gboolean _gdk_disable_multidevice;
393
394GdkEvent* _gdk_event_unqueue (GdkDisplay *display);
395
396void _gdk_event_filter_unref (GdkWindow *window,
397 GdkEventFilter *filter);
398
399void gdk_event_set_pointer_emulated (GdkEvent *event,
400 gboolean emulated);
401
402void gdk_event_set_scancode (GdkEvent *event,
403 guint16 scancode);
404
405void gdk_event_set_seat (GdkEvent *event,
406 GdkSeat *seat);
407
408void _gdk_event_emit (GdkEvent *event);
409GList* _gdk_event_queue_find_first (GdkDisplay *display);
410void _gdk_event_queue_remove_link (GdkDisplay *display,
411 GList *node);
412GList* _gdk_event_queue_append (GdkDisplay *display,
413 GdkEvent *event);
414GList* _gdk_event_queue_insert_after (GdkDisplay *display,
415 GdkEvent *after_event,
416 GdkEvent *event);
417GList* _gdk_event_queue_insert_before(GdkDisplay *display,
418 GdkEvent *after_event,
419 GdkEvent *event);
420
421void _gdk_event_queue_handle_motion_compression (GdkDisplay *display);
422void _gdk_event_queue_flush (GdkDisplay *display);
423
424void _gdk_event_button_generate (GdkDisplay *display,
425 GdkEvent *event);
426
427void _gdk_windowing_event_data_copy (const GdkEvent *src,
428 GdkEvent *dst);
429void _gdk_windowing_event_data_free (GdkEvent *event);
430
431void _gdk_set_window_state (GdkWindow *window,
432 GdkWindowState new_state);
433
434gboolean _gdk_cairo_surface_extents (cairo_surface_t *surface,
435 GdkRectangle *extents);
436void gdk_gl_texture_from_surface (cairo_surface_t *surface,
437 cairo_region_t *region);
438
439typedef struct {
440 float x1, y1, x2, y2;
441 float u1, v1, u2, v2;
442} GdkTexturedQuad;
443
444void gdk_gl_texture_quads (GdkGLContext *paint_context,
445 guint texture_target,
446 int n_quads,
447 GdkTexturedQuad *quads,
448 gboolean flip_colors);
449
450void gdk_cairo_surface_mark_as_direct (cairo_surface_t *surface,
451 GdkWindow *window);
452cairo_region_t *gdk_cairo_region_from_clip (cairo_t *cr);
453
454void gdk_cairo_set_drawing_context (cairo_t *cr,
455 GdkDrawingContext *context);
456
457/*************************************
458 * Interfaces used by windowing code *
459 *************************************/
460
461cairo_surface_t *
462 _gdk_window_ref_cairo_surface (GdkWindow *window);
463
464void _gdk_window_destroy (GdkWindow *window,
465 gboolean foreign_destroy);
466void _gdk_window_clear_update_area (GdkWindow *window);
467void _gdk_window_update_size (GdkWindow *window);
468gboolean _gdk_window_update_viewable (GdkWindow *window);
469GdkGLContext * gdk_window_get_paint_gl_context (GdkWindow *window,
470 GError **error);
471void gdk_window_get_unscaled_size (GdkWindow *window,
472 int *unscaled_width,
473 int *unscaled_height);
474
475GdkDrawingContext *gdk_window_get_drawing_context (GdkWindow *window);
476
477cairo_region_t *gdk_window_get_current_paint_region (GdkWindow *window);
478
479void _gdk_window_process_updates_recurse (GdkWindow *window,
480 cairo_region_t *expose_region);
481
482void _gdk_screen_set_resolution (GdkScreen *screen,
483 gdouble dpi);
484void _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
492void _gdk_cursor_destroy (GdkCursor *cursor);
493
494extern const GOptionEntry _gdk_windowing_args[];
495
496void _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
503void _gdk_window_invalidate_for_expose (GdkWindow *window,
504 cairo_region_t *region);
505
506GdkWindow * _gdk_window_find_child_at (GdkWindow *window,
507 double x, double y);
508GdkWindow * _gdk_window_find_descendant_at (GdkWindow *toplevel,
509 double x, double y,
510 double *found_x,
511 double *found_y);
512
513GdkEvent * _gdk_make_event (GdkWindow *window,
514 GdkEventType type,
515 GdkEvent *event_in_queue,
516 gboolean before_event);
517gboolean _gdk_window_event_parent_of (GdkWindow *parent,
518 GdkWindow *child);
519
520void _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);
533void _gdk_display_set_window_under_pointer (GdkDisplay *display,
534 GdkDevice *device,
535 GdkWindow *window);
536
537
538void _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window);
539
540gboolean _gdk_window_has_impl (GdkWindow *window);
541GdkWindow * _gdk_window_get_impl_window (GdkWindow *window);
542
543/*****************************
544 * offscreen window routines *
545 *****************************/
546GType gdk_offscreen_window_get_type (void);
547void _gdk_offscreen_window_new (GdkWindow *window,
548 GdkWindowAttr *attributes,
549 gint attributes_mask);
550cairo_surface_t * _gdk_offscreen_window_create_surface (GdkWindow *window,
551 gint width,
552 gint height);
553
554G_END_DECLS
555
556#endif /* __GDK_INTERNALS_H__ */
557