2015-07-21 17 views
60

मैं एक छोटे से विंडो प्रबंधक (सिर्फ मनोरंजन के लिए) बनाने के लिए कोशिश कर रहा हूँ, लेकिन मैं से निपटने फ़ायरफ़ॉक्स द्वारा बनाई खिड़कियों में समस्या आ रही है (केवल कि आवेदन के साथ, अन्य एप्लिकेशन ठीक काम करता है)Xlib और Firefox व्यवहार

समस्या यह है कि, जब मैं फ़ायरफ़ॉक्स लॉन्च करता हूं, और अपनी सजावट जोड़ता हूं, तो यह ठीक काम करता प्रतीत होता है, लेकिन यदि उदाहरण के लिए मैं मेनू बटन पर क्लिक करने का प्रयास करता हूं, तो (उप) विंडो प्रकट नहीं होती है।

क्या लगता है कि क्लिक करने के बाद, एक ClientMessage घटना के बाद मूल्यों के साथ निकाल दिया जाता है:

Data: (null) 
Data: _NET_WM_STATE_HIDDEN 
Data: (null) 
Data: (null) 
Data: (null) 

अब समस्या मैं कैसे खिड़की है, जो खिड़की को दिखाने के लिए नहीं पता है कि है। मैं के साथ की कोशिश की:

  • XRaiseWindow
  • XMapWindow
  • मैं क्षणिक खिड़की हो और यह

लेकिन सफलता नहीं मिली दिखाने की कोशिश की। जो मुझे समझ में नहीं आता है वह यह है कि यदि यह क्लाइंट संदेश मेनू सबविंडो द्वारा उत्पन्न होता है या नहीं।

मुझे _NET_WM_STATE_HIDDEN में एक विंडो कैसे दिखानी चाहिए?

एक और अजीब समस्या यह है कि क्लाइंट मैसेज प्राप्त करने के बाद, मुझे हमेशा 2 UnMapNotify ईवेंट प्राप्त होते हैं।

