Code Monkey home page Code Monkey logo

i3ipc-python's Introduction

i3ipc-python

An improved Python library to control i3wm and sway.

About

i3's interprocess communication (or ipc) is the interface i3wm uses to receive commands from client applications such as i3-msg. It also features a publish/subscribe mechanism for notifying interested parties of window manager events.

i3ipc-python is a Python library for controlling the window manager. This project is intended to be useful for general scripting, and for applications that interact with the window manager like status line generators, notification daemons, and window pagers.

If you have an idea for a script to extend i3wm, you can add your script to the examples folder.

For details on how to use the library, see the reference documentation.

Chat

Installation

i3ipc is on PyPI.

pip3 install i3ipc

Example

from i3ipc import Connection, Event

# Create the Connection object that can be used to send commands and subscribe
# to events.
i3 = Connection()

# Print the name of the focused window
focused = i3.get_tree().find_focused()
print('Focused window %s is on workspace %s' %
      (focused.name, focused.workspace().name))

# Query the ipc for outputs. The result is a list that represents the parsed
# reply of a command like `i3-msg -t get_outputs`.
outputs = i3.get_outputs()

print('Active outputs:')

for output in filter(lambda o: o.active, outputs):
    print(output.name)

# Send a command to be executed synchronously.
i3.command('focus left')

# Take all fullscreen windows out of fullscreen
for container in i3.get_tree().find_fullscreen():
    container.command('fullscreen')

# Print the names of all the containers in the tree
root = i3.get_tree()
print(root.name)
for con in root:
    print(con.name)

# Define a callback to be called when you switch workspaces.
def on_workspace_focus(self, e):
    # The first parameter is the connection to the ipc and the second is an object
    # with the data of the event sent from i3.
    if e.current:
        print('Windows on this workspace:')
        for w in e.current.leaves():
            print(w.name)

# Dynamically name your workspaces after the current window class
def on_window_focus(i3, e):
    focused = i3.get_tree().find_focused()
    ws_name = "%s:%s" % (focused.workspace().num, focused.window_class)
    i3.command('rename workspace to "%s"' % ws_name)

# Subscribe to events
i3.on(Event.WORKSPACE_FOCUS, on_workspace_focus)
i3.on(Event.WINDOW_FOCUS, on_window_focus)

# Start the main loop and wait for events to come in.
i3.main()

Asyncio Support

Support for asyncio is included in the i3ipc.aio package. The interface is similar to the blocking interface but the methods that interact with the socket are coroutines.

from i3ipc.aio import Connection
from i3ipc import Event

import asyncio

async def main():
    def on_window(self, e):
        print(e)

    c = await Connection(auto_reconnect=True).connect()

    workspaces = await c.get_workspaces()

    c.on(Event.WINDOW, on_window)

    await c.main()

asyncio.get_event_loop().run_until_complete(main())

Debug Logging

i3ipc-python uses the standard logging module under the i3ipc namespace.

import logging
logging.basicConfig(level=logging.DEBUG)

Contributing

Development happens on Github. Please feel free to report bugs, request features or add examples by submitting a pull request.

License

This work is available under a BSD-3-Clause license (see LICENSE).

Copyright © 2015, Tony Crisci

All rights reserved.

i3ipc-python's People

Contributors

acrisci avatar alkim0 avatar anon1234 avatar budrich avatar coacher avatar geeseven avatar gibbz00 avatar hi-angel avatar jtsymon avatar julius383 avatar kartoffelspam avatar minus7 avatar miseran avatar msimacek avatar nicoe avatar o-jasper avatar okraits avatar orestisfl avatar pb- avatar pjeanjean avatar rifazn avatar sn4kebite avatar stapelberg avatar tarruda avatar thetheodor avatar toneomgomg avatar un-def avatar vincentbernat avatar xenomachina avatar zopieux avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

i3ipc-python's Issues

focus-last.py cycles only last two windows

There's MAX_WIN_HISTORY in the script, however, AFAICT it's to handle deleted/closed windows.

I've an idea how to implement this with some timeout reading the communication socket, so that multiple invocations could be used to cycle stack-like through windows.

(I'm filing an issue, in case someone else had more time than me :-)

typelib not found

Hi i installed i3ipc from pip, but he cant found it (ubuntu 18.04 py3)

Traceback (most recent call last):
File "", line 888, in _find_spec
AttributeError: 'DynamicImporter' object has no attribute 'find_spec'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "", line 1, in
File "/usr/lib/python3/dist-packages/gi/importer.py", line 127, in find_module
'introspection typelib not found' % namespace)
ImportError: cannot import name i3ipc, introspection typelib not found

i3ipc-python does not compile in Python 3.4 with 'KeyError: '_convert''

When installing i3ipc using PIP in Python 3.4 (ubuntu 15.10), the following error occurs:

Downloading/unpacking enum34 (from i3ipc)
  Downloading enum34-1.0.4.tar.gz
  Running setup.py (path:/tmp/pip-build-00v68qq2/enum34/setup.py) egg_info for package enum34
    Traceback (most recent call last):
      File "/tmp/pip-build-00v68qq2/enum34/enum/__init__.py", line 371, in __getattr__
        return cls._member_map_[name]
    KeyError: '_convert'

Since there doesn't seem to be need for enum34 in Python 3.4. It should be ok to just remove it from the dependencies then.

Library is not importable

Hello,

It looks like the library is not importable:

balisto:~/projets/i3ipc-python% python3 -c 'from gi.repository import i3ipc'
ERROR:root:Could not find any typelib for i3ipc
Traceback (most recent call last):
File "", line 1, in
ImportError: cannot import name 'i3ipc'

Although I have installed i3ipc-glib (using the prefix) without any problem.

window class occasionally missing

Traceback (most recent call last):
  File "./disable-standby-fs.py", line 65, in <module>
    i3.main()
  File "/home/astronouth7303/.local/lib/python3.4/site-packages/i3ipc.py", line 311, in main
    event = WindowEvent(data, self)
  File "/home/astronouth7303/.local/lib/python3.4/site-packages/i3ipc.py", line 70, in __init__
    self.container = Con(data['container'], None, conn)
  File "/home/astronouth7303/.local/lib/python3.4/site-packages/i3ipc.py", line 372, in __init__
    self.window_class = data['window_properties']['class']
KeyError: 'class'

(Sorry, I don't have more info.)

Unable to subscribe to tick events

i3.on('tick', handler) throws an unsupported event type error.

Ticks are the only mean to implement custom events with arbitrary payloads, so supporting this feature is important IMO.

Exception: Failed to retrieve the i3 IPC socket path

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/i3ipc/i3ipc.py", line 341, in __init__
    close_fds=True, universal_newlines=True).strip()
  File "/usr/lib/python3.6/subprocess.py", line 336, in check_output
    **kwargs).stdout
  File "/usr/lib/python3.6/subprocess.py", line 418, in run
    output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['i3', '--get-socketpath']' died with <Signals.SIGUSR1: 10>.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/user/.i3expo/i3expod.py", line 511, in <module>
    update_state(i3, None)
  File "/home/user/.i3expo/i3expod.py", line 218, in update_state
    if current_workspace.num == i3ipc.Connection().get_tree().find_focused().workspace().num:
  File "/usr/local/lib/python3.6/dist-packages/i3ipc/i3ipc.py", line 343, in __init__
    raise Exception('Failed to retrieve the i3 IPC socket path')
Exception: Failed to retrieve the i3 IPC socket path
[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python3: ../../src/xcb_io.c:165: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.

This occurs apparently randomly whenever the above line (i3ipc.Connection().get_tree().find_focused().workspace().num) is executed. Unfortunately it's rare enough that I can't easily narrow down the circumstances, but there appears to be no simple reason. Called in a while True, this does exactly what it's supposed to do for hours at least, suspends included.

Please advise what additional information would be necessary. Installed from pip3, current version 1.5.1.

Edit: Oh, and nvm the SIGUSR1 thing - the function gets executed only when I send that signal.

ConnectionRefusedError: [Errno 111] Connection refused

I downloaded the focus-last.py script:
https://github.com/acrisci/i3ipc-python/blob/master/examples/focus-last.py -> /opt/scripts/i3-focus-last.sh

Added in i3 config:

exec --no-startup-id /opt/scripts/i3-focus-last.sh

Restarted i3, then tried to:

./i3-focus-last.sh --switch

Traceback (most recent call last):
File "./i3-focus-last.sh", line 93, in
client_socket.connect(SOCKET_FILE)
ConnectionRefusedError: [Errno 111] Connection refused

ls -l /tmp | grep focus
srwxr-xr-x 1 root root 0 Dec 1 14:30 i3_focus_last

Error running focus-last.py

Hi,

I'm interested to use the example file focus-last.py. I am executing it from the .xsessionrc file. However, It doesn't work. I'm using i3wm version 4.7.2

In my .xsessionrc, focus-last.py is executed
python3.4 focus-last.py

Get the following error from the .xsession-errors file:

Traceback (most recent call last):
File "/home/dilbert/usr/bin/focus-last.py", line 91, in
focus_watcher = FocusWatcher()
File "/home/dilbert/usr/bin/focus-last.py", line 17, in init
self.i3 = i3ipc.Connection()
File "/usr/local/lib/python3.4/dist-packages/i3ipc.py", line 181, in init
if not data.value:
AttributeError: 'NoneType' object has no attribute 'value'

can't subscribe to ipc-shutdown event

The command-on-exit example no longer works due to a bug that was introduced by commit 8498586. Attempting to subscribe to "ipc-shutdown" triggers an exception:

$ python command-on-exit.py 
Traceback (most recent call last):
  File "command-on-exit.py", line 18, in <module>
    i3.on('ipc-shutdown', on_shutdown)
  File "/home/chrsclmn/git/i3ipc-python/i3ipc.py", line 332, in on
    raise Exception('event not implemented')
Exception: event not implemented

Since commit 8498586, dashes in event names are replaced with underscores, which means event == 'ipc-shutdown' will always be false:

    def on(self, detailed_event, handler):
        event = detailed_event.replace('-', '_')

        if detailed_event.count('::') > 0:
            [event, __] = detailed_event.split('::')

        # special case: ipc-shutdown is not in the protocol
        if event == 'ipc-shutdown':
            self._pubsub.subscribe(event, handler)
            return

Put Connection functions on the import object

Most people use a single Connection in their libraries without any configuration needed.

Put the functions of the Connection (such as get_tree, get_outputs) on the imported i3ipc object. Use a cached and lazily instantiated Connection for this. This simplifies code slightly.

Example:

import i3ipc

tree = i3ipc.get_tree()
outputs = i3ipc.get_outputs()
# etc

Is python 2 still supported?

I get test failures on python 2. It should either be fixed or documented as python 3 only.

msimacek ~/rpms/python-i3ipc/i3ipc-python-1.5.1 (master) $ ./run-tests.py 
================================================ test session starts ================================================
platform linux2 -- Python 2.7.14, pytest-3.2.3, py-1.4.34, pluggy-0.4.0
rootdir: /home/msimacek/rpms/python-i3ipc/i3ipc-python-1.5.1, inifile:
collected 3 items                                                                                                    

test/test_leaves.py F
test/test_window.py ..

===================================================== FAILURES ======================================================
_________________________________________ TestLeaves.test_workspace_leaves __________________________________________

self = <test_leaves.TestLeaves instance at 0x7fae8d0a97e8>, i3 = <i3ipc.Connection object at 0x7fae8d0b8550>

    def test_workspace_leaves(self, i3):
        ws_name = self.fresh_workspace()
        con1 = self.open_window()
        command = i3.command('[id=%s] floating enable' % con1)
        con2 = self.open_window()
        con3 = self.open_window()
    
        ws = next(filter(lambda w: w.name == ws_name,
>           i3.get_tree().workspaces()))
E       TypeError: list object is not an iterator

test/test_leaves.py:14: TypeError
======================================== 1 failed, 2 passed in 0.16 seconds =========================================
[libi3] ../../i3-4.15/libi3/font.c Using Pango font monospace, size 8

focus-last.py does not survive a restart

... so it's not really suitable for .xsessionrc as it claims - better put it in an exec_always clause in ~/.config/i3/config

Here's how to trigger the error:

~/ $ focus-last.py &

 ... do an i3 restart, then:

~/ $ focus-last.py --switch

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib64/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/usr/lib64/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "./focus-last.py", line 68, in launch_server
    callback(key.fileobj)
  File "./focus-last.py", line 51, in read
    tree = self.i3.get_tree()
  File "/usr/lib/python3.6/site-packages/i3ipc.py", line 518, in get_tree
    data = self.message(MessageType.GET_TREE, '')
  File "/usr/lib/python3.6/site-packages/i3ipc.py", line 404, in message
    return self._ipc_send(self.cmd_socket, message_type, payload)
  File "/usr/lib/python3.6/site-packages/i3ipc.py", line 399, in _ipc_send
    sock.sendall(self._pack(message_type, payload))
BrokenPipeError: [Errno 32] Broken pipe

Instead of .xsessionrc or equivalent, you need to use this in i3 config:

exec_always bash -c "ps -ef | awk '/python.*\/focus-last.py/ { system(\\"kill \\"\$2) }'; focus-last.py &"

Doesn’t receive messages on big endian machines

% uname -a
Linux minkus 4.9.0-3-octeon #1 SMP Debian 4.9.30-2+deb9u3 (2017-08-06) mips GNU/Linux

% DISPLAY=:99 python2 ./poc.py
Traceback (most recent call last):
  File "./poc.py", line 11, in <module>
    outputs = i3.get_outputs()
  File "/home/stapelberg/.local/lib/python2.7/site-packages/i3ipc/i3ipc.py", line 276, in get_outputs
    data = self.message(MessageType.GET_OUTPUTS, '')
  File "/home/stapelberg/.local/lib/python2.7/site-packages/i3ipc/i3ipc.py", line 250, in message
    return self._ipc_send(self.cmd_socket, message_type, payload)
  File "/home/stapelberg/.local/lib/python2.7/site-packages/i3ipc/i3ipc.py", line 246, in _ipc_send
    data, msg_type = self._ipc_recv(sock)
  File "/home/stapelberg/.local/lib/python2.7/site-packages/i3ipc/i3ipc.py", line 241, in _ipc_recv
    data += self._recv_robust(sock, msg_length)
  File "/home/stapelberg/.local/lib/python2.7/site-packages/i3ipc/i3ipc.py", line 226, in _recv_robust
    return sock.recv(size)
OverflowError: Python int too large to convert to C long

% DISPLAY=:99 python3 ./poc.py
Traceback (most recent call last):
  File "./poc.py", line 11, in <module>
    outputs = i3.get_outputs()
  File "/home/stapelberg/.local/lib/python3.5/site-packages/i3ipc/i3ipc.py", line 276, in get_outputs
    data = self.message(MessageType.GET_OUTPUTS, '')
  File "/home/stapelberg/.local/lib/python3.5/site-packages/i3ipc/i3ipc.py", line 250, in message
    return self._ipc_send(self.cmd_socket, message_type, payload)
  File "/home/stapelberg/.local/lib/python3.5/site-packages/i3ipc/i3ipc.py", line 246, in _ipc_send
    data, msg_type = self._ipc_recv(sock)
  File "/home/stapelberg/.local/lib/python3.5/site-packages/i3ipc/i3ipc.py", line 241, in _ipc_recv
    data += self._recv_robust(sock, msg_length)
  File "/home/stapelberg/.local/lib/python3.5/site-packages/i3ipc/i3ipc.py", line 226, in _recv_robust
    return sock.recv(size)
OverflowError: Python int too large to convert to C ssize_t

i3ipc removes a window object that is still referenced in code

Steps to reproduce

  1. save the following script as inactive-window-transparency.py:
    import i3ipc
    
    ipc = i3ipc.Connection()
    prev_focused = None
    
    for window in ipc.get_tree():
    	if window.focused:
    		prev_focused = window
    	else:
    		window.command('opacity 0.8')
    
    if (prev_focused == None):
    	raise Exception('No focused window found!')
    
    def on_window_focus(ipc, focused):
    	focused.container.command('opacity 1')
    	prev_focused.command('opacity 0.8')
    	prev_focused = focused.container
    
    ipc.on("window::focus", on_window_focus)
    ipc.main() # enter command loop
  2. Execute python inactive-window-transparency.py
  3. Unfocus a window (e.g. switch a workspace)

Expected

In i3 nothing, in sway the inactive window would become transparent

Actual

The script quits with:

Traceback (most recent call last):
  File "inactive-window-transparency.py", line 21, in <module>
    ipc.main() # enter command loop
  File "/usr/lib/python3.7/site-packages/i3ipc/i3ipc.py", line 728, in main
    while not self.event_socket_poll():
  File "/usr/lib/python3.7/site-packages/i3ipc/i3ipc.py", line 716, in event_socket_poll
    self._pubsub.emit(event_name, event)
  File "/usr/lib/python3.7/site-packages/i3ipc/i3ipc.py", line 311, in emit
    s['handler'](self.conn, data)
  File "inactive-window-transparency.py", line 17, in on_window_focus
    prev_focused.command('opacity 0.8')
UnboundLocalError: local variable 'prev_focused' referenced before assignment

Additional info

Tested on both i3 and sway.
i3ipc version: 1.6.0

Sway compatibility

Hi

This looks very promising, as I've been looking for at way to temporarily freeze unfocused clients.

You mention in the lead paragraph that this is a python library to control i3 and Sway. I am quite new to this whole IPC thing (but willing to learn), but I can't seem to find any further documentation on how to convert the i3 scripts to become sway compatible. Is it just me that need to go learn some more Python, or what am I missing here?

find_marked and mark do not work

find_marked and Con.mark seem broken:

% ipython3
Python 3.5.2 (default, Jul  5 2016, 12:43:10) 

In [1]: import i3ipc

In [2]: i3ipc.Connection().get_tree().find_focused().command('mark m')

# See `[m]` appear in window decoration

In [3]: i3ipc.Connection().get_tree().find_marked('m')
Out[3]: []

In [4]: i3ipc.Connection().get_tree().find_focused().mark

In [5]: 
Do you really want to exit ([y]/n)? y

% pip3 freeze | grep ipc
i3ipc==1.2.0

% i3 --version
i3 version 4.12 (2016-03-06, branch "4.12") © 2009 Michael Stapelberg and contributors

% lsb_release -dcs
Ubuntu 16.04.1 LTS
xenial

i3 scratchpad toggle

Do you think its possible to write a python script for having i3 scratchpad loop through apps insteed of hide and show. I'm trying to do it right now with this library but no luck so far. Is it i3 ipc limitation?

So far I'm getting the number of apps in scratchpad and if there are more than 1, execute 3 times conn.command("scratchpad show") but it doesn't work when I try to bind it.

Thanks

New release

I'd like to get the PID of a window, but no released version has the commit that introduced that feature (bd0224e). Is there a timeline for the next release?

Please add possible events to scan for to documentation

Documentation here gives one example which works perfectly, however...
https://i3ipc-python.readthedocs.io/en/latest/#listening-to-events

There's no actual list that I've been able to find telling me what events I can listen for. I'm refering to the first argument in i3ipc.on('workspace::focus', on_workspace_focus)

i3.on('workspace::focus', on_workspace_focus) # when current workspace changes

With my code below all three of the following don't appear to do anything but they exist (really they certainly do 'something' I just haven't figured it out yet):

i3.on("mode::change", on_mode_changed) # ???
i3.on("binding::mode", on_mode_changed) # ???
i3.on("mode::binding", on_mode_changed) # ???
import i3ipc

i3 = i3ipc.Connection()

# # Define a callback to be called when you switch workspaces.
# def on_workspace_focus(self, e):
#     # The first parameter is the connection to the ipc and the second is an object
#     # with the data of the event sent from i3.
#     if e.current:
#         print('Windows on this workspace:')
#         for w in e.current.leaves():
#             print(w.name)

# # Dynamically name your workspaces after the current window class
# def on_window_focus(i3, e):
#     focused = i3.get_tree().find_focused()
#     ws_name = "%s:%s" % (focused.workspace().num, focused.window_class)
#     i3.command('rename workspace to "%s"' % ws_name)

# Subscribe to events
# i3.on('workspace::focus', on_workspace_focus)
# i3.on("window::focus", on_window_focus)

# Start the main loop and wait for events to come in.
# i3.main()

def on_mode_changed(self, obj):
    if obj.current:
        print(obj.data)
        print(obj.data.name)
        print(dir(obj))

def on_workspace_changed(self, obj):
    if obj.current:
        print(obj.current.name)
        # for x in obj.current:
        #     print(x)

i3.on("mode::change", on_mode_changed)
i3.on("binding::mode", on_mode_changed)
i3.on("mode::binding", on_mode_changed)

i3.on("workspace::focus", on_workspace_changed)

i3.main()

If the documentation simply listed all possible events I could just test and find out myself, what they do:

import i3ipc

i3 = i3ipc.Connection()

def test_event(self, obj):
    # self contains everything in the global
    # scope including i3
    print(dir(obj))

i3.on("workspace::focus", test_event) # returns an object

i3.main()

If I can get a list I would like to help improve documentation if possible.

Thanks

Store i3 status of workspaces

I want to store my current workspace configuration.
Therefore I want to use pickle:

import i3ipc
import pickle
i3 = i3ipc.Connection()
pickle.dumps(i3.get_workspaces()

this will result in an error

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/site-packages/i3ipc/i3ipc.py", line 37, in __getattr__
    return self[name]
KeyError: '__getstate__'

This is happening in python{2,3}.
Used version of i3ipc-python: 1.5.1

Catching exceptions raised by event handlers

Not an issue but rather a design question: Should the main loop intercept exceptions raised by event handlers and swallow them, or, as it is now with i3ipc-python, just don't do anything about them and let them break the main loop?

Intercepting them makes the program more robust in cases of failure, letting them break the main loop makes it easier to discover problems (if the exceptions are not handled appropriately).
Does changing that, or providing a switch or a possibility to hook into them, make sense?

Error with one of the examples: 'Con' object has no attribute 'get_property'

I get this error:

$ ./examples/i3-container-commander.py                                                           
Traceback (most recent call last):
  File "./examples/i3-container-commander.py", line 80, in <module>
    g = find_group(c)
  File "./examples/i3-container-commander.py", line 55, in find_group
    return str(container.get_property(args.group_by)) if args.group_by != 'none' else ''
AttributeError: 'Con' object has no attribute 'get_property'

but this may be because I use i3-next

$ i3 --version                                                                                     
i3 version 4.10.2-145-g37bee99 (2015-04-26, branch "next") © 2009 Michael Stapelberg and contributors

Feel free to close it if that's the case

[Feedback Wanted] Use a generator for pythonic event handling

In addition to connection.on() to subscribe to events, also provide the option to use a generator function.

Example:

for e in conn.events('window::focus'):
    print(e.current.name)

Behind the scenes, this will subscribe to the window event and only yield events with e.change == 'focus'.

This might be a little messy for subscribing to multiple kinds of events, but manageable.

for e in conn.events('window::focus', 'workspace::focus'):
    if type(e) is WorkspaceEvent:
        print('handle workspace event...')
    elif type(e) is WindowEvent:
        print('handle window event...')

'restart' command raises error because of missing ipc socket answer

When executing the restart command through the i3.command methode the following JSONDecodeError is raised, because the ipc socket doesn't return an answer. The command itself is executed correctly.

>>> import i3ipc
>>> i3 = i3ipc.Connection()
>>> i3.command('restart')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/joe/git/_vendor/i3ipc-python/i3ipc/i3ipc.py", line 418, in command
    return json.loads(data, object_hook=CommandReply)
  File "/usr/lib/python3.6/json/__init__.py", line 367, in loads
    return cls(**kw).decode(s)
  File "/usr/lib/python3.6/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.6/json/decoder.py", line 357, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0

I guess this happens, because the socket breaks down in the following method, after the command has been sent:

def _ipc_send(self, sock, message_type, payload):
    sock.sendall(self._pack(message_type, payload))
    data, msg_type = self._ipc_recv(sock)
    return data

I'd send a PR, but I'm not quire sure how this should be fixed best.

Memory leak

I have some code that is run every second:

focused = i3ipc.Connection().get_tree().find_focused()
# I use this to get some information about the current window

After a few hours of running it, it started to really use a lot of memory so I investigated it with objgraph and objgraph.show_growth() showed that this is what's left over after running the code snippet:

dict        5700        +6
tuple       4330        +6
weakref     2033        +3
type        1201        +3

So I don't know if there is any way to get rid of these unused objects as they seriously tax the memory after a while...

Cannot get the correct workspace's layout

#!/usr/bin/env python3
import i3ipc
i3 = i3ipc.Connection()
ws = i3.get_tree().find_focused().workspace()
print(ws.layout)

This script will print splith no matter what the layout is.

How to enter passthrough mode when focus switches to emacs?

I took a stab at writing a script. I think I'm close but I can't quite get it working. I'm thinking the way I'm sending the command 'mode passthrough' is not correct.

#!/usr/bin/env python3

import i3ipc

i3 = i3ipc.Connection()

def pick_mode():
tree = i3.get_tree()
focused = tree.find_focused().name

if focused == 'emacs@arch':
i3.command('mode passthrough')

i3.on('window::focus', pick_mode)

i3.main()

I also put this in my i3 config to exit passthrough mode:

mode 'passthrough' {
bindsym Mod1+Alt_L mode 'default'
}

If no num in WorkspaceReply, output is None

If the num of a WorkspaceReply object is 0 (ie, it has no number in the name), then the output for the workspace is None.
This is contrary to the output given by i3-msg -t get_workspaces, which correctly gives the output for non-numbered workspaces.
If I rename the workspace to have a number with it, the WorkspaceReply object correctly gives the output. Thanks

Make tree traversal from events easier

Currently when you get an event with a container, this container is not connected to the tree (descendents and parent are empty). This is understandable since the event payload doesn't include this information. But could you provide a more convenient interface? Maybe a way to quickly locate the container in the tree returned by get_tree.

How do I access the current mode?

Hey, thanks for this library. I'm pretty new to programming and CS, having just started writing python recently. So having this library is really awesome because I can write some of my first "real" pieces of software for a WM that I love. Anyway.

Is there a way to get the current mode? I tried dir(i3ipc.Connection()) and have managed to acces the status of workspaces through i3ipc.Connection().get_workspaces()

i3 config example:

mode "resize" {
# With vim like bindings
bindsym h resize shrink width 4 px or 4 ppt
bindsym j resize grow height 4 px or 4 ppt
bindsym k resize shrink height 4 px or 4 ppt
bindsym l resize grow width 4 px or 4 ppt
# With arrow keys
bindsym Left resize shrink width 4 px or 4 ppt
bindsym Down resize grow height 4 px or 4 ppt
bindsym Up resize shrink height 4 px or 4 ppt
bindsym Right resize grow width 4 px or 4 ppt
# Esc
bindsym Escape mode "default"
bindsym Return mode "default"
}

Will gladly send you my finished program for example code once it's done. Thanks again.

Can't subscribe to barconfig_update event

When I try to run this code:

import i3ipc

def callback(*args):
    print(args)

i3 = i3ipc.Connection()
i3.on("barconfig_update", callback)
i3.main()

I get:

  File "/usr/lib/python3.5/site-packages/i3ipc.py", line 312, in on
    raise Exception('event not implemented')
Exception: event not implemented

Looks like in the on method it replaces the underscores with dashes but then it tries to check it against the string barconfig_update which still has the underscores?

On a different but related problem, if I work around that I get an error when I reload i3

  File "/usr/lib/python3.5/site-packages/i3ipc.py", line 136, in emit
    detail = data.change
AttributeError: 'BarconfigUpdateEvent' object has no attribute 'change'

Quickly adding and removing borders is not very seamless

I'm not sure where to ask this question, either in i3ipc or in the normal i3 page, or just in Github in general, so please, if there is a better place for me to ask this question please redirect me so.

i3ipc bopping

You can see in this gif that I have it so that when a window is focused a border comes up and then disappears after a couple of seconds. (You can see my code here: http://termbin.com/fsia)
The problem is that the window is sort of "resized", every time you add a border. I don't know if this is possible in i3, but is there a way so that when you add a border it doesn't "resize" the window?

Thanks for any help!

Please support Python2

Hello @acrisci and thank you for developing this library.
Would you consider supporting py2 as well.
It would be useful on systems where python3-xlib is not available yet, or where py2 is the default interpreter.

Undeclared Dependency: pubsub

$ sudo pip3 install i3ipc
$ python
>>> import i3ipc
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.4/dist-packages/i3ipc.py", line 6, in <module>
    from pubsub import pub
ImportError: No module named 'pubsub'

I can only assume it's referring to the PyPI package.

as I get the scripts to run ?

Hi...
Excuse my asking
as I get the scripts to run ?
I searched if you have a manual but do not see it !
It saddens me to do this kind of questions ...
I hope I can get out of doubt

app-on-ws-init.py: accept a list of workspaces

I would like to launch a terminal window for each of the workspaces 1 trough 8 when they're initiated.

In stead of using eight instances of app-on-ws-init.py, I would like to have one script running that compares the initiated WS's name with a list of names (or with an expression). There's no need for argument parsing.

help is greatly appreciated!

Subscription socket not closed properly

Related to i3/i3#2999.

Minimal example:

#!/usr/bin/env python3
import i3ipc


def on_ws_focus(self, e):
    print(e.old.name, '->', e.current.name)


for i in range(10):
    try:
        i3 = i3ipc.Connection()
        i3.on('workspace::focus', on_ws_focus)
        i3.main()
    except KeyboardInterrupt:
        print('ctrl-c pressed for connection #', i)
        # uncomment to unbug: i3.main_quit()

With the line commented out: https://bpaste.net/raw/abbf7e3ea890
With the line uncommented: https://bpaste.net/raw/667fe94a2d58

This will lead i3 to get stuck receiving EAGAIN errors while trying to write to the socket fd because the client is not reading from the pipe:
https://github.com/i3/i3/blob/55dd5b8d8406c45b8ba406eabe453bc8596c1336/libi3/safewrappers.c#L75-L79

Feature Request: Option to restart i3

For certain use cases like moving the primary monitor it would good to have an option to restart i3.
Because it can happen that certain parts of the screen stay black and restarting i3 solves that.

Scratchpad script

Hey there,

I am trying to create a script to solve a problem I am having: I have two monitors with different resolutions and I want a terminal in the scratchpad, a dropbown terminal. In order to have the terminal show up in any of the two screens, whenever I want, I need to call a different command depending on which monitor is active, else the terminal wont fit.

Here's my noob atempt at doing this:

#!/usr/bin/env python3
import subprocess
from json import loads
from os import popen
from sys import argv
import i3ipc


i3 = i3ipc.Connection()

focused = i3.get_tree().find_focused()
print('Focused window %s is on workspace %s' %
      (focused.name, focused.workspace().name))

def ipc_query(req="command", msg=""):
	ans = popen("i3-msg -t " + req + " " +  msg).readlines()[0]
	return loads(ans)

active_display = None
for w in ipc_query(req="get_workspaces"):
	if w['focused']:
		active_display = w['output']
		print("active_display is: ", active_display)
		if active_display=="VGA1":
			i3.command('for_window [class="Tilix"] move scratchpad, move position 0 20, resize set 1270 1004;')
			print("... VGA1")
		elif active_display=="HDMI1":
			i3.command('for_window [class="Tilix"] move scratchpad, move absolute position 0 0, resize set 1920 1060;')
			i3.command('scratchpad show;')
			print("... HDMI1")
		elif active_display=="eDP1":
			i3.command('for_window [class="Tilix"] move scratchpad, move position 0 21, resize set 1920 1059;')
			i3.command('scratchpad show;')
			print("... eDP1")

The very same commands work when plugged directly into i3's config, but for some reason my script is not working.. It is the "for_window [class="Tilix"]" bit that's not working. How can I accomplish that with i3ipc?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.