Projects/Plasma/ScreenManagement: Difference between revisions

From KDE TechBase
(Added some ideas about possible API and behaviour)
m (Changed the xml to the current state of development.)
Line 9: Line 9:


The configuration for this might look like the following. The ideal solution would be to agree with the Gnome-folks on one config-spec.
The configuration for this might look like the following. The ideal solution would be to agree with the Gnome-folks on one config-spec.
This is just a real quick, first draft, so feel free to comment as much as you feel like!
This is actually the xml as used by the current implementation (rev 856215).


<code xml>
<code xml>
<configuration name="single">
<configuration name="single" modifiable="false" primary="0">
     <screen id="0">
     <screen id="0">
     </screen>
     </screen>
</configuration>
</configuration>
<configuration name="presentation">
<configuration name="presentation" modifiable="false" primary="0">
     <screen id="0">
     <screen id="0">
     </screen>
     </screen>
Line 24: Line 24:
     </screen>
     </screen>
</configuration>
</configuration>
<configuration name="extended-right">
<configuration name="extended-right" modifiable="false" primary="0">
     <screen id="0">
     <screen id="0">
     </screen>
     </screen>
     <screen id="1">
     <screen id="1">
         <right-of>0</right-of>
         <right-of>0</right-of>
    </screen>
</configuration>
<configuration name="clone">
    <screen id="0">
    </screen>
    <screen id="1">
        <clone-of>0</clone-of>
     </screen>
     </screen>
</configuration>
</configuration>
Line 48: Line 41:
         <width>1280</width>
         <width>1280</width>
         <height>800</height>
         <height>800</height>
         <rate>60</rate>
         <refresh-rate>60</refresh-rate>
         <rotation>normal</rotation>
         <rotation>0</rotation>
         <reflect_x>no</reflect_x>
         <reflect-x>no</reflect-x>
         <reflect_y>no</reflect_y>
         <reflect-y>no</reflect-y>
     </output>
     </output>
     <output name="VGA">
     <output name="VGA">
Line 65: Line 58:
         <width>1280</width>
         <width>1280</width>
         <height>800</height>
         <height>800</height>
         <rate>60</rate>
         <refresh-rate>60</refresh-rate>
         <rotation>normal</rotation>
         <rotation>normal</rotation>
         <reflect_x>no</reflect_x>
         <reflect-x>no</reflect-x>
         <reflect_y>no</reflect_y>
         <reflect-y>no</reflect-y>
     </output>
     </output>
     <output name="VGA" screen="1">
     <output name="VGA" screen="1">
Line 76: Line 69:
         <width>1024</width>
         <width>1024</width>
         <height>768</height>
         <height>768</height>
         <rate>60</rate>
         <refresh-rate>60</refresh-rate>
         <rotation>normal</rotation>
         <rotation>normal</rotation>
         <reflect_x>no</reflect_x>
         <reflect-x>no</reflect-x>
         <reflect_y>no</reflect_y>
         <reflect-y>no</reflect-y>
     </output>
     </output>
</outputs>
</outputs>
Line 89: Line 82:
         <width>1680</width>
         <width>1680</width>
         <height>1050</height>
         <height>1050</height>
         <rate>60</rate>
         <refresh-rate>60</refresh-rate>
         <rotation>normal</rotation>
         <rotation>normal</rotation>
         <reflect_x>no</reflect_x>
         <reflect-x>no</reflect-x>
         <reflect_y>no</reflect_y>
         <reflect-y>no</reflect-y>
     </output>
     </output>
     <output name="LVDS" screen="1">
     <output name="LVDS" screen="1">
Line 100: Line 93:
         <width>1280</width>
         <width>1280</width>
         <height>800</height>
         <height>800</height>
         <rate>60</rate>
         <refresh-rate>60</refresh-rate>
         <rotation>normal</rotation>
         <rotation>normal</rotation>
         <reflect_x>no</reflect_x>
         <reflect-x>no</reflect-x>
         <reflect_y>no</reflect_y>
         <reflect-y>no</reflect-y>
     </output>
     </output>
     <output name="VGA">
     <output name="VGA">
Line 114: Line 107:
* The naming is basically just supposed to reflect the naming in xrandr.
* The naming is basically just supposed to reflect the naming in xrandr.
* The element <privacy>true</privacy> should inform the window-manager not to open any windows on that screen, as it would be a little annoying if any notification of new messages or similar would pop up on the projector during a presentation.
* The element <privacy>true</privacy> should inform the window-manager not to open any windows on that screen, as it would be a little annoying if any notification of new messages or similar would pop up on the projector during a presentation.
* The screen "0" should always be the primary screen.
* The numbering of the screens is important for ie Plasma to load up the right Containment on the right screen.
* The numbering of the screens is important for ie Plasma to load up the right Containment on the right screen.
* configurations marked as modifiable=false can not be altered, if the user wants to change the positions of the screens another (matching) configuration will be loaded instead


