मैं एक विशिष्ट कार्यक्षेत्र में किसी एप्लिकेशन (और उसकी सभी नई विंडो) को कैसे लॉक कर सकता हूं?


11

में एक Matlabस्क्रिप्ट चलाता हूँ workspace 1। यह कई भूखंड उत्पन्न करता है। इस बीच मैं workspace 2वहां काम करने और काम करने लगा। मेरी समस्या यह है कि भूखंडों की संख्या बढ़ रही है workspace 2। क्या सॉफ्टवेयर को कार्यक्षेत्र में लॉक करना संभव है। इसलिए जब मैं Matlabप्लॉट तैयार करता workspace 1हूं, तो मैं workspace 2प्लॉटिंग पॉप अप के बिना काम कर सकता हूं ?


एकता, GNOME शेल या कुछ और?
एबी

मैं टैग जोड़ता हूं, यह Ubuntu 14.04 यूनिटी के साथ है
OHLÁL

प्लॉट विंडो किस वर्ग की हैं? (क्या आप कमांड के साथ जांच कर सकते हैं xprop WM_CLASS, और फिर विंडो पर क्लिक कर सकते हैं?) कृपया Matlab की WM_CLASS भी जोड़ें।
जैकब व्लिजम

2
मैं आज बाद में पोस्ट करूंगा, अगर कोई इस बीच एक और शानदार समाधान पोस्ट नहीं करता है।
जैकब व्लिजम

1
हाय ओह, मैं वास्तव में इसे अच्छी तरह से काम कर रहा है, आवेदन के सभी अतिरिक्त खिड़कियों को तुरंत अनुप्रयोग के प्रारंभिक कार्यक्षेत्र में ले जाया जाता है, लेकिन .... वास्तव में वर्तमान कार्यक्षेत्र पर वर्तमान विंडो फिर भी फोकस खो देती है। अभी भी एक समाधान पर लगा। आप अभी भी समाधान की कोशिश करेंगे?
याकूब Vlijm

जवाबों:


8

महत्वपूर्ण संस्करण

पहले उत्तर से स्क्रिप्ट का फिर से लिखना संस्करण के नीचे (नीचे)। भिन्नताएं:

  • अब स्क्रिप्ट संसाधनों पर बहुत कम है (जैसे यह पृष्ठभूमि स्क्रिप्ट के साथ होना चाहिए)। क्रियाओं को अब (यदि केवल और केवल) की जरूरत है तो कार्य करने की व्यवस्था की जाती है। लूप व्यावहारिक रूप से कुछ भी नहीं करता है, लेकिन नई खिड़कियों को प्रदर्शित करने के लिए जांचें।
  • बॉट WM_CLASSऔर लक्षित कार्यक्षेत्र अब स्क्रिप्ट को चलाने के लिए तर्क हैं । केवल पहले या दूसरे (पहचानने वाले) भाग का उपयोग करें WM_CLASS(नीचे और देखें: कैसे उपयोग करें)
  • स्क्रिप्ट अब वर्तमान में सक्रिय विंडो पर ध्यान केंद्रित रखती है (वास्तव में फिर से विभाजित दूसरे में फ़ोकस)
  • जब स्क्रिप्ट शुरू होती है, तो यह एक सूचना दिखाता है (उदाहरण gedit):

    यहाँ छवि विवरण दर्ज करें

लिपी

#!/usr/bin/env python3
import subprocess
import sys
import time
import math

app_class = sys.argv[1]
ws_lock = [int(n)-1 for n in sys.argv[2].split(",")]

def check_wlist():
    # get the current list of windows
    try:
        raw_list = [
            l.split() for l in subprocess.check_output(
                ["wmctrl", "-lG"]
                ).decode("utf-8").splitlines()
            ]
        ids = [l[0] for l in raw_list]
        return (raw_list, ids)
    except subprocess.CalledProcessError:
        pass

def get_wssize():
    # get workspace size
    resdata = subprocess.check_output(["xrandr"]).decode("utf-8").split()
    i = resdata.index("current")
    return [int(n) for n in [resdata[i+1], resdata[i+3].replace(",", "")]]

def get_current(ws_size):
    # vector of the current workspace to origin of the spanning desktop
    dt_data = subprocess.check_output(
        ["wmctrl", "-d"]
        ).decode("utf-8").split()
    curr = [int(n) for n in dt_data[5].split(",")]
    return (int(curr[0]/ws_size[0]), int(curr[1]/ws_size[1]))

def get_relativewinpos(ws_size, w_data):
    # vector to the application window, relative to the current workspace
    xpos = int(w_data[2]); ypos = int(w_data[3])
    xw = ws_size[0]; yw = ws_size[1]
    return (math.ceil((xpos-xw)/xw), math.ceil((ypos-yw)/yw))

def get_abswindowpos(ws_size, w_data):
    # vector from the origin to the current window's workspace (flipped y-axis)
    curr_pos = get_current(ws_size)
    w_pos = get_relativewinpos(ws_size, w_data)
    return (curr_pos[0]+w_pos[0], curr_pos[1]+w_pos[1])

def wm_class(w_id):
    # get the WM_CLASS of new windows
    return subprocess.check_output(
        ["xprop", "-id", w_id.strip(), "WM_CLASS"]
        ).decode("utf-8").split("=")[-1].strip()

ws_size = get_wssize()
wlist1 = []
subprocess.Popen(["notify-send", 'workspace lock is running for '+app_class])

while True:
    # check focussed window ('except' for errors during "wild" workspace change)
    try:
        focus = subprocess.check_output(
            ["xdotool", "getwindowfocus"]
            ).decode("utf-8")
    except subprocess.CalledProcessError:
        pass
    time.sleep(1)
    wdata = check_wlist() 
    if wdata !=  None:
        # compare existing window- ids, checking for new ones
        wlist2 = wdata[1]
        if wlist2 != wlist1:
            # if so, check the new window's class
            newlist = [[w, wm_class(w)] for w in wlist2 if not w in wlist1]
            valids = sum([[l for l in wdata[0] if l[0] == w[0]] \
                          for w in newlist if app_class in w[1]], [])
            # for matching windows, check if they need to be moved (check workspace)
            for w in valids:
                abspos = list(get_abswindowpos(ws_size, w))
                if not abspos == ws_lock:
                    current = get_current(ws_size)
                    move = (
                        (ws_lock[0]-current[0])*ws_size[0],
                            (ws_lock[1]-current[1])*ws_size[1]-56
                        )
                    new_w = "wmctrl -ir "+w[0]+" -e "+(",").join(
                        ["0", str(int(w[2])+move[0]),
                         str(int(w[2])+move[1]), w[4], w[5]]
                        )
                    subprocess.call(["/bin/bash", "-c", new_w])
                    # re- focus on the window that was focussed
                    if not app_class in wm_class(focus):
                        subprocess.Popen(["wmctrl", "-ia", focus])
        wlist1 = wlist2

कैसे इस्तेमाल करे

  1. स्क्रिप्ट को दोनों की जरूरत है wmctrlऔर xdotool:

    sudo apt-get install wmctrl xdotool
    
  2. एक खाली फ़ाइल में ऊपर स्क्रिप्ट कॉपी करें, इसे सहेजें lock_towspace.py

  3. अपने विशिष्ट एप्लिकेशन में, यह पता करें WM_CLASS: अपना एप्लिकेशन खोलें, टर्मिनल में दौड़ें:

    xprop WM_CLASS and click on the window of the application
    

    आउटपुट जैसा दिखेगा (आपके मामले में):

    WM_CLASS: WM_CLASS(STRING) = "sun-awt-X11-XFramePeer", "MATLAB R2015a - academic use"
    

    स्क्रिप्ट चलाने के लिए या तो कमांड में पहले या दूसरे भाग का उपयोग करें।

  4. स्क्रिप्ट चलाने के लिए कमांड है:

    python3 /path/to/lock_towspace.py "sun-awt-X11-XFramePeer" 2,2
    

    कमांड में, अंतिम अनुभाग; 2,2वह कार्यक्षेत्र है जहाँ आप एप्लिकेशन को (बिना रिक्त स्थान: (!) कॉलम, पंक्ति ), "मानव" प्रारूप में लॉक करना चाहते हैं ; पहला कॉलम / पंक्ति है1,1

  5. इसे चलाकर स्क्रिप्ट का परीक्षण करें। दौड़ते समय, अपना एप्लिकेशन खोलें और इसे सामान्य रूप से विंडोज़ का उत्पादन करने दें। सभी विंडो को लक्षित कार्यक्षेत्र पर दिखाई देना चाहिए, जैसा कि कमांड में सेट किया गया है।

संबंधित उत्तर:

(दूसरा) टेस्ट संस्करण

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

फ़ोकस समस्या को स्वचालित रूप से उस विंडो पर हल किया जाता है, जो अतिरिक्त विंडो के उत्पादन से पहले फ़ोकस की गई विंडो पर फ़ोकसिंग है।

लिपी

#!/usr/bin/env python3
import subprocess
import time
import math

app_class = '"gedit", "Gedit"'

def get_wssize():
    # get workspace size
    resdata = subprocess.check_output(["xrandr"]).decode("utf-8").split()
    i = resdata.index("current")
    return [int(n) for n in [resdata[i+1], resdata[i+3].replace(",", "")]]

def get_current(ws_size):
    # get vector of the current workspace to the origin of the spanning desktop (flipped y-axis)
    dt_data = subprocess.check_output(["wmctrl", "-d"]).decode("utf-8").split(); curr = [int(n) for n in dt_data[5].split(",")]
    return (int(curr[0]/ws_size[0]), int(curr[1]/ws_size[1]))

def get_relativewinpos(ws_size, w_data):
    # vector to the application window, relative to the current workspace
    xw = ws_size[0]; yw = ws_size[1]
    return (math.ceil((w_data[1]-xw)/xw), math.ceil((w_data[2]-yw)/yw))

def get_abswindowpos(ws_size, w_data):
    curr_pos = get_current(ws_size)
    w_pos = get_relativewinpos(ws_size, w_data)
    return (curr_pos[0]+w_pos[0], curr_pos[1]+w_pos[1])

def wm_class(w_id):
    return subprocess.check_output(["xprop", "-id", w_id, "WM_CLASS"]).decode("utf-8").split("=")[-1].strip()

def filter_windows(app_class):
    # find windows (id, x_pos, y_pos) of app_class
    try:
        raw_list = [l.split() for l in subprocess.check_output(["wmctrl", "-lG"]).decode("utf-8").splitlines()]
        return [(l[0], int(l[2]), int(l[3]), l[4], l[5]) for l in raw_list if wm_class(l[0]) == app_class]
    except subprocess.CalledProcessError:
        pass

ws_size = get_wssize()
init_window = get_abswindowpos(ws_size, filter_windows(app_class)[0])
valid_windows1 = filter_windows(app_class)

while True:
    focus = subprocess.check_output(["xdotool", "getwindowfocus"]).decode("utf-8")
    time.sleep(1)
    valid_windows2 = filter_windows(app_class)
    if all([valid_windows2 != None, valid_windows2 != valid_windows1]):
        for t in [t for t in valid_windows2 if not t[0] in [w[0] for w in valid_windows1]]:
            absolute = get_abswindowpos(ws_size, t)
            if not absolute == init_window:
                current = get_current(ws_size)
                move = ((init_window[0]-current[0])*ws_size[0], (init_window[1]-current[1])*ws_size[1]-56)
                new_w = "wmctrl -ir "+t[0]+" -e "+(",").join(["0", str(t[1]+move[0]), str(t[2]+move[1]), t[3], t[4]])
                subprocess.call(["/bin/bash", "-c", new_w])
            focus = str(hex(int(focus)))
            z = 10-len(focus); focus = focus[:2]+z*"0"+focus[2:]
            if not wm_class(focus) == app_class:
                subprocess.Popen(["wmctrl", "-ia", focus])
        valid_windows1 = valid_windows2

