This is the mail archive of the cygwin-xfree@cygwin.com mailing list for the Cygwin XFree86 project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: question about multiwindow mode and application icons


Howdy Harold,

At 11:45 PM 5/13/2003 -0400, you wrote:
...Wow! You have certainly done your homework here. This is way more complicated than I thought it would have to be.

That's what happens when you put a square peg like X into a round hole like Windoze! I'm really impressed at how well the 2 message loops are behaving presently, it must have been some serious work to get things running! I'm just trying to add the finishing touches, because I have found this server to be more stable and compatible than a commercial one.

As for going from and HWND to a WindowPtr, it seems to me that you can either use the existing WIN_WID_PROP property, which is set in winmultiwindowwindow.c/winCreateWindowsWindow () and contains the XID of the X window, or you could add another property that contains a pointer either to the privates structure or the WindowPtr. Does that solve your problem? I like the window properties because they eliminate searches through linked lists and they eliminate the need to even have a linked list structure in our code base.

That's what I was overlooking! I just added a custom property to each window when mapped in the WM that has the HWND, and voila, no need for lists.

Another way of doing this would be to spawn a 3rd thread that makes a notification
window and sleeps on a XNextEvent() loop. The WM would send a custom message to
the hidden notification window each time a window is mapped, and that 3rd thread would
Hmm... I would have to see the code in order to have some suggestions.

Trust me, you wouldn't want to see that code! I've settled on a timed wait and have been running some jobs and it all seems to work at no noticeable CPU load.

Kensuke Matsuzaki (the originaly author of the MultiWindow mode) might have some ideas, but I have not seem him on the list in quite some time. Even if the code doesn't work I would like to see it... I might be able to help get it working. Shoot me any code that you would like me to look over and I will see what I can do. [Feel free to post a `diff -U3 -N' to the list for all to see and I will pick it up there.]

I'll do one better than that, below is a diff -U3 OLD NEW of all the changes against the text 84 release. It's got stubs for the WM_HINTS already, so if Ralf Habacker wants to try his hand at updating the icons Windows displays, he just needs to add a function call in the TBD section.

In the default bash shell, when you "cd" it changes the window title to
the CWD, after this patch you'll see that reflected in the window title.
It's quite handy if you have multiple machines or multiple dirs you're
working on!

----------8<------------
diff -U3 ./winmultiwindowwm.c /usr/src/xfree/release/programs/Xserver/hw/xwin/winmultiwindowwm.c
--- ./winmultiwindowwm.c 2003-03-12 06:28:12.000000000 -0800
+++ /usr/src/xfree/release/programs/Xserver/hw/xwin/winmultiwindowwm.c 2003-05-13 21:50:54.000000000 -0700
@@ -37,6 +37,7 @@
#include <fcntl.h>
#include <setjmp.h>
#include <pthread.h>
+#include <sys/timeb.h>
#include <X11/X.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
@@ -61,7 +62,6 @@
#define WIN_CONNECT_RETRIES 5
#define WIN_CONNECT_DELAY 5
#define WIN_MSG_QUEUE_FNAME "/dev/windows"
-#define WM_WM_X_EVENT 1
#define WIN_JMP_OKAY 0
#define WIN_JMP_ERROR_IO 2


@@ -87,6 +87,10 @@
   WMMsgQueueRec                wmMsgQueue;
   Atom                 atmWmProtos;
   Atom                 atmWmDelete;
