1/* -------------------------------------------------------------------------
2 * Project: GSocket (Generic Socket) for WX
3 * Name:    src/gtk/gsockgtk.cpp
4 * Purpose: GSocket: GTK part
5 * Licence: The wxWindows licence
6 * CVSID:   $Id: gsockgtk.cpp 67249 2011-03-19 20:35:11Z JS $
7 * -------------------------------------------------------------------------
8 */
9// For compilers that support precompilation, includes "wx.h".
10#include "wx/wxprec.h"
11
12#if wxUSE_SOCKETS
13
14#include <assert.h>
15#include <stdlib.h>
16#include <stdio.h>
17
18// newer versions of glib define its own GSocket but we unfortunately use this
19// name in our own (semi-)public header and so can't change it -- rename glib
20// one instead
21#define GSocket GlibGSocket
22#include <gdk/gdk.h>
23#include <glib.h>
24#undef GSocket
25
26#include "wx/gsocket.h"
27#include "wx/unix/gsockunx.h"
28#if wxUSE_THREADS
29#include "wx/thread.h"
30#endif
31
32extern "C" {
33static
34void _GSocket_GDK_Input(gpointer data,
35                        gint source,
36                        GdkInputCondition condition)
37{
38  GSocket *socket = (GSocket *)data;
39
40  if (condition & GDK_INPUT_READ)
41    socket->Detected_Read();
42  if (condition & GDK_INPUT_WRITE)
43    socket->Detected_Write();
44}
45}
46
47typedef struct {
48#if wxUSE_THREADS
49  wxMutex* m_mutex;
50#endif
51  gint m_id[2];
52} GSocketGTKMutexProtected;
53
54bool GSocketGUIFunctionsTableConcrete::CanUseEventLoop()
55{   return true; }
56
57bool GSocketGUIFunctionsTableConcrete::OnInit(void)
58{
59    return 1;
60}
61
62void GSocketGUIFunctionsTableConcrete::OnExit(void)
63{
64}
65
66bool GSocketGUIFunctionsTableConcrete::Init_Socket(GSocket *socket)
67{
68  socket->m_gui_dependent = (char *)malloc(sizeof(GSocketGTKMutexProtected));
69
70  GSocketGTKMutexProtected* guispecific = (GSocketGTKMutexProtected*)socket->m_gui_dependent;
71
72#if wxUSE_THREADS
73  guispecific->m_mutex = new wxMutex(wxMUTEX_RECURSIVE);
74#endif
75
76  guispecific->m_id[0] = -1;
77  guispecific->m_id[1] = -1;
78
79  return TRUE;
80}
81
82void GSocketGUIFunctionsTableConcrete::Destroy_Socket(GSocket *socket)
83{
84  GSocketGTKMutexProtected* guispecific = (GSocketGTKMutexProtected*)socket->m_gui_dependent;
85
86#if wxUSE_THREADS
87  delete guispecific->m_mutex;
88#endif
89
90  free(guispecific);
91}
92
93void GSocketGUIFunctionsTableConcrete::Install_Callback(GSocket *socket, GSocketEvent event)
94{
95  GSocketGTKMutexProtected* guispecific = (GSocketGTKMutexProtected*)socket->m_gui_dependent;
96
97  assert(guispecific != NULL);
98
99  int c;
100
101  if (socket->m_fd == -1)
102    return;
103
104  switch (event)
105  {
106    case GSOCK_LOST:       /* fall-through */
107    case GSOCK_INPUT:      c = 0; break;
108    case GSOCK_OUTPUT:     c = 1; break;
109    case GSOCK_CONNECTION: c = ((socket->m_server) ? 0 : 1); break;
110    default: return;
111  }
112
113#if wxUSE_THREADS
114  guispecific->m_mutex->Lock();
115#endif
116  gint current_id = guispecific->m_id[c];
117  guispecific->m_id[c] = -1;
118#if wxUSE_THREADS
119  guispecific->m_mutex->Unlock();
120#endif
121
122  if (current_id != -1) {
123    gdk_input_remove(current_id);
124  }
125
126  current_id  = gdk_input_add(socket->m_fd,
127                          (c ? GDK_INPUT_WRITE : GDK_INPUT_READ),
128                          _GSocket_GDK_Input,
129                          (gpointer)socket);
130
131#if wxUSE_THREADS
132  guispecific->m_mutex->Lock();
133#endif
134  guispecific->m_id[c] = current_id;
135#if wxUSE_THREADS
136  guispecific->m_mutex->Unlock();
137#endif
138
139}
140
141void GSocketGUIFunctionsTableConcrete::Uninstall_Callback(GSocket *socket, GSocketEvent event)
142{
143  GSocketGTKMutexProtected* guispecific = (GSocketGTKMutexProtected*)socket->m_gui_dependent;
144  int c;
145
146  assert( guispecific != NULL );
147
148  switch (event)
149  {
150    case GSOCK_LOST:       /* fall-through */
151    case GSOCK_INPUT:      c = 0; break;
152    case GSOCK_OUTPUT:     c = 1; break;
153    case GSOCK_CONNECTION: c = ((socket->m_server) ? 0 : 1); break;
154    default: return;
155  }
156
157#if wxUSE_THREADS
158  guispecific->m_mutex->Lock();
159#endif
160  gint current_id = guispecific->m_id[c];
161  guispecific->m_id[c] = -1;
162#if wxUSE_THREADS
163  guispecific->m_mutex->Unlock();
164#endif
165
166  if (current_id != -1)
167  {
168    gdk_input_remove(current_id);
169  }
170}
171
172void GSocketGUIFunctionsTableConcrete::Enable_Events(GSocket *socket)
173{
174  Install_Callback(socket, GSOCK_INPUT);
175  Install_Callback(socket, GSOCK_OUTPUT);
176}
177
178void GSocketGUIFunctionsTableConcrete::Disable_Events(GSocket *socket)
179{
180  Uninstall_Callback(socket, GSOCK_INPUT);
181  Uninstall_Callback(socket, GSOCK_OUTPUT);
182}
183
184#else /* !wxUSE_SOCKETS */
185
186/* some compilers don't like having empty source files */
187static int wxDummyGsockVar = 0;
188
189#endif /* wxUSE_SOCKETS/!wxUSE_SOCKETS */
190