Esempio n. 1
0
GtkWidget *
na_tray_child_new (GdkScreen *screen,
                   Window     icon_window)
{
  XWindowAttributes window_attributes;
  Display *xdisplay;
  NaTrayChild *child;
  GdkVisual *visual;
  gboolean visual_has_alpha;
  int red_prec, green_prec, blue_prec, depth;
  int result;

  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
  g_return_val_if_fail (icon_window != None, NULL);

  xdisplay = GDK_SCREEN_XDISPLAY (screen);

  /* We need to determine the visual of the window we are embedding and create
   * the socket in the same visual.
   */

  gdk_error_trap_push ();
  result = XGetWindowAttributes (xdisplay, icon_window,
                                 &window_attributes);
  gdk_error_trap_pop_ignored ();

  if (!result) /* Window already gone */
    return NULL;

  visual = gdk_x11_screen_lookup_visual (screen,
                                         window_attributes.visual->visualid);
  if (!visual) /* Icon window is on another screen? */
    return NULL;

  child = g_object_new (NA_TYPE_TRAY_CHILD, NULL);
  child->icon_window = icon_window;

  gtk_widget_set_visual (GTK_WIDGET (child), visual);

  /* We have alpha if the visual has something other than red, green,
   * and blue */
  gdk_visual_get_red_pixel_details (visual, NULL, NULL, &red_prec);
  gdk_visual_get_green_pixel_details (visual, NULL, NULL, &green_prec);
  gdk_visual_get_blue_pixel_details (visual, NULL, NULL, &blue_prec);
  depth = gdk_visual_get_depth (visual);

  visual_has_alpha = red_prec + blue_prec + green_prec < depth;
  child->has_alpha = (visual_has_alpha &&
                      gdk_display_supports_composite (gdk_screen_get_display (screen)));

  child->composited = child->has_alpha;

  return GTK_WIDGET (child);
}
Esempio n. 2
0
static void
init_randr_support (GdkScreen *screen)
{
  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);

  XSelectInput (GDK_SCREEN_XDISPLAY (screen),
                x11_screen->xroot_window,
                StructureNotifyMask);

#ifdef HAVE_RANDR
  if (!GDK_X11_DISPLAY (gdk_screen_get_display (screen))->have_randr12)
    return;

  XRRSelectInput (GDK_SCREEN_XDISPLAY (screen),
                  x11_screen->xroot_window,
                  RRScreenChangeNotifyMask
                  | RRCrtcChangeNotifyMask
                  | RROutputPropertyNotifyMask);