कैसे इस्तेमाल करे

  1. स्क्रिप्ट को दोनों की जरूरत है wmctrlऔरxdotool

    sudo apt-get install wmctrl xdotool
    
  2. स्क्रिप्ट को एक खाली फ़ाइल में कॉपी करें, इसे इस रूप में सहेजें keep_workspace.py

  3. आवेदन खोलकर अपने आवेदन का `WM_CLASS 'निर्धारित करें, फिर एक टर्मिनल खोलें और कमांड चलाएँ:

    xprop WM_CLASS
    

    इसके बाद अपने एप्लिकेशन की विंडो पर क्लिक करें। "sun-awt-X11-XFramePeer", "MATLAB R2015a - academic use"अपने मामले की तरह, आउटपुट की प्रतिलिपि बनाएँ , और इसे स्क्रिप्ट के मुख्य भाग में एकल उद्धरणों के बीच रखें , जैसा कि संकेत दिया गया है।

  4. कमांड के साथ स्क्रिप्ट चलाएँ:

    python3 /path/to/keep_workspace.py
    

यदि यह आपकी तरह काम करता है, तो मैं एक टॉगल फ़ंक्शन जोड़ूंगा। हालांकि यह मेरे सिस्टम पर कुछ घंटों के लिए पहले से ही काम करता है, लेकिन इसे पहले कुछ ट्विकिंग की आवश्यकता हो सकती है।

टिप्पणियाँ

यद्यपि आप यह महसूस नहीं होना चाहिए, स्क्रिप्ट करता व्यवस्था करने के लिए कुछ प्रोसेसर लोड जोड़ें। मेरी बुजुर्ग प्रणाली में मैंने 3-10% की वृद्धि देखी। यदि आपको यह पसंद है कि यह कैसे काम करता है, तो मैं शायद लोड को कम करने के लिए इसे आगे बढ़ा दूंगा।

स्क्रिप्ट, जैसा कि यह है, मानती है कि सेकेंडरी विंडो मुख्य विंडो के समान हैं, जैसे आपने टिप्पणी में इंगित किया है। एक (बहुत) सरल परिवर्तन के साथ, द्वितीयक खिड़कियां अन्य वर्ग की हो सकती हैं।

व्याख्या

हालांकि शायद एक औसत पाठक के लिए बहुत दिलचस्प नहीं है, स्क्रिप्ट वैक्टर में गणना करके काम करती है। स्टार्टअप पर, स्क्रिप्ट की गणना करता है:

  • के मूल से वर्तमान कार्यक्षेत्र के लिए वेक्टर उत्पादन के साथ wmctrl -d
  • वेक्टर, एप्लिकेशन के विंडो में, वर्तमान कार्यक्षेत्र के सापेक्ष, आउटपुट के द्वारा wmctrl -lG
  • इन दोनों से, स्क्रिप्ट फैली हुई डेस्कटॉप पर एप्लिकेशन की विंडो की पूर्ण स्थिति की गणना करती है (एक मैट्रिक्स में सभी कार्यक्षेत्र)

तब से, स्क्रिप्ट उसी एप्लिकेशन की नई विंडो की तलाश में है, जिसके आउटपुट के साथ xprop WM_CLASS, ऊपर की तरह उनकी स्थिति को देखता है और उन्हें "मूल" कार्यक्षेत्र में ले जाता है।

चूंकि नई बनाई गई विंडो "चुराया गया" अंतिम उपयोग की गई खिड़की से उपयोगकर्ता जिस पर काम कर रहा था, उस पर ध्यान बाद में उस विंडो पर सेट किया गया था, जिस पर पहले फोकस था।


यह बहुत ही विस्मयकारी है। यह एक संकेतक बनाने के लिए एक अच्छा विचार हो सकता है जहां उपयोगकर्ता विभिन्न अनुप्रयोगों को कार्यक्षेत्रों में बंद कर सकता है। अभी मुझे
मतलाब के

@ OHL questionL OH जैसा कि उल्लेख किया गया है, मुझे सवाल बहुत दिलचस्प लगता है और इस पर काम करना जारी रखूंगा । मेरे पास जो कुछ भी है वह एक फाइल है जिसमें उपयोगकर्ता सेट applicationऔर workspace-सेट कर सकता है । यदि आप संभावित बगों में भाग लेते हैं, तो कृपया इसका उल्लेख करें!
याकूब Vlijm

अलग-अलग कार्यस्थलों पर दो मतलब शुरू होने पर क्या व्यवहार होगा?
OHL:58L OH

@ OHL toL OH तब वे दोनों कमांड में आपके द्वारा निर्धारित कार्यक्षेत्र में बंद हो जाएंगे। चूँकि उनका WM_CLASSसमान है, दूसरे को आपके द्वारा निर्धारित कमांड में ले जाया जाएगा।
जैकब व्लिजम

क्या WM_CLASS के अलावा किसी एप्लिकेशन की पहचान करने के लिए अन्य सकारात्मकताएं हैं?
OHL:03L OH
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.