Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4K screen adaptation #60

Open
boussou opened this issue Dec 21, 2015 · 23 comments
Open

4K screen adaptation #60

boussou opened this issue Dec 21, 2015 · 23 comments

Comments

@boussou
Copy link

boussou commented Dec 21, 2015

Hi, I would like to patch the code to make the most of my 4K screen.

What I need is get rid of that 0.5 factor but insteal allow 5 to 7 vertical columns and be able to cycle through them.

The problem: I need to learn Python before ;-(
I have seen those gravities enums, the POSITIONS array.
Can someone help me doing the proper change?

@ssokolow
Copy link
Owner

Hi. Sorry for not providing a GUI to make that easy. It's been on my TODO list for ages but more important things (typically university-related) keep coming up. (At the moment, I'm working on my degree project.)

QuickTile should be able to do any layout you want, but in order to help you, I'll need you to explain exactly what kind of layout you want to generate, since there are multiple ways to have a 5-7 column layout mapped to commands.

However, I can give you a quick overview of how that code works without needing clarification from you.

Start with this bit:

col, gv = 1.0 / 3, GravityLayout()

# TODO: Figure out how best to put this in the config file.
POSITIONS = {
    'middle': [gv(x, 1, 'middle') for x in (1.0, col, col * 2)],
}  #: command-to-position mappings for L{cycle_dimensions}

for grav in ('top', 'bottom'):
    POSITIONS[grav] = [gv(x, 0.5, grav) for x in (1.0, col, col * 2)]
for grav in ('left', 'right'):
    POSITIONS[grav] = [gv(x, 1, grav) for x in (0.5, col, col * 2)]
for grav in ('top-left', 'top-right', 'bottom-left', 'bottom-right'):
    POSITIONS[grav] = [gv(x, 0.5, grav) for x in (0.5, col, col * 2)]

If you paste this in below it and run quicktile...

import pprint
pprint.pprint(POSITIONS)

...you'll see that it's a compact, easy-to-adjust way to generate this table:

POSITIONS = {
 'bottom': [(0.0, 0.5, 1.0, 0.5),
            (0.33333333333333337, 0.5, 0.3333333333333333, 0.5),
            (0.16666666666666669, 0.5, 0.6666666666666666, 0.5)],
 'bottom-left': [(0.0, 0.5, 0.5, 0.5),
                 (0.0, 0.5, 0.3333333333333333, 0.5),
                 (0.0, 0.5, 0.6666666666666666, 0.5)],
 'bottom-right': [(0.5, 0.5, 0.5, 0.5),
                  (0.6666666666666667, 0.5, 0.3333333333333333, 0.5),
                  (0.33333333333333337, 0.5, 0.6666666666666666, 0.5)],
 'left': [(0.0, 0.0, 0.5, 1),
          (0.0, 0.0, 0.3333333333333333, 1),
          (0.0, 0.0, 0.6666666666666666, 1)],
 'middle': [(0.0, 0.0, 1.0, 1),
            (0.33333333333333337, 0.0, 0.3333333333333333, 1),
            (0.16666666666666669, 0.0, 0.6666666666666666, 1)],
 'right': [(0.5, 0.0, 0.5, 1),
           (0.6666666666666667, 0.0, 0.3333333333333333, 1),
           (0.33333333333333337, 0.0, 0.6666666666666666, 1)],
 'top': [(0.0, 0.0, 1.0, 0.5),
         (0.33333333333333337, 0.0, 0.3333333333333333, 0.5),
         (0.16666666666666669, 0.0, 0.6666666666666666, 0.5)],
 'top-left': [(0.0, 0.0, 0.5, 0.5),
              (0.0, 0.0, 0.3333333333333333, 0.5),
              (0.0, 0.0, 0.6666666666666666, 0.5)],
 'top-right': [(0.5, 0.0, 0.5, 0.5),
               (0.6666666666666667, 0.0, 0.3333333333333333, 0.5),
               (0.33333333333333337, 0.0, 0.6666666666666666, 0.5)]}

That dict (associative array/hash/map/whatever term you may know) maps commands like bottom-left to lists of positions to cycle through if the key is tapped repeatedly.

Each position tuple takes the form (x, y, width, height) in the form of values between 0 and 1.
(eg. (0.0, 0.5, 1.0, 0.5) from the bottom section means (left, 50% wide, bottom, 50% tall))

GravityHelper just abstracts away the math for positioning a window using a point other than its top-left corner. For example, if you look at the second bottom position, it's (0.33333333333333337, 0.5, 0.3333333333333333, 0.5). That was generated by gv(col, 0.5, 'bottom') where col = 1.0 / 3. GravityHelper did the hard work translating between intuitive coordinates and the "always top-left corner" coordinates the window system expects.

Once you've got commands that do what you want, then you can edit your ~/.config/quicktile.cfg to assign keys to them.

@boussou
Copy link
Author

boussou commented Dec 21, 2015

Awesome !
Even if I don't know the langage, it is pretty clear (besides I am a programmer ;-)

4K is 3840x2160, if you want to take benefit from this huge defintiion on a 28" I want to put side by side from 5 to 7 columns.

I would like to do 2 types of layouts:

  • full heights columns
  • approx 1500px height + a banner of 660px height (for terminals, bdd, logs etc)

btw I am not sure I understood your explanation.
you said "Each position tuple takes the form (x, y, width, height) "
and then your example " (0.0, 0.5, 1.0, 0.5) from the bottom section means (left, 50% wide, bottom, 50% tall))" ....
..50% wide???

To clarify, do (0.0, 0.5, 1.0, 0.5) means

  • 0.0 =x is the left border of the screen
  • 0.5 = y starts from half the height
  • 1.0 = w = 100% wide?
  • 0.5 = h = height 50%?

Thanks for your quick answer.

@ssokolow
Copy link
Owner

Yes, your interpretation of (0.0, 0.5, 1.0, 0.5) is correct.

As for the two types of layouts you want, I'm still not sure I understand. What I was asking for (but too tired to ask for properly) was an explanation of exactly what should happen for each keybind.

As is, I don't know the answers to questions like: "Do you want to be able to put more than three windows side-by-side? If so, how do you want to deal with the fact that the numeric keypad doesn't have that many columns?"

@boussou
Copy link
Author

boussou commented Dec 22, 2015

Ah, easy answer, I use only laptops - no keypad ;-)

so my idea is to use the top number keys. (or Fx keys maybe?)

@senorsmile
Copy link

(a possible recommendation... please ignore if not helpful as I do not yet
have a 4k display) One of the things that I do is change the binding from
num keys to the keys:

u i o
j k l
m , .

This allows me to have the same keys on a laptop without a number pad as I
do on a regular keyboard. This could easily be extended to cover more keys
to have multiple possibilities on the screen. E.g.

y u i o p
h j k l ;
n m , . /

On Mon, Dec 21, 2015 at 4:15 PM Stephan Sokolow notifications@github.com
wrote:

Yes, your interpretation of (0.0, 0.5, 1.0, 0.5) is correct.

As for the two types of layouts you want, I'm still not sure I understand.
What I was asking for (but too tired to ask for properly) was an
explanation of exactly what should happen for each keybind.

As is, I don't know the answers to questions like: "Do you want to be able
to put more than three windows side-by-side? If so, how do you want to deal
with the fact that the numeric keypad doesn't have that many columns?"


Reply to this email directly or view it on GitHub
#60 (comment).

@ssokolow
Copy link
Owner

It's not so much the keys I need to know about (those are easy to set in ~/.config/quicktile.cfg) but, rather, how you want to actually map the grid.

You just clarified that you want five columns in the full sense of the word. I'll assume you also want more rows in the full sense of the word. (I currently use a 3840x1024 desktop spanned across three 19" monitors, so I rely on Ctrl+Alt+KP_Enter, but I did do the research for a 4K display. One 4K display at 49" would have size and pixel density equivalent to a 3x2 grid of 19" monitors.)

I'm starting to generalize the code for your use case and I'll have something for you to look at in a bit.

@ssokolow
Copy link
Owner

Ok, take a look at commit c4f1300. I haven't yet added an easy way to define (x, y) for more than three columns, but I've added a COLUMN_COUNT constant and editing it will adjust the number of width steps for more than 3 columns.