What this leaves open for now:
What this leaves open for now:
Line 121: Line 114:
* What set of configurations will be shipped?
* What set of configurations will be shipped?
* Will it be possible create new configurations for the user?
* Will it be possible create new configurations for the user?
* Will it be possible to change or even delete shipped configurations?
* When the user selects to change the positions of his screens, should this switch or modify the configuration?


==== Defaults ====
==== Defaults ====

Revision as of 11:35, 2 September 2008

Architecture

The management of multiple screens and hot-plug thereof will make extensive use of XRandR 1.2, there should be a fallback mechanism for systems not supporting it though. For the client (ie Plasma, but also others) this should be completely transparent, so the API needs to be designed to be able to give all information it can get, but also act sensible when there is little or no information about the screen configuration available.

The system should offer a set of configurations/profiles which will be autoselected depending on the pugged devices. Clients should be able to easily change the used configuration, which will then be remembered for the next time these devices are plugged in.

Configuration

The configuration for this might look like the following. The ideal solution would be to agree with the Gnome-folks on one config-spec. This is actually the xml as used by the current implementation (rev 856215).

<configuration name="single" modifiable="false" primary="0">

   <screen id="0">
   </screen>

</configuration> <configuration name="presentation" modifiable="false" primary="0">

   <screen id="0">
   </screen>
   <screen id="1">
       <privacy>true</privacy>
       <right-of>0</right-of>
   </screen>

</configuration> <configuration name="extended-right" modifiable="false" primary="0">

   <screen id="0">
   </screen>
   <screen id="1">
       <right-of>0</right-of>
   </screen>

</configuration>

<outputs configuration="single">

   <output name="TMDS-1">
   </output>
   <output name="LVDS" screen="0">
       <vendor>X</vendor>
       <product>0x1234</product>
       <serial>0x12345678</serial>
       <width>1280</width>
       <height>800</height>
       <refresh-rate>60</refresh-rate>
       <rotation>0</rotation>
       <reflect-x>no</reflect-x>
       <reflect-y>no</reflect-y>
   </output>
   <output name="VGA">
   </output>

</outputs> <outputs configuration="presentation">

   <output name="TMDS-1">
   </output>
   <output name="LVDS" screen="0">
       <vendor>X</vendor>
       <product>0x1234</product>
       <serial>0x12345678</serial>
       <width>1280</width>
       <height>800</height>
       <refresh-rate>60</refresh-rate>
       <rotation>normal</rotation>
       <reflect-x>no</reflect-x>
       <reflect-y>no</reflect-y>
   </output>
   <output name="VGA" screen="1">
       <vendor>Y</vendor>
       <product>0x9876</product>
       <serial>0x98765432</serial>
       <width>1024</width>
       <height>768</height>
       <refresh-rate>60</refresh-rate>
       <rotation>normal</rotation>
       <reflect-x>no</reflect-x>
       <reflect-y>no</reflect-y>
   </output>

</outputs> <outputs configuration="extended-right">

   <output name="TMDS-1" screen="0">
       <vendor>Z</vendor>
       <product>0xABCD</product>
       <serial>0xABCDEF01</serial>
       <width>1680</width>
       <height>1050</height>
       <refresh-rate>60</refresh-rate>
       <rotation>normal</rotation>
       <reflect-x>no</reflect-x>
       <reflect-y>no</reflect-y>
   </output>
   <output name="LVDS" screen="1">
       <vendor>X</vendor>
       <product>0x1234</product>
       <serial>0x12345678</serial>
       <width>1280</width>
       <height>800</height>
       <refresh-rate>60</refresh-rate>
       <rotation>normal</rotation>
       <reflect-x>no</reflect-x>
       <reflect-y>no</reflect-y>
   </output>
   <output name="VGA">
   </output>

</outputs>

Most of this should be rather self-explanatory (at least to me ;-) ). Just a few quick explanations:

  • The naming is basically just supposed to reflect the naming in xrandr.
  • The element <privacy>true</privacy> should inform the window-manager not to open any windows on that screen, as it would be a little annoying if any notification of new messages or similar would pop up on the projector during a presentation.
  • The numbering of the screens is important for ie Plasma to load up the right Containment on the right screen.
  • configurations marked as modifiable=false can not be altered, if the user wants to change the positions of the screens another (matching) configuration will be loaded instead

