LCOV - code coverage report
Current view: top level - widget/gtkxtbin - gtk2xtbin.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 306 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 29 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * vim: set expandtab shiftwidth=2 tabstop=2: */
       3             :  
       4             : /* This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       7             :  
       8             : /*
       9             :  * The GtkXtBin widget allows for Xt toolkit code to be used
      10             :  * inside a GTK application.  
      11             :  */
      12             : 
      13             : #include "xembed.h"
      14             : #include "gtk2xtbin.h"
      15             : #include <gtk/gtk.h>
      16             : #include <gdk/gdkx.h>
      17             : #include <glib.h>
      18             : #include <assert.h>
      19             : #include <sys/time.h>
      20             : #include <sys/types.h>
      21             : #include <stdio.h>
      22             : #include <stdlib.h>
      23             : #include <unistd.h>
      24             : 
      25             : /* Xlib/Xt stuff */
      26             : #include <X11/Xlib.h>
      27             : #include <X11/Xutil.h>
      28             : #include <X11/Shell.h>
      29             : #include <X11/Intrinsic.h>
      30             : #include <X11/StringDefs.h>
      31             : 
      32             : /* uncomment this if you want debugging information about widget
      33             :    creation and destruction */
      34             : #undef DEBUG_XTBIN
      35             : 
      36             : #define XTBIN_MAX_EVENTS 30
      37             : 
      38             : static void            gtk_xtbin_class_init (GtkXtBinClass *klass);
      39             : static void            gtk_xtbin_init       (GtkXtBin      *xtbin);
      40             : static void            gtk_xtbin_realize    (GtkWidget      *widget);
      41             : static void            gtk_xtbin_unrealize    (GtkWidget      *widget);
      42             : static void            gtk_xtbin_destroy    (GtkObject      *object);
      43             : 
      44             : /* Xt aware XEmbed */
      45             : static void       xt_client_handle_xembed_message (Widget w, 
      46             :                                                    XtPointer client_data, 
      47             :                                                    XEvent *event);
      48             : static void       xt_add_focus_listener( Widget w, XtPointer user_data );
      49             : static void       xt_add_focus_listener_tree ( Widget treeroot, XtPointer user_data); 
      50             : static void       xt_remove_focus_listener(Widget w, XtPointer user_data);
      51             : static void       xt_client_event_handler (Widget w, XtPointer client_data, XEvent *event);
      52             : static void       xt_client_focus_listener (Widget w, XtPointer user_data, XEvent *event);
      53             : static void       xt_client_set_info (Widget xtplug, unsigned long flags);
      54             : static void       send_xembed_message (XtClient *xtclient,
      55             :                                        long message, 
      56             :                                        long detail, 
      57             :                                        long data1, 
      58             :                                        long data2,
      59             :                                        long time);  
      60             : static int        error_handler       (Display *display, 
      61             :                                        XErrorEvent *error);
      62             : /* For error trap of XEmbed */
      63             : static void       trap_errors(void);
      64             : static int        untrap_error(void);
      65             : static int        (*old_error_handler) (Display *, XErrorEvent *);
      66             : static int        trapped_error_code = 0;
      67             : 
      68             : static GtkWidgetClass *parent_class = NULL;
      69             : 
      70             : static Display         *xtdisplay = NULL;
      71             : static String          *fallback = NULL;
      72             : static gboolean         xt_is_initialized = FALSE;
      73             : static gint             num_widgets = 0;
      74             : 
      75             : static GPollFD          xt_event_poll_fd;
      76             : static gint             xt_polling_timer_id = 0;
      77             : static guint            tag = 0;
      78             : 
      79             : static gboolean
      80           0 : xt_event_prepare (GSource*  source_data,
      81             :                    gint     *timeout)
      82             : {   
      83             :   int mask;
      84             : 
      85           0 :   mask = XPending(xtdisplay);
      86             : 
      87           0 :   return (gboolean)mask;
      88             : }
      89             : 
      90             : static gboolean
      91           0 : xt_event_check (GSource*  source_data)
      92             : {
      93           0 :   if (xt_event_poll_fd.revents & G_IO_IN) {
      94             :     int mask;
      95           0 :     mask = XPending(xtdisplay);
      96           0 :     return (gboolean)mask;
      97             :   }
      98             : 
      99           0 :   return FALSE;
     100             : }   
     101             : 
     102             : static gboolean
     103           0 : xt_event_dispatch (GSource*  source_data,
     104             :                     GSourceFunc call_back,
     105             :                     gpointer  user_data)
     106             : {
     107             :   XtAppContext ac;
     108           0 :   int i = 0;
     109             : 
     110           0 :   ac = XtDisplayToApplicationContext(xtdisplay);
     111             : 
     112             :   /* Process only real X traffic here.  We only look for data on the
     113             :    * pipe, limit it to XTBIN_MAX_EVENTS and only call
     114             :    * XtAppProcessEvent so that it will look for X events.  There's no
     115             :    * timer processing here since we already have a timer callback that
     116             :    * does it.  */
     117           0 :   for (i=0; i < XTBIN_MAX_EVENTS && XPending(xtdisplay); i++) {
     118           0 :     XtAppProcessEvent(ac, XtIMXEvent);
     119             :   }
     120             : 
     121           0 :   return TRUE;  
     122             : }
     123             : 
     124             : static GSourceFuncs xt_event_funcs = {
     125             :   xt_event_prepare,
     126             :   xt_event_check,
     127             :   xt_event_dispatch,
     128             :   NULL,
     129             :   (GSourceFunc)NULL,
     130             :   (GSourceDummyMarshal)NULL
     131             : };
     132             : 
     133             : static gboolean
     134           0 : xt_event_polling_timer_callback(gpointer user_data)
     135             : {
     136             :   Display * display;
     137             :   XtAppContext ac;
     138           0 :   int eventsToProcess = 20;
     139             : 
     140           0 :   display = (Display *)user_data;
     141           0 :   ac = XtDisplayToApplicationContext(display);
     142             : 
     143             :   /* We need to process many Xt events here. If we just process
     144             :      one event we might starve one or more Xt consumers. On the other hand
     145             :      this could hang the whole app if Xt events come pouring in. So process
     146             :      up to 20 Xt events right now and save the rest for later. This is a hack,
     147             :      but it oughta work. We *really* should have out of process plugins.
     148             :   */
     149           0 :   while (eventsToProcess-- && XtAppPending(ac))
     150           0 :     XtAppProcessEvent(ac, XtIMAll);
     151           0 :   return TRUE;
     152             : }
     153             : 
     154             : GType
     155           0 : gtk_xtbin_get_type (void)
     156             : {
     157             :   static GType xtbin_type = 0;
     158             : 
     159           0 :   if (!xtbin_type) {
     160             :       static const GTypeInfo xtbin_info =
     161             :       {
     162             :         sizeof (GtkXtBinClass), /* class_size */
     163             :         NULL, /* base_init */
     164             :         NULL, /* base_finalize */
     165             :         (GClassInitFunc) gtk_xtbin_class_init, /* class_init */
     166             :         NULL, /* class_finalize */
     167             :         NULL, /* class_data */
     168             :         sizeof (GtkXtBin), /* instance_size */
     169             :         0, /* n_preallocs */
     170             :         (GInstanceInitFunc) gtk_xtbin_init, /* instance_init */
     171             :         NULL /* value_table */
     172             :       };
     173           0 :       xtbin_type = g_type_register_static(GTK_TYPE_SOCKET, "GtkXtBin",
     174             :         &xtbin_info, 0);
     175             :     }
     176           0 :   return xtbin_type;
     177             : }
     178             : 
     179             : static void
     180           0 : gtk_xtbin_class_init (GtkXtBinClass *klass)
     181             : {
     182             :   GtkWidgetClass *widget_class;
     183             :   GtkObjectClass *object_class;
     184             : 
     185           0 :   parent_class = g_type_class_peek_parent(klass);
     186             : 
     187           0 :   widget_class = GTK_WIDGET_CLASS (klass);
     188           0 :   widget_class->realize = gtk_xtbin_realize;
     189           0 :   widget_class->unrealize = gtk_xtbin_unrealize;
     190             : 
     191           0 :   object_class = GTK_OBJECT_CLASS (klass);
     192           0 :   object_class->destroy = gtk_xtbin_destroy;
     193           0 : }
     194             : 
     195             : static void
     196           0 : gtk_xtbin_init (GtkXtBin *xtbin)
     197             : {
     198           0 :   xtbin->xtdisplay = NULL;
     199           0 :   xtbin->parent_window = NULL;
     200           0 :   xtbin->xtwindow = 0;
     201           0 : }
     202             : 
     203             : static void
     204           0 : gtk_xtbin_realize (GtkWidget *widget)
     205             : {
     206             :   GtkXtBin     *xtbin;
     207           0 :   GtkAllocation allocation = { 0, 0, 200, 200 };
     208             :   gint  x, y, w, h, d; /* geometry of window */
     209             : 
     210             : #ifdef DEBUG_XTBIN
     211             :   printf("gtk_xtbin_realize()\n");
     212             : #endif
     213             : 
     214           0 :   g_return_if_fail (GTK_IS_XTBIN (widget));
     215             : 
     216           0 :   xtbin = GTK_XTBIN (widget);
     217             : 
     218             :   /* caculate the allocation before realize */
     219           0 :   gdk_window_get_geometry(xtbin->parent_window, &x, &y, &w, &h, &d);
     220           0 :   allocation.width = w;
     221           0 :   allocation.height = h;
     222           0 :   gtk_widget_size_allocate (widget, &allocation);
     223             : 
     224             : #ifdef DEBUG_XTBIN
     225             :   printf("initial allocation %d %d %d %d\n", x, y, w, h);
     226             : #endif
     227             : 
     228             :   /* use GtkSocket's realize */
     229           0 :   (*GTK_WIDGET_CLASS(parent_class)->realize)(widget);
     230             : 
     231             :   /* create the Xt client widget */
     232           0 :   xt_client_create(&(xtbin->xtclient), 
     233           0 :        gtk_socket_get_id(GTK_SOCKET(xtbin)), 
     234             :        h, w);
     235           0 :   xtbin->xtwindow = XtWindow(xtbin->xtclient.child_widget);
     236             : 
     237           0 :   gdk_flush();
     238             : 
     239             :   /* now that we have created the xt client, add it to the socket. */
     240           0 :   gtk_socket_add_id(GTK_SOCKET(widget), xtbin->xtwindow);
     241             : }
     242             : 
     243             : 
     244             : 
     245             : GtkWidget*
     246           0 : gtk_xtbin_new (GdkWindow *parent_window, String * f)
     247             : {
     248             :   GtkXtBin *xtbin;
     249             :   gpointer user_data;
     250             : 
     251           0 :   assert(parent_window != NULL);
     252           0 :   xtbin = g_object_new (GTK_TYPE_XTBIN, NULL);
     253             : 
     254           0 :   if (!xtbin)
     255           0 :     return (GtkWidget*)NULL;
     256             : 
     257           0 :   if (f)
     258           0 :     fallback = f;
     259             : 
     260             :   /* Initialize the Xt toolkit */
     261           0 :   xtbin->parent_window = parent_window;
     262             : 
     263           0 :   xt_client_init(&(xtbin->xtclient), 
     264             :       GDK_VISUAL_XVISUAL(gdk_rgb_get_visual()),
     265             :       GDK_COLORMAP_XCOLORMAP(gdk_rgb_get_colormap()),
     266           0 :       gdk_rgb_get_visual()->depth);
     267             : 
     268           0 :   if (!xtbin->xtclient.xtdisplay) {
     269             :     /* If XtOpenDisplay failed, we can't go any further.
     270             :      *  Bail out.
     271             :      */
     272             : #ifdef DEBUG_XTBIN
     273             :     printf("gtk_xtbin_init: XtOpenDisplay() returned NULL.\n");
     274             : #endif
     275           0 :     g_free (xtbin);
     276           0 :     return (GtkWidget *)NULL;
     277             :   }
     278             : 
     279             :   /* Launch X event loop */
     280           0 :   xt_client_xloop_create();
     281             : 
     282             :   /* Build the hierachy */
     283           0 :   xtbin->xtdisplay = xtbin->xtclient.xtdisplay;
     284           0 :   gtk_widget_set_parent_window(GTK_WIDGET(xtbin), parent_window);
     285           0 :   gdk_window_get_user_data(xtbin->parent_window, &user_data);
     286           0 :   if (user_data)
     287           0 :     gtk_container_add(GTK_CONTAINER(user_data), GTK_WIDGET(xtbin));
     288             : 
     289             :   /* This GtkSocket has a visible window, but the Xt plug will cover this
     290             :    * window.  Normally GtkSockets let the X server paint their background and
     291             :    * this would happen immediately (before the plug is mapped).  Setting the
     292             :    * background to None prevents the server from painting this window,
     293             :    * avoiding flicker.
     294             :    */
     295           0 :   gtk_widget_realize(GTK_WIDGET(xtbin));
     296           0 :   gdk_window_set_back_pixmap(GTK_WIDGET(xtbin)->window, NULL, FALSE);
     297             : 
     298           0 :   return GTK_WIDGET (xtbin);
     299             : }
     300             : 
     301             : static void
     302           0 : gtk_xtbin_unrealize (GtkWidget *object)
     303             : {
     304             :   GtkXtBin *xtbin;
     305             :   GtkWidget *widget;
     306             : 
     307             : #ifdef DEBUG_XTBIN
     308             :   printf("gtk_xtbin_unrealize()\n");
     309             : #endif
     310             : 
     311             :   /* gtk_object_destroy() will already hold a refcount on object
     312             :    */
     313           0 :   xtbin = GTK_XTBIN(object);
     314           0 :   widget = GTK_WIDGET(object);
     315             : 
     316           0 :   GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
     317           0 :   if (GTK_WIDGET_REALIZED (widget)) {
     318           0 :     xt_client_unrealize(&(xtbin->xtclient));
     319             :   }
     320             : 
     321           0 :   (*GTK_WIDGET_CLASS (parent_class)->unrealize)(widget);
     322           0 : }
     323             : 
     324             : static void
     325           0 : gtk_xtbin_destroy (GtkObject *object)
     326             : {
     327             :   GtkXtBin *xtbin;
     328             : 
     329             : #ifdef DEBUG_XTBIN
     330             :   printf("gtk_xtbin_destroy()\n");
     331             : #endif
     332             : 
     333           0 :   g_return_if_fail (object != NULL);
     334           0 :   g_return_if_fail (GTK_IS_XTBIN (object));
     335             : 
     336           0 :   xtbin = GTK_XTBIN (object);
     337             : 
     338           0 :   if(xtbin->xtwindow) {
     339             :     /* remove the event handler */
     340           0 :     xt_client_destroy(&(xtbin->xtclient));
     341           0 :     xtbin->xtwindow = 0;
     342             : 
     343             :     /* stop X event loop */
     344           0 :     xt_client_xloop_destroy();
     345             :   }
     346             : 
     347           0 :   GTK_OBJECT_CLASS(parent_class)->destroy(object);
     348             : }
     349             : 
     350             : /*
     351             : * Following is the implementation of Xt XEmbedded for client side
     352             : */
     353             : 
     354             : /* Initial Xt plugin */
     355             : void
     356           0 : xt_client_init( XtClient * xtclient, 
     357             :                 Visual *xtvisual, 
     358             :                 Colormap xtcolormap,
     359             :                 int xtdepth)
     360             : {
     361             :   XtAppContext  app_context;
     362             :   char         *mArgv[1];
     363           0 :   int           mArgc = 0;
     364             : 
     365             :   /*
     366             :    * Initialize Xt stuff
     367             :    */
     368           0 :   xtclient->top_widget = NULL;
     369           0 :   xtclient->child_widget = NULL;
     370           0 :   xtclient->xtdisplay  = NULL;
     371           0 :   xtclient->xtvisual   = NULL;
     372           0 :   xtclient->xtcolormap = 0;
     373           0 :   xtclient->xtdepth = 0;
     374             : 
     375           0 :   if (!xt_is_initialized) {
     376             : #ifdef DEBUG_XTBIN
     377             :     printf("starting up Xt stuff\n");
     378             : #endif
     379           0 :     XtToolkitInitialize();
     380           0 :     app_context = XtCreateApplicationContext();
     381           0 :     if (fallback)
     382           0 :       XtAppSetFallbackResources(app_context, fallback);
     383             : 
     384           0 :     xtdisplay = XtOpenDisplay(app_context, gdk_get_display(), NULL, 
     385             :                             "Wrapper", NULL, 0, &mArgc, mArgv);
     386           0 :     if (xtdisplay)
     387           0 :       xt_is_initialized = TRUE;
     388             :   }
     389           0 :   xtclient->xtdisplay  = xtdisplay;
     390           0 :   xtclient->xtvisual   = xtvisual;
     391           0 :   xtclient->xtcolormap = xtcolormap;
     392           0 :   xtclient->xtdepth    = xtdepth;
     393           0 : }
     394             : 
     395             : void
     396           0 : xt_client_xloop_create(void)
     397             : {
     398             :   /* If this is the first running widget, hook this display into the
     399             :      mainloop */
     400           0 :   if (0 == num_widgets) {
     401             :     int cnumber;
     402             :     GSource* gs;
     403             : 
     404             :     /* Set up xtdisplay in case we're missing one */
     405           0 :     if (!xtdisplay) {
     406           0 :       (void)xt_client_get_display();
     407             :     }
     408             : 
     409             :     /*
     410             :      * hook Xt event loop into the glib event loop.
     411             :      */
     412             :     /* the assumption is that gtk_init has already been called */
     413           0 :     gs = g_source_new(&xt_event_funcs, sizeof(GSource));
     414           0 :     if (!gs) {
     415           0 :       return;
     416             :     }
     417             : 
     418           0 :     g_source_set_priority(gs, GDK_PRIORITY_EVENTS);
     419           0 :     g_source_set_can_recurse(gs, TRUE);
     420           0 :     tag = g_source_attach(gs, (GMainContext*)NULL);
     421           0 :     g_source_unref(gs);
     422             : #ifdef VMS
     423             :     cnumber = XConnectionNumber(xtdisplay);
     424             : #else
     425           0 :     cnumber = ConnectionNumber(xtdisplay);
     426             : #endif
     427           0 :     xt_event_poll_fd.fd = cnumber;
     428           0 :     xt_event_poll_fd.events = G_IO_IN; 
     429           0 :     xt_event_poll_fd.revents = 0;    /* hmm... is this correct? */
     430             : 
     431           0 :     g_main_context_add_poll ((GMainContext*)NULL, 
     432             :                              &xt_event_poll_fd, 
     433             :                              G_PRIORITY_LOW);
     434             :     /* add a timer so that we can poll and process Xt timers */
     435           0 :     xt_polling_timer_id =
     436           0 :       g_timeout_add(25,
     437             :                     (GtkFunction)xt_event_polling_timer_callback,
     438             :                     xtdisplay);
     439             :   }
     440             : 
     441             :   /* Bump up our usage count */
     442           0 :   num_widgets++;
     443             : }
     444             : 
     445             : void
     446           0 : xt_client_xloop_destroy(void)
     447             : {
     448           0 :   num_widgets--; /* reduce our usage count */
     449             : 
     450             :   /* If this is the last running widget, remove the Xt display
     451             :      connection from the mainloop */
     452           0 :   if (0 == num_widgets) {
     453             : #ifdef DEBUG_XTBIN
     454             :     printf("removing the Xt connection from the main loop\n");
     455             : #endif
     456           0 :     g_main_context_remove_poll((GMainContext*)NULL, &xt_event_poll_fd);
     457           0 :     g_source_remove(tag);
     458             : 
     459           0 :     g_source_remove(xt_polling_timer_id);
     460           0 :     xt_polling_timer_id = 0;
     461             :   }
     462           0 : }
     463             : 
     464             : /* Get Xt Client display */
     465             : Display *
     466           0 : xt_client_get_display(void)
     467             : {
     468           0 :   if (!xtdisplay) {
     469             :     XtClient tmp;
     470           0 :     xt_client_init(&tmp,NULL,0,0);
     471             :   }
     472           0 :   return xtdisplay;
     473             : }
     474             : 
     475             : /* Create the Xt client widgets
     476             : *  */
     477             : void
     478           0 : xt_client_create ( XtClient* xtclient , 
     479             :                    Window embedderid, 
     480             :                    int height, 
     481             :                    int width ) 
     482             : {
     483             :   int           n;
     484             :   Arg           args[6];
     485             :   Widget        child_widget;
     486             :   Widget        top_widget;
     487             : 
     488             : #ifdef DEBUG_XTBIN
     489             :   printf("xt_client_create() \n");
     490             : #endif
     491           0 :   top_widget = XtAppCreateShell("drawingArea", "Wrapper", 
     492             :                                 applicationShellWidgetClass, 
     493             :                                 xtclient->xtdisplay, 
     494             :                                 NULL, 0);
     495           0 :   xtclient->top_widget = top_widget;
     496             : 
     497             :   /* set size of Xt window */
     498           0 :   n = 0;
     499           0 :   XtSetArg(args[n], XtNheight,   height);n++;
     500           0 :   XtSetArg(args[n], XtNwidth,    width);n++;
     501           0 :   XtSetValues(top_widget, args, n);
     502             : 
     503           0 :   child_widget = XtVaCreateWidget("form", 
     504             :                                   compositeWidgetClass, 
     505             :                                   top_widget, NULL);
     506             : 
     507           0 :   n = 0;
     508           0 :   XtSetArg(args[n], XtNheight,   height);n++;
     509           0 :   XtSetArg(args[n], XtNwidth,    width);n++;
     510           0 :   XtSetArg(args[n], XtNvisual,   xtclient->xtvisual ); n++;
     511           0 :   XtSetArg(args[n], XtNdepth,    xtclient->xtdepth ); n++;
     512           0 :   XtSetArg(args[n], XtNcolormap, xtclient->xtcolormap ); n++;
     513           0 :   XtSetArg(args[n], XtNborderWidth, 0); n++;
     514           0 :   XtSetValues(child_widget, args, n);
     515             : 
     516           0 :   XSync(xtclient->xtdisplay, FALSE);
     517           0 :   xtclient->oldwindow = top_widget->core.window;
     518           0 :   top_widget->core.window = embedderid;
     519             : 
     520             :   /* this little trick seems to finish initializing the widget */
     521             : #if XlibSpecificationRelease >= 6
     522           0 :   XtRegisterDrawable(xtclient->xtdisplay, 
     523             :                      embedderid,
     524             :                      top_widget);
     525             : #else
     526             :   _XtRegisterWindow( embedderid,
     527             :                      top_widget);
     528             : #endif
     529           0 :   XtRealizeWidget(child_widget);
     530             : 
     531             :   /* listen to all Xt events */
     532           0 :   XSelectInput(xtclient->xtdisplay, 
     533             :                embedderid, 
     534           0 :                XtBuildEventMask(top_widget));
     535           0 :   xt_client_set_info (child_widget, 0);
     536             : 
     537           0 :   XtManageChild(child_widget);
     538           0 :   xtclient->child_widget = child_widget;
     539             : 
     540             :   /* set the event handler */
     541           0 :   XtAddEventHandler(child_widget,
     542             :                     StructureNotifyMask | KeyPressMask,
     543             :                     TRUE, 
     544             :                     (XtEventHandler)xt_client_event_handler, xtclient);
     545           0 :   XtAddEventHandler(child_widget, 
     546             :                     SubstructureNotifyMask | ButtonReleaseMask, 
     547             :                     FALSE,
     548             :                     (XtEventHandler)xt_client_focus_listener, 
     549             :                     xtclient);
     550           0 :   XSync(xtclient->xtdisplay, FALSE);
     551           0 : }
     552             : 
     553             : void
     554           0 : xt_client_unrealize ( XtClient* xtclient )
     555             : {
     556             :   /* Explicitly destroy the child_widget window because this is actually a
     557             :      child of the socket window.  It is not a child of top_widget's window
     558             :      when that is destroyed. */
     559           0 :   XtUnrealizeWidget(xtclient->child_widget);
     560             : 
     561             : #if XlibSpecificationRelease >= 6
     562           0 :   XtUnregisterDrawable(xtclient->xtdisplay,
     563           0 :                        xtclient->top_widget->core.window);
     564             : #else
     565             :   _XtUnregisterWindow(xtclient->top_widget->core.window,
     566             :                       xtclient->top_widget);
     567             : #endif
     568             : 
     569             :   /* flush the queue before we returning origin top_widget->core.window
     570             :      or we can get X error since the window is gone */
     571           0 :   XSync(xtclient->xtdisplay, False);
     572             : 
     573           0 :   xtclient->top_widget->core.window = xtclient->oldwindow;
     574           0 :   XtUnrealizeWidget(xtclient->top_widget);
     575           0 : }
     576             : 
     577             : void            
     578           0 : xt_client_destroy   (XtClient* xtclient)
     579             : {
     580           0 :   if(xtclient->top_widget) {
     581           0 :     XtRemoveEventHandler(xtclient->child_widget,
     582             :                          StructureNotifyMask | KeyPressMask,
     583             :                          TRUE, 
     584             :                          (XtEventHandler)xt_client_event_handler, xtclient);
     585           0 :     XtDestroyWidget(xtclient->top_widget);
     586           0 :     xtclient->top_widget = NULL;
     587             :   }
     588           0 : }
     589             : 
     590             : void         
     591           0 : xt_client_set_info (Widget xtplug, unsigned long flags)
     592             : {
     593             :   unsigned long buffer[2];
     594             : 
     595           0 :   Atom infoAtom = XInternAtom(XtDisplay(xtplug), "_XEMBED_INFO", False); 
     596             : 
     597           0 :   buffer[1] = 0;                /* Protocol version */
     598           0 :   buffer[1] = flags;
     599             : 
     600           0 :   XChangeProperty (XtDisplay(xtplug), XtWindow(xtplug),
     601             :                    infoAtom, infoAtom, 32,
     602             :                    PropModeReplace,
     603             :                    (unsigned char *)buffer, 2);
     604           0 : }
     605             : 
     606             : static void
     607           0 : xt_client_handle_xembed_message(Widget w, XtPointer client_data, XEvent *event)
     608             : {
     609           0 :   XtClient *xtplug = (XtClient*)client_data;
     610           0 :   switch (event->xclient.data.l[1])
     611             :   {
     612             :   case XEMBED_EMBEDDED_NOTIFY:
     613           0 :     break;
     614             :   case XEMBED_WINDOW_ACTIVATE:
     615             : #ifdef DEBUG_XTBIN
     616             :     printf("Xt client get XEMBED_WINDOW_ACTIVATE\n");
     617             : #endif
     618           0 :     break;
     619             :   case XEMBED_WINDOW_DEACTIVATE:
     620             : #ifdef DEBUG_XTBIN
     621             :     printf("Xt client get XEMBED_WINDOW_DEACTIVATE\n");
     622             : #endif
     623           0 :     break;
     624             :   case XEMBED_MODALITY_ON:
     625             : #ifdef DEBUG_XTBIN
     626             :     printf("Xt client get XEMBED_MODALITY_ON\n");
     627             : #endif
     628           0 :     break;
     629             :   case XEMBED_MODALITY_OFF:
     630             : #ifdef DEBUG_XTBIN
     631             :     printf("Xt client get XEMBED_MODALITY_OFF\n");
     632             : #endif
     633           0 :     break;
     634             :   case XEMBED_FOCUS_IN:
     635             :   case XEMBED_FOCUS_OUT:
     636             :     {
     637             :       XEvent xevent;
     638           0 :       memset(&xevent, 0, sizeof(xevent));
     639             : 
     640           0 :       if(event->xclient.data.l[1] == XEMBED_FOCUS_IN) {
     641             : #ifdef DEBUG_XTBIN
     642             :         printf("XTEMBED got focus in\n");
     643             : #endif
     644           0 :         xevent.xfocus.type = FocusIn;
     645             :       }
     646             :       else {
     647             : #ifdef DEBUG_XTBIN
     648             :         printf("XTEMBED got focus out\n");
     649             : #endif
     650           0 :         xevent.xfocus.type = FocusOut;
     651             :       }
     652             : 
     653           0 :       xevent.xfocus.window = XtWindow(xtplug->child_widget);
     654           0 :       xevent.xfocus.display = XtDisplay(xtplug->child_widget);
     655           0 :       XSendEvent(XtDisplay(xtplug->child_widget), 
     656             :                  xevent.xfocus.window,
     657             :                  False, NoEventMask,
     658             :                  &xevent );
     659           0 :       XSync( XtDisplay(xtplug->child_widget), False);
     660             :     }
     661           0 :     break;
     662             :   default:
     663           0 :     break;
     664             :   } /* End of XEmbed Message */
     665           0 : }
     666             : 
     667             : void         
     668           0 : xt_client_event_handler( Widget w, XtPointer client_data, XEvent *event)
     669             : {
     670           0 :   XtClient *xtplug = (XtClient*)client_data;
     671             :   
     672           0 :   switch(event->type)
     673             :     {
     674             :     case ClientMessage:
     675             :       /* Handle xembed message */
     676           0 :       if (event->xclient.message_type==
     677           0 :                  XInternAtom (XtDisplay(xtplug->child_widget),
     678             :                               "_XEMBED", False)) {
     679           0 :         xt_client_handle_xembed_message(w, client_data, event);
     680             :       }
     681           0 :       break;
     682             :     case ReparentNotify:
     683           0 :       break;
     684             :     case MappingNotify:
     685           0 :       xt_client_set_info (w, XEMBED_MAPPED);
     686           0 :       break;
     687             :     case UnmapNotify:
     688           0 :       xt_client_set_info (w, 0);
     689           0 :       break;
     690             :     case KeyPress:
     691             : #ifdef DEBUG_XTBIN
     692             :       printf("Key Press Got!\n");
     693             : #endif
     694           0 :       break;
     695             :     default:
     696           0 :       break;
     697             :     } /* End of switch(event->type) */
     698           0 : }
     699             : 
     700             : static void
     701           0 : send_xembed_message (XtClient  *xtclient,
     702             :                      long      message,
     703             :                      long      detail, 
     704             :                      long      data1,  
     705             :                      long      data2,  
     706             :                      long      time)   
     707             : {
     708             :   XEvent xevent; 
     709           0 :   Window w=XtWindow(xtclient->top_widget);
     710           0 :   Display* dpy=xtclient->xtdisplay;
     711             :   int errorcode;
     712             : 
     713           0 :   memset(&xevent,0,sizeof(xevent));
     714           0 :   xevent.xclient.window = w;
     715           0 :   xevent.xclient.type = ClientMessage;
     716           0 :   xevent.xclient.message_type = XInternAtom(dpy,"_XEMBED",False);
     717           0 :   xevent.xclient.format = 32;
     718           0 :   xevent.xclient.data.l[0] = time; 
     719           0 :   xevent.xclient.data.l[1] = message;
     720           0 :   xevent.xclient.data.l[2] = detail; 
     721           0 :   xevent.xclient.data.l[3] = data1;
     722           0 :   xevent.xclient.data.l[4] = data2;
     723             : 
     724           0 :   trap_errors ();
     725           0 :   XSendEvent (dpy, w, False, NoEventMask, &xevent);
     726           0 :   XSync (dpy,False);
     727             : 
     728           0 :   if((errorcode = untrap_error())) {
     729             : #ifdef DEBUG_XTBIN
     730             :     printf("send_xembed_message error(%d)!!!\n",errorcode);
     731             : #endif
     732             :   }
     733           0 : }
     734             : 
     735             : static int             
     736           0 : error_handler(Display *display, XErrorEvent *error)
     737             : {
     738           0 :   trapped_error_code = error->error_code;
     739           0 :   return 0;
     740             : }
     741             : 
     742             : static void          
     743           0 : trap_errors(void)
     744             : {
     745           0 :   trapped_error_code =0;
     746           0 :   old_error_handler = XSetErrorHandler(error_handler);
     747           0 : }
     748             : 
     749             : static int         
     750           0 : untrap_error(void)
     751             : {
     752           0 :   XSetErrorHandler(old_error_handler);
     753           0 :   if(trapped_error_code) {
     754             : #ifdef DEBUG_XTBIN
     755             :     printf("Get X Window Error = %d\n", trapped_error_code);
     756             : #endif
     757             :   }
     758           0 :   return trapped_error_code;
     759             : }
     760             : 
     761             : void         
     762           0 : xt_client_focus_listener( Widget w, XtPointer user_data, XEvent *event)
     763             : {
     764           0 :   Display *dpy = XtDisplay(w);
     765           0 :   XtClient *xtclient = user_data;
     766           0 :   Window win = XtWindow(w);
     767             : 
     768           0 :   switch(event->type)
     769             :     {
     770             :     case CreateNotify:
     771           0 :       if(event->xcreatewindow.parent == win) {
     772           0 :         Widget child=XtWindowToWidget( dpy, event->xcreatewindow.window);
     773           0 :         if (child)
     774           0 :           xt_add_focus_listener_tree(child, user_data);
     775             :       }
     776           0 :       break;
     777             :     case DestroyNotify:
     778           0 :       xt_remove_focus_listener( w, user_data);
     779           0 :       break;
     780             :     case ReparentNotify:
     781           0 :       if(event->xreparent.parent == win) {
     782             :         /* I am the new parent */
     783           0 :         Widget child=XtWindowToWidget(dpy, event->xreparent.window);
     784           0 :         if (child)
     785           0 :           xt_add_focus_listener_tree( child, user_data);
     786             :       }
     787           0 :       else if(event->xreparent.window == win) {
     788             :         /* I am the new child */
     789             :       }
     790             :       else {
     791             :         /* I am the old parent */
     792             :       }
     793           0 :       break;
     794             :     case ButtonRelease:
     795             : #if 0
     796             :       XSetInputFocus(dpy, XtWindow(xtclient->child_widget), RevertToParent, event->xbutton.time);
     797             : #endif
     798           0 :       send_xembed_message ( xtclient,
     799             :                             XEMBED_REQUEST_FOCUS, 0, 0, 0, 0);
     800           0 :       break;
     801             :     default:
     802           0 :       break;
     803             :     } /* End of switch(event->type) */
     804           0 : }
     805             : 
     806             : static void
     807           0 : xt_add_focus_listener( Widget w, XtPointer user_data)
     808             : {
     809           0 :   XtClient *xtclient = user_data;
     810             : 
     811           0 :   trap_errors ();
     812           0 :   XtAddEventHandler(w, 
     813             :                     SubstructureNotifyMask | ButtonReleaseMask, 
     814             :                     FALSE, 
     815             :                     (XtEventHandler)xt_client_focus_listener, 
     816             :                     xtclient);
     817           0 :   untrap_error();
     818           0 : }
     819             : 
     820             : static void
     821           0 : xt_remove_focus_listener(Widget w, XtPointer user_data)
     822             : {
     823           0 :   trap_errors ();
     824           0 :   XtRemoveEventHandler(w, SubstructureNotifyMask | ButtonReleaseMask, FALSE, 
     825             :                       (XtEventHandler)xt_client_focus_listener, user_data);
     826             : 
     827           0 :   untrap_error();
     828           0 : }
     829             : 
     830             : static void
     831           0 : xt_add_focus_listener_tree ( Widget treeroot, XtPointer user_data) 
     832             : {
     833           0 :   Window win = XtWindow(treeroot);
     834             :   Window *children;
     835             :   Window root, parent;
     836           0 :   Display *dpy = XtDisplay(treeroot);
     837             :   unsigned int i, nchildren;
     838             : 
     839             :   /* ensure we don't add more than once */
     840           0 :   xt_remove_focus_listener( treeroot, user_data);
     841           0 :   xt_add_focus_listener( treeroot, user_data);
     842           0 :   trap_errors();
     843           0 :   if(!XQueryTree(dpy, win, &root, &parent, &children, &nchildren)) {
     844           0 :     untrap_error();
     845           0 :     return;
     846             :   }
     847             : 
     848           0 :   if(untrap_error()) 
     849           0 :     return;
     850             : 
     851           0 :   for(i=0; i<nchildren; ++i) {
     852           0 :     Widget child = XtWindowToWidget(dpy, children[i]);
     853           0 :     if (child) 
     854           0 :       xt_add_focus_listener_tree( child, user_data);
     855             :   }
     856           0 :   XFree((void*)children);
     857             : 
     858           0 :   return;
     859             : }
     860             : 

Generated by: LCOV version 1.13