>From 08f07fb2baad3122e8b4b822803fce2b33d95ece Mon Sep 17 00:00:00 2001 From: Timo Savola Date: Tue, 23 Jan 2007 11:55:54 +0200 Subject: [PATCH] xembed-support XEmbed protocol support for Xlib, X-toolkit and GTK+ versions. --- src/gtkutil.c | 6 +++- src/xfns.c | 4 ++ src/xterm.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/xterm.h | 63 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 4 deletions(-) diff --git a/src/gtkutil.c b/src/gtkutil.c index 02e42f7..bb52ebb 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -769,7 +769,11 @@ xg_create_frame_widgets (f) BLOCK_INPUT; - wtop = gtk_window_new (GTK_WINDOW_TOPLEVEL); + if (FRAME_X_EMBEDDED_P (f)) + wtop = gtk_plug_new (f->output_data.x->parent_desc); + else + wtop = gtk_window_new (GTK_WINDOW_TOPLEVEL); + xg_set_screen (wtop, f); wvbox = gtk_vbox_new (FALSE, 0); diff --git a/src/xfns.c b/src/xfns.c index 104b513..716b282 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -2604,6 +2604,10 @@ x_window (f, window_prompting, minibuffer_only) XtManageChild (pane_widget); XtRealizeWidget (shell_widget); + if (FRAME_X_EMBEDDED_P (f)) + XReparentWindow (FRAME_X_DISPLAY (f), XtWindow (shell_widget), + f->output_data.x->parent_desc, 0, 0); + FRAME_X_WINDOW (f) = XtWindow (frame_widget); validate_x_resource_name (); diff --git a/src/xterm.c b/src/xterm.c index bc4fd36..8764ada 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -3306,6 +3306,15 @@ x_detect_focus_change (dpyinfo, event, bufp) FOCUS_IMPLICIT : FOCUS_EXPLICIT), dpyinfo, frame, bufp); break; + + case ClientMessage: + if (event->xclient.message_type == dpyinfo->Xatom_XEMBED) + { + enum xembed_message msg = event->xclient.data.l[1]; + x_focus_changed ((msg == XEMBED_FOCUS_IN ? FocusIn : FocusOut), + FOCUS_EXPLICIT, dpyinfo, frame, bufp); + } + break; } } @@ -5876,6 +5885,18 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) } #endif /* USE_TOOLKIT_SCROLL_BARS */ + /* XEmbed messages from the embedder (if any). */ + if (event.xclient.message_type + == dpyinfo->Xatom_XEMBED) + { + enum xembed_message msg = event.xclient.data.l[1]; + if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT) + x_detect_focus_change (dpyinfo, &event, &inev.ie); + + *finish = X_EVENT_GOTO_OUT; + goto done; + } + f = x_any_window_to_frame (dpyinfo, event.xclient.window); if (!f) goto OTHER; @@ -6796,6 +6817,10 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) else construct_mouse_click (&inev.ie, &event.xbutton, f); } + + if (FRAME_X_EMBEDDED_P (f)) + xembed_send_message (f, event.xbutton.time, + XEMBED_REQUEST_FOCUS, 0, 0, 0); } } else @@ -8889,6 +8914,51 @@ XTframe_raise_lower (f, raise_flag) x_lower_frame (f); } +/* XEmbed implementation. */ + +void +xembed_set_info (f, flags) + struct frame *f; + enum xembed_info flags; +{ + Atom atom; + unsigned long data[2]; + + atom = XInternAtom (FRAME_X_DISPLAY (f), "_XEMBED_INFO", False); + + data[0] = XEMBED_VERSION; + data[1] = flags; + + XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), atom, atom, + 32, PropModeReplace, (unsigned char *) data, 2); +} + +void +xembed_send_message (f, time, message, detail, data1, data2) + struct frame *f; + Time time; + enum xembed_message message; + long detail; + long data1; + long data2; +{ + XEvent event; + + event.xclient.type = ClientMessage; + event.xclient.window = FRAME_X_OUTPUT (f)->parent_desc; + event.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_XEMBED; + event.xclient.format = 32; + event.xclient.data.l[0] = time; + event.xclient.data.l[1] = message; + event.xclient.data.l[2] = detail; + event.xclient.data.l[3] = data1; + event.xclient.data.l[4] = data2; + + XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc, + False, NoEventMask, &event); + XSync (FRAME_X_DISPLAY (f), False); +} + /* Change of visibility. */ /* This tries to wait until the frame is really visible. @@ -8929,14 +8999,22 @@ x_make_frame_visible (f) if (! EQ (Vx_no_window_manager, Qt)) x_wm_set_window_state (f, NormalState); #ifdef USE_X_TOOLKIT - /* This was XtPopup, but that did nothing for an iconified frame. */ - XtMapWidget (f->output_data.x->widget); + if (FRAME_X_EMBEDDED_P (f)) + xembed_set_info (f, XEMBED_MAPPED); + else + { + /* This was XtPopup, but that did nothing for an iconified frame. */ + XtMapWidget (f->output_data.x->widget); + } #else /* not USE_X_TOOLKIT */ #ifdef USE_GTK gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); #else - XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); + if (FRAME_X_EMBEDDED_P (f)) + xembed_set_info (f, XEMBED_MAPPED); + else + XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); #endif /* not USE_GTK */ #endif /* not USE_X_TOOLKIT */ #if 0 /* This seems to bring back scroll bars in the wrong places @@ -9088,6 +9166,10 @@ x_make_frame_invisible (f) if (FRAME_GTK_OUTER_WIDGET (f)) gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f)); else +#else + if (FRAME_X_EMBEDDED_P (f)) + xembed_set_info (f, 0); + else #endif { #ifdef HAVE_X11R4 @@ -10851,6 +10933,9 @@ x_term_init (display_name, xrm_option, resource_name) dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR", False); + dpyinfo->Xatom_XEMBED = XInternAtom (dpyinfo->display, "_XEMBED", + False); + dpyinfo->cut_buffers_initialized = 0; dpyinfo->x_dnd_atoms_size = 8; diff --git a/src/xterm.h b/src/xterm.h index 13b0b49..a4920aa 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -327,6 +327,9 @@ struct x_display_info /* Atom used in toolkit scroll bar client messages. */ Atom Xatom_Scrollbar; + /* Atom used in XEmbed client messages. */ + Atom Xatom_XEMBED; + #ifdef MULTI_KBOARD struct kboard *kboard; #endif @@ -1101,6 +1104,66 @@ extern int x_session_check_input P_ ((struct input_event *bufp)); extern int x_session_have_connection P_ ((void)); #endif +/* XEmbed implementation. */ + +#define XEMBED_VERSION 0 + +enum xembed_info + { + XEMBED_MAPPED = 1 << 0 + }; + +enum xembed_message + { + XEMBED_EMBEDDED_NOTIFY = 0, + XEMBED_WINDOW_ACTIVATE = 1, + XEMBED_WINDOW_DEACTIVATE = 2, + XEMBED_REQUEST_FOCUS = 3, + XEMBED_FOCUS_IN = 4, + XEMBED_FOCUS_OUT = 5, + XEMBED_FOCUS_NEXT = 6, + XEMBED_FOCUS_PREV = 7, + + XEMBED_MODALITY_ON = 10, + XEMBED_MODALITY_OFF = 11, + XEMBED_REGISTER_ACCELERATOR = 12, + XEMBED_UNREGISTER_ACCELERATOR = 13, + XEMBED_ACTIVATE_ACCELERATOR = 14 + }; + +enum xembed_focus + { + XEMBED_FOCUS_CURRENT = 0, + XEMBED_FOCUS_FIRST = 1, + XEMBED_FOCUS_LAST = 2 + }; + +enum xembed_modifier + { + XEMBED_MODIFIER_SHIFT = 1 << 0, + XEMBED_MODIFIER_CONTROL = 1 << 1, + XEMBED_MODIFIER_ALT = 1 << 2, + XEMBED_MODIFIER_SUPER = 1 << 3, + XEMBED_MODIFIER_HYPER = 1 << 4 + }; + +enum xembed_accelerator + { + XEMBED_ACCELERATOR_OVERLOADED = 1 << 0 + }; + +/* Defined in xterm.c */ + +extern void xembed_set_info P_ ((struct frame *f, enum xembed_info flags)); +extern void xembed_send_message P_ ((struct frame *f, Time time, + enum xembed_message message, + long detail, long data1, long data2)); + +/* Is the frame embedded into another application? */ + +#define FRAME_X_EMBEDDED_P(f) (FRAME_X_OUTPUT(f)->explicit_parent != 0) + + #define FONT_TYPE_FOR_UNIBYTE(font, ch) 0 #define FONT_TYPE_FOR_MULTIBYTE(font, ch) 0 -- 1.5.2