What this leaves open for now:

  • What set of configurations will be shipped?
  • Will it be possible create new configurations for the user?

Defaults

If it's possible to detect the type of plugged device, ie projector or plasma-tv ;-) the configuration could be extended to include defaults like this:

<outputs configuration="presentation">

   <output name="LVDS" output="0">
       <type>*</type>
   </output>
   <output name="*" output="1">
       <type>projector</type>
   </output>

</outputs>

Forcing outputs

For setups where the hardware/driver can not detect a device to be plugged in it might be necessary to force a certain output to be activated and to some mode. That could look like:

<configuration name="tv">

   <screen id="0">
   </screen>
   <screen id="1" force="composite">
       <privacy>true</privacy>
       <right-of>0</right-of>
   </screen>

</configuration>

<force name="composite" output="Composite">

   <width>768</width>
   <height>576</height>
   <rate>50</rate>
   <rotation>normal</rotation>
   <reflect_x>no</reflect_x>
   <reflect_y>no</reflect_y>

</force>

This could of course not be auto-selected, but would make it a lot easier for user to activate devices if needed.


Base-Component

There should be a base-component, that will take care of the followings tasks:

  • On startup check the connected devices and select a matching configuration.
  • Publish informations such as primary or private
  • Listen to XRandR events and switch configurations accordingly.
  • Allow clients to select for what kind of events they want to be notified
    • Screen added/removed
    • Screen resized
    • Screen position changed
    • Rate changed
  • Dispatch notifications to the clients
  • Allow clients to change the selected configuration

This component should be able to fallback to XRandR 1.1/Xinerama if XRandR 1.2 is not available. Maybe it should even be able to fallback to using Qt's QDesktopWidget as its only source for information, that should allow this component to be used on all platforms. In that situation there would be no modifications possible, but it might still be interesting for applications that need to be informed of some screen-events.


API / Library

The functionality of the base-component should be transparently provided by a qt-style library. A quick first draft of the provided API would be this:

Configurations

QList<Configuration> getAllConfigurations(); Configuration getActiveConfiguration(); void activateConfiguration(Configuration c);

void removeConfiguration(Configuration c); void addConfiguration(Configuration c);

Signal activeConfigurationChanged(Configuration oldConfig, Configuration newConfig);

Configuration

QList<Screen> getScreens(); void addScreen(Screen screen); void removeScreen(Screen screen);

void commit();

Screens

QList<Screen> getScreens();

Signal screenAdded(Screen s); Signal screenRemoved(Screen s); Signal screenResized(Screen s, QPoint oldSize, QPoint newSize); Signal screenMoved(Screen s, QPoint oldPosition, QPoint newPosition);

Screen

int getId();

QPoint getResolution(); void setResolution(QPoint size); QPoint getPosition(); QList<PositionType> getRelativePosition();

bool isPrivacyMode(); void setPrivacyMode(bool b); bool isPrimary(); void setAsPrimary();

QList<Output> getOutputs();

Outputs

QList<Output> getOutputs();

Signal outputConnected(Output o); Signal outputDisconnected(Output o); Signal outputResized(Output o, QPoint oldSize, QPoint newSize); Signal outputMoved(Output o, QPoint oldPosition, QPoint newPosition); Signal outputRateChanged(Output o, int oldRate, int newRate);

Output

bool isConnected(); void forceConnected(); void forceDisconnected();

QPoint getResolution(); void setResolution(QPoint size); int getRate(); void setRate(int rate); RotationType getRotation(); void setRotation(RotationType rotation); ReflectType getReflect(); void setReflect(ReflectType reflect);

QPoint getPosition(); void setPosition(QPoint position); QList<PositionType> getRelativePosition(); void setRelativePosition(QList<PositionType> position);

QString getName(); QString getVendor(); int getProduct(); int getSerial();


Typical events

Plugging in a second unknown monitor

  • Signal outputConnected is emitted
  • If no configuration has been activated in response to that signal, a Configuration will be chosen based on the type (if available) of the connected monitor
  • Defaults might be:
    • Regular monitor: Clone mode
    • Video-projector or TV: Presentation mode
    • Unknown: Inactive
  • Signal outputMoved() is emitted for each output whose position changed
  • Signal outputResized() is emitted for each output whose resolution changed
  • Signal screenAdded() is emitted, if the result is a new screen
  • Signal screenResized() is emitted for each screen that existed previously and whose resolution changed
  • Signal screenMoved() is emitted for each screen that existed previously and whose position changed
  • Signal activeConfigurationChanged() is emitted, if config actually changed

