Add basic multihead support to kwin

For now there is autostart support on all screens and support for different resolutions on different screens.
Keyboard shortcuts are still TODO
REVIEW: 101125
BUG: 256242
icc-effect-5.14.5
Alberto Mattea 2011-05-08 20:39:27 +02:00
parent 2534acc961
commit 9bbed0335a
2 changed files with 89 additions and 56 deletions

View File

@ -56,6 +56,9 @@ namespace KWin
// Workspace
//********************************************
extern int screen_number;
extern bool is_multihead;
/*!
Resizes the workspace after an XRANDR screen size change
*/
@ -236,6 +239,7 @@ void Workspace::updateClientArea()
\sa geometry()
*/
QRect Workspace::clientArea(clientAreaOption opt, int screen, int desktop) const
{
if (desktop == NETWinInfo::OnAllDesktops || desktop == 0)
@ -243,49 +247,82 @@ QRect Workspace::clientArea(clientAreaOption opt, int screen, int desktop) const
if (screen == -1)
screen = activeScreen();
QRect sarea = (!screenarea.isEmpty()
QRect sarea, warea;
if (is_multihead) {
sarea = (!screenarea.isEmpty()
&& screen < screenarea[ desktop ].size()) // screens may be missing during KWin initialization or screen config changes
? screenarea[ desktop ][ screen ]
: Kephal::ScreenUtils::screenGeometry(screen);
QRect warea = workarea[ desktop ].isNull()
? Kephal::ScreenUtils::desktopGeometry()
: workarea[ desktop ];
? screenarea[ desktop ][ screen_number ]
: Kephal::ScreenUtils::screenGeometry(screen_number);
warea = workarea[ desktop ].isNull()
? Kephal::ScreenUtils::screenGeometry(screen_number)
: workarea[ desktop ];
} else {
sarea = (!screenarea.isEmpty()
&& screen < screenarea[ desktop ].size()) // screens may be missing during KWin initialization or screen config changes
? screenarea[ desktop ][ screen ]
: Kephal::ScreenUtils::screenGeometry(screen);
warea = workarea[ desktop ].isNull()
? Kephal::ScreenUtils::desktopGeometry()
: workarea[ desktop ];
}
switch(opt) {
case MaximizeArea:
if (options->xineramaMaximizeEnabled)
if (is_multihead)
return sarea;
else if (options->xineramaMaximizeEnabled)
return sarea;
else
return warea;
case MaximizeFullArea:
if (options->xineramaMaximizeEnabled)
if (is_multihead)
return Kephal::ScreenUtils::screenGeometry(screen_number);
else if (options->xineramaMaximizeEnabled)
return Kephal::ScreenUtils::screenGeometry(screen);
else
return Kephal::ScreenUtils::desktopGeometry();
case FullScreenArea:
if (options->xineramaFullscreenEnabled)
if (is_multihead)
return Kephal::ScreenUtils::screenGeometry(screen_number);
else if (options->xineramaFullscreenEnabled)
return Kephal::ScreenUtils::screenGeometry(screen);
else
return Kephal::ScreenUtils::desktopGeometry();
case PlacementArea:
if (options->xineramaPlacementEnabled)
if (is_multihead)
return sarea;
else if (options->xineramaPlacementEnabled)
return sarea;
else
return warea;
case MovementArea:
if (options->xineramaMovementEnabled)
if (is_multihead)
return Kephal::ScreenUtils::screenGeometry(screen_number);
else if (options->xineramaMovementEnabled)
return Kephal::ScreenUtils::screenGeometry(screen);
else
return Kephal::ScreenUtils::desktopGeometry();
case WorkArea:
return warea;
if (is_multihead)
return sarea;
else
return warea;
case FullArea:
return Kephal::ScreenUtils::desktopGeometry();
if (is_multihead)
return Kephal::ScreenUtils::screenGeometry(screen_number);
else
return Kephal::ScreenUtils::desktopGeometry();
case ScreenArea:
return Kephal::ScreenUtils::screenGeometry(screen);
if (is_multihead)
return Kephal::ScreenUtils::screenGeometry(screen_number);
else
return Kephal::ScreenUtils::screenGeometry(screen);
}
abort();
}
QRect Workspace::clientArea(clientAreaOption opt, const QPoint& p, int desktop) const
{
int screen = Kephal::ScreenUtils::screenId(p);

View File

@ -74,6 +74,7 @@ Options* options;
Atoms* atoms;
int screen_number = -1;
bool is_multihead = false;
bool initting = false;
@ -407,50 +408,45 @@ KDE_EXPORT int kdemain(int argc, char * argv[])
// or command line settings to raster or OpenGL.
QApplication::setGraphicsSystem("native");
if (!restored) {
// We only do the multihead fork if we are not restored by the session
// manager, since the session manager will register multiple kwins,
// one for each screen...
QByteArray multiHead = qgetenv("KDE_MULTIHEAD");
if (multiHead.toLower() == "true") {
Display* dpy = XOpenDisplay(NULL);
if (!dpy) {
fprintf(stderr, "%s: FATAL ERROR while trying to open display %s\n",
argv[0], XDisplayName(NULL));
exit(1);
Display* dpy = XOpenDisplay(NULL);
if (!dpy) {
fprintf(stderr, "%s: FATAL ERROR while trying to open display %s\n",
argv[0], XDisplayName(NULL));
exit(1);
}
int number_of_screens = ScreenCount(dpy);
// multi head
if (number_of_screens != 1) {
KWin::is_multihead = true;
KWin::screen_number = DefaultScreen(dpy);
int pos; // Temporarily needed to reconstruct DISPLAY var if multi-head
QByteArray display_name = XDisplayString(dpy);
XCloseDisplay(dpy);
dpy = 0;
if ((pos = display_name.lastIndexOf('.')) != -1)
display_name.remove(pos, 10); // 10 is enough to be sure we removed ".s"
QString envir;
for (int i = 0; i < number_of_screens; i++) {
// If execution doesn't pass by here, then kwin
// acts exactly as previously
if (i != KWin::screen_number && fork() == 0) {
KWin::screen_number = i;
// Break here because we are the child process, we don't
// want to fork() anymore
break;
}
}
// In the next statement, display_name shouldn't contain a screen
// number. If it had it, it was removed at the "pos" check
envir.sprintf("DISPLAY=%s.%d", display_name.data(), KWin::screen_number);
int number_of_screens = ScreenCount(dpy);
KWin::screen_number = DefaultScreen(dpy);
int pos; // Temporarily needed to reconstruct DISPLAY var if multi-head
QByteArray display_name = XDisplayString(dpy);
XCloseDisplay(dpy);
dpy = 0;
if ((pos = display_name.lastIndexOf('.')) != -1)
display_name.remove(pos, 10); // 10 is enough to be sure we removed ".s"
QString envir;
if (number_of_screens != 1) {
for (int i = 0; i < number_of_screens; i++) {
// If execution doesn't pass by here, then kwin
// acts exactly as previously
if (i != KWin::screen_number && fork() == 0) {
KWin::screen_number = i;
// Break here because we are the child process, we don't
// want to fork() anymore
break;
}
}
// In the next statement, display_name shouldn't contain a screen
// number. If it had it, it was removed at the "pos" check
envir.sprintf("DISPLAY=%s.%d", display_name.data(), KWin::screen_number);
if (putenv(strdup(envir.toAscii()))) {
fprintf(stderr, "%s: WARNING: unable to set DISPLAY environment variable\n", argv[0]);
perror("putenv()");
}
}
if (putenv(strdup(envir.toAscii()))) {
fprintf(stderr, "%s: WARNING: unable to set DISPLAY environment variable\n", argv[0]);
perror("putenv()");
}
}