+  Atom                  atmWmName;
+  Atom                  atmWmIconName;
+  Atom                  atmWmHints;
+  Atom                  atmPrivMap;
 } WMInfoRec, *WMInfoPtr;

 typedef struct _WMProcArgRec {
@@ -113,7 +117,7 @@
 PushMessage (WMMsgQueuePtr pQueue, WMMsgNodePtr pNode);

 static WMMsgNodePtr
-PopMessage (WMMsgQueuePtr pQueue);
+PopMessage (WMMsgQueuePtr pQueue, WMInfoPtr);

 static Bool
 InitQueue (WMMsgQueuePtr pQueue);
@@ -148,7 +152,6 @@
 static jmp_buf                 g_jmpEntry;


- /* * PushMessage - Push a message onto the queue */ @@ -237,9 +240,12 @@ */

 static WMMsgNodePtr
-PopMessage (WMMsgQueuePtr pQueue)
+PopMessage (WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo)
 {
   WMMsgNodePtr         pNode;
+  struct timeb          now;
+  struct timespec       timeOut;
+  winWMMessageRec       msg;

/* Lock the queue mutex */
pthread_mutex_lock (&pQueue->pmMutex);
@@ -247,7 +253,27 @@
/* Wait for --- */
while (pQueue->pHead == NULL)
{
- pthread_cond_wait (&pQueue->pcNotEmpty, &pQueue->pmMutex);
+ /* Set a timeout for 50ms from now to see if any X events are waiting... */
+ ftime(&now);
+ timeOut.tv_sec = now.time;
+ timeOut.tv_nsec = (now.millitm + 50)*1000*1000;
+ if (timeOut.tv_nsec>1000000000) {
+ timeOut.tv_nsec -= 1000000000;
+ timeOut.tv_sec += 1;
+ }
+ pthread_cond_timedwait (&pQueue->pcNotEmpty, &pQueue->pmMutex, &timeOut);
+
+ if (XPending(pWMInfo->pDisplay)) {
+ pthread_mutex_unlock (&pQueue->pmMutex);
+
+ memset( &msg, 0, sizeof(msg) );
+ msg.msg = WM_WM_X_EVENT;
+ /* Other fields ignored */
+ winSendMessageToWM (pWMInfo, &msg);
+
+ pthread_mutex_lock (&pQueue->pmMutex);
+ }
+
}


   pNode = pQueue->pHead;
@@ -447,7 +473,7 @@
       WMMsgNodePtr     pNode;

       /* Pop a message off of our queue */
-      pNode = PopMessage (&pWMInfo->wmMsgQueue);
+      pNode = PopMessage (&pWMInfo->wmMsgQueue, pWMInfo);
       if (pNode == NULL)
        {
          /* Bail if PopMessage returns without a message */
@@ -515,6 +541,19 @@
                free (pszName);
              }
          }
+         /* Put a note as to the HWND associated with this Window */
+         XChangeProperty( pWMInfo->pDisplay,
+                          pNode->msg.iWindow,
+                          pWMInfo->atmPrivMap,
+                          pWMInfo->atmPrivMap,
+                          32,
+                          PropModeReplace,
+                          (unsigned char *)&(pNode->msg.hwndWindow),
+                          1 );
+         /* We need to know when it changes name or icon */
+         XSelectInput( pWMInfo->pDisplay,
+                       pNode->msg.iWindow,
+                       PropertyChangeMask );
          break;

        case WM_WM_UNMAP:
@@ -586,7 +625,7 @@
       free (pNode);

       /* Flush any pending events on our display */
-      XFlush (pWMInfo->pDisplay);
+      //      XFlush (pWMInfo->pDisplay);
     }

   /* Free the condition variable */
