Better error message when defaults file is missing.
[xfwm4.git] / src / display.c
blob69d4a646e1499ac1badad68cb0b09c0e44908990
1 /* $Id$
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 xfwm4 - (c) 2002-2007 Olivier Fourdan
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
25 #include <X11/X.h>
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
28 #include <X11/cursorfont.h>
29 #include <X11/extensions/shape.h>
30 #include <glib.h>
31 #include <gdk/gdk.h>
32 #include <gdk/gdkx.h>
33 #include <gtk/gtk.h>
34 #include <libxfce4util/libxfce4util.h>
35 #ifdef HAVE_RENDER
36 #include <X11/extensions/Xrender.h>
37 #endif
39 #include "spinning_cursor.h"
40 #include "display.h"
41 #include "screen.h"
42 #include "client.h"
43 #include "compositor.h"
45 #ifndef MAX_HOSTNAME_LENGTH
46 #define MAX_HOSTNAME_LENGTH 32
47 #endif /* MAX_HOSTNAME_LENGTH */
49 #ifndef CURSOR_ROOT
50 #define CURSOR_ROOT XC_left_ptr
51 #endif
53 #ifndef CURSOR_MOVE
54 #define CURSOR_MOVE XC_fleur
55 #endif
57 static int
58 handleXError (Display * dpy, XErrorEvent * err)
60 #if DEBUG
61 char buf[64];
63 XGetErrorText (dpy, err->error_code, buf, 63);
64 g_print ("XError: %s\n", buf);
65 g_print ("==> XID 0x%lx, Request %d, Error %d <==\n",
66 err->resourceid, err->request_code, err->error_code);
67 #endif
68 return 0;
71 static gboolean
72 myDisplayInitAtoms (DisplayInfo *display_info)
74 static const char *atom_names[] = {
75 "COMPOSITING_MANAGER",
76 "GNOME_PANEL_DESKTOP_AREA",
77 "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
78 "KWM_WIN_ICON",
79 "_MOTIF_WM_HINTS",
80 "_MOTIF_WM_INFO",
81 "_NET_ACTIVE_WINDOW",
82 "_NET_CLIENT_LIST",
83 "_NET_CLIENT_LIST_STACKING",
84 "_NET_CLOSE_WINDOW",
85 "_NET_CURRENT_DESKTOP",
86 "_NET_DESKTOP_GEOMETRY",
87 "_NET_DESKTOP_LAYOUT",
88 "_NET_DESKTOP_NAMES",
89 "_NET_DESKTOP_VIEWPORT",
90 "_NET_FRAME_EXTENTS",
91 "_NET_NUMBER_OF_DESKTOPS",
92 "_NET_REQUEST_FRAME_EXTENTS",
93 "_NET_SHOWING_DESKTOP",
94 "_NET_STARTUP_ID",
95 "_NET_SUPPORTED",
96 "_NET_SUPPORTING_WM_CHECK",
97 "_NET_SYSTEM_TRAY_OPCODE",
98 "_NET_WM_ACTION_CHANGE_DESKTOP",
99 "_NET_WM_ACTION_CLOSE",
100 "_NET_WM_ACTION_MAXIMIZE_HORZ",
101 "_NET_WM_ACTION_MAXIMIZE_VERT",
102 "_NET_WM_ACTION_MOVE",
103 "_NET_WM_ACTION_RESIZE",
104 "_NET_WM_ACTION_SHADE",
105 "_NET_WM_ACTION_STICK",
106 "_NET_WM_ALLOWED_ACTIONS",
107 "_NET_WM_CONTEXT_HELP",
108 "_NET_WM_DESKTOP",
109 "_NET_WM_ICON",
110 "_NET_WM_ICON_GEOMETRY",
111 "_NET_WM_ICON_NAME",
112 "_NET_WM_MOVERESIZE",
113 "_NET_WM_NAME",
114 "_NET_WM_WINDOW_OPACITY",
115 "_NET_WM_WINDOW_OPACITY_LOCKED",
116 "_NET_WM_STATE",
117 "_NET_WM_STATE_ABOVE",
118 "_NET_WM_STATE_BELOW",
119 "_NET_WM_STATE_DEMANDS_ATTENTION",
120 "_NET_WM_STATE_FULLSCREEN",
121 "_NET_WM_STATE_HIDDEN",
122 "_NET_WM_STATE_MAXIMIZED_HORZ",
123 "_NET_WM_STATE_MAXIMIZED_VERT",
124 "_NET_WM_STATE_MODAL",
125 "_NET_WM_STATE_SHADED",
126 "_NET_WM_STATE_SKIP_PAGER",
127 "_NET_WM_STATE_SKIP_TASKBAR",
128 "_NET_WM_STATE_STICKY",
129 "_NET_WM_STRUT",
130 "_NET_WM_STRUT_PARTIAL",
131 "_NET_WM_SYNC_REQUEST",
132 "_NET_WM_SYNC_REQUEST_COUNTER",
133 "_NET_WM_USER_TIME",
134 "_NET_WM_WINDOW_TYPE",
135 "_NET_WM_WINDOW_TYPE_DESKTOP",
136 "_NET_WM_WINDOW_TYPE_DIALOG",
137 "_NET_WM_WINDOW_TYPE_DOCK",
138 "_NET_WM_WINDOW_TYPE_MENU",
139 "_NET_WM_WINDOW_TYPE_NORMAL",
140 "_NET_WM_WINDOW_TYPE_SPLASH",
141 "_NET_WM_WINDOW_TYPE_TOOLBAR",
142 "_NET_WM_WINDOW_TYPE_UTILITY",
143 "_NET_WORKAREA",
144 "MANAGER",
145 "PIXMAP",
146 "SM_CLIENT_ID",
147 "UTF8_STRING",
148 "_WIN_CLIENT_LIST",
149 "_WIN_DESKTOP_BUTTON_PROXY",
150 "_WIN_HINTS",
151 "_WIN_LAYER",
152 "_WIN_PROTOCOLS",
153 "_WIN_STATE",
154 "_WIN_SUPPORTING_WM_CHECK",
155 "_WIN_WORKSPACE",
156 "_WIN_WORKSPACE_COUNT",
157 "WM_CHANGE_STATE",
158 "WM_CLIENT_LEADER",
159 "WM_CLIENT_MACHINE",
160 "WM_COLORMAP_WINDOWS",
161 "WM_DELETE_WINDOW",
162 "WM_HINTS",
163 "WM_PROTOCOLS",
164 "WM_STATE",
165 "WM_TAKE_FOCUS",
166 "WM_TRANSIENT_FOR",
167 "WM_WINDOW_ROLE",
168 "XFWM4_COMPOSITING_MANAGER",
169 "XFWM4_TIMESTAMP_PROP",
170 "_XROOTPMAP_ID",
171 "_XSETROOT_ID"
174 g_assert (ATOM_COUNT == G_N_ELEMENTS (atom_names));
175 return (XInternAtoms (display_info->dpy,
176 (char **) atom_names,
177 ATOM_COUNT,
178 FALSE, display_info->atoms) != 0);
181 static void
182 myDisplayCreateTimestampWin (DisplayInfo *display_info)
184 XSetWindowAttributes attributes;
186 attributes.event_mask = PropertyChangeMask;
187 attributes.override_redirect = TRUE;
188 display_info->timestamp_win =
189 XCreateWindow (display_info->dpy, DefaultRootWindow (display_info->dpy),
190 -100, -100, 10, 10, 0, 0, CopyFromParent, CopyFromParent,
191 CWEventMask | CWOverrideRedirect, &attributes);
194 DisplayInfo *
195 myDisplayInit (GdkDisplay *gdisplay)
197 DisplayInfo *display;
198 int major, minor;
199 int dummy;
201 display = g_new0 (DisplayInfo, 1);
203 display->gdisplay = gdisplay;
204 display->dpy = (Display *) gdk_x11_display_get_xdisplay (gdisplay);
206 display->session = NULL;
207 display->quit = FALSE;
208 display->reload = FALSE;
210 XSetErrorHandler (handleXError);
212 /* Initialize internal atoms */
213 if (!myDisplayInitAtoms (display))
215 g_warning ("Some internal atoms were not properly created.");
218 /* Test XShape extension support */
219 major = 0;
220 minor = 0;
221 display->shape_version = 0;
222 if (XShapeQueryExtension (display->dpy,
223 &display->shape_event_base,
224 &dummy))
226 display->have_shape = TRUE;
227 if (XShapeQueryVersion (display->dpy, &major, &minor))
229 display->shape_version = major * 1000 + minor;
232 else
234 g_warning ("The display does not support the XShape extension.");
235 display->have_shape = FALSE;
236 display->shape_event_base = 0;
239 #ifdef HAVE_XSYNC
240 display->have_xsync = FALSE;
242 display->xsync_error_base = 0;
243 display->xsync_event_base = 0;
245 major = SYNC_MAJOR_VERSION;
246 minor = SYNC_MINOR_VERSION;
248 if (XSyncQueryExtension (display->dpy,
249 &display->xsync_event_base,
250 &display->xsync_error_base)
251 && XSyncInitialize (display->dpy,
252 &major,
253 &minor))
255 display->have_xsync = TRUE;
257 else
259 g_warning ("The display does not support the XSync extension.");
260 display->have_xsync = FALSE;
261 display->xsync_event_base = 0;
262 display->xsync_error_base = 0;
264 #endif /* HAVE_XSYNC */
266 #ifdef HAVE_RENDER
267 if (XRenderQueryExtension (display->dpy,
268 &display->render_event_base,
269 &display->render_error_base))
271 display->have_render = TRUE;
273 else
275 g_warning ("The display does not support the XRender extension.");
276 display->have_render = FALSE;
277 display->render_event_base = 0;
278 display->render_error_base = 0;
280 #else /* HAVE_RENDER */
281 display->have_render = FALSE;
282 #endif /* HAVE_RENDER */
284 #ifdef HAVE_RANDR
285 if (XRRQueryExtension (display->dpy,
286 &display->xrandr_event_base,
287 &display->xrandr_error_base))
289 display->have_xrandr = TRUE;
291 else
293 g_warning ("The display does not support the XRandr extension.");
294 display->have_xrandr = FALSE;
295 display->xrandr_event_base = 0;
296 display->xrandr_error_base = 0;
298 #else /* HAVE_RANDR */
299 display->have_xrandr = FALSE;
300 #endif /* HAVE_RANDR */
302 display->root_cursor =
303 XCreateFontCursor (display->dpy, CURSOR_ROOT);
304 display->move_cursor =
305 XCreateFontCursor (display->dpy, CURSOR_MOVE);
306 display->busy_cursor =
307 cursorCreateSpinning (display->dpy);
308 display->resize_cursor[CORNER_TOP_LEFT] =
309 XCreateFontCursor (display->dpy, XC_top_left_corner);
310 display->resize_cursor[CORNER_TOP_RIGHT] =
311 XCreateFontCursor (display->dpy, XC_top_right_corner);
312 display->resize_cursor[CORNER_BOTTOM_LEFT] =
313 XCreateFontCursor (display->dpy, XC_bottom_left_corner);
314 display->resize_cursor[CORNER_BOTTOM_RIGHT] =
315 XCreateFontCursor (display->dpy, XC_bottom_right_corner);
316 display->resize_cursor[CORNER_COUNT + SIDE_LEFT] =
317 XCreateFontCursor (display->dpy, XC_left_side);
318 display->resize_cursor[CORNER_COUNT + SIDE_RIGHT] =
319 XCreateFontCursor (display->dpy, XC_right_side);
320 display->resize_cursor[CORNER_COUNT + SIDE_TOP] =
321 XCreateFontCursor (display->dpy, XC_top_side);
322 display->resize_cursor[CORNER_COUNT + SIDE_BOTTOM] =
323 XCreateFontCursor (display->dpy, XC_bottom_side);
325 myDisplayCreateTimestampWin (display);
327 display->xfilter = NULL;
328 display->screens = NULL;
329 display->clients = NULL;
330 display->xgrabcount = 0;
331 display->dbl_click_time = 300;
332 display->nb_screens = 0;
333 display->current_time = CurrentTime;
335 display->hostname = g_new0 (gchar, (size_t) MAX_HOSTNAME_LENGTH);
336 if (gethostname ((char *) display->hostname, MAX_HOSTNAME_LENGTH - 1))
338 g_free (display->hostname);
339 display->hostname = NULL;
342 compositorInitDisplay (display);
344 return display;
347 DisplayInfo *
348 myDisplayClose (DisplayInfo *display)
350 int i;
352 XFreeCursor (display->dpy, display->busy_cursor);
353 display->busy_cursor = None;
354 XFreeCursor (display->dpy, display->move_cursor);
355 display->move_cursor = None;
356 XFreeCursor (display->dpy, display->root_cursor);
357 display->root_cursor = None;
358 XDestroyWindow (display->dpy, display->timestamp_win);
359 display->timestamp_win = None;
361 if (display->hostname)
363 g_free (display->hostname);
364 display->hostname = NULL;
367 for (i = 0; i < SIDE_COUNT + CORNER_COUNT; i++)
369 XFreeCursor (display->dpy, display->resize_cursor[i]);
370 display->resize_cursor[i] = None;
373 g_slist_free (display->clients);
374 display->clients = NULL;
376 g_slist_free (display->screens);
377 display->screens = NULL;
379 return display;
382 gboolean
383 myDisplayHaveShape (DisplayInfo *display)
385 g_return_val_if_fail (display != NULL, FALSE);
387 return (display->have_shape);
390 gboolean
391 myDisplayHaveRender (DisplayInfo *display)
393 g_return_val_if_fail (display != NULL, FALSE);
395 return (display->have_render);
398 Cursor
399 myDisplayGetCursorBusy (DisplayInfo *display)
401 g_return_val_if_fail (display, None);
403 return display->busy_cursor;
406 Cursor
407 myDisplayGetCursorMove (DisplayInfo *display)
409 g_return_val_if_fail (display, None);
411 return display->move_cursor;
414 Cursor
415 myDisplayGetCursorRoot (DisplayInfo *display)
417 g_return_val_if_fail (display, None);
419 return display->root_cursor;
422 Cursor
423 myDisplayGetCursorResize (DisplayInfo *display, guint index)
425 g_return_val_if_fail (display, None);
426 g_return_val_if_fail (index < 8, None);
428 return display->resize_cursor [index];
432 void
433 myDisplayGrabServer (DisplayInfo *display)
435 g_return_if_fail (display);
437 DBG ("entering myDisplayGrabServer");
438 if (display->xgrabcount == 0)
440 DBG ("grabbing server");
441 XGrabServer (display->dpy);
443 display->xgrabcount++;
444 DBG ("grabs : %i", display->xgrabcount);
447 void
448 myDisplayUngrabServer (DisplayInfo *display)
450 g_return_if_fail (display);
452 DBG ("entering myDisplayUngrabServer");
453 display->xgrabcount = display->xgrabcount - 1;
454 if (display->xgrabcount < 0) /* should never happen */
456 display->xgrabcount = 0;
458 if (display->xgrabcount == 0)
460 DBG ("ungrabbing server");
461 XUngrabServer (display->dpy);
462 XFlush (display->dpy);
464 DBG ("grabs : %i", display->xgrabcount);
467 void
468 myDisplayAddClient (DisplayInfo *display, Client *c)
470 g_return_if_fail (c != None);
471 g_return_if_fail (display != NULL);
473 display->clients = g_slist_append (display->clients, c);
476 void
477 myDisplayRemoveClient (DisplayInfo *display, Client *c)
479 g_return_if_fail (c != None);
480 g_return_if_fail (display != NULL);
482 display->clients = g_slist_remove (display->clients, c);
485 Client *
486 myDisplayGetClientFromWindow (DisplayInfo *display, Window w, unsigned short mode)
488 GSList *index;
490 g_return_val_if_fail (w != None, NULL);
491 g_return_val_if_fail (display != NULL, NULL);
493 for (index = display->clients; index; index = g_slist_next (index))
495 Client *c = (Client *) index->data;
496 if (clientGetFromWindow (c, w, mode))
498 return (c);
501 TRACE ("no client found");
503 return NULL;
506 void
507 myDisplayAddScreen (DisplayInfo *display, ScreenInfo *screen)
509 g_return_if_fail (screen != NULL);
510 g_return_if_fail (display != NULL);
512 display->screens = g_slist_append (display->screens, screen);
513 display->nb_screens = display->nb_screens + 1;
516 void
517 myDisplayRemoveScreen (DisplayInfo *display, ScreenInfo *screen)
519 g_return_if_fail (screen != NULL);
520 g_return_if_fail (display != NULL);
522 display->screens = g_slist_remove (display->screens, screen);
523 display->nb_screens = display->nb_screens - 1;
524 if (display->nb_screens < 0)
526 display->nb_screens = 0;
530 ScreenInfo *
531 myDisplayGetScreenFromRoot (DisplayInfo *display, Window root)
533 GSList *index;
535 g_return_val_if_fail (root != None, NULL);
536 g_return_val_if_fail (display != NULL, NULL);
538 for (index = display->screens; index; index = g_slist_next (index))
540 ScreenInfo *screen = (ScreenInfo *) index->data;
541 if (screen->xroot == root)
543 return screen;
546 TRACE ("myDisplayGetScreenFromRoot: no screen found");
548 return NULL;
551 ScreenInfo *
552 myDisplayGetScreenFromNum (DisplayInfo *display, int num)
554 GSList *index;
556 g_return_val_if_fail (display != NULL, NULL);
558 for (index = display->screens; index; index = g_slist_next (index))
560 ScreenInfo *screen = (ScreenInfo *) index->data;
561 if (screen->screen == num)
563 return screen;
566 TRACE ("myDisplayGetScreenFromNum: no screen found");
568 return NULL;
571 Window
572 myDisplayGetRootFromWindow(DisplayInfo *display, Window w)
574 XWindowAttributes attributes;
576 g_return_val_if_fail (w != None, None);
577 g_return_val_if_fail (display != NULL, None);
579 if (!XGetWindowAttributes(display->dpy, w, &attributes))
581 TRACE ("myDisplayGetRootFromWindow: no root found for 0x%lx", w);
582 return None;
584 return attributes.root;
587 ScreenInfo *
588 myDisplayGetScreenFromWindow (DisplayInfo *display, Window w)
590 Window root;
592 g_return_val_if_fail (w != None, NULL);
593 g_return_val_if_fail (display != NULL, NULL);
595 root = myDisplayGetRootFromWindow (display, w);
596 if (root != None)
598 return myDisplayGetScreenFromRoot (display, root);
600 TRACE ("myDisplayGetScreenFromWindow: no screen found");
602 return NULL;
605 #ifdef ENABLE_KDE_SYSTRAY_PROXY
606 ScreenInfo *
607 myDisplayGetScreenFromSystray (DisplayInfo *display, Window w)
609 GSList *index;
611 g_return_val_if_fail (w != None, NULL);
612 g_return_val_if_fail (display != NULL, NULL);
614 for (index = display->screens; index; index = g_slist_next (index))
616 ScreenInfo *screen = (ScreenInfo *) index->data;
617 if (screen->systray == w)
619 return screen;
622 TRACE ("myDisplayGetScreenFromSystray: no screen found");
624 return NULL;
626 #endif /* ENABLE_KDE_SYSTRAY_PROXY */
628 #ifdef HAVE_XSYNC
629 Client *
630 myDisplayGetClientFromXSyncAlarm (DisplayInfo *display, XSyncAlarm alarm)
632 GSList *index;
634 g_return_val_if_fail (alarm != None, NULL);
635 g_return_val_if_fail (display != NULL, NULL);
637 for (index = display->clients; index; index = g_slist_next (index))
639 Client *c = (Client *) index->data;
640 if (alarm == c->xsync_alarm)
642 return (c);
645 TRACE ("no client found");
647 return NULL;
649 #endif /* HAVE_XSYNC */
651 ScreenInfo *
652 myDisplayGetDefaultScreen (DisplayInfo *display)
654 GSList *index;
656 g_return_val_if_fail (display != NULL, NULL);
658 index = display->screens;
659 if (index)
661 return (ScreenInfo *) index->data;
664 return NULL;
667 Time
668 myDisplayUpdateCurrentTime (DisplayInfo *display, XEvent *ev)
670 g_return_val_if_fail (display != NULL, (Time) CurrentTime);
672 switch (ev->type)
674 case KeyPress:
675 case KeyRelease:
676 display->current_time = (Time) ev->xkey.time;
677 break;
678 case ButtonPress:
679 case ButtonRelease:
680 display->current_time = (Time) ev->xbutton.time;
681 break;
682 case MotionNotify:
683 display->current_time = (Time) ev->xmotion.time;
684 break;
685 case EnterNotify:
686 case LeaveNotify:
687 display->current_time = (Time) ev->xcrossing.time;
688 break;
689 case PropertyNotify:
690 display->current_time = (Time) ev->xproperty.time;
691 break;
692 case SelectionClear:
693 display->current_time = (Time) ev->xselectionclear.time;
694 break;
695 case SelectionRequest:
696 display->current_time = (Time) ev->xselectionrequest.time;
697 break;
698 case SelectionNotify:
699 display->current_time = (Time) ev->xselection.time;
700 break;
701 default:
702 display->current_time = (Time) CurrentTime;
703 break;
705 return display->current_time;
708 Time
709 myDisplayGetCurrentTime (DisplayInfo *display)
711 g_return_val_if_fail (display != NULL, (Time) CurrentTime);
713 TRACE ("myDisplayGetCurrentTime gives timestamp=%u", (unsigned int) display->current_time);
714 return (Time) display->current_time;
717 Time
718 myDisplayGetTime (DisplayInfo * display, Time timestamp)
720 Time time;
722 time = timestamp;
723 if (time == (Time) CurrentTime)
725 time = getXServerTime (display);
728 TRACE ("myDisplayGetTime gives timestamp=%u", (unsigned int) time);
729 return (time);
732 Time
733 myDisplayGetLastUserTime (DisplayInfo *display)
735 g_return_val_if_fail (display != NULL, (Time) CurrentTime);
737 TRACE ("myDisplayGetLastUserTime gives timestamp=%u", (unsigned int) display->last_user_time);
738 return (Time) display->last_user_time;
741 void
742 myDisplaySetLastUserTime (DisplayInfo *display, Time timestamp)
744 g_return_if_fail (display != NULL);
746 if (TIMESTAMP_IS_BEFORE(display->last_user_time, timestamp))
748 display->last_user_time = timestamp;
752 gboolean
753 myDisplayTestXrender (DisplayInfo *display, gdouble min_time)
755 #ifdef HAVE_RENDER
756 GTimeVal t1, t2;
757 gdouble dt;
758 Display *dpy;
759 Picture picture1, picture2, picture3;
760 XRenderPictFormat *format_src, *format_dst;
761 Pixmap fillPixmap, rootPixmap;
762 XRenderPictureAttributes pa;
763 XSetWindowAttributes attrs;
764 XImage *ximage;
765 Window output;
766 XRenderColor c;
767 Visual *visual;
768 Screen *screen;
769 int x, y, w, h;
770 int screen_number;
771 int depth;
772 int iterations;
774 g_return_val_if_fail (display != NULL, FALSE);
775 TRACE ("entering myDisplayTesxrender");
777 c.alpha = 0x7FFF;
778 c.red = 0xFFFF;
779 c.green = 0xFFFF;
780 c.blue = 0xFFFF;
782 dpy = display->dpy;
783 screen_number = DefaultScreen (dpy);
784 screen = DefaultScreenOfDisplay (dpy);
785 visual = DefaultVisual (dpy, screen_number);
786 depth = DefaultDepth (dpy, screen_number);
788 w = WidthOfScreen(screen) / 16;
789 h = HeightOfScreen(screen) / 16;
790 x = (WidthOfScreen(screen) - w);
791 y = (HeightOfScreen(screen) - h);
793 format_dst = XRenderFindVisualFormat (dpy, visual);
794 g_return_val_if_fail (format_dst != NULL , FALSE);
796 format_src = XRenderFindStandardFormat (dpy, PictStandardA8);
797 g_return_val_if_fail (format_src != NULL , FALSE);
799 ximage = XGetImage (dpy,
800 DefaultRootWindow(dpy),
801 x, y, w, h,
802 AllPlanes, ZPixmap);
803 g_return_val_if_fail (ximage != NULL , FALSE);
805 rootPixmap = XCreatePixmap (dpy,
806 DefaultRootWindow(dpy),
807 w, h, depth);
808 XPutImage (dpy, rootPixmap,
809 DefaultGC (dpy, screen_number), ximage,
810 0, 0, 0, 0, w, h);
811 XDestroyImage (ximage);
813 attrs.override_redirect = TRUE;
814 output = XCreateWindow (dpy,
815 DefaultRootWindow(dpy),
816 x, y, w, h,
817 0, CopyFromParent, CopyFromParent,
818 (Visual *) CopyFromParent,
819 CWOverrideRedirect, &attrs);
820 XMapRaised (dpy, output);
822 fillPixmap = XCreatePixmap (dpy,
823 DefaultRootWindow(dpy),
824 1, 1, 8);
826 g_get_current_time (&t1);
828 pa.repeat = TRUE;
829 picture1 = XRenderCreatePicture (dpy,
830 rootPixmap,
831 format_dst, 0, NULL);
832 picture2 = XRenderCreatePicture (dpy,
833 fillPixmap,
834 format_src, CPRepeat, &pa);
835 picture3 = XRenderCreatePicture (dpy,
836 output,
837 format_dst, 0, NULL);
838 XRenderComposite (dpy, PictOpSrc,
839 picture1, None, picture3,
840 0, 0, 0, 0, 0, 0, w, h);
841 XRenderFillRectangle (dpy, PictOpSrc,
842 picture2, &c, 0, 0,
843 1, 1);
844 for (iterations = 0; iterations < 10; iterations++)
846 XRenderComposite (dpy, PictOpOver,
847 picture1, picture2, picture3,
848 0, 0, 0, 0, 0, 0, w, h);
849 ximage = XGetImage (dpy, output,
850 0, 0, 1, 1,
851 AllPlanes, ZPixmap);
852 if (ximage)
854 XDestroyImage (ximage);
857 XRenderFreePicture (dpy, picture1);
858 XRenderFreePicture (dpy, picture2);
859 XRenderFreePicture (dpy, picture3);
861 XFreePixmap (dpy, fillPixmap);
862 XFreePixmap (dpy, rootPixmap);
864 XDestroyWindow (dpy, output);
866 g_get_current_time (&t2);
868 dt = (gdouble) (t2.tv_sec - t1.tv_sec) * G_USEC_PER_SEC +
869 (gdouble) (t2.tv_usec - t1.tv_usec) / 1000.0;
871 if (dt < min_time)
873 TRACE ("XRender test passed (target %3.4f sec., measured %3.4f sec.).", min_time, dt);
874 return TRUE;
876 g_print ("XRender test failed (target %3.4f sec., measured %3.4f sec.).\n", min_time, dt);
877 return FALSE;
878 #else /* HAVE_RENDER */
879 return FALSE;
880 #endif /* HAVE_RENDER */