unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* embedding gtk widgets in a buffer
@ 2008-05-07 23:23 joakim
  2008-05-08  0:21 ` joakim
                   ` (3 more replies)
  0 siblings, 4 replies; 20+ messages in thread
From: joakim @ 2008-05-07 23:23 UTC (permalink / raw
  To: emacs-devel

I'm working on a patch to embed gtk widgets in a buffer.
Its going unexpectedly well!

I'm able to embed different types of widgets, and they move with the
text rather like images in emacs.

I've tested 2 different types of buttons, and an xembed widget.

Heres a screenshot:
http://www.emacswiki.org/cgi-bin/wiki/EmacsXembedScreenshot

Heres the elisp I use to test, which shows the interface:

-----------------------------------------
(insert "xwidgetdemo<<< a button. another button\n")
(goto-char (point-min))
(put-text-property (point) (+ 1 (point)) 'display '(xwidget :xwidget-id 1 :type 1 :title "1"))

(goto-char 15)
(put-text-property (point) (+ 1 (point)) 'display '(xwidget :xwidget-id 2 :type 2 :title "2"))

(goto-char 30)
(put-text-property (point) (+ 1 (point)) 'display '(xwidget :xwidget-id 3 :type 3 :title "3"))
------------------------------------------

Ok, thats rather nice and all, but heres what I dont have:

- callback interface for the widgets. It would be nice with some ideas
how to do this. For instance:
  - button pressed handler
  - when a xembed widget is ready, a callback to start an external
  program in the widget would be nice, now it has to be done manually on
  the cmd line

- currently all xwidgets must have a unique id, ":xwidget-id 3" for
  instance. I havent figured out how to handle this.

- 2 windows showing the same buffer doesnt quite work and is probably tricky

- only 1 frame supported

- beautiful code

-- 
Joakim Verona




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-07 23:23 embedding gtk widgets in a buffer joakim
@ 2008-05-08  0:21 ` joakim
  2008-05-08  9:02 ` BVK
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 20+ messages in thread
From: joakim @ 2008-05-08  0:21 UTC (permalink / raw
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 123 bytes --]

joakim@verona.se writes:

Heres the actual patch. As I said previously, its early times yet, and
its not beautiful code. 


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: emacsembedgtk.diff --]
[-- Type: text/x-patch, Size: 24024 bytes --]

=== modified file 'src/Makefile.in'
--- src/Makefile.in	2008-03-04 20:29:10 +0000
+++ src/Makefile.in	2008-04-09 07:17:55 +0000
@@ -593,6 +593,7 @@
 	process.o callproc.o \
 	region-cache.o sound.o atimer.o \
 	doprnt.o strftime.o intervals.o textprop.o composite.o md5.o \
+	xwidget.o \
 	$(MSDOS_OBJ) $(MAC_OBJ) $(CYGWIN_OBJ) $(FONTOBJ)
 
 /* Object files used on some machine or other.
@@ -1221,6 +1222,8 @@
 sound.o: sound.c dispextern.h $(config_h)
 atimer.o: atimer.c atimer.h systime.h $(config_h)
 
+xwidget.o: xwidget.c xwidget.h
+
 /* The files of Lisp proper */
 
 alloc.o: alloc.c process.h frame.h window.h buffer.h  puresize.h syssignal.h keyboard.h \

=== modified file 'src/dispextern.h'
--- src/dispextern.h	2008-03-02 05:30:51 +0000
+++ src/dispextern.h	2008-05-07 21:38:08 +0000
@@ -26,7 +26,6 @@
 #define DISPEXTERN_H_INCLUDED
 
 #ifdef HAVE_X_WINDOWS
-
 #include <X11/Xlib.h>
 #ifdef USE_X_TOOLKIT
 #include <X11/Intrinsic.h>
@@ -283,7 +282,10 @@
   IMAGE_GLYPH,
 
   /* Glyph is a space of fractional width and/or height.  */
-  STRETCH_GLYPH
+  STRETCH_GLYPH,
+
+  /* Glyph is an external widget drawn by the GUI toolkit.   */
+  XWIDGET_GLYPH
 };
 
 
@@ -333,7 +335,7 @@
 
   /* Which kind of glyph this is---character, image etc.  Value
      should be an enumerator of type enum glyph_type.  */
-  unsigned type : 2;
+  unsigned type : 3;
 
   /* 1 means this glyph was produced from multibyte text.  Zero
      means it was produced from unibyte text, i.e. charsets aren't
@@ -394,6 +396,8 @@
     /* Image ID for image glyphs (type == IMAGE_GLYPH).  */
     unsigned img_id;
 
+    unsigned xwidget_id;
+    
     /* Sub-structure for type == STRETCH_GLYPH.  */
     struct
     {
@@ -1229,6 +1233,8 @@
   /* Image, if any.  */
   struct image *img;
 
+  int xwidget_id;
+
   /* Slice */
   struct glyph_slice slice;
 
@@ -1798,7 +1804,9 @@
   IT_TRUNCATION,
 
   /* Continuation glyphs.  See the comment for IT_TRUNCATION.  */
-  IT_CONTINUATION
+  IT_CONTINUATION,
+
+  IT_XWIDGET
 };
 
 
@@ -1841,6 +1849,7 @@
   GET_FROM_C_STRING,
   GET_FROM_IMAGE,
   GET_FROM_STRETCH,
+  GET_FROM_XWIDGET,
   NUM_IT_METHODS
 };
 
@@ -1985,6 +1994,12 @@
       struct {
 	Lisp_Object object;
       } stretch;
+      /* method == GET_FROM_XWIDGET */
+      struct {
+	Lisp_Object object;
+        int xwidget_lalala;
+      } xwidget;
+
     } u;
 
     /* current text and display positions.  */
@@ -2088,6 +2103,10 @@
   /* If what == IT_IMAGE, the id of the image to display.  */
   int image_id;
 
+  /* If what == IT_XWIDGET*/
+  int xwidget_id;
+
+  
   /* Values from `slice' property.  */
   struct it_slice slice;
 
@@ -3110,3 +3129,4 @@
 
 /* arch-tag: c65c475f-1c1e-4534-8795-990b8509fd65
    (do not change this comment) */
+

=== modified file 'src/emacs.c'
--- src/emacs.c	2008-03-14 08:40:13 +0000
+++ src/emacs.c	2008-04-09 19:18:33 +0000
@@ -54,6 +54,8 @@
 #include "buffer.h"
 #include "window.h"
 
+#include "xwidget.h"
+
 #include "systty.h"
 #include "blockinput.h"
 #include "syssignal.h"
@@ -1612,6 +1614,7 @@
       syms_of_xterm ();
       syms_of_xfns ();
       syms_of_fontset ();
+      syms_of_xwidget();
 #ifdef HAVE_X_SM
       syms_of_xsmfns ();
 #endif

