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
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
|
Highlevel overview:
Tablet rotation things
only when there is a tablet attached.
Here is the OS X Display menu:
Detect Displays
Turn on mirroring
--------------------------
SyncMaster
- 1280 x 1024, 60 Hz, Millions
- 1344 x ...
--------------------------------
Color LCD
- 1024 x 1024 ...
--------------------------
Displays Preferences
Color LCD means "laptop panel".
- GTK+ work.
Allow applications to be notified whenever monitors are added
or removed. Allow applications to get more detailed
information about the connected monitors.
The main complication is that XRRGetScreenResources() is very
slow. We could call it only when the X server sends an event,
but it's not desirable to have every application freeze for
half a second. And certainly not desirable to have the X
server block for n * 0.5 seconds.
With the X server work below we should be fine just calling
XRRGetScreenResources on startup and in response to events.
- X server work:
X server needs to poll for whether a monitor is plugged
in. Whenever it detects a change, it should do an EDID query,
and cache the resulting information. That way XRRGetScreenResources()
can be the speed of a normal roundtrip. It's desirable that
normal client requests can still be processed during the EDID
querying, but only a nice-to-have.
Drivers need to work reliably. There could be substantial work
here. For F9, possibly only the Intel driver can be made to
work.
Interrupts and events must be generated whenever something changes
about the outputs, if necessary by polling.
Events must be emitted whenever something changes, including when
the reason for the change is a manual change.
The maximum framebuffer must be dynamically changable.
- Control panel work:
Capplet needs to be written. The main complications:
- It needs to pay attention to events from the X server
and update itself, ie., add show new monitors if they become
available when the applet is shown.
- It needs to store information under a key computed
from a monitor identifier. The complication here is that
it's not completely clear how to do this in GConf.
- Would probably be worthwhile to drop libgnome/libgnomeui from
the craplets.
- Metacity work:
- Metacity is already Xinerama aware, but it needs to update itself
when monitors come and go.
- GNOME panel work:
- Is already Xinerama aware, but needs to listen and update itself
when monitors change.
- Evince work:
- Make sure it deals sensibly with multiple monitors
- OpenOffice work:
- Make sure it deals sensibly with multiple monitors
- An Xlib call to just return all the available information would be
useful. At the moment we have to do a bunch of roundtrips to
get the information. This is a would-be-nice though.
- A dbus service could be written that pops up the applet whenever a
monitor. It should only pop up if the new monitor is unknown. This
is at best a nice-to-have, and low priority in my opinion.
******************* Metacity
Havoc:
> I was just talking to bryan about this and "helping" him design it ;-)
> But I wanted to be sure and lobby for a fix window managers
> need. Basically right now the WM can't tell "physical" from
> "logical" monitors.
> A "logical" monitor is a desktop; it has its own panel, windows
> maximize to it, etc.
> A "physical" monitor is a piece of hardware.
> Sometimes people want to combine physical monitors into a video wall
> or just two monitors treated as one. Or at least a couple of noisy
> people in bugzilla want to do this.
> When people talk about a "Xinerama aware" app or WM they usually
> mean that all physical monitors are treated as logical monitors,
> while lack of Xinerama-aware means treating the entire X screen (all
> physical monitors) as one logical monitor.
> The problem is that the setting for "ignore Xinerama" or "don't be
> Xinerama aware" should be global to the desktop (GTK, all apps, WM)
> and should not be a window manager setting.
> Bryan thought people who wanted non-Xinerama-aware should just use
> fvwm, which may be right, but what I'd say is that if there is any
> setting for this, it should be desktop-global and in this monitor
> config dialog.
> It should not be a metacity or Compiz option, but in some way an X
> option in short. The implementation could be either an X server
> feature or an EWMH hint or whatever, but it should be controlled by
> the monitor config dialog and used by apps, GTK, etc. in addition to
> used by the WM.
> People tend to insist this should be a WM option, but that's just
> busted, since GTK and apps also have Xinerama-awareness features.
******************* EDID
edid-decode enhancements:
- Rejects years <= 0x0f for all versions, but this should only be done
for monitors claiming conformance to 1.4 (since 1.4 was released in
2006). A monitor produced in 2005 should have 0x0f - it's the only
reasonable thing to do.
- Uses 0x80 as the conformance mask for 1.4, should be 0
- Should read from stdin
- Should parse xrandr -verbose output more robustly
- Color depth computation is wrong. It uses the formula
(edid[0x14] >> 3) + 2
The correct formula to use is
(edid[0x14] & 0x70) >> 3 + 4
-
-=-=-=-
Computing a display name from EDID information:
vendor = lookup_vendor (code);
if (dsc_product && !is_gobbledigook (dsc_product))
{
if (vendor && !fuzzy_string_search (vendor, dsc_product))
prepend (vendor);
}
else
{
if (vendor)
append (vendor);
else
append ("Unknown");
}
if (has size)
{
convert_to_inches()
append (" %d\"", inches)
}
(Does this internationalize at all)?
We also need the ability to get laptop names. The laptop panel may report
a manufacturer that has nothing to do with the laptop manufacturer.
Needed XRandr output properties:
- Modes that the monitor supports, or enough information that the
client can go throught the list of modes for the relevant
CRTC/Outputs and filter those out that the monitor can't support.
- The preferred mode, if any. Also useful if we could get a "strongly
preferred" indication if it's an LCD with a fixed resolution.
- Sufficient information that a fairly specific identifier can be
computed. The algorithm the client should use is:
1 Have we seen exactly this monitor before? If yes, use
settings for that.
2 Have we seen a monitor with similar specs before? If yes,
use settings for that. (But don't save, unless the user
changes the settings).
3 Otherwise, use some reasonable default for the monitor and
save it.
A setting should only be used if the CRTC/Output allows it. Ie,. if
a user has installed a new video card, then previously-used settings
may no longer apply, so this must be checked every time.
(1) Implies that we really need a globally unique identifier for
monitors. (2) is useful in an enterprise setting, but not absolutely
critical, since (3) would still handle the majority of cases.
There is a question here: Where are machine specific preferences
stored? Havoc mentions three possibilities here:
http://mail.gnome.org/archives/gnomecc-list/2001-October/msg00023.html
I'm not sure if any of them are implementable at this point. Also
(1) may mostly take care of the problem.
Usecases:
1. Fixed setup with some number of monitors.
- They should be set to the correct mode on login.
Note that this involves setting the right position in the
framebuffer too.
What if someone swaps two monitors? Users are going to expect
that the images will switch position.
2. Laptop being moved between home and work
- Setups should be detected and the correct mode set, at least on
login, but ideally when you put the laptop into the docking
station.
3. Laptop gets projector plugged in.
Note the same model monitor can be used in two different ways. Ie.,
at home, it's being used at one resolution, at work the same type of
monitor is used at a different resolution.
Simple solution:
- The on-disk database is just a list of monitors. Each monitor has an
associated mode. This has these problems:
- If someone uses the same monitor model in two different ways.
- If someone swaps the monitors around
Better solution
- The on-disk database is a list of configurations, where a
configuration is a list of monitors and what outputs they are
connected to, and the position in the framebuffer.
- Picking a default configuration is then a matter of selecting the
closest existing configuration from the database.
- If the stored configuration is a subset of the existing,
then use that - then pick the best mode available for the
rest of the monitors
- If the stored configuration is a superset of the existing,
then use the projection of the configuration onto the monitors.
- Pick the configuration with the most overlap in monitors.
Although, if a configuration differs only in what outputs
they are connected to, then those outputs should probably
get their original modes set.
- Or maybe simply:
- If there is an exact match, use it, if not, pick a default.
- Picking a new default must never change the mode of any existing
output.
******************* Capplet
Somehow the applet will find out that a new monitor is plugged in
(either through notification, or through a refresh button). When this
happens, this monitor is looked up in a database and if it is found,
some suitable mode is set.
Restrictions on the modes:
- Monitors that are already plugged in should not get their mode
changed just because a new monitor is plugged in.
- If the exact configuration of monitors is known, and all the old
monitors have the same mode as the known configuration, then just use
the known configuration. Also do this, if the configuration is a
subset of something known.
- Otherwise, if the configuration is a subset of a known configuration
where the only difference is that existing monitors have different
modes, then try and convert that mode to something we can know
about. Maybe configurations should be stored in terms of edges that
line up.
- Otherwise, just pick some good default for the mode, probably based
on the EDID prferred mode if possible. By default cloning is
probably best.
- How do virtual desktops interact with this?
g-s-d:
- On startup
- It reads the configuration file into memory
capplet --configure
- It gathers the existing configuration from randr
- If the existing config is in the file, set that mode
- On changes, including changes to the config file [this is crack]
- Reread configuration file
- Compare new configuration to database, if it is there, set the
mode as appropriate
- If a monitor was added, pop up a bubble
capplet --show-bubble
capplet --set-mode
capplet
- On changes
- Update GUI
- When user changes something,
- Write configuration to file
- Signal gsd somehow
Schemes:
- configuration file changes
- randr code will have to be shared between gcc and gsd
- binary installed by gcc
- something will still have to listen for changes to pop
up the notification bubble.
Structure of capplet:
- There is a database on disk with monitors and their corresponding
settings.
- On startup, this database is read into memory. When the user accepts
new settings, it is written back to disk.
- When something changes about the settings
- If new configuration is in the database, use that mode
- Else, find all outputs that are now connected but weren't before,
and set a default mode for them.
- If GUI is running, update graphics.
- Notification thing:
- if
- if the new configuration is found in the database, use it
and added if they are not already there. Initial settings are
1 what the output is already doing, if anything
2 based on an existing sufficiently similar monitor, if possible
3 some reasonable default.
- When the user changes settings in the GUI, the corresponding monitor
in the database is updated.
- Whenever the GUI settings change, for all displayed monitors the
possible modes are recomputed.
- Whenever a new monitor is selected in the GUI, it first gets all its
possible modes computed based on the selections on other
outputs. Then, if the possible modes include the existing choice of
resolution, that is selected.
Actually,
- initially, the settings are copied from the current settings
- whenever a gui setting changes for a monitor, all the other
monitors get their list of choices set to whatever is possible
given the chocie for the current monitor. A 'desired mode' is
maintained, and the closest choice to that is displayed. Whenever
the user actively selects something, that becomes the desired mode
for that monitor.
- Required
- Generate all outputs that are newly connected
foreach_newly_connected (Configuration *before, Configuration *after,
OutputFunc);
- A way to generate the best mode for a connected output
existing best_mode() can probably be used
- Given a list of modes, pick the one closest to a given mode.
(a possibility here is: pick an exact match, if that's
impossible, then pick the best one with the same
width/height, if that's impossible, then just pick the
best mode on the list).
- For a configuation, fix the mode for a subset of the outputs, then
list the combinations for the rest of the outputs.
An obvious possibility here is to simply list all possibilities,
then weed out those that don't work. Is this too expensive?
It might be.
Structure of login time program:
- The configuration database is read
- The current hardware configuration is generated
- If the current configuration is found in the database, that mode is set.
- If it isn't found, then nothing changes.
This could just be gnome-screen-resolution-capplet --reset
******************* Things that need to be done to the xrandr.patch:
===
XRRGetScreenResources() is a roundtrip and very slow (~0.5 s). GTK+
needs to keep information up-to-date by tracking events rather than
calling this function. In fact we probably can't call it at all unless
its performance improves significantly.
If EDID processing really has to be this slow, and we can't get
interrupts when monitors are plugged in, then we have a problem,
because we can't do anything this expensive once per second.
Detailed notes (but most of the patch should be rewritten):
=== FIXME in gdkscreen-x11.c in get_width_mm()
/* monitor pixel width / screen pixel width * screen_physical width */
=== Check for 1.2 library
The patch should check that the 1.2 version of the XRandR library is
available before using the functions. A possibility is to not use any
RandR unless 1.2 is available, another is to conditionalize the code.
The most sane thing is probably to just require 1.2.
On the other hand, installing a newer gtk+ on a system with older X is
probably not that unusual, so maybe it's better to do the full 1.0,
vs. 1.1 vs 1.2 check.
For now it just requires 1.2.
Actually, this might be fine because the only place where we make use
of a 1.1 library is in the _gdk_x11_screen_size_changed() function,
but there we have a fallback that just updates the variables in the
Screen struct itself.
So, only defining HAVE_RANDR if we detect 1.2 should be ok.
=== Monitor information available
- Subpixel information. This should be set automatically for the fonts and
store under the name of the monitor. If the user changes the font
configuration, that change should also be stored under the monitor name.
- When a monitor we don't know about is plugged in, a configuration should
be generated:
- Screen size, computed based on the location of the screens
- RGBA information
- Whether the screen has a panel on it
- If there is a conflict between stored information and EDID,
the stored information wins
New API so far:
(* monitors_changed) signal
gdk_screen_get_monitor_width_mm()
gdk_screen_get_monitor_height_mm()
gdk_screen_get_monitor_name() => Note this is the output (eg. "DVI-0")
We should probably also have
get_manufacturer()
get_serial()
get_resolutions()
etc.
Should there be a GdkMonitor object that would correspond to an
output? Or maybe GdkOutput?
screen_list_monitors()
*************************** Issues XRandR/Xserver
- We need polling in the X server, whenever something changes, X must
recompute the information and cache it, then send an event. Note the
situation where the user disconnects and reconnects a monitor within
the polling interval. The event could missed in that case since the polling
cannot do a full EDID query. Difficult to see a way around this.
Actually, DDC allows random access, so it should be possible to just
read theq vendor id and manufacturer codes. This can be done once a
second without a problem. The polling should be turned off in power
saving mode anyway.
- Driver work:
- Intel driver:
- EDID information is not reported for VGA when the output is not
turned on (i945 laptop).
- Screen size must be dynamically changable. (No xorg.conf changes
should be required).
- Make use of ACPI information when possible.
Adam has code on his freedesktop page.
- i830 laptop can be put in a state where XRandr reports that no
outputs are connected to a CRTC, but the panel is on.
- Plug in VGA
- xrandr --auto
- xrandr --output VGA --off
- run chk
- xrandr --verbose will now not report any outputs as turned on
- run chk again - all screens will be turned off
- Small Sun monitor - an 1152x921 mode is generated, but the
monitor doesn't handle that. The monitor itself only claims to
handle 1152x920. It doesn't look to me like there is anything
in the EDID information that would indicate that it could handle
1152x921.
This happens with a radeon as wellso it may be a bug in the
generic X server EDID parsing. The X server apparently
interpretes the standard timing 1152x920 as 1152x921.
This happens because the X server uses
hsize * 4 / 5
which gives 921 for 1152. By using
(hsize / 5) * 4
you get 920. The 66 Hz version can bet set, the 76 Hz mode gets
sync out of range. (Would be interesting to find out whether the
1152x920 ModeLine would allow the 76 Hz version to be set).
This is for the ATI driver as shipped in F8:
- XRRGetScreenResources() takes half a second.
- Adam has now removed a workaround that caused some of the slowdown.
- If a DVI monitor is disconnected, you get "Unknown" for connection
status.
- If a VGA monitor is plugged in, then EDID information is not
available, even after running xrandr --verbose. The monitor has
to be plugged in at driver startup time, apparently.
- Logging out and logging back in often results in some random mode being
set. We need mode selection to not be completely screwed up.
Currently it is.
- The set up at server startup needs to be fixed. *If* randr actually works,
then we might be able to do something sensible.
- We need to revisit the idea that many monitors have broken EDID data.
This may be less widespread than previously believed.
- It may be useful to return the connector names as identifiers instead
of relying on UTF-8 strings. Ie., have an enum
{ UNKNOWN, OTHER, DVI, VGA, HDMI, ..., }
in addition to the string. The difference between UNKNOWN and OTHER is that
UNKNOWN means the driver doesn't know, whereas OTHER means it is something
not listed in the enum (which could be listed in a later version).
- Mouse cursor should be confined to the visible area. (It is already, I think)
- It looks like EDID information is only available for one output
even though it is actually read according to the log file.
(nv, intel drivers)
*********************************
DONE:
Server work:
- i830 laptop incorrectly reports BadMatch when you configure the
CRTC to drive both VGA and LVDS with the 1024x768 mode that both
outputs can handle. (It should return 'failed' if it can't do
that). Same for i945 laptop. It seems as if the same CRTC can't
drive more than one output at the same time on Intel.
This was a client bug, but the documentation for SetCrtcConfig
should say that BadMatch will be returned if the outputs aren't
clones.
GTK+ patch is in now.
=== Add helper function
+ if (screen_x11->randr12)
+ {
+ XRRScreenResources *sr;
+ XRROutputInfo *output;
+ gchar *retval;
+
+ sr = XRRGetScreenResources ( screen_x11->xdisplay,
+ screen_x11->xroot_window );
+
+ output = XRRGetOutputInfo ( screen_x11->xdisplay,
+ sr,
+ (RROutput)screen_x11->act_outputs[monitor_num]
);
Might be worthwhile to factor this out into a
gdk_screen_get_output_info (screen, monitor_num)
helper function ?
Instead of cutting and pasting all over creation
* Calling XRRGetScreenResources all the time is not going to fly. It
takes hundreds of milliseconds ... Even if it didn't, it wouldn't
be acceptable to do all those roundtrips.
=== Some g_prints left
=== Version check
Should be (maj > 1) || (maj == 1 && min >= 2)
=== Grep for TODO
=== Setup XRRSelectInput()
You should call XRRSelectInput() at the same place where you are
calling XSelectInput() right now. The right place to handle the
XRandr events is the huge switch in gdkevents-x11.c:gdk_event_translate
Check out how other extension events are handled there, like
XKB, or XFixes.
=== Lots of variable naming issues, such as act_output and noutput
=== Needs to select the input, and hook it up to the signal
=== Add version markers to API
=== API to turn monitors on and off?
- DPMS not exposed through randr, maybe should be
- DPMS is presumably a property of either an
output or a CRTC. Logically it's an output.
- Need events when DPMS happens. Exposing the "screen saving on" on
dbus may not be good enough.
=== Why does init_multihead_support() start by freeing monitors and
outputs?
=== Do we disable Xinerama support entirely when 1.2 is in use?
=== We should expose information about what parts of the screen monitors
are viewing.
=== Make use of the EDID information?
-- details for X server --
In nv driver SorSetOutputProperty should return TRUE for unknown
properties. (Like the Intel driver does).
Detecting plugged in
- Periodically poll
-
- One ddc probe takes 5 ms, according to a comment in the intel
driver. Running this twice a second would mean spending 1% of
overall time doing ddc polling, which is almost certainly not
acceptable.
1) Async I2C:
void I2CProbeAsync(..., callback, data);
Bool I2CPending()
void I2CUpdate()
In Dispatch, call I2CUpdate()
Before going idle, do
while (I2CPending())
I2CUpdate()
Would need
RegisterDispatchFunction() (Is this called Wakeup?)
RegisterIdleFunction()
Note the idle function should have the option of saying:
"check if something else happened; if not, call me again" and
"ok, I'm done - go idle". Otherwise, we would be blocking for
5 ms whenever the X server went idle. So actually the idle
function should be
if (I2CPending())
{
I2CUpdate();
return TRUE; /* call me again */
}
else
{
return FALSE; /* I'm done */
}
What happens if another I2C requests come in while an async one
is pending? Most likely we simply finish whatever is going on,
then process the new request.
What happens if an X request takes so long that we get timeouts on
the i2c bus? Good question. Need to read the VESA ddc spec.
2) Run the polling in a separate thread.
Probably crack.
3) Run the polling less, maybe once every three seconds.
-- details for control panel --
Screen changes
- Currently it is polling via rw_screen_refresh(), which will always emit
a screen-changed event. In reponse to this event the capplet currently
checks whether anything changed physically about the setup. This means
the capplet can't react to external changes to modes. On the other hand
if it didn't
Disallow combinations that would exceed the screen ranges.
- Note rotations
Give rw objects stable positions in memory so that they can be cached
across screen_changed events.
Add Clone Mode
Drag and drop for the monitors
- 2 dimensional layout
Store make and model in monitors.xml, then if serial numbers don't
match, fall back to a make and model match. Users with an nfs mounted
home directory should not have to reconfigure for each new system they
log in to.
Make sure text is scaled correctly
Need to sanitize naming
RWOutput vs Output - should probably be OutputInfo
rate vs. freq - decide on one
Should probably reconsider the use of null terminated arrays.
Maybe lists would be better.
Pick a fixed scale, so that two 1024x768 don't look like two 6x4.
- An alternative would be to draw a checkerboard pattern
below the monitors.
done:
Add rotation
Disable panel checkbox for now
Patch into gnome-desktop
Find out how to share code between gcc and gsd
Make it assign coordinates correctly
- including computing correct screen size
|