(COLUMN_COUNT is a constant because, currently, commands are defined before the config file is read and I wanted to push something for you to look at as quickly as reasonably possible.)

@boussou
Copy link
Author

boussou commented Dec 22, 2015

that is exactly what I wanted.
Thanks!
It works perfectly, I tried it with key mapping as @senorsmile suggested.

Now quicktile is the only tool around that works in large screen.

Some ideas & suggestions:

  • I think the best value for COLUMN_COUNT is 6 or 7. I am starting with 7 and wil see how it "feels"
  • IMHO, when cycling, there are width size that are not useful. I mean when size is wider than half the screen, you will never need windows so wide. But it is not a problem at all, the behavior is "logical" after all.

other thoughts for future releases:

  • It would be nice to have some way to map 7 keys to the 7 columns directly
  • it would be nice to have a way to split the height in more rows (5 I think) too

I think the "grid" 3x3 should be replaced by a grid of 7x5 on wide screens.

But for my personal need, I don't need more than this change.
Thanks again

@ssokolow
Copy link
Owner

Mapping keys to the seven columns and adding support for more rows is the "part 2" I didn't have time for now.

When I have time to move COLUMN_COUNT into quicktile.cfg and add properly generic support for defining keybinds, my plan is to generate default values based on the dimensions of the screen.

I'm not yet sure what form it will take, but once I have time to design a new, JSON-based config file format, I'll look into adding support for per-monitor tiling grids so each monitor can have the columns most suited to it.

(I also want to completely re-architect how columns and rows are handled so that I can implement keys to shrink/grow the current window's column/row and have all of the other windows adjust to match.

@boussou
Copy link
Author

boussou commented Dec 22, 2015

careful not to turn this program into a bloatware :-)

After a short time of use, finally I think that beeing able to target the other columns becomes necessary.

A suggestion: I think the grid cells should be named like in excel, A1 to G1 (7 columns of 1rst row).
Then I expect there would be a lot of changes to do like ie:

Line 105:

GRAVITIES = {
    'top-left': (0.0, 0.0),
    'top': (0.5, 0.0),
    'top-right': (1.0, 0.0),
    'left': (0.0, 0.5),
    'middle': (0.5, 0.5),
    'right': (1.0, 0.5),

    'A': (1/7, 0.5),
    'B': (2/7, 0.5),
    'C': (3/7, 0.5),
    'D': (4/7, 0.5),
    'E': (5/7, 0.5),
    'F': (6/7, 0.5),
    'G': (7/7, 0.5),

below

for grav in ('A', 'B', 'C', 'D', 'E', 'F', 'G'): 
 #--> instead of "for grav in ('left', 'right'):"
     POSITIONS[grav] = [gv(width, 1, grav) for width in corner_steps]

etc.
If I understand correctly reading the code, the current gravity names (eg "top-left") could coexist with other new ones (eg "A1")?

@ssokolow
Copy link
Owner

It doesn't work that way for two reasons:

  1. Those names like left and right are used in keybindings and the external API and predate things like gv = GravityLayout() by quite a while. If you rename them (rather than making copies), then everyone's quicktile.cfg will break, as will any scripts which use the command-line or D-Bus APIs.
  2. Note that grav is being fed into gv() as the third argument. That determines which point on the window to use as a point of reference for positioning and corresponds to one of the nine X11 window gravities. (gv() has other arguments for specifying x and y but you can omit them if they're the same as the gravity.)

Also, using Excel-style coordinates doesn't really gain anything over using integer (col, row) tuples and complicates things elsewhere because, for dynamic generation, you need routines to translate back and forth between letters and numbers.

@boussou
Copy link
Author

boussou commented Dec 22, 2015

Understood.
How would you name the cells like below?
(generated via http://www.tablesgenerator.com/markdown_tables)

| A1 | B1 | C1 | D1 | E1 | F1 | G1 |
|----|----|----|----|----|----|----|
| A2 | B2 | C2 | D2 | E2 | F2 | G2 |
|----|----|----|----|----|----|----|
| A3 | B3 | C3 | D3 | E3 | F3 | G3 |

Currently if I can get at least smthing like this working that would be perfect++ :

| A  | B  | C  | D  | E  | F  | G  |
|    |    |    |    |    |    |    |
|    |    |    |    |    |    |    |
|    |    |    |    |    |    |    |
|    |    |    |    |    |    |    |
|    |    |    |    |    |    |    |

and as a dream far away a 2/3rd layout ;-)

| A1 | B1 | C1 | D1 | E1 | F1 | G1 |
|    |    |    |    |    |    |    |
|    |    |    |    |    |    |    |
|----|----|----|----|----|----|----|
| A3 | B3 | C3 | D3 | E3 | F3 | G3 |

@ssokolow
Copy link
Owner

In my implementation, I'd write a new command which can take arguments and then, to tile for the cell you call B3, I'd bind a key to reposition-to-grid 2 3.

That way, I don't need to either favour one person's set of positions or flood --help with every possible position because each position is its own command.

If you don't mind your --help output being cluttered up, here is an attempt at code to define the commands you want (I'm very sleepy, so I don't have time to test it):

    ROW_COUNT = 3
    row_height = 1.0 / ROW_COUNT

    # Start the cycle at the width of one cell, rather than 50% or 100%
    cell_steps = (col_width,) + cycle_steps

    # Generate a string of letters that we can index into for column names
    colnames = ''.join((chr(x) for x in range(65, 65 + COLUMN_COUNT)))

    # Generate a command for each cell...
    for col in range(0, COLUMN_COUNT):
        for row in range(0, ROW_COUNT):
            # Each command will be named after an Excel-style cell coordinate
            POSITIONS['%s%d' % (colnames[col], row)] = [
                # gv(width, height, gravity, x, y)
                # "gravity" determines where on the window (x, y) refers to.
                gv(width, row_height * row, 'top-left', col_width * col, row_height * row)
                for width in cell_steps]

@boussou
Copy link
Author

boussou commented Dec 22, 2015

The way you state it sounds easy to understand.
and regarding the help display, "less is more" ;-)
So it is fine for me.

Thanks for you help, I we were near I would offer you a beer or 2 ;-)

@ssokolow
Copy link
Owner

chuckle I've never seen the appeal to alcohol, nor to bitter drinks, but thanks anyway.

@ssokolow
Copy link
Owner

I'll leave this open as a reminder to myself.

@ssokolow
Copy link
Owner

Just so you know, I'm finally back to working on this and I'm in the process of making the layout more adaptable.

So far, I've added a ColumnCount config key which allows you to easily change the number of columns... but there's a bug that makes the left/right edge commands still only cycle through three steps which I still need to track down.

Also, be aware that, in order to make it easier to work on QuickTile, I split it up into multiple files so you'll need to re-read the install instructions. (Don't worry. I kept the "copy into place" install option... it's just slightly different.)

@ssokolow
Copy link
Owner

Ok, the fix for #20 should have also fixed the cycling bug. :)

@boussou
Copy link
Author

boussou commented Aug 23, 2017

Great.
I'm still using your awesome tool, i'll check that asap ;-)

@ssokolow
Copy link
Owner

ssokolow commented Jan 24, 2020

In case you're interested in trying it out, the GTK 3 port that I'll be working toward a fix for this on is available in the gtk3_port branch now.

I still need to fix regressions #107 and #108 before it'll be at parity with the GTK+ 2 version, but it's already got much cleaner internals and a growing suite of automated tests.

Just don't use the pip3 URL from its README. That'll point to the GTK+ 2.x version until the port gets merged into master.

@ssokolow
Copy link
Owner

Note to Self: See also discussion on #99.

@boussou
Copy link
Author

boussou commented Jan 24, 2020

I myself don't know anything about Python, so I will wait until the setup is easy.

@ssokolow
Copy link
Owner

It's no more difficult than with QuickTile for GTK+ 2.x. If you're on Debian, Ubuntu, Mint, or Fedora, I can give you trivially simple instructions.

(The same instructions will be in the README and on the site once I finish the new manual.)

@ssokolow ssokolow added this to the JSON Config milestone Aug 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants