From d38a1c18374319326e351bbdc377a31d92fd637f Mon Sep 17 00:00:00 2001
From: Lars Kanis <kanis@comcard.de>
Date: Thu, 25 Jun 2015 15:15:57 +0200
Subject: [PATCH] Add a working version for FXApp#addInput event handling on
 Windows.

This works for sockets only for now.
---
 ext/fox16_c/FXRuby.cpp       | 39 ++++++++++++++++++++++++++++++++----
 ext/fox16_c/include/FXRuby.h |  6 ++++--
 swig-interfaces/FXApp.i      | 36 +++++++++++++--------------------
 3 files changed, 53 insertions(+), 28 deletions(-)

diff --git a/ext/fox16_c/FXRuby.cpp b/ext/fox16_c/FXRuby.cpp
index 4d014fd..090e7ca 100644
--- a/ext/fox16_c/FXRuby.cpp
+++ b/ext/fox16_c/FXRuby.cpp
@@ -185,23 +185,38 @@ void* FXRbConvertPtr(VALUE obj,swig_type_info* ty){
 FXbool FXRbCatchExceptions=FALSE;
 
 // Returns an FXInputHandle for this Ruby file object
-FXInputHandle FXRbGetReadFileHandle(VALUE obj) {
+FXInputHandle FXRbGetReadFileHandle(VALUE obj,FXuint mode) {
   int fd;
   fd = FIX2INT(rb_funcall(obj, rb_intern("fileno"), 0));
 #ifdef WIN32
 #ifdef __CYGWIN__
   return (FXInputHandle) get_osfhandle(fd);
 #else
-  return (FXInputHandle) _get_osfhandle(fd);
+  WSAEVENT hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+  long events = 0;
+  if(mode&INPUT_READ) events |= FD_READ|FD_ACCEPT|FD_OOB;
+  if(mode&INPUT_EXCEPT) events |= FD_CLOSE|FD_QOS|FD_GROUP_QOS|FD_ROUTING_INTERFACE_CHANGE|FD_ADDRESS_LIST_CHANGE;
+  if ( WSAEventSelect(_get_osfhandle(fd), hEvent, events) == SOCKET_ERROR ) {
+    WSACloseEvent( hEvent );
+    rb_raise( rb_eRuntimeError, "WSAEventSelect sockett error: %d", WSAGetLastError() );
+  }
+  rb_iv_set(obj, "FXRuby::FXRbGetReadFileHandle", ULL2NUM((intptr_t)hEvent));
+  return (FXInputHandle) hEvent;
 #endif
 #else
   return (FXInputHandle) fd;
 #endif
   }
 
+void FXRbRemoveReadFileHandle(VALUE obj,FXuint mode) {
+#ifdef WIN32
+  WSAEVENT hEvent = (HANDLE)NUM2ULL(rb_iv_get(obj, "FXRuby::FXRbGetReadFileHandle"));
+  CloseHandle( hEvent );
+#endif
+}
 
 // Returns an FXInputHandle for this Ruby file object
-FXInputHandle FXRbGetWriteFileHandle(VALUE obj) {
+FXInputHandle FXRbGetWriteFileHandle(VALUE obj,FXuint mode) {
   int fd;
 #if defined(RUBINIUS)
   VALUE vwrite = rb_intern("@write");
@@ -223,13 +238,29 @@ FXInputHandle FXRbGetWriteFileHandle(VALUE obj) {
 #ifdef __CYGWIN__
   return (FXInputHandle) get_osfhandle(fd);
 #else
-  return (FXInputHandle) _get_osfhandle(fd);
+  WSAEVENT hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+  long events = 0;
+  if(mode&INPUT_WRITE) events |= FD_WRITE|FD_CONNECT;
+  if(mode&INPUT_EXCEPT) events |= FD_CLOSE|FD_QOS|FD_GROUP_QOS|FD_ROUTING_INTERFACE_CHANGE|FD_ADDRESS_LIST_CHANGE;
+  if ( WSAEventSelect(_get_osfhandle(fd), hEvent, events) == SOCKET_ERROR ) {
+    WSACloseEvent( hEvent );
+    rb_raise( rb_eRuntimeError, "WSAEventSelect sockettt error: %d", WSAGetLastError() );
+  }
+  rb_iv_set(obj, "FXRuby::FXRbGetWriteFileHandle", ULL2NUM((intptr_t)hEvent));
+  return (FXInputHandle) hEvent;
 #endif
 #else
   return (FXInputHandle) fd;
 #endif
   }
 
+void FXRbRemoveWriteFileHandle(VALUE obj,FXuint mode) {
+#ifdef WIN32
+  WSAEVENT hEvent = (HANDLE)NUM2ULL(rb_iv_get(obj, "FXRuby::FXRbGetWriteFileHandle"));
+  CloseHandle( hEvent );
+#endif
+}
+
 
 // Register this Ruby class instance
 void FXRbRegisterRubyObj(VALUE rubyObj,const void* foxObj) {
diff --git a/ext/fox16_c/include/FXRuby.h b/ext/fox16_c/include/FXRuby.h
index c601e36..b04f858 100644
--- a/ext/fox16_c/include/FXRuby.h
+++ b/ext/fox16_c/include/FXRuby.h
@@ -91,8 +91,10 @@ swig_type_info *FXRbTypeQuery(const char *name);
 void* FXRbConvertPtr(VALUE obj,swig_type_info* typeinfo);
 
 // Returns an FXInputHandle for this Ruby file object
-FXInputHandle FXRbGetReadFileHandle(VALUE obj);
-FXInputHandle FXRbGetWriteFileHandle(VALUE obj);
+FXInputHandle FXRbGetReadFileHandle(VALUE obj,FXuint mode);
+FXInputHandle FXRbGetWriteFileHandle(VALUE obj,FXuint mode);
+void FXRbRemoveReadFileHandle(VALUE obj,FXuint mode);
+void FXRbRemoveWriteFileHandle(VALUE obj,FXuint mode);
 
 // Register mapping from Ruby objects to FOX objects
 void FXRbRegisterRubyObj(VALUE rubyObj, const void* foxObj);
diff --git a/swig-interfaces/FXApp.i b/swig-interfaces/FXApp.i
index 9f20fca..f25f8b4 100644
--- a/swig-interfaces/FXApp.i
+++ b/swig-interfaces/FXApp.i
@@ -357,18 +357,13 @@ public:
     */
     bool addInput(VALUE obj,FXuint mode,FXObject *tgt,FXSelector sel){
       FXInputHandle fd;
-      FXuint m;
-      if(mode&INPUT_READ){
-        m=INPUT_READ;
-        if(mode&INPUT_EXCEPT) m|=INPUT_EXCEPT;
-        fd=FXRbGetReadFileHandle(obj);
-        self->addInput(fd,m,tgt,sel);
+      if(mode&(INPUT_READ|INPUT_EXCEPT)){
+        fd=FXRbGetReadFileHandle(obj, mode);
+        self->addInput(fd,mode,tgt,sel);
         }
-      if(mode&INPUT_WRITE){
-        m=INPUT_WRITE;
-        if(mode&INPUT_EXCEPT) m|=INPUT_EXCEPT;
-        fd=FXRbGetWriteFileHandle(obj);
-        self->addInput(fd,m,tgt,sel);
+      if(mode&(INPUT_WRITE|INPUT_EXCEPT)){
+        fd=FXRbGetWriteFileHandle(obj, mode);
+        self->addInput(fd,mode,tgt,sel);
         }
       return true;
       }
@@ -379,18 +374,15 @@ public:
     */
     bool removeInput(VALUE obj,FXuint mode){
       FXInputHandle fd;
-      FXuint m;
-      if(mode&INPUT_READ){
-        m=INPUT_READ;
-        if(mode&INPUT_EXCEPT) m|=INPUT_EXCEPT;
-        fd=FXRbGetReadFileHandle(obj);
-        self->removeInput(fd,m);
+      if(mode&INPUT_READ|INPUT_EXCEPT){
+        fd=FXRbGetReadFileHandle(obj, mode);
+        self->removeInput(fd,mode);
+        FXRbRemoveReadFileHandle(obj, mode);
         }
-      if(mode&INPUT_WRITE){
-        m=INPUT_WRITE;
-        if(mode&INPUT_EXCEPT) m|=INPUT_EXCEPT;
-        fd=FXRbGetWriteFileHandle(obj);
-        self->removeInput(fd,m);
+      if(mode&(INPUT_WRITE|INPUT_EXCEPT)){
+        fd=FXRbGetWriteFileHandle(obj, mode);
+        self->removeInput(fd,mode);
+        FXRbRemoveWriteFileHandle(obj, mode);
         }
       return true;
       }
-- 
GitLab