Back to index

lightning-sunbird  0.9+nobinonly
Defines | Functions | Variables
gtkxtbin.c File Reference
#include "gtkxtbin.h"
#include <gtk/gtkcontainer.h>
#include <gtk/gtkmain.h>
#include <gdk/gdkx.h>
#include <glib.h>
#include <assert.h>
#include <sys/time.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Shell.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>

Go to the source code of this file.

Defines

#define XTBIN_MAX_EVENTS   30

Functions

static void gtk_xtbin_class_init (GtkXtBinClass *klass)
static void gtk_xtbin_init (GtkXtBin *xtbin)
static void gtk_xtbin_realize (GtkWidget *widget)
static void gtk_xtbin_destroy (GtkObject *object)
static void gtk_xtbin_shutdown (GtkObject *object)
static void gtk_xtbin_show (GtkWidget *widget)
static gboolean xt_event_prepare (gpointer source_data, GTimeVal *current_time, gint *timeout, gpointer user_data)
static gboolean xt_event_check (gpointer source_data, GTimeVal *current_time, gpointer user_data)
static gboolean xt_event_dispatch (gpointer source_data, GTimeVal *current_time, gpointer user_data)
static gboolean xt_event_polling_timer_callback (gpointer user_data)
GtkType gtk_xtbin_get_type (void)
GtkWidget * gtk_xtbin_new (GdkWindow *parent_window, String *f)
void gtk_xtbin_set_position (GtkXtBin *xtbin, gint x, gint y)
void gtk_xtbin_resize (GtkWidget *widget, gint width, gint height)

Variables

static GtkWidgetClass * parent_class = NULL
static Stringfallback = NULL
static gboolean xt_is_initialized = FALSE
static gint num_widgets = 0
static GPollFD xt_event_poll_fd
static GSourceFuncs xt_event_funcs
static gint xt_polling_timer_id = 0

Define Documentation

Definition at line 68 of file gtkxtbin.c.


Function Documentation

static void gtk_xtbin_class_init ( GtkXtBinClass *  klass) [static]

Definition at line 208 of file gtkxtbin.c.