=== modified file 'src/gtkutil.c'
--- src/gtkutil.c	2008-03-30 23:37:59 +0000
+++ src/gtkutil.c	2008-05-07 15:30:40 +0000
@@ -795,6 +795,10 @@
 /* Create and set up the GTK widgets for frame F.
    Return 0 if creation failed, non-zero otherwise.  */
 
+GtkWidget *gwfixed;
+
+GtkWidget *getGwfixed(){return gwfixed;};
+
 int
 xg_create_frame_widgets (f)
      FRAME_PTR f;
@@ -817,7 +821,7 @@
   xg_set_screen (wtop, f);
 
   wvbox = gtk_vbox_new (FALSE, 0);
-  wfixed = gtk_fixed_new ();  /* Must have this to place scroll bars  */
+  gwfixed = wfixed = gtk_fixed_new ();  /* Must have this to place scroll bars  */
 
   if (! wtop || ! wvbox || ! wfixed)
     {

=== modified file 'src/xdisp.c'
--- src/xdisp.c	2008-04-02 03:27:06 +0000
+++ src/xdisp.c	2008-05-07 21:44:13 +0000
@@ -191,6 +191,7 @@
 #include "region-cache.h"
 #include "fontset.h"
 #include "blockinput.h"
+#include "xwidget.h"
 
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
@@ -939,6 +940,7 @@
 static int next_element_from_buffer P_ ((struct it *));
 static int next_element_from_composition P_ ((struct it *));
 static int next_element_from_image P_ ((struct it *));
+static int next_element_from_xwidget  P_ ((struct it *));
 static int next_element_from_stretch P_ ((struct it *));
 static void load_overlay_strings P_ ((struct it *, int));
 static int init_from_display_pos P_ ((struct it *, struct window *,
@@ -3891,6 +3893,7 @@
   if (CONSP (prop)
       /* Simple properties.  */
       && !EQ (XCAR (prop), Qimage)
+      && !EQ (XCAR (prop), Qxwidget)
       && !EQ (XCAR (prop), Qspace)
       && !EQ (XCAR (prop), Qwhen)
       && !EQ (XCAR (prop), Qslice)
@@ -4000,6 +4003,7 @@
   Lisp_Object location, value;
   struct text_pos start_pos, save_pos;
   int valid_p;
+  printf("handle_single_display_spec:\n");
 
   /* If SPEC is a list of the form `(when FORM . VALUE)', evaluate FORM.
      If the result is non-nil, use VALUE instead of SPEC.  */
@@ -4283,11 +4287,22 @@
      LOCATION specifies where to display: `left-margin',
      `right-margin' or nil.  */
 
+
+  printf("handle_single_display_spec xwidgetp:%d  imagep:%d spacep:%d display_replaced_before_p:%d stringp:%d\n",
+         XWIDGETP(value),
+         valid_image_p (value),
+         (CONSP (value) && EQ (XCAR (value), Qspace)),
+         display_replaced_before_p,
+         STRINGP (value));
+  
   valid_p = (STRINGP (value)
+             
 #ifdef HAVE_WINDOW_SYSTEM
              || (FRAME_WINDOW_P (it->f) && valid_image_p (value))
 #endif /* not HAVE_WINDOW_SYSTEM */
-             || (CONSP (value) && EQ (XCAR (value), Qspace)));
+             || (CONSP (value) && EQ (XCAR (value), Qspace))
+             || XWIDGETP(value)
+             );
 
   if (valid_p && !display_replaced_before_p)
     {
@@ -4333,8 +4348,20 @@
 	  it->object = value;
 	  *position = it->position = start_pos;
 	}
+      else if (XWIDGETP(value))
+	{
+          printf("handle_single_display_spec: im an xwidget!!\n");
+          it->what = IT_XWIDGET;
+          it->method = GET_FROM_XWIDGET;
+          it->position = start_pos;
+	  it->object = NILP (object) ? it->w->buffer : object;
+	  *position = start_pos;
+
+          it->xwidget_id=lookup_xwidget(value);
+          
+	}      
 #ifdef HAVE_WINDOW_SYSTEM
-      else
+      else //if nothing else, its an image
 	{
 	  it->what = IT_IMAGE;
 	  it->image_id = lookup_image (it->f, value);
@@ -4398,7 +4425,8 @@
 
   return (CONSP (prop)
 	  && (EQ (XCAR (prop), Qimage)
-	      || EQ (XCAR (prop), Qspace)));
+	      || EQ (XCAR (prop), Qspace)
+              || XWIDGETP(prop)));
 }
 
 
@@ -5187,6 +5215,10 @@
     case GET_FROM_STRETCH:
       p->u.stretch.object = it->object;
       break;
+    case GET_FROM_XWIDGET:
+      p->u.xwidget.object = it->object;
+      break;
+      
     }
   p->position = it->position;
   p->current = it->current;
@@ -5234,6 +5266,10 @@
       it->object = p->u.image.object;
       it->slice = p->u.image.slice;
       break;
+    case GET_FROM_XWIDGET:
+      it->object = p->u.xwidget.object;
+      break;
+      
     case GET_FROM_COMPOSITION:
       it->object = p->u.comp.object;
       it->c = p->u.comp.c;
@@ -5701,7 +5737,8 @@
   next_element_from_string,
   next_element_from_c_string,
   next_element_from_image,
-  next_element_from_stretch
+  next_element_from_stretch,
+  next_element_from_xwidget
 };
 
 #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
@@ -6159,6 +6196,7 @@
 
     case GET_FROM_IMAGE:
     case GET_FROM_STRETCH:
+    case GET_FROM_XWIDGET:
       /* The position etc with which we have to proceed are on
 	 the stack.  The position may be at the end of a string,
          if the `display' property takes up the whole string.  */
@@ -6410,6 +6448,17 @@
   return 1;
 }
 
