আমি কীভাবে কোনও অ্যাপ্লিকেশন (এবং এর সমস্ত নতুন উইন্ডো) একটি নির্দিষ্ট কর্মপরিসে লক করতে পারি?


11

আমি Matlabস্ক্রিপ্ট চালাচ্ছি workspace 1। এটি বেশ কয়েকটি প্লট জেনারেট করে। মাঝামাঝি সময়ে আমি workspace 2সেখানে চলেছি এবং সেখানে কাজ করছি। আমার সমস্যা হ'ল প্লটগুলি পপ আপ করছে workspace 2। কোনও ওয়ার্ক স্পেসে সফ্টওয়্যার লক করা কি সম্ভব? সুতরাং Matlabপ্লটগুলি জেনারেট করার সময় workspace 1, আমি workspace 2পপআপ প্লটের ব্যত্যয় ছাড়াই কাজ করতে পারি ?


Ityক্য, জিনোম শেল না অন্য কিছু?
এবি

আমি ট্যাগগুলি যুক্ত করছি, এটি উবুন্টু 14.04
Unক্যের

প্লট উইন্ডো কোন শ্রেণীর অন্তর্গত? (আপনি কি কমান্ডটি দিয়ে পরীক্ষা করতে পারেন xprop WM_CLASS, এবং তারপরে উইন্ডোতে ক্লিক করতে পারেন?) দয়া করে মতলবের WM_CLASS যুক্ত করুন SS
জ্যাকব Vlijm

2
আমি আজ পরে পোস্ট করব, যদি না এর মধ্যে কেউ অন্য একটি উজ্জ্বল সমাধান পোস্ট করে।
জ্যাকব Vlijm

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% বৃদ্ধি লক্ষ্য করেছি। এটি কীভাবে কাজ করে তা যদি আপনি পছন্দ করেন তবে লোড হ্রাস করার জন্য আমি সম্ভবত এটি আরও টুইঙ্ক করব will

স্ক্রিপ্টটি যেমনটি রয়েছে, ধরে নিয়েছে যে সেকেন্ডারি উইন্ডোজগুলি মূল উইন্ডো হিসাবে একই শ্রেণীর, যেমনটি আপনি একটি মন্তব্যে নির্দেশ করেছেন। একটি (খুব) সহজ পরিবর্তনের সাথে সাথে, মাধ্যমিক জানালা পারেন তবে অন্য ক্লাসের হও।

ব্যাখ্যা

যদিও গড় পাঠকের পক্ষে খুব আকর্ষণীয় না হলেও স্ক্রিপ্টটি ভেক্টরগুলিতে গণনা করে কাজ করে। প্রারম্ভকালে, স্ক্রিপ্ট গণনা করে:

  • এর আউটপুট সহ উত্স থেকে বর্তমান কর্মক্ষেত্রে ভেক্টর wmctrl -d
  • এর আউটপুট দ্বারা বর্তমান কর্মক্ষেত্রের তুলনায় অ্যাপ্লিকেশনটির উইন্ডোতে ভেক্টর wmctrl -lG
  • এই দুটি থেকে স্ক্রিপ্টটি বিস্তৃত ডেস্কটপে অ্যাপ্লিকেশনটির উইন্ডোটির নিখুঁত অবস্থান গণনা করে (এক ম্যাট্রিক্সের সমস্ত কর্মক্ষেত্র)

তারপরে, স্ক্রিপ্টটি একই অ্যাপ্লিকেশনটির নতুন উইন্ডোগুলির সন্ধান করে, আউটপুট সহ xprop WM_CLASS, তাদের অবস্থানটি উপরের মতো একইভাবে দেখায় এবং তাদের "মূল" ওয়ার্কস্পেসে নিয়ে যায়।

যেহেতু নতুন তৈরি উইন্ডোটি ব্যবহারকারী ব্যবহৃত শেষ ব্যবহৃত উইন্ডোটি থেকে ফোকাসটি "চুরি" করেছে, ফোকাসটি পরবর্তী সময়ে ফোকাসটি সেই উইন্ডোতে সেট করা হয়েছিল যা আগে ফোকাস করেছিল।


এটা খুব awsome। কোনও সূচক তৈরি করা ভাল ধারণা হতে পারে যেখানে ব্যবহারকারীরা বিভিন্ন অ্যাপ্লিকেশনটিকে ওয়ার্কস্পেসে লক করতে পারে। এই মুহুর্তে মতলব নিয়ে আমার সমস্যা ছিল, তবে একই সমস্যাটি
ম্যাটপ্ল্লিটিবের

@ OHLÁLÁ হিসাবে উল্লিখিত হয়েছে, আমি প্রশ্নটি খুব আকর্ষণীয় মনে করি এবং এটি নিয়ে কাজ করে যাব। আমার মনে যা আছে তা হ'ল একটি ফাইল যা ব্যবহারকারী সেট করতে applicationএবং সেট করতে পারে workspace। আপনি যদি সম্ভাব্য বাগগুলিতে চলে যান তবে দয়া করে এটি উল্লেখ করুন!
জ্যাকব ভিলিজম

দুটি মতলব পৃথক ওয়ার্কস্পেসে শুরু করা হলে তার আচরণটি কী হবে?
OHL 13LÁ

@ OHLÁLÁ তারপরে সেগুলি উভয়ই আপনি কমান্ডের যে ওয়ার্কস্পেসে রেখেছেন তা লক হয়ে যাবে। যেহেতু WM_CLASSসেগুলি অভিন্ন, দ্বিতীয়টি আপনি কমান্ডটিতে সেট করা একটিতে স্থানান্তরিত হবে।
জ্যাকব Vlijm

ডাব্লুএম_সিএলএসএস ব্যতীত কোনও অ্যাপ্লিকেশন শনাক্ত করার অন্যান্য সম্ভাবনা কি আছে?
OHLÁLÁ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.