{
  GtkWidgetClass *widget_class;
  GtkObjectClass *object_class;

  parent_class = gtk_type_class (gtk_widget_get_type ());

  widget_class = GTK_WIDGET_CLASS (klass);
  widget_class->realize = gtk_xtbin_realize;
  widget_class->show = gtk_xtbin_show;

  object_class = GTK_OBJECT_CLASS (klass);
  object_class->shutdown= gtk_xtbin_shutdown;
  object_class->destroy = gtk_xtbin_destroy;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void gtk_xtbin_destroy ( GtkObject *  object) [static]

Definition at line 543 of file gtkxtbin.c.

{
  GtkXtBin *xtbin;

#ifdef DEBUG_XTBIN
  printf("gtk_xtbin_destroy()\n");
#endif

  g_return_if_fail (object != NULL);
  g_return_if_fail (GTK_IS_XTBIN (object));

  xtbin = GTK_XTBIN (object);

  XtDestroyWidget(xtbin->xtwidget);

  num_widgets--; /* reduce our usage count */

  /* If this is the last running widget, remove the Xt display
     connection from the mainloop */
  if (0 == num_widgets) {
    XtAppContext  ac;

#ifdef DEBUG_XTBIN
    printf("removing the Xt connection from the main loop\n");
#endif

    g_main_remove_poll(&xt_event_poll_fd);
    g_source_remove_by_user_data(xtbin->xtdisplay);

    gtk_timeout_remove(xt_polling_timer_id);
    xt_polling_timer_id = 0;

  }

  GTK_OBJECT_CLASS(parent_class)->destroy(object);
}

Here is the caller graph for this function:

GtkType gtk_xtbin_get_type ( void  )

Definition at line 183 of file gtkxtbin.c.

{
  static GtkType xtbin_type = 0;

  if (!xtbin_type)
    {
      static const GtkTypeInfo xtbin_info =
      {
        "GtkXtBin",
        sizeof (GtkXtBin),
        sizeof (GtkXtBinClass),
        (GtkClassInitFunc) gtk_xtbin_class_init,
        (GtkObjectInitFunc) gtk_xtbin_init,
        /* reserved_1 */ NULL,
        /* reserved_2 */ NULL,
        (GtkClassInitFunc) NULL
      };

      xtbin_type = gtk_type_unique (GTK_TYPE_WIDGET, &xtbin_info);
    }

  return xtbin_type;
}

Here is the call graph for this function:

static void gtk_xtbin_init ( GtkXtBin *  xtbin) [static]

Definition at line 225 of file gtkxtbin.c.

Here is the caller graph for this function:

GtkWidget* gtk_xtbin_new ( GdkWindow *  parent_window,
String f 
)

Definition at line 381 of file gtkxtbin.c.

{
  static Display *xtdisplay = NULL;

  GtkXtBin *xtbin;
  assert(parent_window != NULL);

  xtbin = gtk_type_new (GTK_TYPE_XTBIN);

  if (!xtbin)
    return (GtkWidget*)NULL;

  /* Initialize the Xt toolkit */
  if (!xt_is_initialized) {
    char         *mArgv[1];
    int           mArgc = 0;
    XtAppContext  app_context;

#ifdef DEBUG_XTBIN
    printf("starting up Xt stuff\n");
#endif
    /*
     * Initialize Xt stuff
     */

    XtToolkitInitialize();
    app_context = XtCreateApplicationContext();
    if (fallback)
      XtAppSetFallbackResources(app_context, fallback);
  
    xtdisplay = XtOpenDisplay(app_context, gdk_get_display(), NULL, 
                              "Wrapper", NULL, 0, &mArgc, mArgv);

    if (!xtdisplay) {
      /* If XtOpenDisplay failed, we can't go any further.
       *  Bail out.
       */
#ifdef DEBUG_XTBIN
      printf("gtk_xtbin_init: XtOpenDisplay() returned NULL.\n");
#endif

      gtk_type_free (GTK_TYPE_XTBIN, xtbin);
      return (GtkWidget *)NULL;
    }

    xt_is_initialized = TRUE;
  }

  /* If this is the first running widget, hook this display into the
     mainloop */
  if (0 == num_widgets) {
    int           cnumber;
    /*
     * hook Xt event loop into the glib event loop.
     */

    /* the assumption is that gtk_init has already been called */
    g_source_add (GDK_PRIORITY_EVENTS, TRUE, 
                  &xt_event_funcs, NULL, xtdisplay, (GDestroyNotify)NULL);
    
#ifdef VMS
    cnumber = XConnectionNumber(xtdisplay);
#else
    cnumber = ConnectionNumber(xtdisplay);
#endif
    xt_event_poll_fd.fd = cnumber;
    xt_event_poll_fd.events = G_IO_IN; 
    xt_event_poll_fd.revents = 0;    /* hmm... is this correct? */

    g_main_add_poll (&xt_event_poll_fd, G_PRIORITY_LOW);

    /* add a timer so that we can poll and process Xt timers */
    xt_polling_timer_id =
      gtk_timeout_add(25,
                      (GtkFunction)xt_event_polling_timer_callback,
                      xtdisplay);
  }

  /* Bump up our usage count */
  num_widgets++;

  xtbin->xtdisplay = xtdisplay;
  xtbin->parent_window = parent_window;
  if (f)
    fallback = f;

  return GTK_WIDGET (xtbin);
}

Here is the call graph for this function:

static void gtk_xtbin_realize ( GtkWidget *  widget) [static]

Definition at line 236 of file gtkxtbin.c.

{
  GdkWindowAttr attributes;
  gint          attributes_mask, n;
  GtkXtBin     *xtbin;
  Arg           args[5];
  gint          width, height;
  Widget        top_widget;
  Window        win;
  Widget        embedded;

#ifdef DEBUG_XTBIN
  printf("gtk_xtbin_realize()\n");
#endif

  g_return_if_fail (GTK_IS_XTBIN (widget));

  gdk_flush();
  xtbin = GTK_XTBIN (widget);

  if (widget->allocation.x == -1 &&
      widget->allocation.y == -1 &&
      widget->allocation.width == 1 &&
      widget->allocation.height == 1)
  {
    GtkRequisition requisition;
    GtkAllocation allocation = { 0, 0, 200, 200 };

    gtk_widget_size_request (widget, &requisition);
    if (requisition.width || requisition.height)
    {
      /* non-empty window */
      allocation.width = requisition.width;
      allocation.height = requisition.height;
    }
    gtk_widget_size_allocate (widget, &allocation);
  }

  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);

  attributes.window_type  = GDK_WINDOW_CHILD;
  attributes.x            = xtbin->x;
  attributes.y            = xtbin->y;
  attributes.width        = widget->allocation.width;
  attributes.height       = widget->allocation.height;
  attributes.wclass       = GDK_INPUT_OUTPUT;
  attributes.visual       = gdk_window_get_visual (xtbin->parent_window);
  attributes.colormap     = gdk_window_get_colormap (xtbin->parent_window);
  attributes.event_mask   = gdk_window_get_events (xtbin->parent_window);
  attributes.event_mask  |= GDK_EXPOSURE_MASK;
  attributes_mask         = GDK_WA_X      | GDK_WA_Y | 
                            GDK_WA_VISUAL | GDK_WA_COLORMAP;

  xtbin->width = attributes.width;
  xtbin->height = attributes.height;

  widget->window = gdk_window_new (xtbin->parent_window,
                                   &attributes, attributes_mask);

  /* Turn off any event catching for this window by */
  /* the Gtk/Gdk event loop... otherwise some strange */
  /* things happen */
  XSelectInput(GDK_WINDOW_XDISPLAY(widget->window), 
               GDK_WINDOW_XWINDOW(widget->window),
               0);

  gdk_window_set_user_data (widget->window, xtbin);

  widget->style = gtk_style_attach (widget->style, widget->window);
  gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);

  /* ensure all the outgoing events are flushed */
  /* before we try this crazy dual toolkit stuff */
  gdk_flush();


  /***
   * I'm sure there is a better way, but for now I'm 
   * just creating a new application shell (since it doesn't
   * need a parent widget,) and then swapping out the XWindow
   * from under it.  This seems to mostly work, but it's
   * an ugly hack.
   */

  top_widget = XtAppCreateShell("drawingArea", "Wrapper", 
                                applicationShellWidgetClass, xtbin->xtdisplay, 
                                NULL, 0);

  xtbin->xtwidget = top_widget;

  /* set size of Xt window */
  n = 0;
  XtSetArg(args[n], XtNheight, xtbin->height);n++;
  XtSetArg(args[n], XtNwidth,  xtbin->width);n++;
  XtSetValues(top_widget, args, n);

  embedded = XtVaCreateWidget("form", compositeWidgetClass, top_widget, NULL);

  n = 0;
  XtSetArg(args[n], XtNheight, xtbin->height);n++;
  XtSetArg(args[n], XtNwidth,  xtbin->width);n++;
  XtSetArg(args[n], XtNvisual, GDK_VISUAL_XVISUAL(gdk_window_get_visual( xtbin->parent_window )) ); n++;
  XtSetArg(args[n], XtNdepth, gdk_window_get_visual( xtbin->parent_window )->depth ); n++;
  XtSetArg(args[n], XtNcolormap, GDK_COLORMAP_XCOLORMAP(gdk_window_get_colormap( xtbin->parent_window)) ); n++;
  XtSetValues(embedded, args, n);

  /* Ok, here is the dirty little secret on how I am */
  /* switching the widget's XWindow to the GdkWindow's XWindow. */
  /* I should be ashamed of myself! */
  gtk_object_set_data(GTK_OBJECT(widget), "oldwindow",
                      GUINT_TO_POINTER(top_widget->core.window)); /* save it off so we can get it during destroy */

  top_widget->core.window = GDK_WINDOW_XWINDOW(widget->window);
  

  /* this little trick seems to finish initializing the widget */
