2014-09-21 2 views
0

Я преобразование этого Topis в jsctypes для X11:Получение окна X11 из PID - правильный доступ к массиву? сбой

Это работает нормально. Я просто сталкиваюсь с одной проблемой, когда я зацикливаю код на его сбой.

Для тестирования Im только один раз зацикливание пока он по-прежнему падает:

код Проблема здесь:

searchForPidStartingAtWindow(wChildElementCasted, _disp, targetPid, true); 

как только я запускаю этот код он выходит из строя. даже он возвращается на вторую итерацию этой функции. 4argument is true

Полный код, можно скопировать и вставить в Scratchpad (Borwser> Environment) и запустить.

Cu.import('resource://gre/modules/ctypes.jsm'); 


function doit() { 
    try { 
     _x11 = ctypes.open('libX11.so.6'); 
    } catch (e) { 
     try { 
      var libName = ctypes.libraryName('X11'); 
     } catch (e) { 
      _x11 = false; 
      console.error('Integration: Could not get libX11 name; not activating'); 
      return; 
     } 

     try { 
      _x11 = ctypes.open(libName); 
     } catch (e) { 
      _x11 = false; 
      console.error('Integration: Could not open ' + libName + '; not activating'); 
      return; 
     } 
    } 

    //start - type constants 
    X11Atom = ctypes.unsigned_long; 
    X11Bool = ctypes.int; 
    X11Display = new ctypes.StructType('Display'); 
    X11Window = ctypes.unsigned_long; 
    X11Status = ctypes.int; 
    //end - type constants 

    //start - constants 
    var XA_CARDINAL = 6; //https://github.com/foudfou/FireTray/blob/d0c49867ea7cb815647bf13f2f1edb26439506ff/src/modules/ctypes/linux/x11.jsm#L117 
    var None = 0; //https://github.com/foudfou/FireTray/blob/d0c49867ea7cb815647bf13f2f1edb26439506ff/src/modules/ctypes/linux/x11.jsm#L63 
    var Success = 0; 
    //end - constants 

    /* 
    * typedef struct { 
    *  int type; 
    *  unsigned long serial; /* # of last request processed by server */
    *  Bool send_event;  /* true if this came from a SendEvent request */
    *  Display *display;  /* Display the event was read from */
    *  Window window; 
    *  Atom message_type; 
    *  int format; 
    *  union { 
    *   char b[20]; 
    *   short s[10]; 
    *   long l[5]; 
    *  } data; 
    * } XClientMessageEvent; 
    */ 
    XClientMessageEvent = new ctypes.StructType('XClientMessageEvent', [ 
     {'type': ctypes.int}, 
     {'serial': ctypes.unsigned_long}, 
     {'send_event': X11Bool}, 
     {'display': X11Display.ptr}, 
     {'window': X11Window}, 
     {'message_type': X11Atom}, 
     {'format': ctypes.int}, 
     {'l0': ctypes.long}, 
     {'l1': ctypes.long}, 
     {'l2': ctypes.long}, 
     {'l3': ctypes.long}, 
     {'l4': ctypes.long} 
    ]); 

    /* 
    * Status XFetchName(
    * Display*  display, 
    * Window  w, 
    * char**  window_name_return 
    *); 
    */ 
    XFetchName = _x11.declare('XFetchName', ctypes.default_abi, X11Status, 
     X11Display.ptr, X11Window, ctypes.char.ptr.ptr); 

    /* 
    * Status XQueryTree(
    * Display*  display, 
    * Window  w, 
    * Window*  root_return, 
    * Window*  parent_return, 
    * Window**  children_return, 
    * unsigned int* nchildren_return 
    *); 
    */ 
    XQueryTree = _x11.declare('XQueryTree', ctypes.default_abi, X11Status, 
     X11Display.ptr, X11Window, X11Window.ptr, X11Window.ptr, X11Window.ptr.ptr, 
     ctypes.unsigned_int.ptr); 

    /* 
    * int XFree(
    * void*  data 
    *); 
    */ 
    XFree = _x11.declare('XFree', ctypes.default_abi, ctypes.int, ctypes.voidptr_t); 

    /* 
    * Display *XOpenDisplay(
    *  _Xconst char* display_name 
    *); 
    */ 
    XOpenDisplay = _x11.declare('XOpenDisplay', ctypes.default_abi, X11Display.ptr, 
     ctypes.char.ptr); 

    /* 
    * int XCloseDisplay(
    *  Display*  display 
    *); 
    */ 
    XCloseDisplay = _x11.declare('XCloseDisplay', ctypes.default_abi, ctypes.int, 
     X11Display.ptr); 

    /* 
    * int XFlush(
    *  Display*  display 
    *); 
    */ 
    XFlush = _x11.declare('XFlush', ctypes.default_abi, ctypes.int, X11Display.ptr); 

    /* 
    * Window XDefaultRootWindow(
    *  Display*  display 
    *); 
    */ 
    XDefaultRootWindow = _x11.declare('XDefaultRootWindow', ctypes.default_abi, 
     X11Window, X11Display.ptr); 

    /* 
    * Atom XInternAtom(
    *  Display*   display, 
    *  _Xconst char* atom_name, 
    *  Bool    only_if_exists 
    *); 
    */ 
    XInternAtom = _x11.declare('XInternAtom', ctypes.default_abi, X11Atom, 
     X11Display.ptr, ctypes.char.ptr, X11Bool); 

    /* 
    * Status XSendEvent(
    *  Display*  display, 
    *  Window  w, 
    *  Bool   propagate, 
    *  long   event_mask, 
    *  XEvent*  event_send 
    *); 
    */ 
    XSendEvent = _x11.declare('XSendEvent', ctypes.default_abi, X11Status, 
     X11Display.ptr, X11Window, X11Bool, ctypes.long, XClientMessageEvent.ptr); 

    /* 
    * int XMapRaised(
    *  Display*  display, 
    *  Window  w 
    *); 
    */ 
    XMapRaised = _x11.declare('XMapRaised', ctypes.default_abi, ctypes.int, 
     X11Display.ptr, X11Window); 

    /* 
    * extern int XGetWindowProperty(
    *  Display*  display, 
    *  Window  w, 
    *  Atom  property, 
    *  long  long_offset, 
    *  long  long_length, 
    *  Bool  delete, 
    *  Atom  req_type, 
    *  Atom*   actual_type_return, 
    *  int*  actual_format_return, 
    *  unsigned long* nitems_return, 
    *  unsigned long* bytes_after_return, 
    *  unsigned char** prop_return 
    *); 
    */ 
    XGetWindowProperty = _x11.declare('XGetWindowProperty', ctypes.default_abi, 
     ctypes.int, X11Display.ptr, X11Window, X11Atom, ctypes.long, ctypes.long, 
     X11Bool, X11Atom, X11Atom.ptr, ctypes.int.ptr, ctypes.unsigned_long.ptr, 
     ctypes.unsigned_long.ptr, ctypes.char.ptr.ptr); 

    //////////////////////// 
    ////END DECLARATIONS 
    //////////////////////// 

    var _x11Display = XOpenDisplay(null); 
    if (!_x11Display) { 
     console.error('Integration: Could not open display; not activating'); 
     _x11 = false; 
     return; 
    } 


    var _x11RootWindow = XDefaultRootWindow(_x11Display); 
    if (!_x11RootWindow) { 
     console.error('Integration: Could not get root window; not activating'); 
     _x11 = false; 
     return; 
    } 

    //start - WindowsMatchingPid from https://stackoverflow.com/questions/151407/how-to-get-an-x11-window-from-a-process-id 
    //start - searchForPidStartingAtWindow func 
    var _atomPIDInited = false; 
    var _atomPID; 
    var _matchingWins = []; 
    function searchForPidStartingAtWindow(w, _disp, targetPid, isRecurse) { // when you call must always leave isRecurse null or false, its only used by the function to identify when to clear out _matchingWins 
     if (!isRecurse) { 
      //user just called this function so clear _matchingWins 
      _matchingWins = []; 
     } else { 
      console.log('isRecurse so return'); 
     } 
     console.log('h1'); 
     //make sure to clear _matchingWins arr before running this 
     if (!_atomPIDInited) { 
      _atomPID = XInternAtom(_disp, '_NET_WM_PID', true); 
      console.log('_atomPID:', _atomPID, _atomPID.toString(), parseInt(_atomPID)); 
      if(_atomPID == None) { 
       throw new Error('No such atom ("_NET_WM_PID"), _atomPID:', _atomPID); 
      } 
      _atomPIDInited = true; 
     } 

     var returnType = new X11Atom(), 
     returnFormat = new ctypes.int(), 
     nItemsReturned = new ctypes.unsigned_long(), 
     nBytesAfterReturn = new ctypes.unsigned_long(), 
     propData = new ctypes.char.ptr(); 
     console.log('h2'); 
     console.log('_disp:', _disp, 'w:', w, '_atomPID:', _atomPID); 
     var rez = XGetWindowProperty(_disp, w, _atomPID, 0, 1024, false, XA_CARDINAL, returnType.address(), returnFormat.address(), nItemsReturned.address(), nBytesAfterReturn.address(), propData.address()); 
     console.log('h3'); 
     console.log('XGetWindowProperty', 'rez:', rez, 'returnType:', returnType, 'nItemsReturned:', nItemsReturned, 'nBytesAfterReturn:', nBytesAfterReturn, 'propData:', propData); 
     console.log('propData:', ctypes.cast(propData, ctypes.unsigned_int).value); 
     if (rez == Success) { 
      var nElements = ctypes.cast(nItemsReturned, ctypes.unsigned_int).value; 
      if(nElements) { 
       var rezArr = [propData, nElements]; 
       console.log('rezArr:', rezArr); 
      } else { 
       console.log('no elements for rezArr, nElements:', nElements); 
      } 
      var nPid = ctypes.cast(propData, ctypes.unsigned_int).value; 
      if (nPid != 0) { 
       _matchingWins.push(w); 
       console.log('h4'); 
       var rez = XFree(propData); 
       console.log('rez of XFree on propData:', rez); 
      } else { 
       console.log('no pid on this window'); 
      } 
     } else { 
      console.error('failed on XGetWindowProperty, rez:', rez); 
     } 
     if (isRecurse) { 
      return; 
     } 

     console.log('recurse into'); 

     // recurse into child windows 
     var wRoot = new X11Window(); 
     var wParent = new X11Window(); 
     var wChild = new X11Window.ptr(); 
     var nChildren = new ctypes.unsigned_int(); 

     var rez = XQueryTree(_disp, w, wRoot.address(), wParent.address(), wChild.address(), nChildren.address()); 
     if(rez != 0) { //can probably test this against `None` instead of `0` 
      var nChildrenCasted = ctypes.cast(nChildren, ctypes.unsigned_int).value; 
      var wChildCasted = ctypes.cast(wChild, ctypes.ArrayType(X11Window, nChildrenCasted).ptr).contents; //console.log('wChildCasted:', wChildCasted); 
      //var wChildElementCasted = ctypes.cast(wChildCasted.addressOfElement(0), X11Window).value; 
      //console.log('wChildElementCasted:', wChildElementCasted, 'w:', w); 
      //for(var i=0; i<wChildCasted.length; i++) { 
      for(var i=0; i<1; i++) { 
       var wChildElementCasted = ctypes.cast(wChildCasted.addressOfElement(i), X11Window).value; 
       console.log('wChildElementCasted:', wChildElementCasted, 'w:', w); 
       searchForPidStartingAtWindow(wChildElementCasted, _disp, targetPid, true); 
      } 
     } else { 
      console.warn('this window has no children, rez:', rez); 
     } 

     return _matchingWins; 
    } 
    //end - searchForPidStartingAtWindow func 

    var wins = searchForPidStartingAtWindow(_x11RootWindow, _x11Display, 12312132); //dont pass isRecurse here, important, otherwise if use this func multiple times, you'll have left over windows in the returned array from a previous run of this func 
    console.log('wins:', wins); 

    //end - WindowsMatchingPid 

    XCloseDisplay(_x11Display); 

    //_X11BringToForeground(win, intervalID); 
} 

doit(); 

ответ

0

решаемые, я должен был использовать этот код:

  var wChildCasted = ctypes.cast(wChild, X11Window.array(nChildrenCasted).ptr).contents; //SAME AS: `var wChildCasted = ctypes.cast(wChild, ctypes.ArrayType(X11Window, nChildrenCasted).ptr).contents;` 

      for(var i=0; i<wChildCasted.length; i++) { 
       var wChildElementCasted = wChildCasted.addressOfElement(i).contents; //DO NOT DO `var wChildElementCasted = ctypes.cast(wChildCasted.addressOfElement(i), X11Window).value;`, it crashes on line 234 when passing as `w` into `XGetWindowProperty` 
       //console.log('wChildElementCasted:', wChildElementCasted, 'w:', w); 
       searchForPidStartingAtWindow(wChildElementCasted, _disp, targetPid, true); 
      } 

уведомление как wChildElementCasted не больше с приведением, я просто прочитал .contents. это правильный способ сделать это наверняка.

копировальная и полностью работающая здесь: https://gist.github.com/Noitidart/5a24e8a4f8886ce7bbf6