LCOV - code coverage report
Current view: directory - widget/gtkxtbin - gtk2xtbin.c (source / functions) Found Hit Coverage
Test: app.info Lines: 332 0 0.0 %
Date: 2012-06-02 Functions: 28 0 0.0 %

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

Generated by: LCOV version 1.7