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