मैं भी अन्य प्रश्न है, अगर मैं दिखाना चाहता हूँ "फाइल, संपादन" मेनू (Firefox में यह प्रतीत होता है, अगर मैं सही ढंग से याद है, जब आप Alt बटन दबाएँ।

शायद Firefox का वह पेड़ बनाता है ? विंडोज़

इस पाश मैं कहाँ ईवेंट प्रबंधित है:

while(1){ 
    XNextEvent(display, &local_event); 
    switch(local_event.type){ 
     case ConfigureNotify: 
      configure_notify_handler(local_event, display); 
     break; 
     case MotionNotify: 
      motion_handler(local_event, display); 
     break; 
     case CreateNotify: 
      cur_win = local_event.xcreatewindow.window; 
      char *window_name; 
      XFetchName(display, cur_win, &window_name); 
      printf("Window name: %s\n", window_name); 
      if(window_name!=NULL){ 
       if(!strcmp(window_name, "Parent")){ 
        printf("Adding borders\n"); 
        XSetWindowBorderWidth(display, cur_win, BORDER_WIDTH); 
       } 
       XFree(window_name); 
      } 
     break; 
     case MapNotify: 
      map_notify_handler(local_event,display, infos); 
     break; 
     case UnmapNotify: 
      printf("UnMapNotify\n"); 
     break; 
     case DestroyNotify: 
      printf("Destroy Event\n"); 
      destroy_notify_handler(local_event,display); 
     break; 
     case ButtonPress: 
      printf("Event button pressed\n"); 
      button_handler(local_event, display, infos); 
     break; 
     case KeyPress: 
      printf("Keyboard key pressed\n"); 
      keyboard_handler(local_event, display); 
     break; 
     case ClientMessage: 
      printf("------------ClientMessage\n"); 
      printf("\tMessage: %s\n", XGetAtomName(display,local_event.xclient.message_type)); 
      printf("\tFormat: %d\n", local_event.xclient.format); 
      Atom *atoms = (Atom *)local_event.xclient.data.l; 
      int i =0; 
      for(i=0; i<=5; i++){ 
       printf("\t\tData %d: %s\n", i, XGetAtomName(display, atoms[i])); 
      } 
      int nchild; 
      Window *child_windows; 
      Window parent_window; 
      Window root_window; 
      XQueryTree(display, local_event.xclient.window, &root_window, &parent_window, &child_windows, &nchild); 
      printf("\tNumber of childs: %d\n", nchild); 
     break; 
    } 

अब clientmessage वास्तव में मैं सिर्फ कुछ जानकारी एकत्रित समझने के लिए क्या हो रहा है देखने के लिए कोशिश कर रहा हूँ और क्या मैं से देख सकते हैं में। उपरोक्त कोड, यह है कि खिड़की जो वें उठाया ई घटना में एक बच्चा होता है (फिर से: वह मेनू है? या नहीं)

MapNotify घटना है, जहां मैं सजावट जोड़ने के लिए कोड निम्नलिखित है:

void map_notify_handler(XEvent local_event, Display* display, ScreenInfos infos){ 
    printf("----------Map Notify\n"); 
    XWindowAttributes win_attr; 
    char *child_name; 
    XGetWindowAttributes(display, local_event.xmap.window, &win_attr); 
    XFetchName(display, local_event.xmap.window, &child_name); 
    printf("\tAttributes: W: %d - H: %d - Name: %s - ID %lu\n", win_attr.width, win_attr.height, child_name, local_event.xmap.window); 
    Window trans = None;  
    XGetTransientForHint(display, local_event.xmap.window, &trans); 
    printf("\tIs transient: %ld\n", trans); 
    if(child_name!=NULL){ 
     if(strcmp(child_name, "Parent") && local_event.xmap.override_redirect == False){ 
     Window new_win = draw_window_with_name(display, RootWindow(display, infos.screen_num), "Parent", infos.screen_num, 
          win_attr.x, win_attr.y, win_attr.width, win_attr.height+DECORATION_HEIGHT, 0, 
          BlackPixel(display, infos.screen_num)); 
     XMapWindow(display, new_win); 
     XReparentWindow(display,local_event.xmap.window, new_win,0, DECORATION_HEIGHT); 
     set_window_item(local_event.xmap.window, new_win); 
     XSelectInput(display, local_event.xmap.window, StructureNotifyMask); 
     printf("\tParent window id: %lu\n", new_win); 
     put_text(display, new_win, child_name, "9x15", 10, 10, BlackPixel(display,infos.screen_num), WhitePixel(display, infos.screen_num)); 
     } 
    } 
    XFree(child_name); 
} 

अब किसी को इन समस्याओं के साथ मेरी मदद कर सकते? दुर्भाग्यवश मैं पहले से ही कई बार गुगल रहा हूं, लेकिन सफलता के बिना।

समेकित करने के लिए, मेरे मुद्दे दो हैं: 1. फ़ायरफ़ॉक्स से सबविंडो कैसे दिखाएं 2. फ़ाइल को कैसे संपादित करें, मेनू संपादित करें।

अद्यतन

मैं xev के साथ कुछ अजीब परीक्षण फ़ायरफ़ॉक्स देखा समझने के लिए घटनाओं के क्रम एक आवेदन को दिखाने के लिए में निकाल दिया जाता है। मैंने देखा कि एकता में फ़ायरफ़ॉक्स का उपयोग करके, और किसी अन्य विंडो मैनेजर में फ़ायरफ़ॉक्स का उपयोग करके, निकाले गए ईवेंट पूरी तरह से अलग हैं।एकता में मैं केवल है:

  1. ClientMessage
  2. UnmapNotify

इसके बजाय Firefox का उपयोग कर, xfce4 साथ उदाहरण के लिए, उत्पन्न xevents अधिक कर रहे हैं:

  1. VisiblityNotify (एक से अधिक)
  2. घटना का खुलासा करें (एक से अधिक)

लेकिन अगर मैं अपने wm में VisibilityChangeMask सक्षम करने के लिए प्रयास करते हैं, मैं निम्न इवेंट प्राप्त करते हैं:

  • ConfigureNotify
  • ClientMessage
  • MapNotify
  • 2 UnMapNotify

अद्यतन 2

मैं ClientMessage विंडो में XWMhints गुण (शायद मेनू विंडो) को पढ़ने के लिए कोशिश की और मान हैं:

  • झंडे के लिए 67 = InputHint, StateHint, WIndowGroupHint

  • प्रारंभिक अवस्था के लिए NormalState

अद्यतन 3

मैं कैसे एक देखने के लिए करने की कोशिश की नोटर विंडो प्रबंधक काम करता है, और मैं शांतwm के स्रोत कोड को देख रहा था। मेरी समझ क्या है कि, जब क्लाइंट मैसेज ईवेंट आता है, _NET_WM_STATE संदेश के साथ, यह इन गुणों को अपडेट करता है, और _NET_WM_STATE_HIDDEN के मामले में यह इस संपत्ति को साफ़ करता है, और नतीजा यह होगा कि संपत्ति हटा दी जाएगी। तो मैंने उस संपत्ति को हटाने के लिए अपना कोड अपडेट करने का प्रयास किया, लेकिन यह अभी भी काम नहीं कर रहा है। वैसे भी client_message_handler में प्रासंगिक अद्यतन कोड अब इस तरह दिखता है:

Atom *atoms = (Atom *)local_event.xclient.data.l; 
int i =0; 
for(i=0; i<=5; i++){ 
    printf("\t\tData %d: %s\n", i, XGetAtomName(display, atoms[i])); 
    if(i==1){ 
     printf("\t Deleting Property: _NET_WM_STATE_HIDDEN \n"); 
     XDeleteProperty(display, cur_window, atoms[i]); 
    } 
} 

यह केवल एक परीक्षण है, और मुझे यकीन है कि मैं = मेरे मामले में 1 _NET_WM_STATE_HIDDEN संपत्ति है हूँ।

यहाँ

calmwm स्रोत कोड के लिए एक लिंक: https://github.com/chneukirchen/cwm/blob/linux/xevents.c

तो मैं अभी भी उस बिंदु पर अटक कर रहा हूँ।

अद्यतन 4

सच मैं अगर यह मदद करता है पता नहीं है, लेकिन मैं खिड़की MapNotify घटना में जिम्मेदार बताते हैं पढ़ने के लिए करने की कोशिश की, और खिड़की map_state IsViewable है (2)।

अद्यतन 5

मैं एक ऐसी ही समस्या अतः में यहां पाया, अजगर के साथ Xlib का उपयोग कर: Xlib python: cannot map firefox menus

समाधान XSetInputFocus उपयोग करने के लिए सुझाव देते हैं, मैं करने की कोशिश की है कि मेरे XMapNotify हैंडलर:

XSetInputFocus(display, local_event.xmap.window, RevertToParent, CurrentTime); 

लेकिन यह अभी भी मदद नहीं करता है, फ़ायरफ़ॉक्स मेनू अभी भी प्रकट नहीं होता है !! और मुझे राइट-क्लिक के साथ एक ही समस्या है।

अद्यतन 6

xconfigurenotify घटना और unmap घटना के साथ खेलना मैंने पाया है कि: Xconfigure अनुरोध 2 खिड़की फ़ील्ड होते हैं: खिड़की और इसके बाद के संस्करण, और जब xconfigurerequest.window मूल्य xunmap का एक ही है विन्डो मूल्य।

और यह भी कि xconfigurerequest.above हमेशा बदल रहा है, लेकिन xconfigurerequest.window हमेशा सभी घटनाओं में समान होता है।

ऐसा लगता है कि xconfigurerequest.above उस मेनू से संबंधित है जिसे मैं खोलने की कोशिश कर रहा हूं। उदाहरण के लिए:

  • एक पृष्ठ मैं एक आईडी (हमेशा बाद के हर क्लिक के लिए एक ही)
  • पाने पर अगर राइट क्लिक करता है, तो मैं एक टैब पर राइट-clik, ऊपर मूल्य एक और एक
  • है और वैसे ही अगर मैं फ़ायरफ़ॉक्स मुख्य मेनू

पर बायाँ-क्लिक करें तो अभी भी यह नहीं पता कि इससे मदद मिलती है या नहीं।

वास्तव में किसी को भी कोई जानकारी नहीं है?

+3

मेरे दोस्त और मैं फ़ायरफ़ॉक्स के साथ x11, gtk, gdk, और अन्य सी lib सामग्री का बहुत कुछ करता हूं। हमने '_NET_ACTIVE_WINDOW' संकेत और 'XMapRaised' सेट करके एक विंडो पर ध्यान केंद्रित किया: https://gist.github.com/Noitidart/c7be5489fd38f8ecc76b#file-_ff-addon-snippet-x11_focuswindowbynativehandle-js-L280-L283 बीमार और अधिक देखें आपकी समस्या और मेरे मित्र को भी – yatg

+0

आपकी टिप्पणी के लिए @yatg धन्यवाद, मेरे पास कोड स्निपेट पर एक प्रश्न है जिसे आपने मुझे भेजा है, l0 फ़ील्ड एक ही फ़ील्ड है जो c में xclient.data.l0 होगा?और आप इसे 2 क्यों सेट करते हैं? – Ivan

+3

असल में इस कोड को अपने क्लीनर को देखें: https://github.com/Noitidart/NativeShot/blob/winnt-found-workaround-for-winnt-nondpi-scale/modules/workers/MainWorker.js#L132-L159 मूल रूप से कारण 2 था क्योंकि यह यहां देखा गया है कि '_NET_WM_STATE_TOGGLE' के लिए जादू संख्या है: https://github.com/Noitidart/NativeShot/blob/winnt-found-workaround-for-winnt-nondpi-scale/modules/ ostypes_x11.jsm # L245 'XFlush'' कार्रवाई करने के लिए महत्वपूर्ण है, यदि 'एक्सफ्लश' नहीं किया जाता है, तो कम से कम हमारे प्रयोगकर्ता में यह आगे नहीं आएगा, इसलिए 'एक्सएफएलश' का उपयोग करके आपका समाधान मुझे बता सकता है कि यह कैसे plz चला जाता है। – yatg

उत्तर

1

उपयोग xtruss - एक आसान से उपयोग एक्स प्रोटोकॉल अनुरेखण कार्यक्रम


अवलोकन

किसी भी प्रोग्रामर लिनक्स या सिस्टम वी-प्रकार पर कार्यक्रम लेखन के आदी यूनिक्सों को इस कार्यक्रम का सामना करना पड़ेगा जो विभिन्न प्रकार के स्ट्रेस या ट्रस के रूप में जाना जाता है, जो किसी अन्य कार्यक्रम पर नज़र रखता है और प्रत्येक sys का विस्तृत लॉग बनाता है tem कॉल प्रोग्राम बनाता है - दूसरे शब्दों में, ओएस कर्नेल के साथ सभी प्रोग्राम की इंटरैक्शन। यह अक्सर एक अमूल्य डीबगिंग उपकरण होता है, और लगभग एक शैक्षणिक व्यक्ति के रूप में।

जब यह एक जीयूआई प्रोग्राम (या बल्कि, एक प्रोग्राम का जीयूआई-संबंधित व्यवहार) है जिसे आप समझना या डिबग करना चाहते हैं, हालांकि, ओएस कर्नेल के साथ बातचीत का स्तर शायद ही कभी सबसे उपयोगी है। अधिक मददगार, कोई भी एक्स सर्वर के साथ सभी कार्यक्रमों के इंटरैक्शन को उसी तरह लॉग करना चाहता है।

प्रोग्राम पहले से मौजूद हैं जो ऐसा करेंगे। मुझे एक्समोन और एक्सट्रैस से अवगत है।लेकिन उन्हें स्थापित करने के लिए बहुत मेहनत की आवश्यकता होती है: आपको एक सुनवाई सर्वर स्थापित करने के लिए प्रोग्राम चलाया जाना है, फिर वास्तविक प्रोग्राम के बजाय मैन्युअल रूप से संपर्क करने के लिए लक्ष्य प्रोग्राम की व्यवस्था करना है - जिसमें xauth के साथ कुछ विचित्र काम शामिल हैं। आदर्श रूप में, आप किसी प्रोग्राम के एक्स ऑपरेशंस को अपने कर्नेल सिस्टम कॉल का पता लगाने के समान ही आसान बनाना चाहते हैं: आप एक कमांड प्रोग्राम-नाम तर्क के रूप में सरल आदेश टाइप करना चाहते हैं, और आपके लिए सब कुछ स्वचालित रूप से संभाला जाता है।

इसके अलावा, उन कार्यक्रमों का आउटपुट मुझे पढ़ने की तुलना में पढ़ने में आसान नहीं है - जिसके द्वारा मुझे काफी हद तक मतलब है कि यह स्ट्रेस की तरह कम है जितना मैं चाहता हूं। स्ट्रेस में प्रत्येक सिस्टम कॉल और उसके रिटर्न वैल्यू को आउटपुट की उसी पंक्ति पर डालने की अच्छी संपत्ति होती है, ताकि आप एक नज़र में देख सकें कि प्रत्येक प्रतिक्रिया किस प्रतिक्रिया का था। एक्स प्रोटोकॉल मॉनीटर, हालांकि, एक्स प्रोटोकॉल की संरचना का ईमानदारी से पालन करते हैं, जिसका अर्थ है कि प्रत्येक अनुरोध और प्रतिक्रिया अनुक्रम संख्या के साथ मुद्रित होती है, और आपको आंखों से दो मिलना होगा।

तो यह पृष्ठ एक्स प्रोटोकॉल लॉगर्स के क्षेत्र में अपना योगदान, xtruss प्रस्तुत करता है। इसमें स्ट्रेस के समान कमांड-लाइन सिंटैक्स है - इसके डिफ़ॉल्ट मोड में, आप वही कमांड लाइन पर "xtruss" उपसर्ग करते हैं जिसे आप वैसे भी चलाते थे - और इसका आउटपुट प्रारूप भी स्ट्रेस की तरह है, अनुरोधों और प्रतिक्रियाओं को उसी पर डाल रहा है आउटपुट की लाइन जहां उचित रूप से संभव है।

स्ट्रेस भी पहले से चलने वाली प्रक्रिया को जोड़ने और इसे चलाने के बीच से ट्रेस करने की सुविधा का समर्थन करता है, जब एक लंबी चल रही प्रक्रिया के साथ कुछ गलत हो जाता है जिसे आप पहले से नहीं जानते थे पता लगाने की जरूरत है। एक्सट्रॉस एक्स रिकॉर्ड्स एक्सटेंशन के माध्यम से, वही सुविधा का समर्थन करता है (बशर्ते आपका एक्स सर्वर इसका समर्थन करता हो, जो आधुनिक एक्स.ऑर्ग लोग करते हैं); तो उस मोड में, आप माउस के साथ एक विंडो की पहचान कर सकते हैं (इसी प्रकार मानक प्रोग्राम जैसे xwininfo और xkill), और एक्सट्रस एक्स क्लाइंट प्रोग्राम से जुड़ा होगा जो आपके द्वारा निर्दिष्ट विंडो का मालिक है, और इसे ढूंढना शुरू करें।


विवरण

xtruss एक उपयोगिता जो सब कुछ है कि X सर्वर और एक या अधिक एक्स क्लाइंट प्रोग्राम के बीच से गुजरता लॉग है। इसमें यह xmon (1) के समान है, लेकिन एक्सएमन की बुनियादी कार्यक्षमता को एक इंटरफ़ेस के साथ गठबंधन (1) के समान जोड़ना है।

xmon की तरह, xtruss अपने डिफ़ॉल्ट मोड में प्रॉक्सी एक्स सर्वर सेट करके, उसके कनेक्शन के लिए प्रतीक्षा करके और उन्हें वास्तविक एक्स सर्वर पर अग्रेषित करके काम करता है। हालांकि, एक्समोन के विपरीत, आपको किसी भी हाथ से निपटने की ज़रूरत नहीं है: एक टर्मिनल में ट्रेस यूटिलिटी शुरू करने की आवश्यकता नहीं है और जब तक आप वास्तव में नहीं चाहते हैं, तब तक मैन्युअल रूप से इसे अन्य प्रक्रियाओं को संलग्न करें। पी विकल्प ऐसा करेगा)। उपयोग का मुख्य तरीका सिर्फ आपके एक्स प्रोग्राम की कमांड लाइन के बाद xtruss टाइप करना है; xtruss स्वचालित रूप से अपने प्रॉक्सी सर्वर को इंगित करने के लिए नए प्रोग्राम के पर्यावरण को समायोजित करने का ख्याल रखेगा, और (एक्सएमएन के विपरीत भी) यह एक्स प्रमाणीकरण का भी ख्याल रखेगा।

उपयोग के वैकल्पिक तरीके के रूप में, आप पहले से चल रहे एक्स अनुप्रयोग में xtruss को भी संलग्न कर सकते हैं, अगर आपको एहसास नहीं हुआ कि आप इसे तब तक ट्रेस करना चाहते हैं जब तक कि यह पहले से शुरू नहीं हुआ था। इस मोड को एक्स सर्वर से सहयोग की आवश्यकता है - विशेष रूप से, यह तब तक काम नहीं कर सकता जब तक कि सर्वर रिकॉर्ड्स प्रोटोकॉल एक्सटेंशन का समर्थन नहीं करता - लेकिन आधुनिक X.Org सर्वर प्रदान करते हैं, यह अक्सर उपयोगी होता है।

+0

धन्यवाद, मैं इसे एक नज़र दूंगा! :) – Ivan

संबंधित मुद्दे