#endif
}
Esempio n. 3
0
static void
gdk_x11_draw_rectangle (GdkDrawable *drawable,
			GdkGC       *gc,
			gboolean     filled,
			gint         x,
			gint         y,
			gint         width,
			gint         height)
{
  GdkDrawableImplX11 *impl;

  impl = GDK_DRAWABLE_IMPL_X11 (drawable);
  
  if (filled)
    XFillRectangle (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
		    GDK_GC_GET_XGC (gc), x, y, width, height);
  else
    XDrawRectangle (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
		    GDK_GC_GET_XGC (gc), x, y, width, height);
}
WidgetBackingStoreGtkX11::WidgetBackingStoreGtkX11(GtkWidget* widget, const IntSize& size)
    : WidgetBackingStore(size)
{
    GdkVisual* visual = gtk_widget_get_visual(widget);
    GdkScreen* screen = gdk_visual_get_screen(visual);
    m_display = GDK_SCREEN_XDISPLAY(screen);
    m_pixmap = XCreatePixmap(m_display, GDK_WINDOW_XID(gdk_screen_get_root_window(screen)),
        size.width(), size.height(), gdk_visual_get_depth(visual));
    m_gc = XCreateGC(m_display, m_pixmap, 0, 0);

    m_surface = adoptRef(cairo_xlib_surface_create(m_display, m_pixmap,
        GDK_VISUAL_XVISUAL(visual), size.width(), size.height()));
}
Esempio n. 5
0
static void
gdk_x11_drawable_update_picture_clip (GdkDrawable *drawable,
				      GdkGC       *gc)
{
  GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
  Display *xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
  Picture picture = gdk_x11_drawable_get_picture (drawable);
  GdkRegion *clip_region = gc ? _gdk_gc_get_clip_region (gc) : NULL;

  if (clip_region)
    {
      GdkRegionBox *boxes = clip_region->rects;
      gint n_boxes = clip_region->numRects;
      XRectangle *rects = g_new (XRectangle, n_boxes);
      int i;

      for (i=0; i < n_boxes; i++)
	{
	  rects[i].x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
	  rects[i].y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
	  rects[i].width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rects[i].x;
	  rects[i].height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rects[i].y;
	}
      
      XRenderSetPictureClipRectangles (xdisplay, picture,
				       0, 0, rects, n_boxes);
      
      g_free (rects);
    }
  else
    {
      XRenderPictureAttributes pa;
      GdkBitmap *mask;
      gulong pa_mask;

      pa_mask = CPClipMask;
      if (gc && (mask = _gdk_gc_get_clip_mask (gc)))
	{
	  pa.clip_mask = GDK_PIXMAP_XID (mask);
	  pa.clip_x_origin = gc->clip_x_origin;
	  pa.clip_y_origin = gc->clip_y_origin;
	  pa_mask |= CPClipXOrigin | CPClipYOrigin;
	}
      else
	pa.clip_mask = None;

      XRenderChangePicture (xdisplay, picture,
			    pa_mask, &pa);
    }
}
Esempio n. 6
0
static void
gdk_x11_draw_text_wc (GdkDrawable    *drawable,
		      GdkFont	     *font,
		      GdkGC	     *gc,
		      gint	      x,
		      gint	      y,
		      const GdkWChar *text,
		      gint	      text_length)
{
  GdkDrawableImplX11 *impl;
  Display *xdisplay;

  impl = GDK_DRAWABLE_IMPL_X11 (drawable);
  xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
  
  if (font->type == GDK_FONT_FONT)
    {
      XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
      gchar *text_8bit;
      gint i;
      XSetFont(xdisplay, GDK_GC_GET_XGC (gc), xfont->fid);
      text_8bit = g_new (gchar, text_length);
      for (i=0; i<text_length; i++) text_8bit[i] = text[i];
      XDrawString (xdisplay, impl->xid,
                   GDK_GC_GET_XGC (gc), x, y, text_8bit, text_length);
      g_free (text_8bit);
    }
  else if (font->type == GDK_FONT_FONTSET)
    {
      if (sizeof(GdkWChar) == sizeof(wchar_t))
	{
	  XwcDrawString (xdisplay, impl->xid,
			 (XFontSet) GDK_FONT_XFONT (font),
			 GDK_GC_GET_XGC (gc), x, y, (wchar_t *)text, text_length);
	}
      else
	{
	  wchar_t *text_wchar;
	  gint i;
	  text_wchar = g_new (wchar_t, text_length);
	  for (i=0; i<text_length; i++) text_wchar[i] = text[i];
	  XwcDrawString (xdisplay, impl->xid,
			 (XFontSet) GDK_FONT_XFONT (font),
			 GDK_GC_GET_XGC (gc), x, y, text_wchar, text_length);
	  g_free (text_wchar);
	}
    }
  else
Esempio n. 7
0
static gboolean
init_xfree_xinerama (GdkScreen *screen)
{
#ifdef HAVE_XFREE_XINERAMA
  Display *dpy = GDK_SCREEN_XDISPLAY (screen);
  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
  XineramaScreenInfo *monitors;
  int i, n_monitors;
  
  if (!XineramaIsActive (dpy))
    return FALSE;

  monitors = XineramaQueryScreens (dpy, &n_monitors);
  
  if (n_monitors <= 0 || monitors == NULL)
    {
      /* If Xinerama doesn't think we have any monitors, try acting as
       * though we had no Xinerama. If the "no monitors" condition
       * is because XRandR 1.2 is currently switching between CRTCs,
       * we'll be notified again when we have our monitor back,
       * and can go back into Xinerama-ish mode at that point.
       */
      if (monitors)
	XFree (monitors);
      
      return FALSE;
    }

  x11_screen->n_monitors = n_monitors;
  x11_screen->monitors = g_new0 (GdkX11Monitor, n_monitors);
  
  for (i = 0; i < n_monitors; ++i)
    {
      init_monitor_geometry (&x11_screen->monitors[i],
			     monitors[i].x_org, monitors[i].y_org,
			     monitors[i].width, monitors[i].height);
    }
  
  XFree (monitors);
  
  x11_screen->primary_monitor = 0;

  return TRUE;
#endif /* HAVE_XFREE_XINERAMA */
  
  return FALSE;
}
Esempio n. 8
0
/**
 * _gdk_x11_drawable_finish:
 * @drawable: a #GdkDrawableImplX11.
 * 
 * Performs necessary cleanup prior to freeing a pixmap or
 * destroying a window.
 **/
void
_gdk_x11_drawable_finish (GdkDrawable *drawable)
{
  GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
  
  if (impl->picture)
    {
      XRenderFreePicture (GDK_SCREEN_XDISPLAY (impl->screen),
			  impl->picture);
      impl->picture = None;
    }
  
  if (impl->cairo_surface)
    {
      cairo_surface_finish (impl->cairo_surface);
      cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
				   NULL, NULL);
    }
}
Esempio n. 9
0
static gboolean
init_solaris_xinerama (GdkScreen *screen)
{
#ifdef HAVE_SOLARIS_XINERAMA
  Display *dpy = GDK_SCREEN_XDISPLAY (screen);
  int screen_no = gdk_screen_get_number (screen);
  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
  XRectangle monitors[MAXFRAMEBUFFERS];
  unsigned char hints[16];
  gint result;
  int n_monitors;
  int i;
  
  if (!XineramaGetState (dpy, screen_no))
    return FALSE;

  result = XineramaGetInfo (dpy, screen_no, monitors, hints, &n_monitors);

  /* Yes I know it should be Success but the current implementation 
   * returns the num of monitor
   */
  if (result == 0)
    {
      return FALSE;
    }

  x11_screen->monitors = g_new0 (GdkX11Monitor, n_monitors);
  x11_screen->n_monitors = n_monitors;

  for (i = 0; i < n_monitors; i++)
    {
      init_monitor_geometry (&x11_screen->monitors[i],
			     monitors[i].x, monitors[i].y,
			     monitors[i].width, monitors[i].height);
    }

  x11_screen->primary_monitor = 0;

  return TRUE;
#endif /* HAVE_SOLARIS_XINERAMA */

  return FALSE;
}
Esempio n. 10
0
static void
init_multihead (GdkScreen *screen)
{
  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
  int opcode, firstevent, firsterror;

  /* There are four different implementations of multihead support: 
   *
   *  1. Fake Xinerama for debugging purposes
   *  2. RandR 1.2
   *  3. Solaris Xinerama
   *  4. XFree86/Xorg Xinerama
   *
   * We use them in that order.
   */
  if (init_fake_xinerama (screen))
    return;

  if (init_randr13 (screen))
    return;

  if (XQueryExtension (GDK_SCREEN_XDISPLAY (screen), "XINERAMA",
		       &opcode, &firstevent, &firsterror))
    {
      if (init_solaris_xinerama (screen))
	return;
      
      if (init_xfree_xinerama (screen))
	return;
    }

  /* No multihead support of any kind for this screen */
  x11_screen->n_monitors = 1;
  x11_screen->monitors = g_new0 (GdkX11Monitor, 1);
  x11_screen->primary_monitor = 0;

  init_monitor_geometry (x11_screen->monitors, 0, 0,
			 WidthOfScreen (x11_screen->xscreen),
			 HeightOfScreen (x11_screen->xscreen));
}
Esempio n. 11
0
static GdkRegion *
window_get_shape (GdkScreen       *screen,
                  GdkNativeWindow  window)
{
  GdkRegion  *shape = NULL;

#if defined(GDK_WINDOWING_X11) && defined(HAVE_X11_EXTENSIONS_SHAPE_H)
  XRectangle *rects;
  gint        rect_count;
  gint        rect_order;

  rects = XShapeGetRectangles (GDK_SCREEN_XDISPLAY (screen), window,
                               ShapeBounding,
                               &rect_count, &rect_order);

  if (rects)
    {
      if (rect_count > 1)
        {
          gint i;

          shape = gdk_region_new ();

          for (i = 0; i < rect_count; i++)
            {
              GdkRectangle rect = { rects[i].x,
                                    rects[i].y,
                                    rects[i].width,
                                    rects[i].height };

              gdk_region_union_with_rect (shape, &rect);
            }
        }

      XFree (rects);
    }
#endif

  return shape;
}
Esempio n. 12
0
/* gdk_x11_draw_text
 *
 * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
 *
 * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
 */
static void
gdk_x11_draw_text (GdkDrawable *drawable,
		   GdkFont     *font,
		   GdkGC       *gc,
		   gint         x,
		   gint         y,
		   const gchar *text,
		   gint         text_length)
{
  GdkDrawableImplX11 *impl;
  Display *xdisplay;

  impl = GDK_DRAWABLE_IMPL_X11 (drawable);
  xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
  
  if (font->type == GDK_FONT_FONT)
    {
      XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
      XSetFont(xdisplay, GDK_GC_GET_XGC (gc), xfont->fid);
      if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
	{
	  XDrawString (xdisplay, impl->xid,
		       GDK_GC_GET_XGC (gc), x, y, text, text_length);
	}
      else
	{
	  XDrawString16 (xdisplay, impl->xid,
			 GDK_GC_GET_XGC (gc), x, y, (XChar2b *) text, text_length / 2);
	}
    }
  else if (font->type == GDK_FONT_FONTSET)
    {
      XFontSet fontset = (XFontSet) GDK_FONT_XFONT (font);
      XmbDrawString (xdisplay, impl->xid,
		     fontset, GDK_GC_GET_XGC (gc), x, y, text, text_length);
    }
  else
    g_error("undefined font type\n");
}
Esempio n. 13
0
GtkWidget *
na_tray_child_new (GdkScreen *screen,
                   Window     icon_window)
{
  XWindowAttributes window_attributes;
  Display *xdisplay;
  NaTrayChild *child;
  GdkVisual *visual;
  gboolean visual_has_alpha;
  GdkColormap *colormap;
  gboolean new_colormap;
  int result;

  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
  g_return_val_if_fail (icon_window != None, NULL);

  xdisplay = GDK_SCREEN_XDISPLAY (screen);

  /* We need to determine the visual of the window we are embedding and create
   * the socket in the same visual.
   */

  gdk_error_trap_push ();
  result = XGetWindowAttributes (xdisplay, icon_window,
                                 &window_attributes);
  gdk_error_trap_pop ();

  if (!result) /* Window already gone */
    return NULL;

  visual = gdk_x11_screen_lookup_visual (screen,
                                         window_attributes.visual->visualid);
  if (!visual) /* Icon window is on another screen? */
    return NULL;

  new_colormap = FALSE;

  if (visual == gdk_screen_get_rgb_visual (screen))
    colormap = gdk_screen_get_rgb_colormap (screen);
  else if (visual == gdk_screen_get_rgba_visual (screen))
    colormap = gdk_screen_get_rgba_colormap (screen);
  else if (visual == gdk_screen_get_system_visual (screen))
    colormap = gdk_screen_get_system_colormap (screen);
  else
    {
      colormap = gdk_colormap_new (visual, FALSE);
      new_colormap = TRUE;
    }

  child = g_object_new (NA_TYPE_TRAY_CHILD, NULL);
  child->icon_window = icon_window;

  gtk_widget_set_colormap (GTK_WIDGET (child), colormap);

  /* We have alpha if the visual has something other than red, green,
   * and blue */
  visual_has_alpha = visual->red_prec + visual->blue_prec + visual->green_prec < visual->depth;
  child->has_alpha = (visual_has_alpha &&
		      gdk_display_supports_composite (gdk_screen_get_display (screen)));

  child->composited = child->has_alpha;

  if (new_colormap)
    g_object_unref (colormap);

  return GTK_WIDGET (child);
}
Esempio n. 14
0
static GdkNativeWindow
select_window_x11 (GdkScreen *screen)
{
  Display      *x_dpy       = GDK_SCREEN_XDISPLAY (screen);
  gint          x_scr       = GDK_SCREEN_XNUMBER (screen);
  Window        x_root      = RootWindow (x_dpy, x_scr);
  Window        x_win       = None;
  GC            x_gc          = None;
  Cursor        x_cursor    = XCreateFontCursor (x_dpy, GDK_CROSSHAIR);
  GdkKeymapKey *keys        = NULL;
  gint          status;
  gint          i, num_keys;
  gint          buttons     = 0;
  gint          mask        = ButtonPressMask | ButtonReleaseMask;
  gboolean      cancel      = FALSE;

  if (shootvals.shoot_type == SHOOT_REGION)
    mask |= PointerMotionMask;

  status = XGrabPointer (x_dpy, x_root, False,
                         mask, GrabModeSync, GrabModeAsync,
                         x_root, x_cursor, CurrentTime);

  if (status != GrabSuccess)
    {
      gint  x, y;
      guint xmask;

      /* if we can't grab the pointer, return the window under the pointer */
      XQueryPointer (x_dpy, x_root, &x_root, &x_win, &x, &y, &x, &y, &xmask);

      if (x_win == None || x_win == x_root)
        g_message (_("Error selecting the window"));
    }

  if (shootvals.shoot_type == SHOOT_REGION)
    {
      XGCValues gc_values;

      gc_values.function           = GXxor;
      gc_values.plane_mask         = AllPlanes;
      gc_values.foreground         = WhitePixel (x_dpy, x_scr);
      gc_values.background         = BlackPixel (x_dpy, x_scr);
      gc_values.line_width         = 0;
      gc_values.line_style         = LineSolid;
      gc_values.fill_style         = FillSolid;
      gc_values.cap_style          = CapButt;
      gc_values.join_style         = JoinMiter;
      gc_values.graphics_exposures = FALSE;
      gc_values.clip_x_origin      = 0;
      gc_values.clip_y_origin      = 0;
      gc_values.clip_mask          = None;
      gc_values.subwindow_mode     = IncludeInferiors;

      x_gc = XCreateGC (x_dpy, x_root,
                        GCFunction | GCPlaneMask | GCForeground | GCLineWidth |
                        GCLineStyle | GCCapStyle | GCJoinStyle |
                        GCGraphicsExposures | GCBackground | GCFillStyle |
                        GCClipXOrigin | GCClipYOrigin | GCClipMask |
                        GCSubwindowMode,
                        &gc_values);
    }

  if (gdk_keymap_get_entries_for_keyval (NULL, GDK_Escape, &keys, &num_keys))
    {
      gdk_error_trap_push ();

#define X_GRAB_KEY(index, modifiers) \
      XGrabKey (x_dpy, keys[index].keycode, modifiers, x_root, False, \
                GrabModeAsync, GrabModeAsync)

      for (i = 0; i < num_keys; i++)
        {
          X_GRAB_KEY (i, 0);
          X_GRAB_KEY (i, LockMask);            /* CapsLock              */
          X_GRAB_KEY (i, Mod2Mask);            /* NumLock               */
          X_GRAB_KEY (i, Mod5Mask);            /* ScrollLock            */
          X_GRAB_KEY (i, LockMask | Mod2Mask); /* CapsLock + NumLock    */
          X_GRAB_KEY (i, LockMask | Mod5Mask); /* CapsLock + ScrollLock */
          X_GRAB_KEY (i, Mod2Mask | Mod5Mask); /* NumLock  + ScrollLock */
          X_GRAB_KEY (i, LockMask | Mod2Mask | Mod5Mask); /* all        */
        }

#undef X_GRAB_KEY

      gdk_flush ();
      gdk_error_trap_pop ();
    }

  while (! cancel && ((x_win == None) || (buttons != 0)))
    {
      XEvent x_event;
      gint   x, y, w, h;

      XAllowEvents (x_dpy, SyncPointer, CurrentTime);
      XWindowEvent (x_dpy, x_root, mask | KeyPressMask, &x_event);

      switch (x_event.type)
        {
        case ButtonPress:
          if (x_win == None)
            {
              x_win = x_event.xbutton.subwindow;

              if (x_win == None)
                x_win = x_root;
#ifdef HAVE_X11_XMU_WINUTIL_H
              else if (! shootvals.decorate)
                x_win = XmuClientWindow (x_dpy, x_win);
#endif

              shootvals.x2 = shootvals.x1 = x_event.xbutton.x_root;
              shootvals.y2 = shootvals.y1 = x_event.xbutton.y_root;
            }

          buttons++;
          break;

        case ButtonRelease:
          if (buttons > 0)
            buttons--;

          if (! buttons && shootvals.shoot_type == SHOOT_REGION)
            {
              x = MIN (shootvals.x1, shootvals.x2);
              y = MIN (shootvals.y1, shootvals.y2);
              w = ABS (shootvals.x2 - shootvals.x1);
              h = ABS (shootvals.y2 - shootvals.y1);

              if (w > 0 && h > 0)
                XDrawRectangle (x_dpy, x_root, x_gc, x, y, w, h);

              shootvals.x2 = x_event.xbutton.x_root;
              shootvals.y2 = x_event.xbutton.y_root;
            }
          break;

        case MotionNotify:
          if (buttons > 0)
            {
              x = MIN (shootvals.x1, shootvals.x2);
              y = MIN (shootvals.y1, shootvals.y2);
              w = ABS (shootvals.x2 - shootvals.x1);
              h = ABS (shootvals.y2 - shootvals.y1);

              if (w > 0 && h > 0)
                XDrawRectangle (x_dpy, x_root, x_gc, x, y, w, h);

              shootvals.x2 = x_event.xmotion.x_root;
              shootvals.y2 = x_event.xmotion.y_root;

              x = MIN (shootvals.x1, shootvals.x2);
              y = MIN (shootvals.y1, shootvals.y2);
              w = ABS (shootvals.x2 - shootvals.x1);
              h = ABS (shootvals.y2 - shootvals.y1);

              if (w > 0 && h > 0)
                XDrawRectangle (x_dpy, x_root, x_gc, x, y, w, h);
            }
          break;

        case KeyPress:
          {
            guint *keyvals;
            gint   n;

            if (gdk_keymap_get_entries_for_keycode (NULL, x_event.xkey.keycode,
                                                    NULL, &keyvals, &n))
              {
                gint i;

                for (i = 0; i < n && ! cancel; i++)
                  if (keyvals[i] == GDK_Escape)
                    cancel = TRUE;

                g_free (keyvals);
              }
          }
          break;

        default:
          break;
        }
    }

  if (keys)
    {
#define X_UNGRAB_KEY(index, modifiers) \
      XUngrabKey (x_dpy, keys[index].keycode, modifiers, x_root)

      for (i = 0; i < num_keys; i++)
        {
          X_UNGRAB_KEY (i, 0);
          X_UNGRAB_KEY (i, LockMask);            /* CapsLock              */
          X_UNGRAB_KEY (i, Mod2Mask);            /* NumLock               */
          X_UNGRAB_KEY (i, Mod5Mask);            /* ScrollLock            */
          X_UNGRAB_KEY (i, LockMask | Mod2Mask); /* CapsLock + NumLock    */
          X_UNGRAB_KEY (i, LockMask | Mod5Mask); /* CapsLock + ScrollLock */
          X_UNGRAB_KEY (i, Mod2Mask | Mod5Mask); /* NumLock  + ScrollLock */
          X_UNGRAB_KEY (i, LockMask | Mod2Mask | Mod5Mask); /* all        */
        }
#undef X_UNGRAB_KEY

      g_free (keys);
    }

  if (status == GrabSuccess)
    XUngrabPointer (x_dpy, CurrentTime);

  XFreeCursor (x_dpy, x_cursor);

  if (x_gc != None)
    XFreeGC (x_dpy, x_gc);

  return x_win;
}
Esempio n. 15
0
void
gdk_x11_screen_get_work_area (GdkX11Screen *x11_screen,
                              GdkRectangle *area)
{
  Atom            workarea;
  Atom            type;
  Window          win;
  int             format;
  gulong          num;
  gulong          leftovers;
  gulong          max_len = 4 * 32;
  guchar         *ret_workarea = NULL;
  long           *workareas;
  int             result;
  int             desktop;
  Display        *display;

  display = GDK_SCREEN_XDISPLAY (x11_screen);
  workarea = XInternAtom (display, "_NET_WORKAREA", True);

  /* Defaults in case of error */
  area->x = 0;
  area->y = 0;
  area->width = WidthOfScreen (x11_screen->xscreen);
  area->height = HeightOfScreen (x11_screen->xscreen);

  if (!gdk_x11_screen_supports_net_wm_hint (x11_screen,
                                            g_intern_static_string ("_NET_WORKAREA")))
    return;

  if (workarea == None)
    return;

  win = XRootWindow (display, gdk_x11_screen_get_screen_number (x11_screen));
  result = XGetWindowProperty (display,
                               win,
                               workarea,
                               0,
                               max_len,
                               False,
                               AnyPropertyType,
                               &type,
                               &format,
                               &num,
                               &leftovers,
                               &ret_workarea);
  if (result != Success ||
      type == None ||
      format == 0 ||
      leftovers ||
      num % 4 != 0)
    goto out;

  desktop = get_current_desktop (x11_screen);
  if (desktop + 1 > num / 4) /* fvwm gets this wrong */
    goto out;

  workareas = (long *) ret_workarea;
  area->x = workareas[desktop * 4];
  area->y = workareas[desktop * 4 + 1];
  area->width = workareas[desktop * 4 + 2];
  area->height = workareas[desktop * 4 + 3];

  area->x /= x11_screen->surface_scale;
  area->y /= x11_screen->surface_scale;
  area->width /= x11_screen->surface_scale;
  area->height /= x11_screen->surface_scale;

out:
  if (ret_workarea)
    XFree (ret_workarea);
}
Esempio n. 16
0
static void instance_init( GbdX11emitter* self ) {
	self->priv = G_TYPE_INSTANCE_GET_PRIVATE( self,GBD_TYPE_X11EMITTER,GbdX11emitterPrivate );

	g_datalist_init( &self->priv->mapcache );
	self->priv->dpy = GDK_SCREEN_XDISPLAY( gdk_screen_get_default( ) );
}
Esempio n. 17
0
gboolean vfs_exec_on_screen( GdkScreen* screen,
                             const char* work_dir,
                             char** argv, char** envp,
                             const char* disp_name,
                             GSpawnFlags flags,
                             GError **err )
{
#ifdef HAVE_SN
    SnLauncherContext * ctx = NULL;
    SnDisplay* display;
#endif
    gboolean ret;
    GSpawnChildSetupFunc setup_func = NULL;
    extern char **environ;
    char** new_env = envp;
    int i, n_env = 0;
    char* display_name;
    int display_index = -1, startup_id_index = -1;

    if ( ! envp )
        envp = environ;

    n_env = g_strv_length(envp);

    new_env = g_new0( char*, n_env + 4 );
    for ( i = 0; i < n_env; ++i )
    {
        /* g_debug( "old envp[%d] = \"%s\"" , i, envp[i]); */
        if ( 0 == strncmp( envp[ i ], "DISPLAY=", 8 ) )
            display_index = i;
        else
        {
            if ( 0 == strncmp( envp[ i ], "DESKTOP_STARTUP_ID=", 19 ) )
                startup_id_index = i;
            new_env[i] = g_strdup( envp[ i ] );
        }
    }

#ifdef HAVE_SN
    display = sn_display_new ( GDK_SCREEN_XDISPLAY ( screen ),
                               ( SnDisplayErrorTrapPush ) gdk_error_trap_push,
                               ( SnDisplayErrorTrapPush ) gdk_error_trap_pop );
    if ( G_LIKELY ( display ) )
    {
        if ( !disp_name )
            disp_name = argv[ 0 ];

        ctx = sn_launcher_context_new( display, gdk_screen_get_number( screen ) );

        sn_launcher_context_set_description( ctx, disp_name );
        sn_launcher_context_set_name( ctx, g_get_prgname() );
        sn_launcher_context_set_binary_name( ctx, argv[ 0 ] );

        sn_launcher_context_set_workspace ( ctx, tvsn_get_active_workspace_number( screen ) );

        /* FIXME: I don't think this is correct, other people seem to use CurrentTime here.
                  However, using CurrentTime causes problems, so I so it like this.
                  Maybe this is incorrect, but it works, so, who cares?
        */
        /* time( &cur_time ); */
        sn_launcher_context_initiate( ctx, g_get_prgname(),
                                      argv[ 0 ], gtk_get_current_event_time() /*cur_time*/ );

        setup_func = (GSpawnChildSetupFunc) sn_launcher_context_setup_child_process;
        if( startup_id_index >= 0 )
            g_free( new_env[i] );
        else
            startup_id_index = i++;
        new_env[ startup_id_index ] = g_strconcat( "DESKTOP_STARTUP_ID=",
                                      sn_launcher_context_get_startup_id ( ctx ), NULL );
    }
#endif

    /* This is taken from gdk_spawn_on_screen */
    display_name = gdk_screen_make_display_name ( screen );
    if ( display_index >= 0 )
        new_env[ display_index ] = g_strconcat( "DISPLAY=", display_name, NULL );
    else
        new_env[ i++ ] = g_strconcat( "DISPLAY=", display_name, NULL );

    g_free( display_name );
    new_env[ i ] = NULL;

    ret = g_spawn_async( work_dir,
                         argv,  new_env,
                         flags,
                         NULL, NULL,
                         NULL, err );

    /* for debugging */
#if 0
    g_debug( "debug vfs_execute_on_screen(): flags: %d, display_index=%d", flags, display_index );
    for( i = 0; argv[i]; ++i ) {
        g_debug( "argv[%d] = \"%s\"" , i, argv[i] );
    }
    for( i = 0; i < n_env /*new_env[i]*/; ++i ) {
        g_debug( "new_env[%d] = \"%s\"" , i, new_env[i] );
    }
    if( ret )
        g_debug( "the program was executed without error" );
    else
        g_debug( "launch failed: %s", (*err)->message );
#endif

    g_strfreev( new_env );

#ifdef HAVE_SN
    if ( G_LIKELY ( ctx ) )
    {
        if ( G_LIKELY ( ret ) )
            g_timeout_add ( 20 * 1000, sn_timeout, ctx );
        else
        {
            sn_launcher_context_complete ( ctx );
            sn_launcher_context_unref ( ctx );
        }
    }

    if ( G_LIKELY ( display ) )
        sn_display_unref ( display );
#endif

    return ret;
}
Esempio n. 18
0
static void
init_xft_settings (GdkScreen *screen)
{
  GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
  Display *xdisplay = GDK_SCREEN_XDISPLAY (screen);
  int xscreen = GDK_SCREEN_XNUMBER (screen);
  double dpi_double;

  if (screen_x11->xft_init)
    return;

  screen_x11->xft_init = TRUE;

  if (!get_boolean_default (xdisplay, "antialias", &screen_x11->xft_antialias))
    screen_x11->xft_antialias = TRUE;

  if (!get_boolean_default (xdisplay, "hinting", &screen_x11->xft_hinting))
    screen_x11->xft_hinting = TRUE;

  if (!get_integer_default (xdisplay, "hintstyle", &screen_x11->xft_hintstyle))
    screen_x11->xft_hintstyle = FC_HINT_FULL;

  if (!get_integer_default (xdisplay, "rgba", &screen_x11->xft_rgba))
			    
    {
      int subpixel = FC_RGBA_UNKNOWN;
      
#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
      if (_gdk_x11_have_render (screen_x11->display))
	{
	  int render_order = XRenderQuerySubpixelOrder (xdisplay, xscreen);
	  
	  switch (render_order)
	    {
	    default:
	    case SubPixelUnknown:
	      subpixel = FC_RGBA_UNKNOWN;
	      break;
	    case SubPixelHorizontalRGB:
	      subpixel = FC_RGBA_RGB;
	      break;
	    case SubPixelHorizontalBGR:
	      subpixel = FC_RGBA_BGR;
	      break;
	    case SubPixelVerticalRGB:
	      subpixel = FC_RGBA_VRGB;
	      break;
	    case SubPixelVerticalBGR:
	      subpixel = FC_RGBA_VBGR;
	      break;
	    case SubPixelNone:
	      subpixel = FC_RGBA_NONE;
	      break;
	    }
	}
#endif

      screen_x11->xft_rgba = subpixel;
    }

  if (!get_double_default (xdisplay, "dpi", &dpi_double))
    dpi_double = (((double) DisplayHeight (xdisplay, xscreen) * 25.4) / 
		  (double) DisplayHeightMM (xdisplay, xscreen));

  screen_x11->xft_dpi = (int)(0.5 + PANGO_SCALE * dpi_double);
}
Esempio n. 19
0
/*
 * draw_border_shape
 * Returns: void
 * Description: Draws a slight border around the decoration
 */
static void
draw_border_shape (Display	   *xdisplay,
		   Pixmap	   pixmap,
		   Picture	   picture,
		   int		   width,
		   int		   height,
		   decor_context_t *c,
		   void		   *closure)
{
    static XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
    decor_t		d;
    decor_shadow_info_t *info = (decor_shadow_info_t *) closure;
    double		save_decoration_alpha;
    GdkScreen           *screen;

    memset (&d, 0, sizeof (d));

    if (info)
    {
	gwd_decor_frame_ref (info->frame);

	d.frame = info->frame;
	d.state = info->state;
	d.actions = info->active;
    }
    else
    {
	d.frame = gwd_get_decor_frame ("normal");
	d.state = 0;
	d.active = TRUE;
    }

    screen = gdk_screen_get_default ();

    d.surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (screen),
                                           pixmap,
                                           GDK_VISUAL_XVISUAL (gdk_screen_get_rgba_visual (screen)),
                                           width,
                                           height);
    d.width   = width;
    d.height  = height;
    d.active  = TRUE;
    d.draw    = theme_draw_window_decoration;
    d.picture = picture;
    d.context = c;

    /* we use closure argument if maximized */
    if (info)
	d.state = info->state;
    else
	d.state = 0;

    decor_get_default_layout (c, 1, 1, &d.border_layout);

    /* create shadow from opaque decoration
     * FIXME: Should not modify settings value
     * like this */
    save_decoration_alpha = decoration_alpha;
    decoration_alpha = 1.0;

    (*d.draw) (&d);

    decoration_alpha = save_decoration_alpha;

    XRenderFillRectangle (xdisplay, PictOpSrc, picture, &white,
			  c->left_space,
			  c->top_space,
			  width - c->left_space - c->right_space,
			  height - c->top_space - c->bottom_space);

    if (!info)
	gwd_decor_frame_unref (d.frame);

    cairo_surface_destroy (d.surface);
}
Esempio n. 20
0
/* Returns NULL if screen could not be created.  For instance, if
 * the driver does not support Xrandr 1.2.
 */
MateRRScreen *
mate_rr_screen_new (GdkScreen *gdk_screen,
		     MateRRScreenChanged callback,
		     gpointer data,
		     GError **error)
{
#ifdef HAVE_RANDR
    Display *dpy = GDK_SCREEN_XDISPLAY (gdk_screen);
    int event_base;
    int ignore;
#endif

    g_return_val_if_fail (error == NULL || *error == NULL, NULL);
    
    _mate_desktop_init_i18n ();

#ifdef HAVE_RANDR
    if (XRRQueryExtension (dpy, &event_base, &ignore))
    {
	MateRRScreen *screen = g_new0 (MateRRScreen, 1);
	
	screen->gdk_screen = gdk_screen;
	screen->gdk_root = gdk_screen_get_root_window (gdk_screen);
	screen->xroot = gdk_x11_drawable_get_xid (screen->gdk_root);
	screen->xdisplay = dpy;
	screen->xscreen = gdk_x11_screen_get_xscreen (screen->gdk_screen);
	screen->connector_type_atom = XInternAtom (dpy, "ConnectorType", FALSE);
	
	screen->callback = callback;
	screen->data = data;
	
	screen->randr_event_base = event_base;

	XRRQueryVersion (dpy, &screen->rr_major_version, &screen->rr_minor_version);
	if (screen->rr_major_version > 1 || (screen->rr_major_version == 1 && screen->rr_minor_version < 2)) {
	    g_set_error (error, MATE_RR_ERROR, MATE_RR_ERROR_NO_RANDR_EXTENSION,
			 "RANDR extension is too old (must be at least 1.2)");
	    g_free (screen);
	    return NULL;
	}

	screen->info = screen_info_new (screen, TRUE, error);
	
	if (!screen->info) {
	    g_free (screen);
	    return NULL;
	}

	if (screen->callback) {
	    XRRSelectInput (screen->xdisplay,
			    screen->xroot,
			    RRScreenChangeNotifyMask);

	    gdk_x11_register_standard_event_type (gdk_screen_get_display (gdk_screen),
						  event_base,
						  RRNotify + 1);

	    gdk_window_add_filter (screen->gdk_root, screen_on_event, screen);
	}

	return screen;
    }
    else
    {
#endif /* HAVE_RANDR */
	g_set_error (error, MATE_RR_ERROR, MATE_RR_ERROR_NO_RANDR_EXTENSION,
		     _("RANDR extension is not present"));
	
	return NULL;
#ifdef HAVE_RANDR
   }
#endif
}
Esempio n. 21
0
static void widget_realized (void)
{
    GdkWindow * window = gtk_widget_get_window (s_widget);

#ifdef GDK_WINDOWING_X11
    GdkScreen * screen = gdk_window_get_screen (window);
    int nscreen = GDK_SCREEN_XNUMBER (screen);

    s_display = GDK_SCREEN_XDISPLAY (screen);
    s_xwindow = GDK_WINDOW_XID (window);

    /* Create s_context */
    int attribs[] = {
     GLX_RGBA,
     GLX_RED_SIZE, 1,
     GLX_GREEN_SIZE, 1,
     GLX_BLUE_SIZE, 1,
     GLX_ALPHA_SIZE, 1,
     GLX_DOUBLEBUFFER,
     GLX_DEPTH_SIZE, 1,
     None
    };

    XVisualInfo * xvinfo = glXChooseVisual (s_display, nscreen, attribs);
    g_return_if_fail (xvinfo);

    /* Fix up visual/colormap */
    GdkVisual * visual = gdk_x11_screen_lookup_visual (screen, xvinfo->visualid);
    g_return_if_fail (visual);

    gtk_widget_set_visual (s_widget, visual);

    s_context = glXCreateContext (s_display, xvinfo, 0, True);
    g_return_if_fail (s_context);

    XFree (xvinfo);

    glXMakeCurrent (s_display, s_xwindow, s_context);
#endif

#ifdef GDK_WINDOWING_WIN32
    s_hwnd = GDK_WINDOW_HWND (window);
    s_hdc = GetDC (s_hwnd);

    PIXELFORMATDESCRIPTOR desc = {
     sizeof (PIXELFORMATDESCRIPTOR),
     1,                                 // version number (?)
     PFD_DRAW_TO_WINDOW |               // format must support window
     PFD_SUPPORT_OPENGL |               // format must support OpenGL
     PFD_DOUBLEBUFFER,                  // must support double buffering
     PFD_TYPE_RGBA,                     // request an RGBA format
     24,                                // select a 8:8:8 bit color depth
     0, 0, 0, 0, 0, 0,                  // color bits ignored (?)
     0,                                 // no alpha buffer
     0,                                 // shift bit ignored (?)
     0,                                 // no accumulation buffer
     0, 0, 0, 0,                        // accumulation bits ignored (?)
     16,                                // 16-bit z-buffer (depth buffer)
     0,                                 // no stencil buffer
     0,                                 // no auxiliary buffer (?)
     PFD_MAIN_PLANE,                    // main drawing layer
     0,                                 // reserved (?)
     0, 0, 0                            // layer masks ignored (?)
    };

    int format = ChoosePixelFormat (s_hdc, & desc);
    g_return_if_fail (format != 0);

    SetPixelFormat (s_hdc, format, & desc);

    s_glrc = wglCreateContext (s_hdc);
    g_return_if_fail (s_glrc);

    wglMakeCurrent (s_hdc, s_glrc);
#endif
}
Esempio n. 22
0
static gboolean
panel_multiscreen_get_randr_monitors_for_screen (GdkScreen     *screen,
						 int           *monitors_ret,
						 GdkRectangle **geometries_ret)
{
#ifdef HAVE_RANDR
	Display            *xdisplay;
	Window              xroot;
	XRRScreenResources *resources;
	RROutput            primary;
	GArray             *geometries;
	int                 i;
	gboolean            driver_is_pre_randr_1_2;

	if (!have_randr)
		return FALSE;

	/* GTK+ 2.14.x uses the Xinerama API, instead of RANDR, to get the
	 * monitor geometries. It does this to avoid calling
	 * XRRGetScreenResources(), which is slow as it re-detects all the
	 * monitors --- note that XRRGetScreenResourcesCurrent() had not been
	 * introduced yet.  Using Xinerama in GTK+ has the bad side effect that
	 * gdk_screen_get_monitor_plug_name() will return NULL, as Xinerama
	 * does not provide that information, unlike RANDR.
	 *
	 * Here we need to identify the output names, so that we can put the
	 * built-in LCD in a laptop *before* all other outputs.  This is so
	 * that mate-panel will normally prefer to appear on the "native"
	 * display rather than on an external monitor.
	 *
	 * To get the output names and geometries, we will not use
	 * gdk_screen_get_n_monitors() and friends, but rather we will call
	 * XRR*() directly.
	 *
	 * See https://bugzilla.novell.com/show_bug.cgi?id=479684 for this
	 * particular bug, and and
	 * http://bugzilla.gnome.org/show_bug.cgi?id=562944 for a more
	 * long-term solution.
	 */

	xdisplay = GDK_SCREEN_XDISPLAY (screen);
#if GTK_CHECK_VERSION (3, 0, 0)
	xroot = GDK_WINDOW_XID (gdk_screen_get_root_window (screen));
#else
	xroot = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
#endif

#if (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
	if (have_randr_1_3) {
		resources = XRRGetScreenResourcesCurrent (xdisplay, xroot);
		if (resources->noutput == 0) {
			/* This might happen if nothing tried to get randr
			 * resources from the server before, so we need an
			 * active probe. See comment #27 in
			 * https://bugzilla.gnome.org/show_bug.cgi?id=597101 */
			XRRFreeScreenResources (resources);
			resources = XRRGetScreenResources (xdisplay, xroot);
		}
	} else
		resources = XRRGetScreenResources (xdisplay, xroot);
#else
	resources = XRRGetScreenResources (xdisplay, xroot);
#endif

	if (!resources)
		return FALSE;

	primary = None;
#if (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
	if (have_randr_1_3)
		primary = XRRGetOutputPrimary (xdisplay, xroot);
#endif

	geometries = g_array_sized_new (FALSE, FALSE,
					sizeof (GdkRectangle),
					resources->noutput);

	driver_is_pre_randr_1_2 = FALSE;

	for (i = 0; i < resources->noutput; i++) {
		XRROutputInfo *output;

		output = XRRGetOutputInfo (xdisplay, resources,
					   resources->outputs[i]);

		/* Drivers before RANDR 1.2 return "default" for the output
		 * name */
		if (g_strcmp0 (output->name, "default") == 0)
			driver_is_pre_randr_1_2 = TRUE;

		if (output->connection != RR_Disconnected &&
		    output->crtc != 0) {
			XRRCrtcInfo  *crtc;
			GdkRectangle  rect;

			crtc = XRRGetCrtcInfo (xdisplay, resources,
					       output->crtc);

			rect.x	    = crtc->x;
			rect.y	    = crtc->y;
			rect.width  = crtc->width;
			rect.height = crtc->height;

			XRRFreeCrtcInfo (crtc);

			if (_panel_multiscreen_output_should_be_first (xdisplay,
								       resources->outputs[i],
								       output, primary))
				g_array_prepend_vals (geometries, &rect, 1);
			else
				g_array_append_vals (geometries, &rect, 1);
		}

		XRRFreeOutputInfo (output);
	}

	XRRFreeScreenResources (resources);

	if (driver_is_pre_randr_1_2) {
		/* Drivers before RANDR 1.2 don't provide useful info about
		 * outputs */
		g_array_free (geometries, TRUE);
		return FALSE;
	}

	if (geometries->len == 0) {
		/* This can happen in at least one case:
		 * https://bugzilla.novell.com/show_bug.cgi?id=543876 where all
		 * monitors appear disconnected (possibly because the  screen
		 * is behing a KVM switch) -- see comment #8.
		 * There might be other cases too, so we stay on the safe side.
		 */
		g_array_free (geometries, TRUE);
		return FALSE;
	}

	*monitors_ret = geometries->len;
	*geometries_ret = (GdkRectangle *) g_array_free (geometries, FALSE);

	return TRUE;
#else
	return FALSE;
#endif
}
static GdkNativeWindow
select_window (GdkScreen *screen)
{
#define MASK (ButtonPressMask | ButtonReleaseMask)

  Display    *x_dpy;
  Cursor      x_cursor;
  XEvent      x_event;
  Window      x_win;
  Window      x_root;
  gint        x_scr;
  gint        status;
  gint        buttons;

  x_dpy = GDK_SCREEN_XDISPLAY (screen);
  x_scr = GDK_SCREEN_XNUMBER (screen);

  x_win    = None;
  x_root   = RootWindow (x_dpy, x_scr);
  x_cursor = XCreateFontCursor (x_dpy, GDK_CROSSHAIR);
  buttons  = 0;

  status = XGrabPointer (x_dpy, x_root, False,
                         MASK, GrabModeSync, GrabModeAsync,
                         x_root, x_cursor, CurrentTime);

  if (status != GrabSuccess)
    {
      g_message (_("Error grabbing the pointer %d"), status);
      return 0;
    }

  while ((x_win == None) || (buttons != 0))
    {
      XAllowEvents (x_dpy, SyncPointer, CurrentTime);
      XWindowEvent (x_dpy, x_root, MASK, &x_event);

      switch (x_event.type)
        {
        case ButtonPress:
          if (x_win == None)
            {
              x_win = x_event.xbutton.subwindow;
              if (x_win == None)
                x_win = x_root;
            }
          buttons++;
          break;

        case ButtonRelease:
          if (buttons > 0)
            buttons--;
          break;

        default:
          g_assert_not_reached ();
        }
    }

  XUngrabPointer (x_dpy, CurrentTime);
  XFreeCursor (x_dpy, x_cursor);

  return x_win;
}
Esempio n. 24
0
static gboolean
init_randr13 (GdkScreen *screen)
{
#ifdef HAVE_RANDR
  GdkDisplay *display = gdk_screen_get_display (screen);
  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
  Display *dpy = GDK_SCREEN_XDISPLAY (screen);
  XRRScreenResources *resources;
  RROutput primary_output;
  RROutput first_output = None;
  int i;
  GArray *monitors;
  gboolean randr12_compat = FALSE;

  if (!display_x11->have_randr13)
      return FALSE;

  resources = XRRGetScreenResourcesCurrent (x11_screen->xdisplay,
				            x11_screen->xroot_window);
  if (!resources)
    return FALSE;

  monitors = g_array_sized_new (FALSE, TRUE, sizeof (GdkX11Monitor),
                                resources->noutput);

  for (i = 0; i < resources->noutput; ++i)
    {
      XRROutputInfo *output =
	XRRGetOutputInfo (dpy, resources, resources->outputs[i]);

      /* Non RandR1.2 X driver have output name "default" */
      randr12_compat |= !g_strcmp0 (output->name, "default");

      if (output->connection == RR_Disconnected)
        {
          XRRFreeOutputInfo (output);
          continue;
        }

      if (output->crtc)
	{
	  GdkX11Monitor monitor;
	  XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, output->crtc);

	  monitor.geometry.x = crtc->x;
	  monitor.geometry.y = crtc->y;
	  monitor.geometry.width = crtc->width;
	  monitor.geometry.height = crtc->height;

	  monitor.output = resources->outputs[i];
	  monitor.width_mm = output->mm_width;
	  monitor.height_mm = output->mm_height;
	  monitor.output_name = g_strdup (output->name);
	  /* FIXME: need EDID parser */
	  monitor.manufacturer = NULL;

	  g_array_append_val (monitors, monitor);

          XRRFreeCrtcInfo (crtc);
	}

      XRRFreeOutputInfo (output);
    }

  if (resources->noutput > 0)
    first_output = resources->outputs[0];

  XRRFreeScreenResources (resources);

  /* non RandR 1.2 X driver doesn't return any usable multihead data */
  if (randr12_compat)
    {
      guint n_monitors = monitors->len;

      free_monitors ((GdkX11Monitor *)g_array_free (monitors, FALSE),
		     n_monitors);

      return FALSE;
    }

  g_array_sort (monitors,
                (GCompareFunc) monitor_compare_function);
  x11_screen->n_monitors = monitors->len;
  x11_screen->monitors = (GdkX11Monitor *)g_array_free (monitors, FALSE);

  x11_screen->primary_monitor = 0;

  primary_output = XRRGetOutputPrimary (x11_screen->xdisplay,
                                        x11_screen->xroot_window);

  for (i = 0; i < x11_screen->n_monitors; ++i)
    {
      if (x11_screen->monitors[i].output == primary_output)
	{
	  x11_screen->primary_monitor = i;
	  break;
	}

      /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */
      if (primary_output == None &&
          g_ascii_strncasecmp (x11_screen->monitors[i].output_name, "LVDS", 4) == 0)
	{
	  x11_screen->primary_monitor = i;
	  break;
	}

      /* No primary specified and no LVDS found */
      if (x11_screen->monitors[i].output == first_output)
	x11_screen->primary_monitor = i;
    }

  return x11_screen->n_monitors > 0;
#endif

  return FALSE;
}