#if XlibSpecificationRelease >= 6
  XtRegisterDrawable(xtbin->xtdisplay, 
                     GDK_WINDOW_XWINDOW(widget->window),
                     top_widget);
#else
  _XtRegisterWindow( GDK_WINDOW_XWINDOW(widget->window),
                     top_widget);
#endif
  
  XtRealizeWidget(embedded);
#ifdef DEBUG_XTBIN
  printf("embedded window = %li\n", XtWindow(embedded));
#endif
  XtManageChild(embedded);

  /* now fill out the xtbin info */
  xtbin->xtwindow  = XtWindow(embedded);

  /* listen to all Xt events */
  XSelectInput(xtbin->xtdisplay, 
               XtWindow(top_widget), 
               0x0FFFFF);
  XSelectInput(xtbin->xtdisplay, 
               XtWindow(embedded), 
               0x0FFFFF);
  XFlush(xtbin->xtdisplay);
}

Here is the caller graph for this function:

void gtk_xtbin_resize ( GtkWidget *  widget,
gint  width,
gint  height 
)

Definition at line 483 of file gtkxtbin.c.

{
  Arg args[2];
  GtkXtBin *xtbin = GTK_XTBIN (widget);
  Widget xtwidget = XtWindowToWidget(xtbin->xtdisplay, xtbin->xtwindow);

  XtSetArg(args[0], XtNheight, height);
  XtSetArg(args[1], XtNwidth,  width);
  XtSetValues(XtParent(xtwidget), args, 2);
}
void gtk_xtbin_set_position ( GtkXtBin *  xtbin,
gint  x,
gint  y 
)

Definition at line 471 of file gtkxtbin.c.

{
  xtbin->x = x;
  xtbin->y = y;

  if (GTK_WIDGET_REALIZED (xtbin))
    gdk_window_move (GTK_WIDGET (xtbin)->window, x, y);
}
static void gtk_xtbin_show ( GtkWidget *  widget) [static]

Definition at line 581 of file gtkxtbin.c.

{
  g_return_if_fail (widget != NULL);
  g_return_if_fail (GTK_IS_WIDGET (widget));

#ifdef DEBUG_XTBIN
  printf("gtk_xtbin_show()\n");
#endif

  if (!GTK_WIDGET_VISIBLE (widget))
  {
    GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);

    if (!GTK_WIDGET_MAPPED(widget))
      gtk_widget_map (widget);
  }
}

Here is the caller graph for this function:

static void gtk_xtbin_shutdown ( GtkObject *  object) [static]

Definition at line 497 of file gtkxtbin.c.

{
  GtkXtBin *xtbin;
  GtkWidget *widget;

#ifdef DEBUG_XTBIN
  printf("gtk_xtbin_shutdown()\n");
#endif

  /* gtk_object_destroy() will already hold a refcount on object
   */
  xtbin = GTK_XTBIN(object);
  widget = GTK_WIDGET(object);

  if (widget->parent)
    gtk_container_remove (GTK_CONTAINER (widget->parent), widget);

  GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
  if (GTK_WIDGET_REALIZED (widget)) {
#if XlibSpecificationRelease >= 6
    XtUnregisterDrawable(xtbin->xtdisplay,
                         GDK_WINDOW_XWINDOW(GTK_WIDGET(object)->window));
#else
    _XtUnregisterWindow(GDK_WINDOW_XWINDOW(GTK_WIDGET(object)->window),
                        XtWindowToWidget(xtbin->xtdisplay,
                        GDK_WINDOW_XWINDOW(GTK_WIDGET(object)->window)));
#endif

    /* flush the queue before we returning origin top_widget->core.window
       or we can get X error since the window is gone */
    XSync(xtbin->xtdisplay, False);

    xtbin->xtwidget->core.window = GPOINTER_TO_UINT(gtk_object_get_data(object, "oldwindow"));
    XtUnrealizeWidget(xtbin->xtwidget);

    gtk_widget_unrealize (widget);
  }


  gtk_object_remove_data(object, "oldwindow");

  GTK_OBJECT_CLASS(parent_class)->shutdown (object);
}