+/* im not sure about this FIXME JAVE*/
+static int
+next_element_from_xwidget (it)
+     struct it *it;
+{
+  it->what = IT_XWIDGET;
+  printf("xwidget: in next_element_from_xwidget\n");
+  return 1;
+}
+
+
 
 /* Fill iterator IT with next display element from a stretch glyph
    property.  IT->object is the value of the text property.  Value is
@@ -15456,6 +15505,10 @@
 	       glyph->left_box_line_p,
 	       glyph->right_box_line_p);
     }
+  else if (glyph->type == XWIDGET_GLYPH)
+    {
+      printf("dump xwidget glyph\n");
+    }
 }
 
 
@@ -18944,6 +18997,13 @@
 
 	      return OK_PIXELS (width_p ? img->width : img->height);
 	    }
+
+	  if (FRAME_WINDOW_P (it->f)
+	      && valid_xwidget_p (prop))
+	    {
+              printf("calc_pixel_width_or_height: return dummy size\n");
+              return OK_PIXELS (width_p ? 100 : 100);
+            }
 #endif
 	  if (EQ (car, Qplus) || EQ (car, Qminus))
 	    {
@@ -19477,6 +19537,19 @@
   s->ybase += s->first_glyph->voffset;
 }
 
+static void
+fill_xwidget_glyph_string (s)
+     struct glyph_string *s;
+{
+  xassert (s->first_glyph->type == XWIDGET_GLYPH);
+  printf("fill_xwidget_glyph_string: width:%d \n",s->first_glyph->pixel_width);
+  s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
+  s->font = s->face->font;
+  s->width = s->first_glyph->pixel_width;
+  s->ybase += s->first_glyph->voffset;
+  s->xwidget_id=s->first_glyph->u.xwidget_id;
+}
+
 
 /* Fill glyph string S from a sequence of stretch glyphs.
 
@@ -19835,6 +19908,20 @@
        }								\
      while (0)
 
+#define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
+     do									\
+       { \
+         printf("BUILD_XWIDGET_GLYPH_STRING\n");                                                      \
+	 s = (struct glyph_string *) alloca (sizeof *s);		\
+	 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL);		\
+	 fill_xwidget_glyph_string (s);					\
+	 append_glyph_string (&HEAD, &TAIL, s);				\
+	 ++START;							\
+         s->x = (X);							\
+       }								\
+     while (0)
+
+
 
 /* Add a glyph string for a sequence of character glyphs to the list
    of strings between HEAD and TAIL.  START is the index of the first
@@ -19942,7 +20029,11 @@
 		 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL,	   \
 					   HL, X, LAST_X);		   \
 		 break;							   \
-									   \
+               case XWIDGET_GLYPH:                                        \
+		 BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL,      \
+					   HL, X, LAST_X);              \
+		 break;                                                 \
+                                                                        \
 	       default:							   \
 		 abort ();						   \
 	       }							   \
@@ -20440,6 +20531,113 @@
     }
 }
 
+static void
+produce_xwidget_glyph (it)
+     struct it *it;
+{
+  //  struct image *img;
+  struct face *face;
+  int glyph_ascent, crop;
+  //  struct glyph_slice slice;
+
+  printf("produce_xwidget_glyph:\n");
+  xassert (it->what == IT_XWIDGET);
+
+  face = FACE_FROM_ID (it->f, it->face_id);
+  xassert (face);
+  /* Make sure X resources of the face is loaded.  */
+  PREPARE_FACE_FOR_DISPLAY (it->f, face);
+
+
+
+  /////////////////////////////////////////////
+  
+  //  img = IMAGE_FROM_ID (it->f, it->image_id);
+  //xassert (img);
+  /* Make sure X resources of the image is loaded.  */
+  //prepare_image_for_display (it->f, img);
+
+
+
+
+  it->ascent = it->phys_ascent = glyph_ascent = 50;//image_ascent (img, face, &slice);
+  it->descent = 50;//slice.height - glyph_ascent;
+
+  //it->descent += img->vmargin;
+  //it->descent += img->vmargin;
+  it->phys_descent = it->descent;
+
+  it->pixel_width = 50;
+
+  //it->pixel_width += img->hmargin;
+  //it->pixel_width += img->hmargin;
+
+  /////////////////////////////////////////
+  
+  /* It's quite possible for images to have an ascent greater than
+     their height, so don't get confused in that case.  */
+  if (it->descent < 0)
+    it->descent = 0;
+
+  it->nglyphs = 1;
+
+  if (face->box != FACE_NO_BOX)
+    {
+      if (face->box_line_width > 0)
+	{
+	    it->ascent += face->box_line_width;
+	    it->descent += face->box_line_width;
+	}
+
+      if (it->start_of_box_run_p)
+	it->pixel_width += eabs (face->box_line_width);
+      it->pixel_width += eabs (face->box_line_width);
+    }
+
+  take_vertical_position_into_account (it);
+
+  /* Automatically crop wide image glyphs at right edge so we can
+     draw the cursor on same display row.  */
+  if ((crop = it->pixel_width - (it->last_visible_x - it->current_x), crop > 0)
+      && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
+    {
+      it->pixel_width -= crop;
+    }
+
+  if (it->glyph_row)
+    {
+      struct glyph *glyph;
+      enum glyph_row_area area = it->area;
+
+      glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
+      if (glyph < it->glyph_row->glyphs[area + 1])
+	{
+	  glyph->charpos = CHARPOS (it->position);
+	  glyph->object = it->object;
+	  glyph->pixel_width = it->pixel_width;
+	  glyph->ascent = glyph_ascent;
+	  glyph->descent = it->descent;
+	  glyph->voffset = it->voffset;
+          //	  glyph->type = IMAGE_GLYPH;
+	  glyph->type = XWIDGET_GLYPH;          
+          
+	  glyph->multibyte_p = it->multibyte_p;
+	  glyph->left_box_line_p = it->start_of_box_run_p;
+	  glyph->right_box_line_p = it->end_of_box_run_p;
+	  glyph->overlaps_vertically_p = 0;
+          glyph->padding_p = 0;
+	  glyph->glyph_not_available_p = 0;
+	  glyph->face_id = it->face_id;
+          glyph->u.xwidget_id = it->xwidget_id;
+          //	  glyph->slice = slice;
+	  glyph->font_type = FONT_TYPE_UNKNOWN;
+	  ++it->glyph_row->used[area];
+	}
+      else
+	IT_EXPAND_MATRIX_WIDTH (it, area);
+    }
+}
+
 
 /* Append a stretch glyph to IT->glyph_row.  OBJECT is the source
    of the glyph, WIDTH and HEIGHT are the width and height of the
@@ -21462,6 +21660,8 @@
     produce_image_glyph (it);
   else if (it->what == IT_STRETCH)
     produce_stretch_glyph (it);
+  else if (it->what == IT_XWIDGET)
+    produce_xwidget_glyph (it);
 
   /* Accumulate dimensions.  Note: can't assume that it->descent > 0
      because this isn't true for images with `:ascent 100'.  */

=== modified file 'src/xterm.c'
--- src/xterm.c	2008-03-29 07:46:06 +0000
+++ src/xterm.c	2008-05-06 15:20:29 +0000
@@ -73,6 +73,7 @@
 #include "ccl.h"
 #include "frame.h"
 #include "dispextern.h"
+#include "xwidget.h"
 #include "fontset.h"
 #include "termhooks.h"
 #include "termopts.h"
@@ -86,6 +87,7 @@
 #include "process.h"
 #include "atimer.h"
 #include "keymap.h"
+//#include "xwidget.h"
 
 #ifdef USE_X_TOOLKIT
 #include <X11/Shell.h>
