diff options
| -rw-r--r-- | lisp/xwidget-test.el | 4 | ||||
| -rw-r--r-- | src/xwidget.c | 143 |
2 files changed, 112 insertions, 35 deletions
diff --git a/lisp/xwidget-test.el b/lisp/xwidget-test.el index 29c98684df1..16084c6188e 100644 --- a/lisp/xwidget-test.el +++ b/lisp/xwidget-test.el | |||
| @@ -34,7 +34,7 @@ | |||
| 34 | (xwidget-insert 15 2 "toggle" 60 30 2) | 34 | (xwidget-insert 15 2 "toggle" 60 30 2) |
| 35 | (xwidget-insert 30 3 "emacs" 400 200 3) | 35 | (xwidget-insert 30 3 "emacs" 400 200 3) |
| 36 | (xwidget-insert 20 4 "slider" 100 50 4) | 36 | (xwidget-insert 20 4 "slider" 100 50 4) |
| 37 | (xwidget-insert 40 3 "uzbl" 400 400 5) | 37 | ;; (xwidget-insert 40 3 "uzbl" 400 400 5) |
| 38 | (define-key (current-local-map) [xwidget-event] 'xwidget-handler-demo-basic) | 38 | (define-key (current-local-map) [xwidget-event] 'xwidget-handler-demo-basic) |
| 39 | ) | 39 | ) |
| 40 | 40 | ||
| @@ -105,4 +105,4 @@ | |||
| 105 | 105 | ||
| 106 | ; (xwidget-resize-hack 1 200 200) | 106 | ; (xwidget-resize-hack 1 200 200) |
| 107 | 107 | ||
| 108 | ;(xwidget-demo-basic) \ No newline at end of file | 108 | ;(xwidget-demo-basic) |
diff --git a/src/xwidget.c b/src/xwidget.c index dc103601e5c..9d977ced256 100644 --- a/src/xwidget.c +++ b/src/xwidget.c | |||
| @@ -56,6 +56,7 @@ | |||
| 56 | #include <X11/Shell.h> | 56 | #include <X11/Shell.h> |
| 57 | #endif | 57 | #endif |
| 58 | #include <X11/extensions/Xcomposite.h> | 58 | #include <X11/extensions/Xcomposite.h> |
| 59 | #include <X11/extensions/Xrender.h> | ||
| 59 | 60 | ||
| 60 | #ifdef HAVE_SYS_TIME_H | 61 | #ifdef HAVE_SYS_TIME_H |
| 61 | #include <sys/time.h> | 62 | #include <sys/time.h> |
| @@ -141,6 +142,78 @@ send_xembed_ready_event (int xwid, int xembedid) | |||
| 141 | 142 | ||
| 142 | } | 143 | } |
| 143 | 144 | ||
| 145 | int xwidget_query_composition_called = 0; | ||
| 146 | int hasNamePixmap = 0; | ||
| 147 | |||
| 148 | |||
| 149 | int | ||
| 150 | xwidget_has_composition(void){ | ||
| 151 | int event_base, error_base; | ||
| 152 | Display* dpy = GDK_DISPLAY (); | ||
| 153 | int i; | ||
| 154 | if(xwidget_query_composition_called) | ||
| 155 | return hasNamePixmap; | ||
| 156 | xwidget_query_composition_called = 1; | ||
| 157 | |||
| 158 | //do this once in an emacs session | ||
| 159 | |||
| 160 | if(gdk_display_supports_composite(gdk_display_get_default ())){ | ||
| 161 | hasNamePixmap = 1; | ||
| 162 | }else{ | ||
| 163 | return 0; | ||
| 164 | } | ||
| 165 | |||
| 166 | //redirect all toplevel windows to backing store. | ||
| 167 | //this should probably be optimized so only the gtk sockets we care for get redirected | ||
| 168 | //otoh, the wm might quite possibly already have requested backing store so the code is | ||
| 169 | //probably noop anyway | ||
| 170 | printf("enabling composition\n"); | ||
| 171 | for ( i = 0; i < ScreenCount( dpy ); i++ ) | ||
| 172 | XCompositeRedirectSubwindows( dpy, RootWindow( dpy, i ), | ||
| 173 | CompositeRedirectAutomatic ); | ||
| 174 | return 1; | ||
| 175 | |||
| 176 | |||
| 177 | } | ||
| 178 | |||
| 179 | void | ||
| 180 | xwidget_setup_socket_composition(struct xwidget* xw) | ||
| 181 | { | ||
| 182 | //do this for every gtk_socket | ||
| 183 | //XCompositeRedirectWindow(); should probably replace the global backing request | ||
| 184 | //now residing in xwidget_has_composition() | ||
| 185 | |||
| 186 | // int xid = gtk_socket_get_plug_window (GTK_SOCKET (xw->widget)); | ||
| 187 | // Display* dpy = GDK_DISPLAY (); | ||
| 188 | |||
| 189 | /* | ||
| 190 | XWindowAttributes attr; | ||
| 191 | XGetWindowAttributes( dpy, xid, &attr ); | ||
| 192 | |||
| 193 | XRenderPictFormat *format = XRenderFindVisualFormat( dpy, attr.visual ); | ||
| 194 | int hasAlpha = ( format->type == PictTypeDirect && format->direct.alphaMask ); | ||
| 195 | int x = attr.x; | ||
| 196 | int y = attr.y; | ||
| 197 | int width = attr.width; | ||
| 198 | int height = attr.height; | ||
| 199 | |||
| 200 | |||
| 201 | XRenderPictureAttributes pa; | ||
| 202 | pa.subwindow_mode = IncludeInferiors; // Don't clip child widgets | ||
| 203 | |||
| 204 | Picture picture = XRenderCreatePicture( dpy, xid, format, CPSubwindowMode, &pa ); | ||
| 205 | // p_xid = XCompositeNameWindowPixmap( GDK_DISPLAY (), GDK_WINDOW_XID(xid)) ; | ||
| 206 | |||
| 207 | //this is the actual drawing call that probably should be somewhere else: | ||
| 208 | XRenderComposite( dpy, hasAlpha ? PictOpOver : PictOpSrc, picture, None, | ||
| 209 | dest.x11RenderHandle(), 0, 0, 0, 0, destX, destY, width, height ); | ||
| 210 | */ | ||
| 211 | } | ||
| 212 | |||
| 213 | void | ||
| 214 | xwidget_end_composition(struct xwidget* w){ | ||
| 215 | //XCompositeUnredirectWindow(); stop redirecting, should be called when the socket is destroyed | ||
| 216 | } | ||
| 144 | 217 | ||
| 145 | void | 218 | void |
| 146 | xwidget_init (struct xwidget *xw, struct glyph_string *s, int x, int y) | 219 | xwidget_init (struct xwidget *xw, struct glyph_string *s, int x, int y) |
| @@ -196,10 +269,14 @@ xwidget_init (struct xwidget *xw, struct glyph_string *s, int x, int y) | |||
| 196 | gtk_socket_get_id (GTK_SOCKET (xw->widget))); | 269 | gtk_socket_get_id (GTK_SOCKET (xw->widget))); |
| 197 | send_xembed_ready_event (xw->id, | 270 | send_xembed_ready_event (xw->id, |
| 198 | gtk_socket_get_id (GTK_SOCKET (xw->widget))); | 271 | gtk_socket_get_id (GTK_SOCKET (xw->widget))); |
| 272 | if(xwidget_has_composition()) | ||
| 273 | xwidget_setup_socket_composition(xw); | ||
| 199 | break; | 274 | break; |
| 200 | } | 275 | } |
| 201 | } | 276 | } |
| 202 | 277 | ||
| 278 | |||
| 279 | |||
| 203 | void | 280 | void |
| 204 | xwidget_draw_phantom (struct xwidget *xw, int x, int y, int clipx, int clipy, | 281 | xwidget_draw_phantom (struct xwidget *xw, int x, int y, int clipx, int clipy, |
| 205 | struct glyph_string *s) | 282 | struct glyph_string *s) |
| @@ -216,20 +293,21 @@ xwidget_draw_phantom (struct xwidget *xw, int x, int y, int clipx, int clipy, | |||
| 216 | GdkPixmap *xw_snapshot = NULL; | 293 | GdkPixmap *xw_snapshot = NULL; |
| 217 | GdkGC *gdkgc = NULL; | 294 | GdkGC *gdkgc = NULL; |
| 218 | GdkNativeWindow p_xid; | 295 | GdkNativeWindow p_xid; |
| 219 | GdkNativeWindow xid; | 296 | GdkWindow* xid; |
| 220 | 297 | ||
| 221 | if (0 | 298 | if (xw->type == 3 && xwidget_has_composition()){ |
| 222 | //xw->type == 3 //this doesnt work atm | ||
| 223 | ) { | ||
| 224 | //its a gtk_socket, get_snapshot() doesnt work so try using composition methods | 299 | //its a gtk_socket, get_snapshot() doesnt work so try using composition methods |
| 225 | xid = gtk_socket_get_plug_window (GTK_SOCKET (xw->widget)); | ||
| 226 | p_xid = XCompositeNameWindowPixmap( GDK_DISPLAY (), GDK_WINDOW_XID(xid)) ; | ||
| 227 | //xw_snapshot = gdk_pixmap_foreign_new_for_display(GDK_DISPLAY(), p_xid); | 300 | //xw_snapshot = gdk_pixmap_foreign_new_for_display(GDK_DISPLAY(), p_xid); |
| 301 | xid = gtk_socket_get_plug_window (GTK_SOCKET (xw->widget)); | ||
| 302 | //should check the xid here, because it could be invalid | ||
| 303 | //p_xid = XCompositeNameWindowPixmap( GDK_DISPLAY (), GDK_WINDOW_XID(xid)) ; | ||
| 304 | |||
| 228 | printf("phantom socket 1: %d %d\n", xid, p_xid); | 305 | printf("phantom socket 1: %d %d\n", xid, p_xid); |
| 229 | xw_snapshot = gdk_pixmap_foreign_new(p_xid); //wraps the native window in a gdk windw, but it crashes! | 306 | xw_snapshot = gdk_pixmap_foreign_new(GDK_WINDOW_XID(xid)); //wraps the native window in a gdk windw, but it crashes! |
| 230 | printf("2\n"); | 307 | printf("2\n"); |
| 231 | }else { | 308 | }else { |
| 232 | //if its not a socket, its got a snapshot method that works | 309 | //if its not a socket, its got a snapshot method that works |
| 310 | //or if we dont have composition well try for sockets, but probably get a grey rect | ||
| 233 | printf("phantom other\n"); | 311 | printf("phantom other\n"); |
| 234 | xw_snapshot = gtk_widget_get_snapshot (xw->widget, NULL); | 312 | xw_snapshot = gtk_widget_get_snapshot (xw->widget, NULL); |
| 235 | } | 313 | } |
| @@ -282,7 +360,7 @@ x_draw_xwidget_glyph_string (struct glyph_string *s) | |||
| 282 | //and its phantom counterpart | 360 | //and its phantom counterpart |
| 283 | clipx = min (xw->width, WINDOW_RIGHT_EDGE_X (s->w) - x); | 361 | clipx = min (xw->width, WINDOW_RIGHT_EDGE_X (s->w) - x); |
| 284 | clipy = min (xw->height, | 362 | clipy = min (xw->height, |
| 285 | WINDOW_BOTTOM_EDGE_Y (s->w) - WINDOW_MODE_LINE_HEIGHT (s->w) - y); | 363 | WINDOW_BOTTOM_EDGE_Y (s->w) - WINDOW_MODE_LINE_HEIGHT (s->w) - y); |
| 286 | 364 | ||
| 287 | 365 | ||
| 288 | //TODO: | 366 | //TODO: |
| @@ -353,9 +431,8 @@ DEFUN ("xwidget-embed-steal-window", Fxwidget_embed_steal_window, Sxwidget_embed | |||
| 353 | 431 | ||
| 354 | 432 | ||
| 355 | DEFUN ("xwidget-resize-internal", Fxwidget_resize_internal, Sxwidget_resize_internal, 3, 3, 0, doc: | 433 | DEFUN ("xwidget-resize-internal", Fxwidget_resize_internal, Sxwidget_resize_internal, 3, 3, 0, doc: |
| 356 | /* tell existing embed xwidget to steal other window id. */ | ||
| 357 | ) | 434 | ) |
| 358 | (Lisp_Object xwidget_id, Lisp_Object new_width, Lisp_Object new_height) | 435 | (Lisp_Object xwidget_id, Lisp_Object new_width, Lisp_Object new_height) |
| 359 | { | 436 | { |
| 360 | struct xwidget *xw; | 437 | struct xwidget *xw; |
| 361 | int xid = XFASTINT (xwidget_id); | 438 | int xid = XFASTINT (xwidget_id); |
| @@ -413,10 +490,10 @@ DEFUN ("xwidget-set-keyboard-grab", Fxwidget_set_keyboard_grab, Sxwidget_set_key | |||
| 413 | xwidget_owns_kbd = FALSE; | 490 | xwidget_owns_kbd = FALSE; |
| 414 | } | 491 | } |
| 415 | /* | 492 | /* |
| 416 | gdk_keyboard_grab(xw->widget,TRUE,GDK_CURRENT_TIME); | 493 | gdk_keyboard_grab(xw->widget,TRUE,GDK_CURRENT_TIME); |
| 417 | else | 494 | else |
| 418 | gdk_keyboard_ungrab(GDK_CURRENT_TIME); | 495 | gdk_keyboard_ungrab(GDK_CURRENT_TIME); |
| 419 | */ | 496 | */ |
| 420 | return Qnil; | 497 | return Qnil; |
| 421 | } | 498 | } |
| 422 | 499 | ||
| @@ -620,8 +697,8 @@ xwidget_show (struct xwidget *xw) | |||
| 620 | 697 | ||
| 621 | Lisp_Object | 698 | Lisp_Object |
| 622 | xwidget_spec_value ( | 699 | xwidget_spec_value ( |
| 623 | Lisp_Object spec, Lisp_Object key, | 700 | Lisp_Object spec, Lisp_Object key, |
| 624 | int *found) | 701 | int *found) |
| 625 | { | 702 | { |
| 626 | Lisp_Object tail; | 703 | Lisp_Object tail; |
| 627 | 704 | ||
| @@ -716,14 +793,14 @@ xwidget_touch (struct xwidget *xw) | |||
| 716 | 793 | ||
| 717 | /* redisplay has ended, now we should hide untouched xwidgets | 794 | /* redisplay has ended, now we should hide untouched xwidgets |
| 718 | 795 | ||
| 719 | atm this works as follows: only check if xwidgets are displayed in the | 796 | atm this works as follows: only check if xwidgets are displayed in the |
| 720 | "selected window". if not, hide them or phantom them. | 797 | "selected window". if not, hide them or phantom them. |
| 721 | 798 | ||
| 722 | this means valid cases like xwidgets being displayed only once in | 799 | this means valid cases like xwidgets being displayed only once in |
| 723 | non-selected windows, does not work well. they should also be visible | 800 | non-selected windows, does not work well. they should also be visible |
| 724 | in that case not phantomed. | 801 | in that case not phantomed. |
| 725 | 802 | ||
| 726 | */ | 803 | */ |
| 727 | void | 804 | void |
| 728 | xwidget_end_redisplay (struct glyph_matrix *matrix) | 805 | xwidget_end_redisplay (struct glyph_matrix *matrix) |
| 729 | { | 806 | { |
| @@ -783,17 +860,17 @@ xwidget_end_redisplay (struct glyph_matrix *matrix) | |||
| 783 | } | 860 | } |
| 784 | } | 861 | } |
| 785 | 862 | ||
| 786 | for (i = 0; i < MAX_XWIDGETS; i++) | 863 | for (i = 0; i < MAX_XWIDGETS; i++) |
| 787 | { | 864 | { |
| 788 | xw = &xwidgets[i]; | 865 | xw = &xwidgets[i]; |
| 789 | if (xw->initialized) | 866 | if (xw->initialized) |
| 790 | { | 867 | { |
| 791 | if (xw->redisplayed) | 868 | if (xw->redisplayed) |
| 792 | xwidget_show (xw); | 869 | xwidget_show (xw); |
| 793 | else | 870 | else |
| 794 | xwidget_hide (xw); | 871 | xwidget_hide (xw); |
| 795 | } | 872 | } |
| 796 | } | 873 | } |
| 797 | 874 | ||
| 798 | } | 875 | } |
| 799 | 876 | ||