@@ -612,7 +651,9 @@
 FlushXEvents (WMInfoPtr pWMInfo)
 {
   XEvent               event;
-
+  HWND                  hWnd;
+  char                  *pszName;
+
 #if CYGMULTIWINDOW_DEBUG
   ErrorF ("FlushXEvents ()\n");
 #endif
@@ -623,12 +664,56 @@
       /* Get the next event - will not block because one is ready */
       XNextEvent (pWMInfo->pDisplay, &event);

-#if 0
       /* Branch on the event type */
       switch (event.type)
        {
-       }
+         Atom atmType;
+         int fmtRet;
+         unsigned long items, remain;
+         HWND *retHwnd;
+
+       case PropertyNotify:
+         hWnd = 0;
+         /* See if we can get the cached HWND for this window... */
+         if (XGetWindowProperty(pWMInfo->pDisplay,
+                                event.xproperty.window,
+                                pWMInfo->atmPrivMap,
+                                0,
+                                1,
+                                False,
+                                pWMInfo->atmPrivMap,
+                                &atmType,
+                                &fmtRet,
+                                &items,
+                                &remain,
+                                (unsigned char **)&retHwnd ) == Success) {
+           hWnd = *retHwnd;
+           XFree(retHwnd);
+         }
+
+         /* Some sanity checks */
+         if (!hWnd) break;
+         if (!IsWindow(hWnd)) break;
+
+         if (event.xproperty.atom==pWMInfo->atmWmName) {
+           /* Set the Windows window name */
+           GetWindowName(pWMInfo->pDisplay, event.xproperty.window, &pszName);
+           SetWindowText(hWnd, pszName);
+           free (pszName);
+         } else if (event.xproperty.atom==pWMInfo->atmWmIconName) {
+#if CYGMULTIWINDOW_DEBUG
+           /* TBD */
+           ErrorF("Changed WM_ICON_NAME\n");
+#endif
+         } else if (event.xproperty.atom==pWMInfo->atmWmHints) {
+#if CYGMULTIWINDOW_DEBUG
+           /* TBD */
+           ErrorF("Changed WM_HINTS -> Should update window icon\n");
 #endif
+         }
+
+         break;
+       }
     }

 #if CYGMULTIWINDOW_DEBUG
@@ -862,12 +947,24 @@
   XSetIOErrorHandler (winMutliWindowWMIOErrorHandler);

   /* Create some atoms */
-  pWMInfo->atmWmProtos = XInternAtom (pWMInfo->pDisplay,
-                                     "WM_PROTOCOLS",
-                                     False);
-  pWMInfo->atmWmDelete = XInternAtom (pWMInfo->pDisplay,
-                                     "WM_DELETE_WINDOW",
-                                     False);
+  pWMInfo->atmWmProtos   = XInternAtom (pWMInfo->pDisplay,
+                                       "WM_PROTOCOLS",
+                                       False);
+  pWMInfo->atmWmDelete   = XInternAtom (pWMInfo->pDisplay,
+                                       "WM_DELETE_WINDOW",
+                                       False);
+  pWMInfo->atmWmName     = XInternAtom (pWMInfo->pDisplay,
+                                       "WM_NAME",
+                                       False);
+  pWMInfo->atmWmIconName = XInternAtom (pWMInfo->pDisplay,
+                                       "WM_ICON_NAME",
+                                       False);
+  pWMInfo->atmWmHints    = XInternAtom (pWMInfo->pDisplay,
+                                       "WM_HINTS",
+                                       False);
+  pWMInfo->atmPrivMap    = XInternAtom (pWMInfo->pDisplay,
+                                       WIN_HWND_CACHE,
+                                       False);
 }


diff -U3 ./winwindow.h /usr/src/xfree/release/programs/Xserver/hw/xwin/winwindow.h
--- ./winwindow.h 2003-05-13 06:26:55.000000000 -0700
+++ /usr/src/xfree/release/programs/Xserver/hw/xwin/winwindow.h 2003-05-13 21:42:50.000000000 -0700
@@ -51,6 +51,7 @@
#define WIN_LOG_FNAME "/tmp/XWin.log"
#define WIN_WID_PROP "cyg_wid_prop_rl"
#define WIN_NEEDMANAGE_PROP "cyg_override_redirect_prop_rl"
+#define WIN_HWND_CACHE "cyg_privmap_rl"
#define CYGMULTIWINDOW_DEBUG NO


 typedef struct _winPrivScreenRec *winPrivScreenPtr;
@@ -94,8 +95,7 @@
 #define                WM_WM_UNMAP     (WM_USER + 6)
 #define                WM_WM_KILL      (WM_USER + 7)
 #define                WM_WM_ACTIVATE  (WM_USER + 8)
-
-#define                WMMSG_MSG       10
+#define                WM_WM_X_EVENT   (WM_USER + 9)


/* ----------8<------------




-Earle F. Philhower, III earle@ziplabel.com cdrlabel - ZipLabel - FlpLabel http://www.cdrlabel.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]