not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kcontrol / randr / krandrtray.cpp
blobe4473dca2120a56699376361ba890118f32aefc9
1 /*
2 * Copyright (c) 2007 Gustavo Pichorim Boiko <gustavo.boiko@kdemail.net>
3 * Copyright (c) 2002,2003 Hamish Rodda <rodda@kde.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "krandrtray.h"
21 #include "krandrpassivepopup.h"
22 #include "krandrtray.moc"
23 #include "legacyrandrscreen.h"
24 #ifdef HAS_RANDR_1_2
25 #include "randrscreen.h"
26 #include "randroutput.h"
27 #include "randrmode.h"
28 #endif
30 #include <config-randr.h>
32 #include <KActionCollection>
33 #include <KApplication>
34 #include <KCMultiDialog>
35 #include <KComponentData>
36 #include <KHelpMenu>
37 #include <KIcon>
38 #include <KIconLoader>
39 #include <KLocale>
40 #include <KMenu>
41 #include <KAction>
42 #include <QMouseEvent>
43 #include <QVariant>
45 KRandRSystemTray::KRandRSystemTray(RandRDisplay *dpy, QWidget* parent)
46 : KSystemTrayIcon("preferences-desktop-display-randr", parent),
47 m_help(new KHelpMenu(parent, KGlobal::mainComponent().aboutData(), false, actionCollection())),
48 m_popupUp(false),
49 m_display(dpy)
51 setIcon(KSystemTrayIcon::loadIcon("preferences-desktop-display-randr"));
52 connect(this, SIGNAL(quitSelected()), kapp, SLOT(quit()));
53 this->setToolTip( i18n("Screen resize & rotate"));
55 m_menu = new KMenu(parentWidget());
56 setContextMenu(m_menu);
58 connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), SLOT(slotActivated(QSystemTrayIcon::ActivationReason)));
60 connect(m_menu, SIGNAL(aboutToShow()), this, SLOT(slotPrepareMenu()));
61 m_display->refresh();
64 void KRandRSystemTray::slotActivated(QSystemTrayIcon::ActivationReason reason)
66 if(reason == QSystemTrayIcon::DoubleClick) {
67 slotPrefs();
71 void KRandRSystemTray::slotPrepareMenu()
73 QAction *action;
75 m_menu->clear();
77 if (!m_display->isValid())
79 action = m_menu->addAction(i18n("Required X Extension Not Available"));
80 action->setEnabled(false);
83 else
85 m_screenPopups.clear();
86 for (int s = 0; s < m_display->numScreens(); s++)
88 m_display->setCurrentScreen(s);
89 if (s == m_display->screenIndexOfWidget(parentWidget()))
91 /*lastIndex = menu->insertItem(i18n("Screen %1").arg(s+1));
92 menu->setItemEnabled(lastIndex, false);*/
94 else
96 KMenu* subMenu = new KMenu(i18n("Screen %1", s+1), m_menu );
97 subMenu->setObjectName( QString("screen%1").arg(s+1) );
98 m_screenPopups.append(subMenu);
99 populateMenu(subMenu);
100 action = m_menu->addMenu(subMenu);
101 connect(subMenu, SIGNAL(activated(int)), SLOT(slotScreenActivated()));
105 m_display->setCurrentScreen(m_display->screenIndexOfWidget(m_menu));
106 if (m_display->needsRefresh()) {
107 kDebug() << "Configuration dirty, reloading settings...";
108 m_display->refresh();
111 populateMenu(m_menu);
114 m_menu->addSeparator();
116 KAction *actPrefs = actionCollection()->addAction( QString() );
117 actPrefs->setIcon( KIcon( "configure" ) );
118 actPrefs->setText( i18n( "Configure Display..." ) );
120 connect( actPrefs, SIGNAL( triggered( bool ) ), SLOT( slotPrefs() ) );
121 m_menu->addAction( actPrefs );
123 m_menu->addMenu(/*SmallIcon("help-contents"),KStandardGuiItem::help().text(),*/ m_help->menu());
124 QAction *quitAction = actionCollection()->action(KStandardAction::name(KStandardAction::Quit));
125 m_menu->addAction( quitAction );
128 void KRandRSystemTray::slotScreenActivated()
130 m_display->setCurrentScreen(m_screenPopups.indexOf(static_cast<KMenu*>(sender())));
133 void KRandRSystemTray::configChanged()
135 m_display->refresh();
137 static bool first = true;
139 if (!first)
141 QString message;
142 #ifdef HAS_RANDR_1_2
143 if (RandR::has_1_2)
144 // TODO: display config changed message
145 message = "Screen config changed";
146 else
147 #endif
148 message = m_display->currentLegacyScreen()->changedMessage();
150 KRandrPassivePopup::message(
151 i18n("Screen configuration has changed"),
152 message, SmallIcon("view-fullscreen"),
153 parentWidget());
156 first = false;
159 void KRandRSystemTray::populateMenu(KMenu* menu)
161 #ifdef HAS_RANDR_1_2
162 if (RandR::has_1_2)
164 QAction *action;
165 QActionGroup *actionGroup;
167 OutputMap outputs = m_display->currentScreen()->outputs();
168 if (outputs.count() <= 0)
169 return;
171 RandRScreen *screen = m_display->currentScreen();
172 Q_ASSERT(screen);
174 // if the outputs are unified, do not show output-specific size
175 // changing options in the tray.
176 if (screen->outputsUnified() && screen->connectedCount() > 1)
178 SizeList sizes = screen->unifiedSizes();
180 if (sizes.count())
182 // populate unified sizes
183 QSize currentSize;
184 currentSize = screen->rect().size();
186 menu->addTitle(SmallIcon("view-fullscreen"), i18n("Screen Size"));
187 actionGroup = populateSizes(menu, sizes, currentSize);
188 connect(actionGroup, SIGNAL(triggered(QAction*)), screen, SLOT(slotResizeUnified(QAction*)));
190 // if the outputs are unified, we can rotate the screen on all outputs
191 int rotations = screen->unifiedRotations();
192 if (rotations != RandR::Rotate0)
194 menu->addTitle(SmallIcon("view-refresh"), i18n("Orientation"));
195 int rotation = RandR::Rotate0;
196 foreach(RandROutput *output, screen->outputs())
197 if (output->isActive())
199 rotation = output->rotation();
200 break;
203 actionGroup = populateRotations(menu, rotations, rotation);
204 connect(actionGroup, SIGNAL(triggered(QAction*)), screen, SLOT(slotRotateUnified(QAction*)));
208 else
210 if (screen->connectedCount() != 1)
211 menu->addTitle(SmallIcon("view-fullscreen"), i18n("Outputs"));
213 foreach(RandROutput *output, outputs)
215 if (output->isConnected())
217 KMenu *outputMenu;
218 if (screen->connectedCount() == 1)
219 outputMenu = menu;
220 else
221 outputMenu = new KMenu(output->name());
222 outputMenu->setIcon(SmallIcon(output->icon()));
223 outputMenu->addTitle(SmallIcon("view-fullscreen"), i18n("%1 - Screen Size", output->name()));
225 QSize currentSize = output->rect().size();
227 // if the output is rotated 90 or 270, the returned rect is inverted
228 // so we need to invert the size before comparing
229 if (output->rotation() & (RandR::Rotate90 | RandR::Rotate270))
230 currentSize = QSize(currentSize.height(), currentSize.width());
232 actionGroup = populateSizes(outputMenu, output->sizes(), currentSize);
233 connect(actionGroup, SIGNAL(triggered(QAction*)), output, SLOT(slotChangeSize(QAction*)));
235 // if there is only one output active, do not show the disable option
236 // this prevents the user from doing wrong things ;)
237 kDebug() << "Active outputs: " << screen->activeCount();
238 if (screen->activeCount() != 1)
240 action = outputMenu->addAction(i18n("Disable"));
241 if (output->crtc() == None)
243 QFont font = action->font();
244 font.setBold(true);
245 action->setFont(font);
247 connect(action, SIGNAL(triggered(bool)), output, SLOT(slotDisable()));
250 // Display the rotations
251 int rotations = output->rotations();
252 // Don't display the rotation options if there is no point (ie. none are supported)
253 // XFree86 4.3 does not include rotation support.
254 if (rotations != RandR::Rotate0)
256 outputMenu->addTitle(SmallIcon("view-refresh"), i18n("Orientation"));
257 actionGroup = populateRotations(outputMenu, rotations, output->rotation());
258 connect(actionGroup, SIGNAL(triggered(QAction*)),
259 output, SLOT(slotChangeRotation(QAction*)));
262 // refresh rate
263 RateList rates = output->refreshRates();
264 if (rates.count())
266 outputMenu->addTitle(SmallIcon("chronometer"), i18n("Refresh Rate"));
267 actionGroup = populateRates(outputMenu, rates, output->refreshRate());
268 connect(actionGroup, SIGNAL(triggered(QAction*)),
269 output, SLOT(slotChangeRefreshRate(QAction*)));
272 if (screen->connectedCount() != 1)
273 menu->addMenu(outputMenu);
277 // if there is more than one output connected, give the option to unify the outputs
278 if (screen->connectedCount() != 1)
280 menu->addSeparator();
281 action = menu->addAction( i18n("Unify Outputs"), screen, SLOT(slotUnifyOutputs(bool)) );
282 action->setCheckable(true);
283 action->setChecked(screen->outputsUnified());
286 else
287 #endif
288 populateLegacyMenu(menu);
291 void KRandRSystemTray::populateLegacyMenu(KMenu* menu)
293 menu->addTitle(SmallIcon("view-fullscreen"), i18n("Screen Size"));
295 LegacyRandRScreen *screen = m_display->currentLegacyScreen();
296 Q_ASSERT(screen);
298 // add sizes
299 QActionGroup *screenSizeGroup = populateSizes(menu, RandR::sortSizes(screen->pixelSizes()), screen->currentPixelSize());
300 connect(screenSizeGroup, SIGNAL(triggered(QAction*)), SLOT(slotResolutionChanged(QAction*)));
302 // Don't display the rotation options if there is no point (ie. none are supported)
303 // XFree86 4.3 does not include rotation support.
304 if (screen->rotations() != RandR::Rotate0)
306 menu->addTitle(SmallIcon("view-refresh"), i18n("Orientation"));
308 QActionGroup *rotationGroup = populateRotations(menu, screen->rotations(), screen->rotation());
309 connect(rotationGroup, SIGNAL(triggered(QAction*)), SLOT(slotOrientationChanged(QAction*)));
312 RateList rr = screen->refreshRates(screen->proposedSize());
313 if (rr.count())
315 menu->addTitle(SmallIcon("clock"), i18n("Refresh Rate"));
317 QActionGroup *rateGroup = populateRates(menu, rr, screen->refreshRate());
318 connect(rateGroup, SIGNAL(triggered(QAction*)), SLOT(slotRefreshRateChanged(QAction*)));
322 QActionGroup *KRandRSystemTray::populateRotations(KMenu *menu, int rotations, int rotation)
324 QAction *action;
325 QActionGroup *rotateGroup = new QActionGroup(menu);
328 for (int i = 0; i < 6; i++)
330 if ((1 << i) & rotations)
332 action = menu->addAction(QIcon(RandR::rotationIcon(1 << i, rotation)),
333 RandR::rotationName(1 << i));
335 action->setData(1 << i);
336 if (rotation & (1 << i))
338 QFont font = action->font();
339 font.setBold(true);
340 action->setFont(font);
342 rotateGroup->addAction(action);
345 return rotateGroup;
348 QActionGroup *KRandRSystemTray::populateSizes(KMenu *menu, const SizeList &sizes, const QSize &size)
350 QAction *action;
351 QActionGroup *sizeGroup = new QActionGroup(menu);
352 for (int i = 0; i < sizes.count(); ++i)
354 QSize s = sizes[i];
355 action = menu->addAction(QString("%1 x %2").arg(s.width()).arg(s.height()));
356 action->setData(s);
357 if (s == size)
359 QFont font = action->font();
360 font.setBold(true);
361 action->setFont(font);
363 sizeGroup->addAction(action);
365 return sizeGroup;
368 QActionGroup *KRandRSystemTray::populateRates(KMenu *menu, const RateList &rates, float rate)
370 QAction *action;
371 QActionGroup *rateGroup = new QActionGroup(menu);
373 foreach(float r, rates)
375 action = menu->addAction(ki18n("%1 Hz").subs(r, 0, 'f', 1).toString());
376 action->setData(r);
377 if (r == rate)
379 QFont f = action->font();
380 f.setBold(true);
381 action->setFont(f);
383 rateGroup->addAction(action);
385 return rateGroup;
388 void KRandRSystemTray::slotResolutionChanged(QAction *action)
390 LegacyRandRScreen *screen = m_display->currentLegacyScreen();
391 Q_ASSERT(screen);
393 QSize s = action->data().toSize();
394 int index = 0;
395 const SizeList pixelSizes = screen->pixelSizes();
396 for (int i = 0; i < pixelSizes.count(); ++i)
397 if (pixelSizes[i] == s)
399 index = i;
400 break;
403 if (screen->size() == index)
404 return;
406 screen->proposeSize(index);
408 screen->proposeRefreshRate(-1);
410 if (screen->applyProposedAndConfirm())
412 KConfig config("krandrrc");
413 if (m_display->syncTrayApp(config))
414 screen->save(config);
418 void KRandRSystemTray::slotOrientationChanged(QAction *action)
420 LegacyRandRScreen *screen = m_display->currentLegacyScreen();
421 Q_ASSERT(screen);
423 int propose = screen->rotation();
424 int rotate = action->data().toInt();
426 if (rotate & RandR::RotateMask)
427 propose &= RandR::ReflectMask;
429 propose ^= rotate;
431 if (screen->rotation() == propose)
432 return;
434 screen->proposeRotation(propose);
436 if (screen->applyProposedAndConfirm())
438 KConfig config("krandrrc");
439 if (m_display->syncTrayApp(config))
440 screen->save(config);
444 void KRandRSystemTray::slotRefreshRateChanged(QAction *action)
446 LegacyRandRScreen *screen = m_display->currentLegacyScreen();
447 Q_ASSERT(screen);
449 int index = action->data().toInt();
451 if (screen->refreshRate() == index)
452 return;
454 screen->proposeRefreshRate(index);
456 if (screen->applyProposedAndConfirm())
458 KConfig config("krandrrc");
459 if (m_display->syncTrayApp(config))
460 screen->save(config);
464 void KRandRSystemTray::slotPrefs()
466 KCMultiDialog *kcm = new KCMultiDialog( parentWidget() );
467 kcm->setFaceType( KCMultiDialog::Plain );
468 kcm->setPlainCaption( i18n( "Configure Display" ) );
469 kcm->addModule( "display" );
470 kcm->exec();
471 delete kcm;