summaryrefslogtreecommitdiff
path: root/constraints-ideas.txt
blob: 06b545a16bed4e3352a6fbda9a264d3e01310338 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
Short-term (I hope...) TODO list/reminders:

  - Need to update the documentation; the huge comment is out of date and
    misleading now

  - Quicklist that I thought of:
    - Titlebar onscreen func should use CLAMP(percent*width, 10, 75) for
      width and 2-3 pixels for height for checking if the titlebar is
      partially onscreen or not
    X on-single-xinerama constraint should not apply if only 1 xinerama
      exists
    X use CLAMP() macro in more places of constraints.c
    X Two of meta_window_move_resize_internal() calling methods in huge
      comment are actually the same; search for "bogus" and "BEFORE"
    X There may be a bug with gravity an onscreen constraints--it seems
      that creating a tab then removing it and repeating this a lot made
      the window drift northwest.  Very weird.
    - Get rid of compiling warnings for constraints.c even if they're dumb

  - Should we turn off fully-onscreen & on-single-xinerama constraints
    for decorationless windows?  Otherwise, most users (those that
    don't know about alt-drag to move or alt+f7 to keyboard move)
    won't be able to move xmms off their current xinerama onscreen
    space.  This might mean that users lose their window (dragging the
    top of the window too far offscreen), but that might be a required
    trade-off for having a stupid-app.

  - Brokenness left in aspect-ratio resizing:
    X gtk+ seems to be doing nit-picky fighting with us over which way to
      round the size.  This means that if the user increases the width of
      an aspect-ratio'ed window, we increase the height of the window in a
      way that keeps the center fixed, gtk+ doesn't like our selected size
      and sends a configure request, and then we resize the window to the
      configure request size using NorthWestGravity instead of
      WestGravity--resulting in the window drifting slightly either upward
      or downward.  Can also result in heavy flickering sometimes.  sucks.
      *UPDATE*: It wasn't gtk+ -- it was window.c:update_resize() causing
      all the flickering that I saw.  However, this configure request stuff
      doesn't appear to be the cause of the drift...
    - There's still a drift...
    - Interplay between various onscreen constraints is not very good
      (resizing should stop when any window edge hits the screen edge,
      instead of arbitrarily clipping that edge).  Similar problems
      probably occur for overlap with other constraints (do we care about
      the others, though?).
      ! Ought to be able to find intersection to any edge of screen (could
        be 3 sided, not just two) and determine the relevant box size for
        that.  Some care will be needed, e.g. for East/West/North/South
        gravity where some sides only get increase/2 amount of change
        instead of increase
    - Doesn't work well with fixed sides--if the aspect ratio needs to
      be enforced, then fixed_directsion should be set to 0.  (Also,
      fixed_directions should probably be reset to its former nonzero
      value if all constraints couldn't be satisfied
      simultaneously...)

  - edge resistance need not be much different than the current code that
    exists for the keyboard except that (a) only non-covered edges should
    count (same ought to be true for keyboard moving/resizing as well), (b)
    it'd be nice to have timeouts (think of two windows, A and B, separated
    by just a little less than the width of C--it may become really hard
    without timeouts to place C where it may be wanted), (c) we should add
    edge stickiness too, (d) it'd be nice to have the pixel-resistance and
    timeout-resistance be much larger for the screen edges, (e) it may be
    difficult determining where the screen edges are

  - Might be good to optimize by storing spanning rects in MetaWorkspace

  - Need to replace xinerama and screen structures (screen.h?) and maybe
    tabpopup stuff (see bug 98340, IIRC) with MetaRectangle's

  - Need to clean out lots of FIXMEs in the code.

  - Need to do the titlebar offscreen checking, partial maximization, etc.

  X It looks like I can nuke work_area_screen in ConstraintInfo

  X Do I need the include_frame parameter to get_size_limits() anymore?
    (Update: yes, do_screen_and_xinerama_relative_constraints() uses it)

  X Ought to rewrite adjust_for_gravity to do less and then just use
    meta_rectangle_resize_with_gravity()

  X Need to add a test_find_closest_linepoint to testboxes.c to test that
    function nice and thoroughly.

  X Ought to add a test_gravity_resize to testboxes.c, and use the new
    meta_rectangle_region_to_string(), and maybe move other printing stuff
    there.

  X Clicking on an XMMS window causes a failed assertion due to unfixed
    FIXME in meta_window_configure_request() (Problem was that we tried to
    call meta_window_move_resize_internal() on restack configure requests)

  X Once the window goes offscreen, clicking on the edge in order to resize
    results in all kinds of weirdness: clipping the window to the screen,
    sending the window totally and completely offscreen, or who knows what
    else.  Very odd.

  X Holy cow, constrain_aspect_ratio is ABSOLUTELY COMPLETELY BORKEN!!!

  X Trying to _move_ the window offscreen results in clipping.  Huh??
    Other weirdness afterwards happens too (keyboard resizing to the
    right went up and right)

  X Need to nuke old #ifdef'd out code

  X Need to make shove_into_rect use shortest distance in addition to
    maximal overlap (especially for totally offscreen case)

  X Need to add testboxes stuff to appropriate Makefile.am thingies

  X Okay the on-single-xinerama/fully-onscreen/partially-onscreen
    constraints aren't as simple as I thought, the boxes.[ch] is still the
    wrong way to go about it and doesn't cover everything needed, and I
    need something else big.  Ideas:
      X Get minimal set of (maximally) covering rects:
        - Start with relevant rect (screen/xinerama)
        - Foreach strut, divide each rect in the set into up to three rects
          (before-strut zone, overlap-strut zone, and after-strut zone)
          - Each new rect must not include the strut
          - If the strut begins where the original rect does, the
            before-strut zone can be ignored; similarly for ending location
            and after-strut zone.
          - For a top or bottom strut, the before and after zones are
            *just* horizontal shrinkages of the original rect while the
            overlap zone is *just* a vertical shrinkage of the original
            rect (do not make the mistake of horizontally shrinking the
            overlap zone in this case).  The left and right struts are
            similar in nature (vertical shrinkage for before and after,
            horizontal shrinkage for overlap)
      X Be careful not to move/clip in the wrong direction
        - For user move, one does not want to shove a rect vertically to
          force it fully onscreen if the user had only been moving the
          window horizontally--even if moving it vertically would result in
          less overall displacement.
        - To do this, need notion of fixed sides:
          - Move (App or user):
            - Horizontal: Top and bottom are fixed
            - Vertical: Left and right are fixed
            - Diagonal: No sides are fixed
          - User resize:
            - Uni-directional: All sides but the given direction are fixed
            - Bi-directional: The two other sides are fixed
          - App resize -- acts like move as far as side fixing
          - Move & resize -- unsure, perhaps no sides are fixed?
      X Regardless of clipping or shoving; there needs to be a good way to
        pick the best of the (maximally) covering rects into which to clip
        or shove.  
        - User resize (clip-into):
          - Entirely determined by
            greatest-area-conserved-when-clipping-unfixed-sides
        - User move or app move (shove-into):
          - Must be able to fit the rect, w/o changing fixed sides
          - Prefer greatest-overlap-before-shoving
          - Prefer short distance moves over long distance ones (this is
            only needed in special cases, such as a move that causes the
            window to be totally offscreen)
        - App resize or user or app move-resize:
          - May first need to clamp size down, then do user/app-move stuff
          - If clamping is needed, clamp to the size of the rectangle that
            preserves as much area in the rect as possible
            - Note: this does not mean picking the largest covering rect
            possible; it may be that the window is really long and skinny,
            there's a covering rect that's long and skinny but
            not-quite-long enough, and then another covering rect that is
            square and overall the largest but not very long.  In this
            case, the square rect should not be picked, because neither
            dimension of the window size should ever be increased.

    Extra notes:
      X Write a get_elijah_region() function, returning a GList*
        X elijah_region is defined as minimal set of possibly overlapping
          rectangles for a region with the property that a window is
          contained in the region iff it is contained in one of the
          rectangles
        X function should take: basic_rect (screen or xinerama), struts,
          extend_amount (0 for fully-onscreen or on-single-xinerama, but
          large relative-to-window amount for partially-onscreen
          constraints; extra amount might be 4x1 array for each of four
          directions)
      X Need to handle minimum size constraints in all this
      - The elijah_region thing would make is_titlebar_partially_onscreen()
        fairly easy to write (get the elijah_region, find the titlebar
        rect, do a whole bunch of intersection operations and see if we
        ever get an intersection area greater than some threshold like 0)

  X My aspect ratio resizing may still not work because perhaps
    closest-in-area should trump whenever one of the two is very far
    away in area (Think about grabbing the SE corner with the mouse,
    resizing way to the right, not letting go of the left mouse
    button, letting constraints catch up, then moving the mouse up
    slightly to shrink the window: That results in a big height
    reduction (since mouse position and window didn't align well), and
    a corresponding massive width reduction since the shrinking window
    stuff rules out the bigger of the two aspects).  Maybe
    closest-in-area should ust always trump--except for some extra
    slop for keyboard resizing?.

  X My attempts to do all contraints in terms of the outer window are
    mislead--most are actually relative to the inner window.
    Comparisons:
       constraint      window
       --------------- ------
       size_increments inner
       size_limits     inner
       maximization    outer
       fullscreen      inner
       aspect_ratio    inner
       onscreen        outer

  X Change documentation in constraints.c to target future maintainers
    first, then explain the basic ideas behind the algorithm and how
    it compares to the old method and why.

  X Need to add the require_fully_onscreen and require_on_single_xinerama
    flags and get them all initialized and everything

Extra window.h flags:
  require_fully_onscreen           (136307)
  vert_maximized, horiz_maximized  (113601)
  require_on_single_xinerama       (unfiled)

Bugs to fix:
  unfiled - constraints.c is overly complicated
  unfiled - constraints.c is not robust when all constraints cannot be met
  unfiled - document our treating of gravities with center as a
            size-increment constraint (or perhaps actually store the
            reference point and don't require the
            even-number-of-pixels in resize)
  unfiled - get_outermost_onscreen_positions is decoration-unaware
  unfiled - constraints.c documentation is difficult to understand
  142016, 143784 - should try to keep windows on a single xinerama
  109553  - gravity w/ simultaneous move & resize doesn't work
  113601  - maximize vert and horiz should toggle & be constrained
  122196  - windows show up under vertical panels
  143145  - clamp to screensize
  143145? - make appear on screen
  136307  - don't allow app resize off screen
            (unless minimum size hints?  No...too big windows are fully clamped)
  156699  - avoid struts when placing windows, if possible
  149867  - fixed aspect ratio windows are difficult to resize
            WARNING: nasty interaction with e.g. onscreen constraints in 2 dim's!
  312007  - snap-resize moves windows with minimium size constraint
  312104  - resize top causes bottom to grow
  144126  - fix stupid old method of strut handling

  Maybe:
    152898  - no way to move a window off the top of the screen
              (warning: requires cleverness as user can accidentally
              trigger alt+click moving; probably needs edge resistance
              and other work first)
    154706  - bouncing weirdness at screen edge w/ keyboard move or resize
    124582  - shift-arrow erroneously moves window multi-dimensionally
    122670  - jerky/random resizing of windows via keyboard
              (drop extra events -- not really needed)
     81704  - edge magnetism/resistance/snapping/etc.
    151842  - maximize to fill feature...
    302456  - dragging offscreen too restrictive
    308521  - better alt-middle-drag resizing

Some ideas:
  - move_rectangle_into_region & clip_rectangle_into_region in
    boxes.[ch] are way over-engineered; only need workarea &
    best-window-area (via modified form of
    get_outermost_onscreen_positions())
  - update_position_limits looks like stupidity without current crufty
    framework
  - get_mouse_deltas_for_resize() shouldn't be necessary (window.c)
  - adjust_for_gravity() ought to move to constraints.c, IMO

  - onscreen cases:
    - user resize: clip into valid region
    - user move: move window into (fully extended) valid region
    - user move & resize: someone lied about what's happening or who's doing it
    <All three below can be handled via the resize algorithm; extras are no-ops>
    - app resize: clamp to workarea size, move into it
    - app move: move into valid region
    - app move & resize: clamp to workarea size, then move into valid region

  - offscreen differences:
    - user resize: don't allow size increase of offscreen sides
    - user move: N/A (valid region extended to include offscreen in both cases)
    - user move & resize: N/A
    <All three below can be handled via the resize algorithm; extras are no-ops>
    - app resize, move, move&resize: same but with bigger region

Constraints in old constraints.c:
  - place the window (huh?), including maximization after placement
  - maximization constraints (both horiz & vert; window-size == workarea size)
  - fullscreen constraints (window-size == xinerama size)
  - desktop window constraints
  - titlebar onscreen constraints
  - min & max window size constraints (restore towards previous size)
  - resize increment constraints (no need for restoration here; but adjust imp.)
  - aspect ratio (geometric average of rects defined by x & y?)

  <should also add>
  - gravity
  - really onscreen
  - clamp to screen size

Add a rectangle calculus packages
  MetaRectangle  rectangle;
  GList*         region;  // list of rectangles

  gboolean rectangles_intersect
  gboolean region_contains_rectangle
  gboolean region_larger_than_rectangle
  void     move_rectangle_into_region
  void     clip_rectangle_into_region
           region_expand                // takes screen region, add 75 -> have
                                        // partially onscreen region contraint

  ** NOTE: Trying to resize at left should not move bigger window onscreen **
  ** NOTE: Resizing aspect ratio windows should resize to rect closest in
           size to the previous one **
  ** NOTE: Trying to resize minimum size window should attempt to restore
           window to previous position, not just resize to minimum size or
           else it could result in the window moving **
  ** NOTE: Might be good to consider gravity somehow; Havoc has test program **
  ** NOTE: Would probably be good to store optimal points, largest
           rectangle(s) (area-wise?) that will fit, and some other stuff
           that only changes when docks are added or removed... **
  ** NOTE: How does application specified placement interact with
           onscreen constraints? **

Enumeration:
  A simple enumeration with explicitly defined values, e.g.
  typedef enum
  {
    PRIORITY_MINIMUM=0,
    PRIORITY_ASPECT_RATIO=0,
    PRIORITY_CLAMP_TO_WORKAREA=1,
    PRIORITY_ENTIRELY_VISIBLE_ON_WORKAREA=1,
    PRIORITY_MEET_MINIMIMUM_SIZE_HINTS=2,
    PRIORITY_PARTIALLY_VISIBLE_ON_WORKAREA=3,
    PRIORITY_TITLEBAR_PARTIALLY_VISIBLE_ON_WORKAREA=3
    PRIORITY_MAXIMUM=3
  }

  Others: (large windows are auto-maximized, 
           maximized windows follow struts,
           fullscreen windows are screensize,
           desktop window is screensize,...)

Function form:
  gboolean
  meta_constrain_whatever (constraint_info info,
                           int priority,
                           gboolean check_only)
  {
    if (priority > PRIORITY_WHATEVER)
      return TRUE;

    if (check_only)
      {
        /* If constraints already satisfied return TRUE, otherwise FALSE */
      }

    /* Enforce constraints */

    return TRUE; /* Though this is ignored when check_only is FALSE */
  }

Extra sanity checking:
  It can be useful to define variables
    <some>_corner_fixed   (where <some> = ne, nw, se, or sw)
    window_size_fixed
  To verify that size or aspect ratio or placement constraints affect
  the correct variables

Advantages:
  - Easier to understand (can easily add/remove/reprioritize constraints)
  - Can handle multi-dimensional constraints such as aspect ratio
  - Can determine which constraints will be violated when there are too many
    - We can even log the fact that constraints will be violated

Minor disadvantage
  - We don't get enforced sanity, but sanity checking is fairly easy

Disadvantages:
  - Major code overhaul



Extra rationale:
  - fully-onscreen vs. strictly following PPosition hints
    Advantages:
    - users are annoyed when they can't see the whole window they are
      interacting with (note that this is why we raise on click too)
    - needed to fully fix placement with vertical panels (bug 122196)
    - needed to fully fix placement for accessibility with docks (bug
      156699)
    - can still benefit from PPosition by putting the window to the
      position as close as possible to the point specified that still
      satisfies the fully-onscreen constraint
    Disadvantages:
    - apps may be trying to place dialogs relative to some other UI in
      their main window, and it may annoy the users to have the windows not
      align exactly
    Other notes:
    - disable_workarounds totally ignores PPosition anyway
    - PPosition is already overridden for totally offscreen or titlebar
      offscreen cases (while keeping the window as close as possible to the
      specified position)
    - users should easily recognize why things don't align as they might
      expect (since the window aligns with the edge of the workarea);
      further, it shouldn't be too problematic as the window should be
      close to the specified location
    - users would still be allowed to manually move the window offscreen
      (see bug 136307 comment 16 for how this works)

  - keep-on-single-xinerama vs. strictly following PPosition hints
    Advantages:
    - users are annoyed when windows are split across xineramas
    - can still benefit from PPosition by putting the window to the
      position as close as possible to the point specified that still
      satisfies the fully-onscreen constraint
    - is consistent with fully-onscreen overriding strictly following
      PPosition
    Disadvantages:
    - apps may be trying to place dialogs relative to some other UI in
      their main window, and it may annoy the users to have the
      windows not exactly align
    Other notes:
    - disable_workarounds totally ignores PPosition anyway
    - PPosition is already overridden for totally offscreen or titlebar
      offscreen cases (while keeping the window as close as possible to the
      specified position)
    - users should easily recognize why things don't align as they might
      expect (since the window aligns with the edge of a monitor); further,
      it shouldn't be too problematic as the window should be close to the
      specified location
    - users would still be allowed to manually move windows to an area
      spanning multiple xineramas (see bug 136307 comment 16 for the idea
      of how this works; it extends to the on-single-xinerama case easily).
    - This constraint should probably not apply for windows with a parent
      that spans multiple xineramas, unless that parent is a DESKTOP or
      DOCK window.
    Question:
    - Should this constraint resize windows to make them fit?  (I'm
      thinking no--but if it should for the general case, DESKTOP and DOCKS
      will need to be exceptions)


General notes on the rewrite:
  Old comments on how to do the rewrite and how it used to work (wish I would
  have seen all these before I embarked on the project...):
    http://bugzilla.gnome.org/show_bug.cgi?id=106740#c62
    http://bugzilla.gnome.org/show_bug.cgi?id=106740#c75
    http://bugzilla.gnome.org/show_bug.cgi?id=106740#c101
    http://bugzilla.gnome.org/show_bug.cgi?id=123838#c2

  Havoc considers the current implementation broken:
    http://log.ometer.com/2004-05.html
    http://bugzilla.gnome.org/show_bug.cgi?id=136307#c20
    http://bugzilla.gnome.org/show_bug.cgi?id=152898#c2
    http://bugzilla.gnome.org/show_bug.cgi?id=152898#c7
    http://bugzilla.gnome.org/show_bug.cgi?id=130834#c1
    http://bugzilla.gnome.org/show_bug.cgi?id=126872#c1
    http://bugzilla.gnome.org/show_bug.cgi?id=116601#c1

  ...to the point that he's more or less admitted he's unwilling to
  review patches for it:
    http://bugzilla.gnome.org/show_bug.cgi?id=136307#c18

  Havoc wants it rewritten:
    http://bugzilla.gnome.org/show_bug.cgi?id=149867#c2

  Note that I'm not referring to this earlier rewrite:
    http://bugzilla.gnome.org/show_bug.cgi?id=107010