ssokolow / quicktile

Adds window-tiling hotkeys to any X11 desktop. (An analogue to WinSplit Revolution for people who don't want to use Compiz Grid)
https://ssokolow.com/quicktile/
GNU General Public License v2.0
860 stars 78 forks source link

python-wnck removed in Ubuntu 18.04 #95

Closed bl4ck5un closed 4 years ago

bl4ck5un commented 6 years ago

python-wnck is no longer available in Ubuntu 18.04. I'm using the package from artful (17.10) as a workaround. Would be great to know how to install quicktile properly in 18.04.

ssokolow commented 6 years ago

Ahh. I didn't catch that because, as every *buntu upgrade I've ever done has unpredictably broken things, I haven't been able to speculatively budget a huge block of time for an upgrade from 14.04 LTS yet.

I suspect python-wnck is gone because applications are expected to use PyGI and the language-agnostic GObject Introspection bindings for libwnck rather than PyGTK and python-wnck.

The proper solution will be me migrating it to Python 3.x and PyGI when I can spare the time (the API adapter to ease porting PyGTK apps to PyGI segfaults when I hook QuickTile up to it, so I need to do it the long way... which also takes time I haven't had).

bl4ck5un commented 6 years ago

Okay. make sense. I'm not familiar with PyGI etc at all so can't help there. For now, using python-wnck from 17.10 works flawlessly.

fidergo-stephane-gourichon commented 6 years ago

If you're reading this because you just want a python-wnck that work on Ubuntu Bionic Beaver 18.04, download it for your architecture from https://packages.ubuntu.com/artful/python-wnck . Thanks @bl4ck5un for the tip!

To @ssokolow: thanks for all.

It seems python-wnck package was removed a month ago, ref https://launchpad.net/ubuntu/bionic/amd64/python-wnck with reference to https://bugs.launchpad.net/ubuntu/+source/gnome-python-desktop/+bug/1739797

gnome-python-desktop was recently removed from Debian Testing since it is GNOME2 tech that has been unmaintained for years.

Falieson commented 6 years ago
sudo sh -c "echo 'deb http://cz.archive.ubuntu.com/ubuntu artful main universe' >> /etc/apt/sources.list" 

then you can run the apt install command

EDIT by ssokolow: For people who don't scroll down to my reply, don't use > unless you're echoing to a brand new file in /etc/apt/sources.list.d/ or you'll wipe out your regular list of package sources. >> will append instead.

perlun commented 5 years ago

The situation is the same with Debian Testing (Buster) which is what Ubuntu 18.04 is based on; python-wnck is unavailable. But, it's available in Debian Unstable i.e. sid - those of you running Debian Testing can download the sid/stretch packages here: https://packages.debian.org/sid/python-wnck and https://packages.debian.org/stretch/python-wnck

fidergo-stephane-gourichon commented 5 years ago

It looks like there is a way to directly have wnck available from python without dedicated python-wnck package, using the GObject introspection infrastructure. Details are on https://stackoverflow.com/a/43349245/1429390

apt-get install python3-gi gir1.2-wnck-3.0

then

>>> import gi
>>> gi.require_version('Wnck', '3.0')
>>> from gi.repository import Wnck
ssokolow commented 5 years ago

I've been aware of that for a while, but there are three problems with it:

  1. That's libwnck 3.x, which is for GTK+ 3.x, while QuickTile is a GTK+ 2.x application.
  2. I don't think it's possible to mix PyGTK and PyGI in the same event loop and, even if it is, it's likely to introduce random crashes.
  3. I've tried to start porting from PyGTK to PyGI in the past, but, when I just swapped in the API shim PyGI provides to ease porting of PyGTK apps, I got segfaults on my *buntu 14.04 LTS system.

Basically, while I do eventually want to use that, it requires a very involved porting process that I'm still trying to make time for:

  1. Port from Python 2.x to Python 3.x, because Python 2.x is soon to be end-of-lifed
  2. Port from PyGTK to PyGI, because PyGTK is end-of-lifed
  3. Port from GTK+ 2.x to GTK+ 3.x, because GTK+ 2.x is end-of-lifed (that's why libwnck 2 is going away)

...and since PyGTK isn't available for Python 3.x and PyGI's support for GTK+ 2.x is flaky at best, I have to do it all at once.

(And it's impossible to keep it working during the intermediate steps so I can port incrementally and test for bugs along the way. It many ways, the complexity approaches a complete rewrite and, if there were a suitable equivalent to libwnck in the Qt ecosystem, I'd probably port to PyQt 5 instead.)

I'd hoped to write an automated test suite first, but other things kept cropping up.

tonoono commented 5 years ago

For those that want to add the artful repo as mentioned by @Falieson I would recommend using the following command:

sudo sh -c "echo 'deb http://cz.archive.ubuntu.com/ubuntu artful main universe' >> /etc/apt/sources.list" Make sure that you have two >> and not just one > The reason being that > will overwrite the file, but >> will append it to the end of the file. Trust me you don't want to wipe out your /etc/apt/sources.list file. I got my setup running using @Falieson command (thanks!) and my little tweak.

ssokolow commented 5 years ago

I recommend adding a file to /etc/apt/sources.list.d instead. That way, you're not even touching sources.list.

sudo sh -c "echo 'deb http://cz.archive.ubuntu.com/ubuntu artful main universe' > /etc/apt/sources.list.d/artful-main-universe.list"
kbsali commented 5 years ago

@ssokolow obviously same issue on 18.10, any plan on fixing this? (maybe you are not an Ubuntu user!? :) )

peteruithoven commented 5 years ago

I wasn't really looking forward to play around with sources so I've figured out a crude way of doing quarter tiling using this script: https://gist.github.com/peteruithoven/db0cba0b0849c8cb5e267f6e75126304 You'll have to adapt some values based on your screen size, top panel size, window margins etc. The default window margins are elementary OS specific for example.

kbsali commented 5 years ago

@peteruithoven nice, although this looks very very basic! :) quicktile does a lot more than just quarter tile! I've been using quicktile for years now and couldn't find a better option (I'm biased & used to it). You script looks good for 1 single "fixed" monitor, I use it on my laptop which I connect to different external devices.

ssokolow commented 5 years ago

@kbsali Oh, I certainly intend to fix it.

It's just that my life has been so busy lately that I'm still on Kubuntu 14.04 LTS despite its support period ending in only a few months.

The problem is that switching to what's supported in newer releases requires a port from GTK+ 2.x to GTK+ 3.x, and that's more complicated than it sounds because of the need to also port from PyGTK to PyGI. (And staying on Python 2.x initially and using the PyGTK->PyGI porting shim to port in stages is complicated by the fact that, last time I tried that, PyGI segfaulted.)

ssokolow commented 5 years ago

I had some free time today, so I decided "appears to work, but potentially buggy" is better than "nothing testable", and I've started to work on getting it ported to PyGI and Wnck 2.x.

I'm to the point where the only thing left that static analysis is complaining about is the handful of sparse unit tests I have, which are use GdkRegion for mocking... and there's no apparent "rename X to Y" porting path for that, so I'll need a little more time to rewrite the relevant bits.

UPDATE: ...and manual testing reminded me of how heavily I use GdkRegion in the code without directly referencing the type name. Time to figure out what the APIs which used to return it are returning now.

UPDATE: To clarify, GdkRegion was replaced with cairo_region_t, but I'm having trouble figuring out how to access it via a Python binding. (The API exposed by PyGI doesn't seem to have a way for me to instantiate one and I'm still on PyCairo 1.8.8, when cairo.Region didn't get exposed until 1.11.0.)

ssokolow commented 5 years ago

I decided I'll just leave the GTK+ 2.x version easily accessible in a branch for anyone needing pre-1.11.0 PyCairo, so I upgraded my copy of PyCairo and I've continued to work on the porting to GTK+ 3.x.

Still not complete enough to run without dying from "no such method" errors, but progress is being made.

kbsali commented 5 years ago

Great news, thanks for the effort! :muscle:

fidergo-stephane-gourichon commented 5 years ago

Download python-wnck for 18.10

I've been, trying Xubuntu 18.10. The link I mentioned above is already broken because artful is considered an old release. You can now find a version for your architecture on: http://old-releases.ubuntu.com/ubuntu/pool/main/g/gnome-python-desktop/

Fail?

But... it did not work for me. Why? See commands and error below.

# I issued those commands (success, result hidden).
wget http://old-releases.ubuntu.com/ubuntu/pool/main/g/gnome-python-desktop/python-wnck_2.32.0-0ubuntu6_amd64.deb
sudo dpkg --install python-wnck_2.32.0-0ubuntu6_amd64.deb 

# I then ran quicktile which failed, see output.
quicktile --daemonize 

Traceback (most recent call last):
  File "/usr/local/bin/quicktile", line 6, in <module>
    from pkg_resources import load_entry_point
  File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 3105, in <module>
    @_call_aside
  File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 3089, in _call_aside
    f(*args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 3118, in _initialize_master_working_set
    working_set = WorkingSet._build_master()
  File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 578, in _build_master
    ws.require(__requires__)
  File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 895, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 781, in resolve
    raise DistributionNotFound(req, requirers)
pkg_resources.DistributionNotFound: The 'python-wnck' distribution was not found and is required by QuickTile

Release info

lsb_release -a

No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.10
Release:    18.10
Codename:   cosmic
uname -a

Linux myhostname 4.18.0-11-generic #12-Ubuntu SMP Tue Oct 23 19:22:37 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

Package info

dpkg -L python-wnck 

/.
/usr
/usr/share
/usr/share/doc
/usr/share/doc/python-wnck
/usr/share/doc/python-wnck/AUTHORS
/usr/share/doc/python-wnck/examples
/usr/share/doc/python-wnck/examples/wnck_example.py
/usr/share/doc/python-wnck/NEWS.gz
/usr/share/doc/python-wnck/copyright
/usr/share/doc/python-wnck/README
/usr/share/doc/python-wnck/changelog.Debian.gz
/usr/share/pyshared
/usr/share/pyshared/gtk-2.0
/usr/lib
/usr/lib/pyshared
/usr/lib/pyshared/python2.7
/usr/lib/pyshared/python2.7/gtk-2.0
/usr/lib/pyshared/python2.6
/usr/lib/pyshared/python2.6/gtk-2.0
/usr/lib/python2.7
/usr/lib/python2.7/dist-packages
/usr/lib/python2.7/dist-packages/gtk-2.0
/usr/lib/python2.7/dist-packages/gtk-2.0/wnck.so
/usr/lib/python2.6
/usr/lib/python2.6/dist-packages
/usr/lib/python2.6/dist-packages/gtk-2.0
/usr/lib/python2.6/dist-packages/gtk-2.0/wnck.so
/usr/lib/pyshared/python2.7/gtk-2.0/wnck.so
/usr/lib/pyshared/python2.6/gtk-2.0/wnck.so
ssokolow commented 5 years ago

It looks like setuptools (the thing which generates the /usr/local/bin/quicktile launcher) isn't seeing python-wnck for some reason.

Does running python2 -m quicktile --daemonize (which should bypass that aspect of setuptools) work?

If so, three options come to mind:

  1. Just run that instead
  2. Uninstall and reinstall QuickTile to see if setuptools will un-confuse itself.
  3. Uninstall QuickTile, remove the test_for_imports("wnck", "python-wnck", "python-wnck") line from setup.py, and then reinstall it so that the dependency on python-wnck is invisible to setuptools.

(For the record, I am still working on the port to GTK+ 3.x which will resolve this mess, but things got a little busy so I haven't had time to figure out how to port over a line which got horrendously ugly in the switch from PyGTK to PyGI.)

fidergo-stephane-gourichon commented 5 years ago

Hi @ssokolow and thank you for reaching back.

At the moment I can just confirm that python2 -m quicktile --daemonize just works, while running only quicktile --daemonize still fails with the same error message.

I hope I'll try the other steps soon, too.

fidergo-stephane-gourichon commented 5 years ago

Hi @ssokolow

Uninstall and reinstall QuickTile to see if setuptools will un-confuse itself.

It appeared to have un-confused itself. Now just running quicktile works.

You will find a slightly edited version of my terminal log (converted from ANSI color to HTML for reading comfort) here: https://gourichon.org/fsi/quicktile/unconfuse_log.html

Reading not only may help you (1) figuring out what became confused, but as it shows the kind of thing that actually happens when trying to follow installation instructions, it might (2) provide insights on how to adjust installation programs or human-readable instructions for maximum efficiency given the variety of people that may follow them.

Thanks again and keep up the good things!

ssokolow commented 5 years ago

Yeah. I definitely need to make some changes. Here is what I gather from that log:

First, I should have explicitly pointed you at the "Removal" section in the README.

As for the issues you ran into, they seem to mostly fall into two categories:

  1. You used the tooling I provided in an unsupported way without fully understanding what it was doing.
  2. I didn't draw enough attention to the existence of uninstallation instructions.

python2 setup.py install ... [Errno 13] Permission non accordée: [...]

I can't find any installation instructions where I forgot to say to to either use sudo or to call ./install.sh, which will do it for you, so I can only assume that you copied a line out of install.sh without also copying the earlier line (exec sudo "$0" "$@") which sets up the required environment by re-running install.sh with root permissions if it wasn't run using sudo.

I can't be responsible for things breaking because people copy-pasted random bits of my scripts without understanding what preconditions must be upheld.

sudo python2 setup.py uninstall

[...]

error: invalid command 'uninstall'

Again, you seem to be extrapolating from incorrect assumptions because you didn't know about the "Removal" section at the bottom of the README. I'll have to make it more visible.

sudo pip2 uninstall quicktile

The directory '/home/stephane/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag. Uninstalling QuickTile-0.3: /usr/local/lib/python2.7/dist-packages/QuickTile-0.3-py2.7.egg Proceed (y/n)? ^COperation cancelled by user

I don't know why you cancelled this. You were on the right track.

My best guess is that I should use sudo -H in the instructions so that warning message doesn't pop up and confuse people.

rm: impossible de supprimer '/usr/local/bin/quicktile': Aucun fichier ou dossier de ce type

The locate command doesn't verify that results still exist, so it'll list files that still existed the last time the updatedb cronjob was run. That's why my removal instructions use find instead. It's slower, but doesn't produce potentially confusing results.

rm: impossible de supprimer '/usr/local/share/applications/quicktile.desktop': Aucun fichier ou dossier de ce type

I should consistently use rm -f in my scripts and instructions rather than rm so it won't produce a spurious error message if the file was already removed.

sudo rm /usr/local/bin/quicktile /usr/local/bin/quicktile.py

Removing quicktile.py is just to make sure that ancient single-file versions of QuickTile can't cause problems when someone uses ./install.sh to upgrade. There's a reason it only exists inside install.sh.

sudo: install.sh : commande introuvable

OK, I admit fault here. I never thought to test that sudo "$0" "$@" was robust in the face of less common ways to run install.sh.

realn0whereman commented 5 years ago
sudo sh -c "echo 'deb http://cz.archive.ubuntu.com/ubuntu artful main universe' >> /etc/apt/sources.list" 

then you can run the apt install command

Can you please edit your comment from > to >> ?

kbsali commented 5 years ago

Anyone has a solution to work around this without adding an old ppa to my sources? I managed to install on 18.10, but now that I have upgraded to 19.04 it does not work anymore... :/

meoso commented 5 years ago

this worked for me today on xubuntu 19.04 (in addition to the pre-reqs):

sudo apt install libpango1.0-0 pip
# used https://pkgs.org to find python-wnck
wget http://ftp.br.debian.org/debian/pool/main/g/gnome-python-desktop/python-wnck_2.32.0+dfsg-3_amd64.deb
sudo dpkg -i python-wnck_2.32.0+dfsg-3_amd64.deb 
sudo -H pip2 install https://github.com/ssokolow/quicktile/archive/master.zip
ssokolow commented 4 years ago

Just a little status update. Time was such a mess for me that I actually spent some time running Kubuntu 14.04 beyond even the LTS support window. (Yes, yes, I know. Bad programmer, no biscuit. That said, I was un-stupid enough to switch my Firefox from Canonical builds to Mozilla builds to ensure it kept getting security fixes and I make heavy use of things like uMatrix-based whitelisting.)

I'm currently on 16.04 while I squash the bugs, feature regressions, and unacceptable annoyances introduced by switching from Upstart to systemd, from KDE 4 to KDE 5, from a pre-CSD version of GTK+ 3.x to a post-CSD version, and just plain breakages that should be expected because I hacked something the first time rather than doing it properly.

Once that's done and I've finished finding Qt replacements for GTK+ 2.x apps that will go GTK+ 3.x in 18.04, I'll upgrade to 18.04 (16.04 isn't a 5-year-supported LTS like 14.04 and 18.04), squash the hopefully smaller number of bugs there, and then get back to work on QuickTile.

kbsali commented 4 years ago

just upgraded to 19.10, good same old game again! :sweat_smile: So here is what I did this time :

sudo apt install python-gtk2 python-xlib python-pip libpango1.0-0
wget http://ftp.br.debian.org/debian/pool/main/g/gnome-python-desktop/python-wnck_2.32.0+dfsg-3_amd64.deb
sudo dpkg -i python-wnck_2.32.0+dfsg-3_amd64.deb 
sudo -H pip2 install https://github.com/ssokolow/quicktile/archive/master.zip
ssokolow commented 4 years ago

Another status update. I've been working on this, but it's slow going because I'm still on Kubuntu 16.04 and the GTK+ 3.x and Cairo bindings appear to be broken, so I'm limited in which parts of QuickTile's codebase I can actually work on and test.

(Specifically, cairo.Region and Gdk.Rectangle seem to have no way to construct them directly and what I was able to dig up indicates that this is a bug in the API definitions... and those are pretty central to something like QuickTile.)

Since I'm still not ready to jump up to 18.04 and beyond, I may have to install something newer in a VM and develop in that to get the port done in reasonable time.

kbsali commented 4 years ago

This is of course none of my business, but why are you "stuck" on very old versions of Ubuntu? Nowadays the upgrade processes are pretty smooth! :)

ssokolow commented 4 years ago

I have trouble finding a large block of time where I can risk having to spend time fixing breakages.

Heck, I'm still finding and squashing the odd thing from the 14.04 -> 16.04 migration and that went well compared to what I'm used to.

ssokolow commented 4 years ago

Status Update: I've been working hard to try to get the GTK+ 3.x port out before New Years.

Here's what I have to report so far:

  1. Even with a Lubuntu 18.04 VM, one of the methods the docs listed wasn't there and the distinctions between methods that are and aren't there don't seem to follow any rhyme or reason.

    (eg. The method to get a monitor object from a monitor number is present, but the method to get total monitor count is missing, despite the API docs saying it should be there and both of them being carry-overs from GTK+ 2.x. I worked around it by using python-xlib to query that before handing off to GDK to query the geometry of each monitor.)

  2. Writing my own Rectangle class to work around the mess Gdk.Rectangle became in GTK+ 3.x has turned out to be a big benefit, because adding a few small features to the Rectangle class allows all the rest of the code to be much cleaner and easier to read:

    • Accepting nifty blends of point/size and point/point coordinates, like Rectangle(x=5, y=5, x2=480, height=600) and offering computed x2 and y2 members.
    • Transparently reinterpreting Rectangle(500, 500, -200, -200) as Rectangle(300, 300, 200, 200).
  3. While puzzling over how to write a replacement for cairo.Region, I realized that it was almost certainly overkill in the first place, so, tomorrow, I'll start work on a much simpler, cleaner solution that I can rethink later. (On that note, if anyone uses panels which don't span the entire width of a monitor, I welcome feedback on how you think QuickTile should handle calculating percentage-based tile grids in their presence.)

  4. Working on Rectangle and the aborted Region made me realize that I could make the parsing of _NET_WM_STRUT_PARTIAL (how panels reserve space that windows aren't allowed to overlap) much simpler. (That was one of the ugliest, most opaque bits of code in the whole thing.)

  5. I've got a complete set of unit tests for the Rectangle class (since that sort of math could easily introduce hair-pullingly subtle bugs) and I intend to do likewise for the StrutPartial class that is now used to provide a clean API around _NET_WM_STRUT_PARTIAL.

    (I also plan to do likewise for window geometry constraints once I finally support them properly, because getting the expected effect from parsing those things was where the work got snarled up on my last push to fix an ancient design flaw.)

  6. Retrofitting the codebase with MyPy type annotations has already revealed over half a dozen corner cases which are now fixed.

Tomorrow, I'm going to try to make a push to get it to the point where, even if it's not doing the right thing, it'll at least be scrambling up windows in the test desktop rather than dying with complaints about failed assertions or GTK+ methods that the API docs say should be there but aren't.

ssokolow commented 4 years ago

It turns out there's more work left to be done than I expected, but I'm continuing to chew my way through it.

Among other things, I'm continuing to refactor the codebase to make it more maintainable and to finally retire my original decision to rely on GTK+ and Wnck data types just because they're there, rather than creating custom types as appropriate.

I still hope to have the GTK+ 3.x version out before New Years.

kbsali commented 4 years ago

Awesome! :)

On Sat, Dec 21, 2019, 10:52 Stephan Sokolow notifications@github.com wrote:

It turns out there's more work left to be done than I expected, but I'm continuing to chew my way through it.

Among other things, I'm continuing to refactor the codebase to make it more maintainable and to finally retire my original decision to rely on GTK+ and Wnck data types just because they're there, rather than creating custom types as appropriate.

I still hope to have the GTK+ 3.x version out before New Years.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ssokolow/quicktile/issues/95?email_source=notifications&email_token=AAANDLGNDS5A2H5LEL32R2DQZXRPFA5CNFSM4E5VYFVKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHOY6PY#issuecomment-568168255, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAANDLCGPD5EPSJWPWWFC4LQZXRPFANCNFSM4E5VYFVA .

ssokolow commented 4 years ago

OK, I hadn't expected to have no time at all to work on this on the 24th and 25th, but I'm now almost done unit testing the core rectangle-handling math and fixing the bugs thus revealed.

Once that's done, things will speed up a lot, because I can just do minimal tweaks to the rest of the code to get it into a "public alpha" state and then continue refactoring and writing unit tests in January.

At the moment, I'm writing the last set of "rectangle math" tests, which are for the UsableRegion class which wraps everything else and calculates a _NET_WORKAREA equivalent that's per-monitor and, thus, useful for non-rectangular desktops.

