1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module gtk.Socket; 26 27 private import gdk.Window; 28 private import glib.ConstructionException; 29 private import gobject.ObjectG; 30 private import gobject.Signals; 31 private import gtk.Container; 32 private import gtk.Widget; 33 private import gtkc.gtk; 34 public import gtkc.gtktypes; 35 private import std.algorithm; 36 37 38 /** 39 * Together with #GtkPlug, #GtkSocket provides the ability to embed 40 * widgets from one process into another process in a fashion that 41 * is transparent to the user. One process creates a #GtkSocket widget 42 * and passes that widget’s window ID to the other process, which then 43 * creates a #GtkPlug with that window ID. Any widgets contained in the 44 * #GtkPlug then will appear inside the first application’s window. 45 * 46 * The socket’s window ID is obtained by using gtk_socket_get_id(). 47 * Before using this function, the socket must have been realized, 48 * and for hence, have been added to its parent. 49 * 50 * ## Obtaining the window ID of a socket. 51 * 52 * |[<!-- language="C" --> 53 * GtkWidget *socket = gtk_socket_new (); 54 * gtk_widget_show (socket); 55 * gtk_container_add (GTK_CONTAINER (parent), socket); 56 * 57 * // The following call is only necessary if one of 58 * // the ancestors of the socket is not yet visible. 59 * gtk_widget_realize (socket); 60 * g_print ("The ID of the sockets window is %#x\n", 61 * gtk_socket_get_id (socket)); 62 * ]| 63 * 64 * Note that if you pass the window ID of the socket to another 65 * process that will create a plug in the socket, you must make 66 * sure that the socket widget is not destroyed until that plug 67 * is created. Violating this rule will cause unpredictable 68 * consequences, the most likely consequence being that the plug 69 * will appear as a separate toplevel window. You can check if 70 * the plug has been created by using gtk_socket_get_plug_window(). 71 * If it returns a non-%NULL value, then the plug has been 72 * successfully created inside of the socket. 73 * 74 * When GTK+ is notified that the embedded window has been destroyed, 75 * then it will destroy the socket as well. You should always, 76 * therefore, be prepared for your sockets to be destroyed at any 77 * time when the main event loop is running. To prevent this from 78 * happening, you can connect to the #GtkSocket::plug-removed signal. 79 * 80 * The communication between a #GtkSocket and a #GtkPlug follows the 81 * [XEmbed Protocol](http://www.freedesktop.org/Standards/xembed-spec). 82 * This protocol has also been implemented in other toolkits, e.g. Qt, 83 * allowing the same level of integration when embedding a Qt widget 84 * in GTK or vice versa. 85 * 86 * The #GtkPlug and #GtkSocket widgets are only available when GTK+ 87 * is compiled for the X11 platform and %GDK_WINDOWING_X11 is defined. 88 * They can only be used on a #GdkX11Display. To use #GtkPlug and 89 * #GtkSocket, you need to include the `gtk/gtkx.h` header. 90 */ 91 public class Socket : Container 92 { 93 /** the main Gtk struct */ 94 protected GtkSocket* gtkSocket; 95 96 /** Get the main Gtk struct */ 97 public GtkSocket* getSocketStruct() 98 { 99 return gtkSocket; 100 } 101 102 /** the main Gtk struct as a void* */ 103 protected override void* getStruct() 104 { 105 return cast(void*)gtkSocket; 106 } 107 108 protected override void setStruct(GObject* obj) 109 { 110 gtkSocket = cast(GtkSocket*)obj; 111 super.setStruct(obj); 112 } 113 114 /** 115 * Sets our main struct and passes it to the parent class. 116 */ 117 public this (GtkSocket* gtkSocket, bool ownedRef = false) 118 { 119 this.gtkSocket = gtkSocket; 120 super(cast(GtkContainer*)gtkSocket, ownedRef); 121 } 122 123 124 /** */ 125 public static GType getType() 126 { 127 return gtk_socket_get_type(); 128 } 129 130 /** 131 * Create a new empty #GtkSocket. 132 * 133 * Returns: the new #GtkSocket. 134 * 135 * Throws: ConstructionException GTK+ fails to create the object. 136 */ 137 public this() 138 { 139 auto p = gtk_socket_new(); 140 141 if(p is null) 142 { 143 throw new ConstructionException("null returned by new"); 144 } 145 146 this(cast(GtkSocket*) p); 147 } 148 149 /** 150 * Adds an XEMBED client, such as a #GtkPlug, to the #GtkSocket. The 151 * client may be in the same process or in a different process. 152 * 153 * To embed a #GtkPlug in a #GtkSocket, you can either create the 154 * #GtkPlug with `gtk_plug_new (0)`, call 155 * gtk_plug_get_id() to get the window ID of the plug, and then pass that to the 156 * gtk_socket_add_id(), or you can call gtk_socket_get_id() to get the 157 * window ID for the socket, and call gtk_plug_new() passing in that 158 * ID. 159 * 160 * The #GtkSocket must have already be added into a toplevel window 161 * before you can make this call. 162 * 163 * Params: 164 * window = the Window of a client participating in the XEMBED protocol. 165 */ 166 public void addId(ulong window) 167 { 168 gtk_socket_add_id(gtkSocket, window); 169 } 170 171 /** 172 * Gets the window ID of a #GtkSocket widget, which can then 173 * be used to create a client embedded inside the socket, for 174 * instance with gtk_plug_new(). 175 * 176 * The #GtkSocket must have already be added into a toplevel window 177 * before you can make this call. 178 * 179 * Returns: the window ID for the socket 180 */ 181 public ulong getId() 182 { 183 return gtk_socket_get_id(gtkSocket); 184 } 185 186 /** 187 * Retrieves the window of the plug. Use this to check if the plug has 188 * been created inside of the socket. 189 * 190 * Returns: the window of the plug if 191 * available, or %NULL 192 * 193 * Since: 2.14 194 */ 195 public Window getPlugWindow() 196 { 197 auto p = gtk_socket_get_plug_window(gtkSocket); 198 199 if(p is null) 200 { 201 return null; 202 } 203 204 return ObjectG.getDObject!(Window)(cast(GdkWindow*) p); 205 } 206 207 protected class OnPlugAddedDelegateWrapper 208 { 209 static OnPlugAddedDelegateWrapper[] listeners; 210 void delegate(Socket) dlg; 211 gulong handlerId; 212 213 this(void delegate(Socket) dlg) 214 { 215 this.dlg = dlg; 216 this.listeners ~= this; 217 } 218 219 void remove(OnPlugAddedDelegateWrapper source) 220 { 221 foreach(index, wrapper; listeners) 222 { 223 if (wrapper.handlerId == source.handlerId) 224 { 225 listeners[index] = null; 226 listeners = std.algorithm.remove(listeners, index); 227 break; 228 } 229 } 230 } 231 } 232 233 /** 234 * This signal is emitted when a client is successfully 235 * added to the socket. 236 */ 237 gulong addOnPlugAdded(void delegate(Socket) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 238 { 239 auto wrapper = new OnPlugAddedDelegateWrapper(dlg); 240 wrapper.handlerId = Signals.connectData( 241 this, 242 "plug-added", 243 cast(GCallback)&callBackPlugAdded, 244 cast(void*)wrapper, 245 cast(GClosureNotify)&callBackPlugAddedDestroy, 246 connectFlags); 247 return wrapper.handlerId; 248 } 249 250 extern(C) static void callBackPlugAdded(GtkSocket* socketStruct, OnPlugAddedDelegateWrapper wrapper) 251 { 252 wrapper.dlg(wrapper.outer); 253 } 254 255 extern(C) static void callBackPlugAddedDestroy(OnPlugAddedDelegateWrapper wrapper, GClosure* closure) 256 { 257 wrapper.remove(wrapper); 258 } 259 260 protected class OnPlugRemovedDelegateWrapper 261 { 262 static OnPlugRemovedDelegateWrapper[] listeners; 263 bool delegate(Socket) dlg; 264 gulong handlerId; 265 266 this(bool delegate(Socket) dlg) 267 { 268 this.dlg = dlg; 269 this.listeners ~= this; 270 } 271 272 void remove(OnPlugRemovedDelegateWrapper source) 273 { 274 foreach(index, wrapper; listeners) 275 { 276 if (wrapper.handlerId == source.handlerId) 277 { 278 listeners[index] = null; 279 listeners = std.algorithm.remove(listeners, index); 280 break; 281 } 282 } 283 } 284 } 285 286 /** 287 * This signal is emitted when a client is removed from the socket. 288 * The default action is to destroy the #GtkSocket widget, so if you 289 * want to reuse it you must add a signal handler that returns %TRUE. 290 * 291 * Returns: %TRUE to stop other handlers from being invoked. 292 */ 293 gulong addOnPlugRemoved(bool delegate(Socket) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 294 { 295 auto wrapper = new OnPlugRemovedDelegateWrapper(dlg); 296 wrapper.handlerId = Signals.connectData( 297 this, 298 "plug-removed", 299 cast(GCallback)&callBackPlugRemoved, 300 cast(void*)wrapper, 301 cast(GClosureNotify)&callBackPlugRemovedDestroy, 302 connectFlags); 303 return wrapper.handlerId; 304 } 305 306 extern(C) static int callBackPlugRemoved(GtkSocket* socketStruct, OnPlugRemovedDelegateWrapper wrapper) 307 { 308 return wrapper.dlg(wrapper.outer); 309 } 310 311 extern(C) static void callBackPlugRemovedDestroy(OnPlugRemovedDelegateWrapper wrapper, GClosure* closure) 312 { 313 wrapper.remove(wrapper); 314 } 315 }