Support WM_DELETE_WINDOW, WMHints.
authorIan Osgood <iano@quirkster.com>
Wed, 22 Mar 2006 02:29:35 +0000 (18:29 -0800)
committerIan Osgood <iano@quirkster.com>
Wed, 22 Mar 2006 02:29:35 +0000 (18:29 -0800)
neko/README
neko/xcbneko.c

index 1902013..e334aff 100644 (file)
@@ -8,11 +8,12 @@ XCB TODO
 * -root needs testing (Mac X is rootless)
 * DEBUG not supported
 * -geometry not supported
-* WM hints, -iconic not supported (don't like the util interfaces)
+* -iconic not supported (don't like the util interfaces)
 
 XCB ENHANCEMENTS
 ----------------
 * autoconf
+* use WM_DELETE_WINDOW protocol
 * too many globals! refactor
 * no X resource cleanup. OK?
 * convert to use threading
index bd7b706..ea12c6e 100644 (file)
@@ -141,15 +141,14 @@ char        *fgColor, *bgColor;
 
 static char  *ProgramName;
 
-/*Display        *theDisplay;*/
 XCBConnection  *xc;
 XCBSCREEN      *theScreen;             /* instead of macro(theDisplay, int theScreen) */
-unsigned int   theDepth;
 unsigned long  theBlackPixel;
 unsigned long  theWhitePixel;
 XCBWINDOW         theWindow;
 XCBCURSOR         theCursor;
 XCBKeySymbols  *theKeySyms;
+XCBATOM deleteWindowAtom;
 
 static unsigned int  WindowWidth;
 static unsigned int  WindowHeight;
@@ -513,11 +512,25 @@ void  InitBitmapAndGCs(void) {
   /* later: XCBFreeGC( c, gc ); */
 }
 
+XCBATOM
+GetAtom(XCBConnection *c, const char *atomName)
+{
+       XCBATOM atom = { XCBNone };
+       XCBInternAtomRep *r = XCBInternAtomReply(c,
+               XCBInternAtom(c, 0, strlen(atomName), atomName), NULL);
+       if (r) {
+               atom = r->atom;
+               free(r);
+       }
+       return atom;
+}
+
 void
 InitScreen( char *DisplayName, char *theGeometry, char *theTitle, Bool iconicState )
 {
   XCBPIXMAP            theCursorSource;
   XCBPIXMAP            theCursorMask;
+  unsigned int   theDepth;
   XCBCOLORMAP          theColormap;
   int screen;
   
@@ -629,19 +642,13 @@ InitScreen( char *DisplayName, char *theGeometry, char *theTitle, Bool iconicSta
                theScreen->root_visual, /* CopyFromParent */
                theWindowMask, theWindowAttributes );
 
+       /* new: obey the window-delete protocol, look for XCBClientMessage */
+       deleteWindowAtom = GetAtom(xc, "WM_DELETE_WINDOW");
+       SetWMProtocols( xc, theWindow, 1, &deleteWindowAtom );
+
        theIconPixmap = CreateBitmapFromData( xc, theWindow,
                                                                                  icon_bits, icon_width, icon_height );
-       
 #ifdef TODO_ICCCM
-    /* Um... there is no function to send the hints...
-       WMHints              theWMHints;
-       WMHintsSetIconPixmap( &theHints, theIconPixmap );
-
-       if ( iconicState )
-         WMHintsSetIconic( &theHints );
-       else
-         WMHintsSetNormal( &theHints );
-    */
        theWMHints.icon_pixmap = theIconPixmap;
        
        if ( iconicState )
@@ -652,36 +659,37 @@ InitScreen( char *DisplayName, char *theGeometry, char *theTitle, Bool iconicSta
        theWMHints.flags = IconPixmapHint | StateHint;
        
        XSetWMHints( theDisplay, theWindow, &theWMHints );
-#endif
+#else
+    /* Um... there is no function to send the hints...
+       WMHints              theWMHints;
+       WMHintsSetIconPixmap( &theHints, theIconPixmap );
 
-#ifdef TODO_ICCCM
-       /*
-       SizeHints *hints = AllocSizeHints();
-       SizeHintsSetPosition(hints, WindowPointX, WindowPointY);
-       SizeHintsSetSize(hints, WindowWidth, WindowHeight);
-       SetWMNormalHints(xc, theWindow, hints);
-       FreeSizeHints(hints);
-       */
-       XSizeHints            theSizeHints;
-
-       theSizeHints.flags = PPosition | PSize;
-       theSizeHints.x = WindowPointX;
-       theSizeHints.y = WindowPointY;
-       theSizeHints.width = WindowWidth;
-       theSizeHints.height = WindowHeight;
-       
-       XSetNormalHints( theDisplay, theWindow, &theSizeHints );
+       if ( iconicState )
+         WMHintsSetIconic( &theHints );
+       else
+         WMHintsSetNormal( &theHints );
+         
+       Now what?
+    */
 #endif
 
+       /* why hide the structure? */
+       SizeHints *theSizeHints = AllocSizeHints();
+
+       /* need enum for second param (user specified) */
+       SizeHintsSetPosition(theSizeHints, 0, WindowPointX, WindowPointY);
+       SizeHintsSetSize(theSizeHints, 0, WindowWidth, WindowHeight);
+
+       SetWMNormalHints(xc, theWindow, theSizeHints);
+
+       FreeSizeHints(theSizeHints);
+
        /* Um, why do I have to specify the encoding in this API? */
        SetWMName( xc, theWindow, STRING, strlen(theTitle), theTitle );
        SetWMIconName( xc, theWindow, STRING, strlen(theTitle), theTitle );
 
        XCBMapWindow( xc, theWindow );
 
-    /* moved to the CreateWindow attribute list */
-       /* XSelectInput( theDisplay, theWindow, EVENT_MASK ); */
-
   }
   
 #ifdef TODO
@@ -1154,6 +1162,11 @@ void  NekoAdjust(void) {
        NekoY = WindowHeight - BITMAP_HEIGHT;
 }
 
+int IsDeleteMessage(XCBClientMessageEvent *msg)
+{
+       return msg->data.data32[0] == deleteWindowAtom.xid;
+}
+
 Bool  ProcessEvent(void) {
   XCBGenericEvent *theEvent;
   XCBConfigureNotifyEvent *theConfigureNotification;
@@ -1164,8 +1177,9 @@ Bool  ProcessEvent(void) {
   
   switch ( EventState ) {
   case NORMAL_STATE:
-    while ( NULL != (theEvent = XCBPollForEvent( xc, &error )) ) {  /*while ( XCheckMaskEvent( theDisplay, EVENT_MASK, &theEvent ) ) {*/
-         switch ( theEvent->response_type ) {
+    while ( ContinueState &&
+            NULL != (theEvent = XCBPollForEvent( xc, &error )) ) {  /*while ( XCheckMaskEvent( theDisplay, EVENT_MASK, &theEvent ) ) {*/
+         switch ( theEvent->response_type & 0x7f ) {
          case XCBConfigureNotify:
            theConfigureNotification = (XCBConfigureNotifyEvent *)theEvent;
                WindowWidth = theConfigureNotification->width;
@@ -1185,26 +1199,24 @@ Bool  ProcessEvent(void) {
                break;
          case XCBKeyPress:
                ContinueState = ProcessKeyPress( (XCBKeyPressEvent *)theEvent );
-               if ( !ContinueState ) {
-                 free(theEvent);
-                 return( ContinueState );
-               }
                break;
          case XCBButtonPress:
            theButtonPress = (XCBButtonPressEvent *)theEvent;
-               if ( theButtonPress->detail.id == 3 ) { /* xbutton.button */
-                 free(theEvent);
-                 return( False );
-               }
+               ContinueState = ( theButtonPress->detail.id != 3 );     /* xbutton.button */
                break;
+         /* new: handle ClientMessage */
+         case XCBClientMessage:
+           ContinueState = !IsDeleteMessage((XCBClientMessageEvent *)theEvent);
+           break;
          default:
                /* Unknown Event */
+               /*printf("event type:%x\n", (int)theEvent->response_type);*/
                break;
          }
          free(theEvent);
          if (error != 0)
                return False;
-       }
+       } /* end while */
        break;
 #ifdef DEBUG
   case DEBUG_LIST: