Search code examples
c++linuxxlib

linux c++ xlib, how to use XSaveContext and XFindContext (example provided)


for XNextEvent(display,&e) returned by some windows I need to access to the class to whom this window belong, after some searchs on the web and books, XSaveContext and XFindContext looks to be usefull, but I didn't found any example of using. So let's try :

I have a class Metallica, I would like to save the adress of a Metallica object when the constructor is called in a XContext :

class Metallica{
  private:
    Window window;
    int i;
    .
    .
  public:
    Metallica(...,int j, XContext *context){
      .
      .
      i=j;
      //XSaveContext(display, this->window, *context, this); // don't work
      XSaveContext(display, this->window, *context, XPointer(this));
      .
      .
      void MasterOfPuppet(){
        cout << i << endl;
      };
      void FadeToBlack(){
        cout << "OK" << endl;
      };
    };

};

so now in my xevent loop I want to get the adress back of one Metallica object,

// at the declaration area :
// XContext Metallica_Context;
// XPointer *XPointerToOneMetallicaObject;

XFindContext(display,
             e.xany.window,
             Metallica_Context,
             XPointerToOneMetallicaObject );

Metallica *SandMan = (Metallica*)(*XPointerToOneMetallicaObject);

SandMan->FadeToBlack();    // no problem
SandMan->MasterOfPuppet(); // return a segmentation fault

So I do something wrong, but what ?


Solution

  • I found where I wrong, when I call XFindContext() the parameter e.xany.window can be called by 'any' window, so even ones not made by a Metallica, then calling MasterOfPuppet() do shit... so I need to protect the call that's it!

    well, here a basic (I don't protect the call, but in this case that don't do shit) working code (this code can be used by you to see how XContext can be used, lucky you...) :

    //g++ test.cc -lX11
    #include<iostream>
    #include<unistd.h>
    #include<X11/Xlib.h>
    #include<X11/Xutil.h>
    
    Display *display;
    
    
    class Metallica{
      private:
        Window window;
        int i;
    
      public:
        Metallica(int j, XContext *context){
          i=j;
          this->window = XCreateSimpleWindow(display,DefaultRootWindow(display),100,100,100,100,0,0,0);
          XSelectInput(display, this->window, ExposureMask|ButtonReleaseMask|KeyReleaseMask);
          XMapWindow(display,this->window);
          XSaveContext(display, this->window, *context, XPointer(this));
        };
        void MasterOfPuppet(){
          std::cout << i << std::endl;
        };
        void FadeToBlack(){
          std::cout << "ok" << std::endl;
        };
    };
    
    int main(){
      XContext Metallica_context;
      XPointer *XPointerToOneMetallicaObject;
      XEvent e;
      int DoNotStop=1;
    
      display = XOpenDisplay(0);
    
      Metallica OneMetallicaObject(2,&Metallica_context);
      Metallica *SandMan;
    
      while(DoNotStop){
        XNextEvent(display, &e);
        switch(e.type){
        case Expose : XFlush(display); break;
        case ButtonRelease : XFindContext(display,e.xany.window,Metallica_context,XPointerToOneMetallicaObject);
                             SandMan = (Metallica*)(*XPointerToOneMetallicaObject);
                             SandMan->MasterOfPuppet();
                             break;
        case KeyRelease    : DoNotStop=0; break;
        }
      }
    
      return 0;
    }