Plugging in a second known monitor

  • Signal outputConnected is emitted
  • If no configuration has been activated in response to that signal, the last used configuration with that monitor will be chosen
  • Signal outputMoved() is emitted for each output whose position changed
  • Signal outputResized() is emitted for each output whose resolution changed
  • Signal screenAdded() is emitted, if the result is a new screen
  • Signal screenResized() is emitted for each screen that existed previously and whose resolution changed
  • Signal screenMoved() is emitted for each screen that existed previously and whose position changed
  • Signal activeConfigurationChanged() is emitted, if config actually changed

Unplugging a monitor

  • Signal outputDisconnected is emitted
  • If no configuration has been activated in response to that signal, the last used configuration for the remaining monitor(s) will be chosen
  • Signal screenRemoved() is emitted, if the new configuration has less screens
  • Signal screenResized() is emitted for each screen whose resolution changed
  • Signal screenMoved() is emitted for each screen whose position changed
  • Signal activeConfigurationChanged() is emitted, if config actually changed


Handling of special setups

Overlapping outputs

If 2 (or more) outputs are overlapping, they will be treated as 1 big screen. This is just as broken behaviour as splitting them up into 2n-1 sub-screens or leaving parts "empty", but anything else would require major changes to other programs. So these kind of setups will just be considered broken and a proper positioning of outputs should be enforced.


Use-Cases

This will mostly be of use to users of laptops, but might also help others. Some possible users/cases are listed below.

Novice users

Users which do not know how to or dont want to waste time on setting up multi-head on their systems might find this to be easy enough to just give it a shot. For them everything needs to be as easy as possible and guided, thus not requiring to know "where to go". On plugging in a second screen they should be "asked" by their computer what to do, giving them advice, what each choice might be good for.

Users with a fixed number of different setups

This is what inspired me to work on this project. Some users will move between different setups with different requirements. This might be an external monitor at work, a different one at home and the video-projector in the meeting-room at work. For these users it is an absolute requirement that settings will be saved for each different setup, so that you get the same session when you get back to work as you left it the other day.

Users with lots of different setups

This might be people travelling and giving presentations a lot, but there are probably way more users, who keep using different monitors/projectors all the time. For those users it should be very quickly possible to change every aspect of the connected device, including resolution and refresh rate. This doesnt need to be a "1-click-action" though.

Special requirements for public screens

Some connected screens might be publicly visible, such as video-projectors for presentations. These should at no time contain any private data. This also includes things like e-mails and im's. In particular this means, that for newly connected screens clone-mode might not be the best idea, as this might expose private data until the mode is reconfigured.


Interaction with the user

In this section i want to explain some possible ways Plasma could react to such events and present them to the user.

The new device notifier

The new device notifier is contained in the panel for most users and deals with hotplugging of devices. So this should be the perfect place for an unobstrusive message about the connected monitor with some choices for easy configuration. An additional choice would be to open the advanced configuration tool.

On plugging in a monitor, it would be something like this:

  • If the monitors are known, choose the appropriate configuration and do nothing else
  • Otherwise, or if the notifier is clicked by the user, pop up the notifier, containing an entry for the monitor
  • The following options should be available:
    • Clone mode
      • This would try to find the best matching resolution for both monitors and activate those
      • The user is then shown a passive popup with some (basic) information about the chosen resolutions and a link to change these
      • If he doesnt click it within x seconds the popup will fade out and the resolutions will stay as selected
    • Extended workspace, presentation mode and mediaplayer mode
      • In each case the user will be asked to click on the correct position in a little image within the popup
      • For extended workspace the monitor with the higher resolution will be chosen as the primary, for the other the previous monitor will stay the primary
    • Single-head mode
      • This simply turns off the previous monitor(s) and activates the newly plugged as only screen
    • Advanced configuration
      • An advanced configuration tool is shown


A dedicated screens plasmoid

This will visualize the connected monitors and the chosen configuration, allowing easy access to:

  • Repositioning of monitors by drag and drop
  • Changing configuration by overlayed icons
  • Changing resolution by dragging a screen corner
  • Changing refresh-rate by drop-down
  • Selecting the primary monitor by clicking a little star

This plasmoid could then also be configured to not show anything unless multiple outputs are connected, thus not cluttering the interface unless it becomes useful.


Context menu

Users expect to be able to configure display settings from the context menu, so it should at least contain entries to launch the advanced configuration ui and to make the current screen the primary.


Desktop toolbox

Maybe the advanced configuration should even be accessible from the desktop toolbox.