(And I just ran into another latent bug. For some reason, it's failing the unit test by not acknowledging the _NET_WM_STRUT_PARTIAL reservation for a 30px panel at the bottom of my centre monitor.)

EDIT: Found the problem. I accidentally wrote usable = monitor.subtract(panel) rather than usable = usable.subtract(panel) so later panel reservations would clobber earlier ones rather than combining with them.

ssokolow commented 4 years ago

There. There are still some bugs to be fixed in some commands before I feel comfortable pushing a public alpha, but the GTK+ 3.x version is now in a state where it starts and binds keys without crashing and a cursory examination shows that most of the commands seem to work.

Known bugs at this point:

Writing automated functional tests is something I still want to do, but that can come after I push a public alpha, because it requires me to finish writing a test harness which spins up an Xvfb or Xephyr instance, loads a window manager, generates mock windows, and then asserts window geometry in the little X playpen before and after running QuickTile commands.

EDIT: Converted into a checklist and added more known bugs.

ssokolow commented 4 years ago

I think I'm now to the point where the only remaining known bugs are logic bugs which were present in some form in the GTK+ 2.x version but didn't manifest to me because my use patterns and monitor layout didn't trigger them.

However, given how problematic the monitor-switch one is, I'd still like to fix at least that one before I make an alpha release for people to try out.

The big question there is how to resolve things.

  1. If I convert the window's dimensions to percentages of the monitor's usable region before moving it and then convert them back on the new monitor, it'd have the effect of faking a unified "snap to grid" system across all monitors, but it won't do well for things like a gVim window that's intended to stay 82 text columns wide regardless of the monitor. (The proper solution is to actually have a grid system, but that's a more involved TODO)
  2. If I bump the window inward, then it becomes important to track its original position so it returns to it if you cycle through all the monitors, but determining when that saved position is stale becomes more complicated.

So far, I'm thinking I'll do solution 2 (bump the window rectangle inward, then crop to the monitor's usable region to produce the target dimensions) since, even without the proper cycle-around behaviour, it's still better than nothing.

From there, I'll ponder whether "remember the dimensions on the original monitor and the dimensions we put it at on the current monitor, then invalidate the former if we no longer match the latter" is sufficient.

I can already imagine one situation where it won't work. Ironically (considering that I just mentioned it as a motivation), gVim... because it resizes in text column/row-sized increments and I don't yet have a reimplementation of the code to process aspect ratio and size-increment restrictions so I can anticipate the dimensions the WM will force the window to.

That won't be a regression though. QuickTile never had that and it's been something I've wanted to get to for years. (Hopefully, now that I'm productive again, it won't be too far off but, once the GTK 3 version of QuickTile is out, I have fix my ITAD Importer userscript first.)

EDIT: OK. Repositioning to another monitor without specifying an explicit destination rectangle will clamp to the bounds of the monitor, so monitor-* commands can't lose windows off the edge of a screen. It doesn't yet have the infrastructure in place to undo the clamping if you cycle back to a bigger monitor, but it's enough to make me comfortable releasing it... just give me a little time to do a little housecleaning and I'll push the development branch.

ssokolow commented 4 years ago

Done. 🎉

The GTK 3 port is now ready for pre-release testing at https://github.com/ssokolow/quicktile/tree/gtk3_port

(i.e. I couldn't find any more bugs in it, but I only tested on my machine so please poke at it and let me know how it goes.)

However, don't follow the instructions for pip3 installing from a URL because the README assumes that it's been merged into the master branch.

If you want to install that way, instead use this command:

sudo pip3 install https://github.com/ssokolow/quicktile/archive/gtk3_port.zip

(But don't feel like I'm encouraging a single particular install method. I did all my development testing using the "run quicktile.sh without installing" method and I double-checked that install.sh still worked before pushing it.)

I'll switch my attention to some other projects that have been languishing now, to bring them back to proper function but, once that's done, I have a stack of things I still want to do here. (Most importantly, switching from ePyDoc to Sphinx to get rid of my last Python 2.x dependency.)

(I'll leave this open until the gtk3_port branch has gotten a little exercise and then been merged to master.)

ssokolow commented 4 years ago

I just found a new bug emerging from something I'd meant to solve later.

QuickTile doesn't currently update its view of the desktop when its shape or panel reservations change. This wasn't an issue before because it re-inspected the desktop every time you called a command but it seems that, at least in Kubuntu 16.04, ./install.sh installation results in it launching before Plasma has announced its panel reservations.

I'm currently working on my ITAD Importer as planned, but I may try to fit in a quick fix for that in the next few days. (At the moment, ITAD Importer doesn't work at all. That's why it's prioritized over fixing this bug.)

svenski commented 4 years ago

Thank you for fixing this over the holidays -- I very much look forward to have this working on Xubuntu again!

I have gotten an exception when trying to use it. Only for actions like top/bottom/left/right, the other ones seem to work, including switching monitors. Here are my bindings: Keybindings defined for use with --daemonize:

Modifier: <Ctrl><Alt>

Key    Action               
------ -------------------- 
 0       monitor-switch       
 C       move-to-center       
 comma   workspace-go-down    
 h       left                 
 i       workspace-send-up    
 j       bottom               
 k       top                  
 l       right                
 m       maximize             
 n       workspace-go-left    
 o       workspace-send-right 
 period  workspace-go-right   
 u       workspace-send-down  
 y       workspace-send-left  

 o       workspace-send-right 
 period  workspace-go-right   
 u       workspace-send-down  
 y       workspace-send-left  

The final error is:

  File '/usr/local/lib/python3.6/dist-packages/Xlib/protocol/rq.py', line 696,
    pack_value(self=<Xlib.protocol.rq.PropertyData object>, value=(8, '[4, 0]'))
                size = fmt // 8
                a = array(array_unsigned_codes[size], val)
                data = encode_array(a)
    Variables (B=Builtin, G=Global, L=Local):
     -            a (N): None
     -        array (G): <class 'array.array'>
     - array_unsigned_codes (G): {1: 'B', 2: 'H', 4: 'I', 8: 'L'}
     -         size (L): 1
     -          val (L): '[4, 0]'
TypeError: cannot use a str to initialize an array with typecode 'B'

I've attached the full stack trace. quicktile.error.txt

I'm running on Xubuntu (Xfce verion 4.12)

Let me know if you need any other info!

ssokolow commented 4 years ago

I have gotten an exception when trying to use it. Only for actions like top/bottom/left/right, the other ones seem to work, including switching monitors.

That makes sense. It looks like it's in the code that remembers where in the cycling sequence it is so it won't get confused if the window specifies sizing increments or aspect ratio restrictions and, thus, doesn't wind up at the expected size.

The final error is:

Odd. That looks like a unicode/bytestring mismatch, which I'd expect to be caused by going between Python 2.x and Python 3.x, but we should both be on Python 3.x.

The solution is probably just for me to .encode('utf8') the bit of JSON that I switched to for storing metadata in X window properties before handing it off to python-xlib.

I'm running on Xubuntu (Xfce verion 4.12)

Which Xubuntu release? I'll try to grab a VM image tomorrow and see if I can replicate the problem.

(Which reminds me. I should try adjusting gtkexcepthook so that, if it finds the lsb_release command, it includes the output of lsb_release -a in the dump.)

svenski commented 4 years ago

Hmm, ok, I might have messed something up on my machine, is any other checks that I can do?

❯ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.3 LTS
Release:    18.04
Codename:   bionic

Python version is 3.6.8.

❯ python3
Python 3.6.8 (default, Oct  7 2019, 12:59:55) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from quicktile.__main__ import main
ssokolow commented 4 years ago

I already had a Lubuntu 18.04 VM on hand, so I was able to reproduce it and it should be fixed now.

It seems that 18.04 has two regressions from whatever version of python3-xlib I'm using on 16.04:

  1. Mine was transparently encoding and decoding Unicode when setting properties of type Xatom.STRING while 18.04's isn't. (I switched to just storing an INTEGER[2]/32 property instead since the JSON was just for future expandability anyway.)
  2. 18.04's version of python-xlib is apparently more fragile if you don't explicitly display.flush() after setting a window property.

The latter seems like a race condition, so I can understand it not cropping up during the testing I was doing on that VM but I'm not sure why the former didn't crop up.

Oh well. More reason to write a bigger automated test suite when I come back to this.

svenski commented 4 years ago

I've verified it works for me - thanks again!

nreith commented 4 years ago

It's very hacky, but if you love Elementary OS like me and neeeeed window tiling, I scripted the entire installation and config of quicktile including old-releases install of python-wnck and other bug fixes such as the large invisible window borders in eos. Works for me. Please comment there if you find issues with my script.

https://raw.githubusercontent.com/nreith/linux_config/master/scripts/quicktile_elementary_os.sh

ssokolow commented 4 years ago

...and, as I just mentioned two days ago, I'm looking for testing on the pre-release version of QuickTile for GTK 3.x that I just pushed to https://github.com/ssokolow/quicktile/tree/gtk3_port

That includes feedback on the installation instructions. Pointing people at that script is counterproductive when I need people to test the port's installation process and give feedback on how to make it easier.

Just make sure you use this URL rather than the one from the README if you're installing via pip and a URL. The README's URL will only stop pointing to the GTK+ 2.x version when the pre-release gets pushed to the master branch:

sudo pip3 install https://github.com/ssokolow/quicktile/archive/gtk3_port.zip
ssokolow commented 4 years ago

That said, thank you for giving an example of how to fix things like the borders issue. Once I get back from fixing another thing that's in even more desperate need of fixing, I'll go through your script and add stuff like that to the QuickTile FAQ.

(I'm holding off on the site changes because I'm planning to rewrite the API docs using Sphinx and, when I do, I can make everything into one Sphinx-generated site.)

nreith commented 4 years ago

Apologies if I didn't grasp the etiquette around these issues. I've been using Linux for a long time, but new at contributing. Elementary has a new feature in Gala with a pull request pending for quite a while and that seems like it would meet my needs. I'd be happy to test out your new version too. Will try it out soon.

I guess I had been scouring the web for solutions for tiling and somehow missed this alpha announcement.

Re: Window border, found that on the Arch Wiki of all places. https://www.linuxsecrets.com/archlinux-wiki/wiki.archlinux.org/index.php/Pantheon.html Seems the user gtk css config is overriden or something.

Thanks for all your great work!

fidergo-stephane-gourichon commented 4 years ago

Thanks a lot for this work! This new branch works perfectly for me on Xubuntu 19.10.

ssokolow commented 4 years ago

Glad to hear it... though, with the ice storm here in Ontario, Canada having brought three power outages in two days, I've become very aware of how easily a certain TODO item can cause very visible bugs, so it's likely I'll need to push and get testing on another release candidate before 0.4.0 gets tagged.

(I was planning to wait for 0.4.1 to add the code to watch for changes like adding/removing/changing monitor rectangles or panel reservations but it turns out that QuickTile starts before Plasma reserves its panels when using ./install.sh on Kubuntu 16.04 LTS.)

fidergo-stephane-gourichon commented 4 years ago

It's very hacky, but if you love Elementary OS like me and neeeeed window tiling,

Thanks @nreith for sharing some scripts. Looks like the debug part of it benefited the auhor.

PR for Debian package

Progress by @ssokolow on branch gtk3_port motivated me to create a debian configuration for the package and open PR #106.

This has the benefit of not requiring old packages and kludge. And the package is nicely installed by Debian and uninstallable.

Would you like to test the Debian package on branch gtk3_port?

If so, you can fetch my branch https://github.com/fidergo-stephane-gourichon/quicktile/tree/feature_debian_package and run recompile_local_debian_package.sh there.

Options: local or Docker

Notice that building the Debian package requires you to install some debian-development-related packages on your main system.

Alternatively, you can install docker and perform package creation inside it. I posted a command line on https://github.com/ssokolow/quicktile/pull/106#issuecomment-570077716-permalink . That latter option consumes a lot of bandwidth because you need to fetch a whole distribution and set of packages. The plus side is that it allows to build packages for other distributions.

Thank you for your attention.

fidergo-stephane-gourichon commented 4 years ago

Glad to hear it...

I spoke a little fast.

There's one regression. I happen to have a xfce panel on the bottom right, with width less than width of window. Usual version of quicktile correctly expands any window on the left side to the full height. New version limits the height uselessly. See attached screenshot, bottom left.

quicktile_regression

though, with the ice storm here in Ontario, Canada having brought three power outages in two days, I've become very aware of how easily a certain TODO item can cause very visible bugs, so it's likely I'll need to push and get testing on another release candidate before 0.4.0 gets tagged.

Here in Paris it's cold, but probably no as cold as in Canada. Because of strikes, the public transportation is severely degraded to the point where it's "safer" for commuters to ride, say, 12-18km on a bike to go to work (then again back in the evening).

"They're professionals. They do this all the time. It can't possibly be this un-optimized. I must be missing something."

"Small steps"