Here is the caller graph for this function:

static gboolean xt_event_check ( gpointer  source_data,
GTimeVal *  current_time,
gpointer  user_data 
) [static]

Definition at line 101 of file gtkxtbin.c.

{
  GDK_THREADS_ENTER ();

  if (xt_event_poll_fd.revents & G_IO_IN) {
    int mask;

    mask = XPending((Display *)user_data);
    
    GDK_THREADS_LEAVE ();

    return (gboolean)mask;
  }

  GDK_THREADS_LEAVE ();
  return FALSE;
}   
static gboolean xt_event_dispatch ( gpointer  source_data,
GTimeVal *  current_time,
gpointer  user_data 
) [static]

Definition at line 122 of file gtkxtbin.c.

{
  XEvent event;
  Display * display;
  XtAppContext ac;
  int i = 0;

  display = (Display *)user_data;
  ac = XtDisplayToApplicationContext(display);

  GDK_THREADS_ENTER ();

  /* Process only real X traffic here.  We only look for data on the
   * pipe, limit it to XTBIN_MAX_EVENTS and only call
   * XtAppProcessEvent so that it will look for X events.  There's no
   * timer processing here since we already have a timer callback that
   * does it.  */
  for (i=0; i < XTBIN_MAX_EVENTS && XPending(display); i++) {
    XtAppProcessEvent(ac, XtIMXEvent);
  }

  GDK_THREADS_LEAVE ();

  return TRUE;  
}
static gboolean xt_event_polling_timer_callback ( gpointer  user_data) [static]

Definition at line 160 of file gtkxtbin.c.

{
  Display * display;
  XtAppContext ac;
  int eventsToProcess = 20;

  display = (Display *)user_data;
  ac = XtDisplayToApplicationContext(display);

  /* We need to process many Xt events here. If we just process
     one event we might starve one or more Xt consumers. On the other hand
     this could hang the whole app if Xt events come pouring in. So process
     up to 20 Xt events right now and save the rest for later. This is a hack,
     but it oughta work. We *really* should have out of process plugins.
  */
  while (eventsToProcess-- && XtAppPending(ac))
    XtAppProcessEvent(ac, XtIMAll);

  /* restart the timer */
  return TRUE;
}

Here is the caller graph for this function:

static gboolean xt_event_prepare ( gpointer  source_data,
GTimeVal *  current_time,
gint *  timeout,
gpointer  user_data 
) [static]

Definition at line 86 of file gtkxtbin.c.

{   
  int mask;

  GDK_THREADS_ENTER();
  mask = XPending((Display *)user_data);
  GDK_THREADS_LEAVE();

  return (gboolean)mask;
}

Variable Documentation

String* fallback = NULL [static]

Definition at line 79 of file gtkxtbin.c.

gint num_widgets = 0 [static]

Definition at line 81 of file gtkxtbin.c.

GtkWidgetClass* parent_class = NULL [static]

Definition at line 77 of file gtkxtbin.c.

GSourceFuncs xt_event_funcs [static]
Initial value:
 {
  xt_event_prepare,
  xt_event_check,
  xt_event_dispatch,
  (GDestroyNotify)g_free
}

Definition at line 150 of file gtkxtbin.c.

GPollFD xt_event_poll_fd [static]

Definition at line 83 of file gtkxtbin.c.

gboolean xt_is_initialized = FALSE [static]

Definition at line 80 of file gtkxtbin.c.

gint xt_polling_timer_id = 0 [static]

Definition at line 157 of file gtkxtbin.c.