@@ -2850,6 +2852,7 @@
 {
   int relief_drawn_p = 0;
 
+  printf("x_draw_glyph_string: %d\n",s->first_glyph->type);
   /* If S draws into the background of its successors, draw the
      background of the successors first so that S can draw into it.
      This makes S->next use XDrawString instead of XDrawImageString.  */
@@ -2903,6 +2906,10 @@
       x_draw_image_glyph_string (s);
       break;
 
+    case XWIDGET_GLYPH:
+      x_draw_xwidget_glyph_string (s);
+      break;
+
     case STRETCH_GLYPH:
       x_draw_stretch_glyph_string (s);
       break;

=== added file 'src/xwidget.c'
--- src/xwidget.c	1970-01-01 00:00:00 +0000
+++ src/xwidget.c	2008-05-07 23:02:17 +0000
@@ -0,0 +1,291 @@
+#include <config.h>
+
+/* On 4.3 these lose if they come after xterm.h.  */
+/* Putting these at the beginning seems to be standard for other .c files.  */
+#include <signal.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_X_WINDOWS
+
+#include "lisp.h"
+#include "blockinput.h"
+
+/* Need syssignal.h for various externs and definitions that may be required
+   by some configurations for calls to signal later in this source file.  */
+#include "syssignal.h"
+
+/* This may include sys/types.h, and that somehow loses
+   if this is not done before the other system files.  */
+#include "xterm.h"
+#include <X11/cursorfont.h>
+
+/* Load sys/types.h if not already loaded.
+   In some systems loading it twice is suicidal.  */
+#ifndef makedev
+#include <sys/types.h>
+#endif /* makedev */
+
+#ifdef BSD_SYSTEM
+#include <sys/ioctl.h>
+#endif /* ! defined (BSD_SYSTEM) */
+
+#include "systime.h"
+
+#ifndef INCLUDED_FCNTL
+#include <fcntl.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <sys/stat.h>
+/* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed.  */
+/* #include <sys/param.h>  */
+
+#include "charset.h"
+#include "character.h"
+#include "coding.h"
+#include "ccl.h"
+#include "frame.h"
+#include "dispextern.h"
+#include "xwidget.h"
+#include "fontset.h"
+#include "termhooks.h"
+#include "termopts.h"
+#include "termchar.h"
+#include "emacs-icon.h"
+#include "disptab.h"
+#include "buffer.h"
+#include "window.h"
+#include "keyboard.h"
+#include "intervals.h"
+#include "process.h"
+#include "atimer.h"
+#include "keymap.h"
+//#include "xwidget.h"
+
+#ifdef USE_X_TOOLKIT
+#include <X11/Shell.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+
+#include "gtkutil.h"
+#include "font.h"
+#endif
+
+/*
+each xwidget instance is described by this struct.
+ */
+struct xwidget{
+  int type;
+  GtkWidget* widget;
+  GtkWindow* widgetwindow;
+  char* title;
+  int initialized;
+};
+
+//just a fixed array of xwidgets for now
+struct xwidget xwidgets[100];
+
+
+  
+static int once=0;
+
+
+//GtkWidget *button;
+//GtkWindow *xxwindow ;
+//GtkFixed *fixed ;
+//GdkWindow *parent;
+    
+Lisp_Object Qxwidget,
+  Qxwidget_id,
+  Qtitle;
+extern Lisp_Object QCdata, QCtype;
+
+/**/
+void x_draw_xwidget_glyph_string (s)
+     struct glyph_string *s;
+{
+/*
+  called from xterm.c:x_draw_glyph_string()
+  similar to x_draw_image_glyph_string
+ */
+  int box_line_hwidth = eabs (s->face->box_line_width);
+  int box_line_vwidth = max (s->face->box_line_width, 0);
+  int height = s->height;
+  Pixmap pixmap = None;
+  
+  //just debug print interesting values for now
+  printf("x_draw_xwidget_glyph_string: id:%d %d %d  (%d,%d,%d,%d)\n",s->xwidget_id, box_line_hwidth, box_line_vwidth, s->x,s->y,s->height,s->width);
+  Screen *screen = FRAME_X_SCREEN (s->f);
+   int depth = DefaultDepthOfScreen (screen); //FIXME
+  ///////////////////////////////////////////////////////
+  // stuff that affects x,y: menu, toolbar, scrollbar
+  int x=s->x;
+  int y=s->y;
+  
+  if(!xwidgets[s->xwidget_id].initialized){
+    printf("once for xwidget %d\n",s->xwidget_id);
+    xwidgets[s->xwidget_id].initialized=1;
+
+    GtkWidget *widget;
+
+    switch(xwidgets[s->xwidget_id].type){
+    case 1:
+      printf("mk button\n");
+      widget=GTK_WIDGET(gtk_button_new_with_label (    xwidgets[s->xwidget_id].title));
+      break;
+    case 2:
+      printf("mk togglebutton\n");
+      widget=GTK_WIDGET(gtk_toggle_button_new_with_label (    xwidgets[s->xwidget_id].title));
+      break;
+    case 3:
+
+      widget=GTK_WIDGET(gtk_socket_new ());
+      printf("mk socket\n");
+      break;
+    }
+        xwidgets[s->xwidget_id].widget = widget;
+    //s->window   Window window; is an xwindows XID
+    //    parent=gdk_window_foreign_new (s->window);
+    //    g_assert(parent);
+    xwidgets[s->xwidget_id].widgetwindow = GTK_WINDOW(gtk_window_new (GTK_WINDOW_TOPLEVEL)); //GTK_WINDOW_POPUP somehow works better than GTK_TOPLEVEL
+    gtk_widget_set_size_request ( xwidgets[s->xwidget_id].widget ,s->background_width,s->height);
+    gtk_fixed_put(GTK_FIXED(getGwfixed()),xwidgets[s->xwidget_id].widget ,x,y);
+    gtk_widget_show_all (xwidgets[s->xwidget_id].widget );
+    if(GTK_SOCKET(widget))
+      printf("socket id:%x %d\n", gtk_socket_get_id (GTK_SOCKET(widget)), gtk_socket_get_id (GTK_SOCKET(widget)));
+  }
+  gtk_fixed_move(GTK_FIXED(getGwfixed()),xwidgets[s->xwidget_id].widget ,x,y);
+}
+
+
+void
+syms_of_xwidget ()
+{
+  int i;
+  Qxwidget = intern ("xwidget");
+  staticpro (&Qxwidget);
+  Qxwidget_id = intern (":xwidget-id");
+  staticpro (&Qxwidget_id);
+  Qtitle = intern (":title");
+  staticpro (&Qtitle);
+
+  for(i=0;i<100;i++)
+    xwidgets[i].initialized=0;
+}
+
+
+/* Value is non-zero if OBJECT is a valid Lisp xwidget specification.  A
+   valid xwidget specification is a list whose car is the symbol
+   `xwidget', and whose rest is a property list.  The property list must
+   contain a value for key `:type'.  That value must be the name of a
+   supported xwidget type.  The rest of the property list depends on the
+   xwidget type.  */
+
+int valid_xwidget_p (object) Lisp_Object object;
+{
+  int valid_p = 0;
+
+  if (XWIDGETP (object))
+    {
+      /* Lisp_Object tem; */
+
+      /* for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem)) */
+      /*   if (EQ (XCAR (tem), QCtype)) */
+      /*     { */
+      /*       tem = XCDR (tem); */
+      /*       if (CONSP (tem) && SYMBOLP (XCAR (tem))) */
+      /*         { */
+      /*   	struct xwidget_type *type; */
+      /*   	type = lookup_xwidget_type (XCAR (tem)); */
+      /*   	if (type) */
+      /*   	  valid_p = type->valid_p (object); */
+      /*         } */
+
+      /*       break; */
+      /*     } */
+      //never mind type support for now
+      valid_p = 1;
+    }
+
+  return valid_p;
+}
+
+//type support nevermind for now
+
+/* /\* List of supported image types.  Use define_image_type to add new */
+/*    types.  Use lookup_image_type to find a type for a given symbol.  *\/ */
+
+/* static struct wxidget_type *wxidget_types; */
+
+/* /\* Look up xwidget type SYMBOL, and return a pointer to its xwidget_type */
+/*    structure.  Value is null if SYMBOL is not a known image type.  *\/ */
+
+/* static INLINE struct xwidget_type *lookup_xwidget_type (Lisp_Object symbol) */
+/* { */
+/*   struct xwidget_type *type; */
+
+/*   for (type = xwidget_types; type; type = type->next) */
+/*     if (EQ (symbol, *type->type)) */
+/*       break; */
+
+/*   return type; */
+/* } */
+
+
+
+Lisp_Object
+xwidget_spec_value (spec, key, found)
+     Lisp_Object spec, key;
+     int *found;
+{
+  Lisp_Object tail;
+
+  xassert (valid_xwidget_p (spec));
+
+  for (tail = XCDR (spec);
+       CONSP (tail) && CONSP (XCDR (tail));
+       tail = XCDR (XCDR (tail)))
+    {
+      if (EQ (XCAR (tail), key))
+	{
+	  if (found)
+	    *found = 1;
+	  return XCAR (XCDR (tail));
+	}
+    }
+
+  if (found)
+    *found = 0;
+  return Qnil;
+}
+
+
+
+int
+lookup_xwidget (spec)
+     Lisp_Object spec;
+{
+  
+  int found=0,found1=0,found2=0;
+  Lisp_Object value;
+  value= xwidget_spec_value(spec, Qxwidget_id, &found1);
+  int id=INTEGERP (value) ? XFASTINT (value) : 0; //id 0 by default, but id must be unique so this is dumb
+      
+  struct xwidget* xw=&xwidgets[id];
+  value=xwidget_spec_value(spec, QCtype,&found);
+  xw->type=INTEGERP (value) ? XFASTINT (value) : 1; //ok
+  value=xwidget_spec_value(spec, Qtitle, &found2);
+  xw->title=STRINGP(value)?SDATA(value):"?";
+  printf("xwidget_id:%d type:%d found:%d %d %d title:%s\n",id,  xw->type, found,found1,found2, xw->title);
+
+  return id;
+}

=== added file 'src/xwidget.h'
--- src/xwidget.h	1970-01-01 00:00:00 +0000
+++ src/xwidget.h	2008-05-06 19:08:12 +0000
@@ -0,0 +1,27 @@
+void x_draw_xwidget_glyph_string P_ ((struct glyph_string *s));
+void syms_of_xwidget ();
+
+extern Lisp_Object Qxwidget;
+/* Test for xwidget (xwidget . spec)  (car must be the symbol xwidget)*/
+#define XWIDGETP(x) (CONSP (x) && EQ (XCAR (x), Qxwidget))
+
+int valid_xwidget_p (Lisp_Object object) ;
+
+
+
+struct xwidget_type
+{
+  /* A symbol uniquely identifying the xwidget type, */
+  Lisp_Object *type;
+
+  /* Check that SPEC is a valid image specification for the given
+     image type.  Value is non-zero if SPEC is valid.  */
+  int (* valid_p) P_ ((Lisp_Object spec));
+
+  /* Next in list of all supported image types.  */
+  struct xwidget_type *next;
+};
+                             
+
+static INLINE struct xwidget_type *lookup_xwidget_type (Lisp_Object symbol);
+


[-- Attachment #3: Type: text/plain, Size: 19 bytes --]


-- 
Joakim Verona

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-07 23:23 embedding gtk widgets in a buffer joakim
  2008-05-08  0:21 ` joakim
@ 2008-05-08  9:02 ` BVK
  2008-05-08 22:28 ` Richard M Stallman
  2008-05-10 21:07 ` joakim
  3 siblings, 0 replies; 20+ messages in thread
From: BVK @ 2008-05-08  9:02 UTC (permalink / raw
  To: joakim; +Cc: emacs-devel

On Thu, May 8, 2008 at 4:53 AM,  <joakim@verona.se> wrote:
>
> Heres a screenshot:
> http://www.emacswiki.org/cgi-bin/wiki/EmacsXembedScreenshot
>

Looking at the screenshot above, i think it would be very nice if
customize buffers can make use of them, when emacs is running in gui
mode.


-- 
bvk-chaitanya




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-07 23:23 embedding gtk widgets in a buffer joakim
  2008-05-08  0:21 ` joakim
  2008-05-08  9:02 ` BVK
@ 2008-05-08 22:28 ` Richard M Stallman
  2008-05-08 23:13   ` joakim
  2008-05-09  8:34   ` YAMAMOTO Mitsuharu
  2008-05-10 21:07 ` joakim
  3 siblings, 2 replies; 20+ messages in thread
From: Richard M Stallman @ 2008-05-08 22:28 UTC (permalink / raw
  To: joakim; +Cc: emacs-devel

    - callback interface for the widgets. It would be nice with some ideas
    how to do this. For instance:
      - button pressed handler

The natural way is for this to generate events, and when those events
reach the main loop, they will do whatever it is.

      - when a xembed widget is ready, a callback to start an external
      program in the widget would be nice, now it has to be done manually on
      the cmd line

This callback does not need to be visible from Lisp.
When you create the widget, you specify the command and args
for the command to start the program.  In the C code,
Emacs can handle the callback by starting it.

    - 2 windows showing the same buffer doesnt quite work and is probably tricky

It would be a pain in the neck to have buffers that are not allowed to
appear in more than one window, but this may be necessary for the
xembed case.

Buttons in the buffer ought to be able to work on more than one Emacs
window.

The only way I can think of to make the xembed widgets work in more
than one Emacs window is if you can tell the other program to display
in a pixmap, and then Emacs redisplay would copy that pixmap to the
screen.




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-08 22:28 ` Richard M Stallman
@ 2008-05-08 23:13   ` joakim
  2008-05-08 23:24     ` Lennart Borgman (gmail)
                       ` (2 more replies)
  2008-05-09  8:34   ` YAMAMOTO Mitsuharu
  1 sibling, 3 replies; 20+ messages in thread
From: joakim @ 2008-05-08 23:13 UTC (permalink / raw
  To: rms; +Cc: emacs-devel

Richard M Stallman <rms@gnu.org> writes:

>     - callback interface for the widgets. It would be nice with some ideas
>     how to do this. For instance:
>       - button pressed handler
>
> The natural way is for this to generate events, and when those events
> reach the main loop, they will do whatever it is.

Ok, I will look into this. does "whatever it is" include calling a
callback I associate with the widget?

>
>       - when a xembed widget is ready, a callback to start an external
>       program in the widget would be nice, now it has to be done manually on
>       the cmd line
>
> This callback does not need to be visible from Lisp.
> When you create the widget, you specify the command and args
> for the command to start the program.  In the C code,
> Emacs can handle the callback by starting it.

Ok. I was thinking more along having the generic callback interface
solve this too, and also that Id like to create the process in lisp, so
I could bind a sentinel to it, and send commands to it through stdio,
etc.


>
>     - 2 windows showing the same buffer doesnt quite work and is probably tricky
>
> It would be a pain in the neck to have buffers that are not allowed to
> appear in more than one window, but this may be necessary for the
> xembed case.
>
> Buttons in the buffer ought to be able to work on more than one Emacs
> window.
>
> The only way I can think of to make the xembed widgets work in more
> than one Emacs window is if you can tell the other program to display
> in a pixmap, and then Emacs redisplay would copy that pixmap to the
> screen.

Well, I wasnt planning on inhibiting the display of a buffer in more
than one window. The problem is also the same for gtk_sockets, which
implement xembed,  and gtk_buttons etc. They can't appear in more then
one place of the screen at the same time. (Or can they?)

I thought of 2 solutions:

- create new instances of the widgets for every window the widget is
  supposed to be shown. This is visualy appealing, but troublesome to
  implement, at least if each widget is really going to look like its
  counterpart in another window, especially for xembed.

- the selected window and other windows are not drawn the same way. The
  selected window contains the real live widgets. The non-selected
  windows show some kind of shadow copy of the widget, in the simplest
  case a grey rectangle, more elaborately a bitmap copy of the widget at
  the time the window selection switch was made.

I will implement the 2nd solution to begin with, since it seems simplest.  


-- 
Joakim Verona




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-08 23:13   ` joakim
@ 2008-05-08 23:24     ` Lennart Borgman (gmail)
  2008-05-10  8:55     ` Richard M Stallman
  2008-05-10  8:55     ` Richard M Stallman
  2 siblings, 0 replies; 20+ messages in thread
From: Lennart Borgman (gmail) @ 2008-05-08 23:24 UTC (permalink / raw
  To: joakim; +Cc: rms, emacs-devel

joakim@verona.se wrote:
> - the selected window and other windows are not drawn the same way. The
>   selected window contains the real live widgets. The non-selected
>   windows show some kind of shadow copy of the widget, in the simplest
>   case a grey rectangle, more elaborately a bitmap copy of the widget at
>   the time the window selection switch was made.

And then of course there is the case that non of these windows is 
selected. That may be an important case too (for example with an 
embedded browser).




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-08 22:28 ` Richard M Stallman
  2008-05-08 23:13   ` joakim
@ 2008-05-09  8:34   ` YAMAMOTO Mitsuharu
  1 sibling, 0 replies; 20+ messages in thread
From: YAMAMOTO Mitsuharu @ 2008-05-09  8:34 UTC (permalink / raw
  To: rms; +Cc: joakim, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 584 bytes --]

>>>>> On Thu, 08 May 2008 18:28:45 -0400, Richard M Stallman <rms@gnu.org> said:

> Buttons in the buffer ought to be able to work on more than one
> Emacs window.

> The only way I can think of to make the xembed widgets work in more
> than one Emacs window is if you can tell the other program to
> display in a pixmap, and then Emacs redisplay would copy that pixmap
> to the screen.

The attached image may not be the exact realization of what you mean,
but this kind of image creation might be useful in some cases.

				     YAMAMOTO Mitsuharu
				mituharu@math.s.chiba-u.ac.jp

[-- Attachment #2: button.png --]
[-- Type: image/png, Size: 20483 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-08 23:13   ` joakim
  2008-05-08 23:24     ` Lennart Borgman (gmail)
@ 2008-05-10  8:55     ` Richard M Stallman
  2008-05-10 11:55       ` joakim
  2008-05-10  8:55     ` Richard M Stallman
  2 siblings, 1 reply; 20+ messages in thread
From: Richard M Stallman @ 2008-05-10  8:55 UTC (permalink / raw
  To: joakim; +Cc: emacs-devel

    > The natural way is for this to generate events, and when those events
    > reach the main loop, they will do whatever it is.

    Ok, I will look into this. does "whatever it is" include calling a
    callback I associate with the widget?

It means anything you want to do.

    Ok. I was thinking more along having the generic callback interface
    solve this too, and also that Id like to create the process in lisp, so
    I could bind a sentinel to it, and send commands to it through stdio,
    etc.

You can't call general Lisp code from a GTK callback.
Please design a way to implement the features you want
without running any Lisp code.




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-08 23:13   ` joakim
  2008-05-08 23:24     ` Lennart Borgman (gmail)
  2008-05-10  8:55     ` Richard M Stallman
@ 2008-05-10  8:55     ` Richard M Stallman
  2008-05-10  9:58       ` joakim
  2 siblings, 1 reply; 20+ messages in thread
From: Richard M Stallman @ 2008-05-10  8:55 UTC (permalink / raw
  To: joakim; +Cc: emacs-devel

    - create new instances of the widgets for every window the widget is
      supposed to be shown. This is visualy appealing, but troublesome to
      implement, at least if each widget is really going to look like its
      counterpart in another window, especially for xembed.

Would that work?  In the case of xembed, can both widgets talk
to the same process and show the same output?

    - the selected window and other windows are not drawn the same way. The
      selected window contains the real live widgets. The non-selected
      windows show some kind of shadow copy of the widget, in the simplest
      case a grey rectangle, more elaborately a bitmap copy of the widget at
      the time the window selection switch was made.

That ought to do the job, if it is possible to get the whole output.
I see a possible problem in the case where the widget is partially or
wholely scrolled off the screen.




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-10  8:55     ` Richard M Stallman
@ 2008-05-10  9:58       ` joakim
  2008-05-10 10:22         ` Lennart Borgman (gmail)
  2008-05-11  7:34         ` Richard M Stallman
  0 siblings, 2 replies; 20+ messages in thread
From: joakim @ 2008-05-10  9:58 UTC (permalink / raw
  To: rms; +Cc: emacs-devel

Richard M Stallman <rms@gnu.org> writes:

>     - create new instances of the widgets for every window the widget is
>       supposed to be shown. This is visualy appealing, but troublesome to
>       implement, at least if each widget is really going to look like its
>       counterpart in another window, especially for xembed.
>
> Would that work?  In the case of xembed, can both widgets talk
> to the same process and show the same output?

No, in the case of xembed it would probably not work very well.
>
>     - the selected window and other windows are not drawn the same way. The
>       selected window contains the real live widgets. The non-selected
>       windows show some kind of shadow copy of the widget, in the simplest
>       case a grey rectangle, more elaborately a bitmap copy of the widget at
>       the time the window selection switch was made.
>
> That ought to do the job, if it is possible to get the whole output.

Just to clarify, the placeholder widgets in non-selected windows, would
be placeholders, not live buttons. They wont become live again until
that window is selected again. The placeholder widgets are a snapshot
copy of the state the widgets had when they were live at that position.
(It should be possible to update the placeholder widgets more often, but
I wont start out with that premise)

Im not quite sure if it would be posible to get a bitmap dump of
any sort of widget either, xembed is again probably a problem.

> I see a possible problem in the case where the widget is partially or
> wholely scrolled off the screen.

I had in mind getting the widgets to temporarily render into offscreen
bitmaps. If that's at all possible, the clipping of the widget should not
be a problem.

-- 
Joakim Verona




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-10  9:58       ` joakim
@ 2008-05-10 10:22         ` Lennart Borgman (gmail)
  2008-05-11  7:34         ` Richard M Stallman
  1 sibling, 0 replies; 20+ messages in thread
From: Lennart Borgman (gmail) @ 2008-05-10 10:22 UTC (permalink / raw
  To: joakim; +Cc: rms, emacs-devel

joakim@verona.se wrote:
>> I see a possible problem in the case where the widget is partially or
>> wholely scrolled off the screen.
> 
> I had in mind getting the widgets to temporarily render into offscreen
> bitmaps. If that's at all possible, the clipping of the widget should not
> be a problem.

Does not xembed take care of clipping? (I know nothing about it.)




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-10  8:55     ` Richard M Stallman
@ 2008-05-10 11:55       ` joakim
  0 siblings, 0 replies; 20+ messages in thread
From: joakim @ 2008-05-10 11:55 UTC (permalink / raw
  To: rms; +Cc: emacs-devel

Richard M Stallman <rms@gnu.org> writes:


>     Ok. I was thinking more along having the generic callback interface
>     solve this too, and also that Id like to create the process in lisp, so
>     I could bind a sentinel to it, and send commands to it through stdio,
>     etc.
>
> You can't call general Lisp code from a GTK callback.
> Please design a way to implement the features you want
> without running any Lisp code.

On Stefans and your suggestion I implemented the gtk callbacks as a new
type of Emacs input event.

It seems to work well now, I can receive button events, and set up
xembed widgets in the input event handler, so thanks for the
suggestions!

-- 
Joakim Verona




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-07 23:23 embedding gtk widgets in a buffer joakim
                   ` (2 preceding siblings ...)
  2008-05-08 22:28 ` Richard M Stallman
@ 2008-05-10 21:07 ` joakim
  2008-05-11  7:35   ` Richard M Stallman
  3 siblings, 1 reply; 20+ messages in thread
From: joakim @ 2008-05-10 21:07 UTC (permalink / raw
  To: emacs-devel


I can now xembed emacs within emacs.

The embedded emacs, however, can't receive keyboard focus. It's
possible, though, to click in the embedded emacs with the mouse to
acivate menus and move the emacs cursor.

Heres the code I'm trying:

DEFUN("xwidget-set-keyboard-grab", Fxwidget_set_keyboard_grab,Sxwidget_set_keyboard_grab,
      2,2,0,
      doc: /* set unset kbd grab for xwidget.*/)
     (xwidget_id,kbd_grab)
     Lisp_Object xwidget_id, kbd_grab;      
{
  struct xwidget *xw;
  int xid=XFASTINT(xwidget_id);
  xw=&xwidgets[xid];
  int kbd_flag=XFASTINT(kbd_grab);
  printf("kbd grab: %d %d\n",xid,kbd_flag);
  if (kbd_flag)
    {
      //      int rv=gtk_widget_activate(xw->widget); //ok, but how deactivate?
      //printf("activation:%d\n",rv);
      //      gtk_window_present(GTK_WINDOW(xw->widget));
      gtk_widget_grab_focus(xw->widget);
    }
      /*
    gdk_keyboard_grab(xw->widget,TRUE,GDK_CURRENT_TIME);
  else
    gdk_keyboard_ungrab(GDK_CURRENT_TIME);
  */
  return Qnil;
}

As you can see I've tried several aproaches to get the gtk socket to get
keyboard events, but none work.

Any hints? I'm going also to try to send a plain XEMBED_WINDOW_ACTIVATE
X message to the widget, but I dont really see why that would work and
the aproaches above wouldnt.



-- 
Joakim Verona




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-10  9:58       ` joakim
  2008-05-10 10:22         ` Lennart Borgman (gmail)
@ 2008-05-11  7:34         ` Richard M Stallman
  1 sibling, 0 replies; 20+ messages in thread
From: Richard M Stallman @ 2008-05-11  7:34 UTC (permalink / raw
  To: joakim; +Cc: emacs-devel

    Just to clarify, the placeholder widgets in non-selected windows, would
    be placeholders, not live buttons. They wont become live again until
    that window is selected again.

I am not sure what a placeholder widget does.
Would it work to click on one of these widgets?
It is supposed to work.

    > I see a possible problem in the case where the widget is partially or
    > wholely scrolled off the screen.

    I had in mind getting the widgets to temporarily render into offscreen
    bitmaps.

If you can do that, it should be easy for Emacs to handle displaying
parts of that bitmap (or pixmap?) onto various parts of the screen as needed,
and translating clicks on any of those parts to give them to the widget.
The widget could be associated with the buffer
and not have any specific location on the screen.




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-10 21:07 ` joakim
@ 2008-05-11  7:35   ` Richard M Stallman
  2008-05-11  8:25     ` joakim
  0 siblings, 1 reply; 20+ messages in thread
From: Richard M Stallman @ 2008-05-11  7:35 UTC (permalink / raw
  To: joakim; +Cc: emacs-devel

    I can now xembed emacs within emacs.

How sick!

    The embedded emacs, however, can't receive keyboard focus.

Many programs would need to get keyboard focus.
The xembed should set up a keymap with a command
to give the focus to that program.

That command could be RET and/or C-c C-c.




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-11  7:35   ` Richard M Stallman
@ 2008-05-11  8:25     ` joakim
  2008-05-11 12:32       ` David Kastrup
  2008-05-11 12:48       ` joakim
  0 siblings, 2 replies; 20+ messages in thread
From: joakim @ 2008-05-11  8:25 UTC (permalink / raw
  To: rms; +Cc: emacs-devel

Richard M Stallman <rms@gnu.org> writes:

>     I can now xembed emacs within emacs.
>
> How sick!

Glad you liked it :)

It makes for a nice demo, and now we can tell people complaining of Gnus
locking up their Emacs sessions to just start a new embedded Emacs!

>
>     The embedded emacs, however, can't receive keyboard focus.
>
> Many programs would need to get keyboard focus.
> The xembed should set up a keymap with a command
> to give the focus to that program.
>
> That command could be RET and/or C-c C-c.

I agree that this is how it should work. I havent found how to implement
yet it though. 

-- 
Joakim Verona




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-11  8:25     ` joakim
@ 2008-05-11 12:32       ` David Kastrup
  2008-05-11 12:48       ` joakim
  1 sibling, 0 replies; 20+ messages in thread
From: David Kastrup @ 2008-05-11 12:32 UTC (permalink / raw
  To: joakim; +Cc: rms, emacs-devel

joakim@verona.se writes:

> Richard M Stallman <rms@gnu.org> writes:
>
>>     I can now xembed emacs within emacs.
>>
>> How sick!
>
> Glad you liked it :)
>
> It makes for a nice demo, and now we can tell people complaining of Gnus
> locking up their Emacs sessions to just start a new embedded Emacs!

Interesting connotations with regard to the use of gnus-slave-mode.  It
probably would be fantastic if one could do this transparently: have
this work on an embedded Emacs with the sole exception that the embedded
gnus does not keep one from switching to other buffers.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-11  8:25     ` joakim
  2008-05-11 12:32       ` David Kastrup
@ 2008-05-11 12:48       ` joakim
  2008-05-11 12:58         ` Lennart Borgman (gmail)
  1 sibling, 1 reply; 20+ messages in thread
From: joakim @ 2008-05-11 12:48 UTC (permalink / raw
  To: rms; +Cc: emacs-devel

joakim@verona.se writes:

> Richard M Stallman <rms@gnu.org> writes:

>> Many programs would need to get keyboard focus.
>> The xembed should set up a keymap with a command
>> to give the focus to that program.
>>
>> That command could be RET and/or C-c C-c.


Apparently this line in xterm.c steals kbd input:

          /* Don't pass keys to GTK.  A Tab will shift focus to the
             tool bar in GTK 2.4.  Keys will still go to menus and
             dialogs because in that case popup_activated is TRUE
             (see above).  */
          *finish = X_EVENT_DROP;

When commented out, kbd input goes to embedder and embedded alike, which
is not very convenient of course.

Even though the case of embedding an emacs within an emacs is probably
not a real world case, it exposes problems all more complex application
embedding will have. Keyboard events would need to be filtered by the
embedding emacs, and forwarded to the embedee on a key-by-key basis.

The simplest filter would have 2 states and work somewhat like:
1: send nothing to the embedee
2: send everything except c-c c-c to the embedee

c-c c-c could toggle between states. (initially I will probably have
some single key for this for simplicity)

This is not perfect in general since one might want to send c-c c-c to
the embedee sometimes, but should be good enough to start with. A
separate command might be made to send a synthetic c-c c-c to the
embedee if needed.

A brief summary of current issues with this patch:
- xwidgets currently only works in 1 window in 1 frame.
- some graphics bugs when moving widgets.
- keyboard handling of xembedded widgets.

All issues seems to be solvable.


-- 
Joakim Verona




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-11 12:48       ` joakim
@ 2008-05-11 12:58         ` Lennart Borgman (gmail)
  2008-05-12  4:38           ` tomas
  0 siblings, 1 reply; 20+ messages in thread
From: Lennart Borgman (gmail) @ 2008-05-11 12:58 UTC (permalink / raw
  To: joakim; +Cc: rms, emacs-devel

joakim@verona.se wrote:
> Keyboard events would need to be filtered by the
> embedding emacs, and forwarded to the embedee on a key-by-key basis.


How do widget libraries (for example wxWidgets) handle similar situations?




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: embedding gtk widgets in a buffer
  2008-05-11 12:58         ` Lennart Borgman (gmail)
@ 2008-05-12  4:38           ` tomas
  0 siblings, 0 replies; 20+ messages in thread
From: tomas @ 2008-05-12  4:38 UTC (permalink / raw
  To: Lennart Borgman (gmail); +Cc: rms, joakim, emacs-devel

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Sun, May 11, 2008 at 02:58:40PM +0200, Lennart Borgman (gmail) wrote:
> joakim@verona.se wrote:
> >Keyboard events would need to be filtered by the
> >embedding emacs, and forwarded to the embedee on a key-by-key basis.
> 
> 
> How do widget libraries (for example wxWidgets) handle similar situations?

As far as I understand it, this is the realm of the keyboard focus
policy -- i.e. there is (hopefully!) an agreement between the user and
the UI as to which widget gets the key presses at the moment.

Very annoying when this agreement isn't there, as happens to me
regularly with firefox-ish browsers :-/

Regards
- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFIJ8niBcgs9XrR2kYRAiw0AJ97n29EMQ5YjemaHaBToXnEdU3AMgCeJONN
RCPQM8sJfQjzzR2YatfIxZ4=
=of1T
-----END PGP SIGNATURE-----




^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2008-05-12  4:38 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-07 23:23 embedding gtk widgets in a buffer joakim
2008-05-08  0:21 ` joakim
2008-05-08  9:02 ` BVK
2008-05-08 22:28 ` Richard M Stallman
2008-05-08 23:13   ` joakim
2008-05-08 23:24     ` Lennart Borgman (gmail)
2008-05-10  8:55     ` Richard M Stallman
2008-05-10 11:55       ` joakim
2008-05-10  8:55     ` Richard M Stallman
2008-05-10  9:58       ` joakim
2008-05-10 10:22         ` Lennart Borgman (gmail)
2008-05-11  7:34         ` Richard M Stallman
2008-05-09  8:34   ` YAMAMOTO Mitsuharu
2008-05-10 21:07 ` joakim
2008-05-11  7:35   ` Richard M Stallman
2008-05-11  8:25     ` joakim
2008-05-11 12:32       ` David Kastrup
2008-05-11 12:48       ` joakim
2008-05-11 12:58         ` Lennart Borgman (gmail)
2008-05-12  4:38           ` tomas

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).