TDE base libraries and programs
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tderandrtray.cpp 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  1. /*
  2. * Copyright (c) 2002,2003 Hamish Rodda <rodda@kde.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. */
  18. #include <tqtimer.h>
  19. #include <tqimage.h>
  20. #include <tqtooltip.h>
  21. #include <tdeaction.h>
  22. #include <tdeapplication.h>
  23. #include <kcmultidialog.h>
  24. #include <kdebug.h>
  25. #include <khelpmenu.h>
  26. #include <kiconloader.h>
  27. #include <tdelocale.h>
  28. #include <tdepopupmenu.h>
  29. #include <kstdaction.h>
  30. #include <kstdguiitem.h>
  31. #include <tdeglobal.h>
  32. #include <tdemessagebox.h>
  33. #include <kstandarddirs.h>
  34. #include <cstdlib>
  35. #include <unistd.h>
  36. #include "configdialog.h"
  37. #include "tderandrtray.h"
  38. #include "tderandrpassivepopup.h"
  39. #include "tderandrtray.moc"
  40. #define OUTPUT_CONNECTED (1 << 0)
  41. #define OUTPUT_UNKNOWN (1 << 1)
  42. #define OUTPUT_DISCONNECTED (1 << 2)
  43. #define OUTPUT_ON (1 << 3)
  44. #define OUTPUT_ALL (0xf)
  45. KRandRSystemTray::KRandRSystemTray(TQWidget* parent, const char *name)
  46. : KSystemTray(parent, name)
  47. , m_popupUp(false)
  48. , m_help(new KHelpMenu(this, TDEGlobal::instance()->aboutData(), false, actionCollection()))
  49. {
  50. setPixmap(KSystemTray::loadSizedIcon("randr", width()));
  51. setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
  52. connect(this, TQT_SIGNAL(quitSelected()), this, TQT_SLOT(_quit()));
  53. TQToolTip::add(this, i18n("Screen resize & rotate"));
  54. my_parent = parent;
  55. //printf("Reading configuration...\n");
  56. globalKeys = new TDEGlobalAccel(TQT_TQOBJECT(this));
  57. TDEGlobalAccel* keys = globalKeys;
  58. #include "tderandrbindings.cpp"
  59. // the keys need to be read from kdeglobals, not kickerrc
  60. globalKeys->readSettings();
  61. globalKeys->setEnabled(true);
  62. globalKeys->updateConnections();
  63. connect(kapp, TQT_SIGNAL(settingsChanged(int)), TQT_SLOT(slotSettingsChanged(int)));
  64. #if (TQT_VERSION-0 >= 0x030200) // XRANDR support
  65. // connect(this, TQT_SIGNAL(screenSizeChanged(int, int)), kapp->desktop(), TQT_SLOT( desktopResized()));
  66. #endif
  67. randr_display = XOpenDisplay(NULL);
  68. if (isValid() == true) {
  69. last_known_x = currentScreen()->currentPixelWidth();
  70. last_known_y = currentScreen()->currentPixelHeight();
  71. }
  72. t_config = new KSimpleConfig("kiccconfigrc");
  73. TQString cur_profile;
  74. cur_profile = getCurrentProfile();
  75. if (cur_profile != "") {
  76. applyIccConfiguration(cur_profile, NULL);
  77. }
  78. TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
  79. connect(hwdevices, TQT_SIGNAL(hardwareUpdated(TDEGenericDevice*)), this, TQT_SLOT(deviceChanged(TDEGenericDevice*)));
  80. }
  81. /*!
  82. * \b TQT_SLOT which called if tderandrtray is exited by the user. In this case the user
  83. * is asked through a yes/no box if "KRandRTray should start automatically on log in" and the
  84. * result is written to the KDE configfile.
  85. */
  86. void KRandRSystemTray::_quit (){
  87. r_config = new KSimpleConfig("tderandrtrayrc");
  88. TQString tmp1 = i18n ("Start KRandRTray automatically when you log in?");
  89. int tmp2 = KMessageBox::questionYesNo ( 0, tmp1, i18n("Question"), i18n("Start Automatically"), i18n("Do Not Start"));
  90. r_config->setGroup("General");
  91. r_config->writeEntry ("Autostart", tmp2 == KMessageBox::Yes);
  92. r_config->sync ();
  93. exit(0);
  94. }
  95. void KRandRSystemTray::resizeEvent ( TQResizeEvent * )
  96. {
  97. // Honor Free Desktop specifications that allow for arbitrary system tray icon sizes
  98. TQPixmap origpixmap;
  99. TQPixmap scaledpixmap;
  100. TQImage newIcon;
  101. origpixmap = KSystemTray::loadSizedIcon( "randr", width() );
  102. newIcon = origpixmap;
  103. newIcon = newIcon.smoothScale(width(), height());
  104. scaledpixmap = newIcon;
  105. setPixmap(scaledpixmap);
  106. }
  107. void KRandRSystemTray::mousePressEvent(TQMouseEvent* e)
  108. {
  109. // Popup the context menu with left-click
  110. if (e->button() == Qt::LeftButton) {
  111. contextMenuAboutToShow(contextMenu());
  112. contextMenu()->popup(e->globalPos());
  113. e->accept();
  114. return;
  115. }
  116. KSystemTray::mousePressEvent(e);
  117. }
  118. void KRandRSystemTray::reloadDisplayConfiguration()
  119. {
  120. // Reload the randr configuration...
  121. int i;
  122. int activeOutputs = 0;
  123. int screenDeactivated = 0;
  124. if (isValid() == true) {
  125. randr_screen_info = read_screen_info(randr_display);
  126. // Count outputs in the active state
  127. activeOutputs = 0;
  128. for (i = 0; i < randr_screen_info->n_output; i++) {
  129. // Look for ON outputs
  130. if (!randr_screen_info->outputs[i]->cur_crtc) {
  131. continue;
  132. }
  133. // Look for CONNECTED outputs
  134. if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
  135. continue;
  136. }
  137. activeOutputs++;
  138. }
  139. if (activeOutputs < 1) {
  140. // Houston, we have a problem!
  141. // There are no active displays!
  142. // Activate the first connected display we come across...
  143. for (i = 0; i < randr_screen_info->n_output; i++) {
  144. // Look for OFF outputs
  145. if (randr_screen_info->outputs[i]->cur_crtc) {
  146. continue;
  147. }
  148. // Look for CONNECTED outputs
  149. if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
  150. continue;
  151. }
  152. // Activate this output
  153. randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
  154. randr_screen_info->cur_output = randr_screen_info->outputs[i];
  155. randr_screen_info->cur_output->auto_set = 1;
  156. randr_screen_info->cur_output->off_set = 0;
  157. output_auto (randr_screen_info, randr_screen_info->cur_output);
  158. i=main_low_apply(randr_screen_info);
  159. if (randr_screen_info->outputs[i]->cur_crtc) {
  160. // Output successfully activated!
  161. set_primary_output(randr_screen_info, randr_screen_info->cur_output->id);
  162. break;
  163. }
  164. }
  165. }
  166. for (i = 0; i < randr_screen_info->n_output; i++) {
  167. // Look for ON outputs
  168. if (!randr_screen_info->outputs[i]->cur_crtc) {
  169. continue;
  170. }
  171. // Look for DISCONNECTED outputs
  172. if (RR_Disconnected != randr_screen_info->outputs[i]->info->connection) {
  173. continue;
  174. }
  175. // Deactivate this display to avoid a crash!
  176. randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
  177. randr_screen_info->cur_output = randr_screen_info->outputs[i];
  178. randr_screen_info->cur_output->auto_set = 0;
  179. randr_screen_info->cur_output->off_set = 1;
  180. output_off(randr_screen_info, randr_screen_info->cur_output);
  181. main_low_apply(randr_screen_info);
  182. screenDeactivated = 1;
  183. }
  184. if (screenDeactivated == 1) {
  185. findPrimaryDisplay();
  186. refresh();
  187. currentScreen()->proposeSize(GetDefaultResolutionParameter());
  188. currentScreen()->applyProposed();
  189. }
  190. }
  191. }
  192. void KRandRSystemTray::contextMenuAboutToShow(TDEPopupMenu* menu)
  193. {
  194. int lastIndex = 0;
  195. reloadDisplayConfiguration();
  196. menu->clear();
  197. menu->setCheckable(true);
  198. bool valid = isValid();
  199. if (!valid) {
  200. lastIndex = menu->insertItem(i18n("Required X Extension Not Available"));
  201. menu->setItemEnabled(lastIndex, false);
  202. }
  203. else {
  204. m_screenPopups.clear();
  205. for (int s = 0; s < numScreens() /*&& numScreens() > 1 */; s++) {
  206. setCurrentScreen(s);
  207. if (s == screenIndexOfWidget(this)) {
  208. /*lastIndex = menu->insertItem(i18n("Screen %1").arg(s+1));
  209. menu->setItemEnabled(lastIndex, false);*/
  210. } else {
  211. TDEPopupMenu* subMenu = new TDEPopupMenu(menu, TQString("screen%1").arg(s+1).latin1());
  212. m_screenPopups.append(subMenu);
  213. populateMenu(subMenu);
  214. lastIndex = menu->insertItem(i18n("Screen %1").arg(s+1), subMenu);
  215. connect(subMenu, TQT_SIGNAL(activated(int)), TQT_SLOT(slotScreenActivated()));
  216. }
  217. }
  218. setCurrentScreen(screenIndexOfWidget(this));
  219. populateMenu(menu);
  220. }
  221. addOutputMenu(menu);
  222. // Find any user ICC profiles
  223. TQStringList cfgProfiles;
  224. cfgProfiles = t_config->groupList();
  225. if (cfgProfiles.isEmpty() == false) {
  226. menu->insertTitle(SmallIcon("kcoloredit"), i18n("Color Profile"));
  227. }
  228. for (TQStringList::Iterator t(cfgProfiles.begin()); t != cfgProfiles.end(); ++t) {
  229. lastIndex = menu->insertItem(*t);
  230. if (t_config->readEntry("CurrentProfile") == (*t)) {
  231. menu->setItemChecked(lastIndex, true);
  232. }
  233. menu->setItemEnabled(lastIndex, t_config->readBoolEntry("EnableICC", false));
  234. menu->connectItem(lastIndex, this, TQT_SLOT(slotColorProfileChanged(int)));
  235. }
  236. if (valid) {
  237. // Find any display profiles
  238. TQStringList displayProfiles;
  239. displayProfiles = getDisplayConfigurationProfiles(locateLocal("config", "/", true));
  240. if (displayProfiles.isEmpty() == false) {
  241. menu->insertTitle(SmallIcon("background"), i18n("Display Profiles"));
  242. }
  243. lastIndex = menu->insertItem(SmallIcon("bookmark"), "<default>");
  244. menu->connectItem(lastIndex, this, TQT_SLOT(slotDisplayProfileChanged(int)));
  245. for (TQStringList::Iterator t(displayProfiles.begin()); t != displayProfiles.end(); ++t) {
  246. lastIndex = menu->insertItem(SmallIcon("bookmark"), *t);
  247. menu->connectItem(lastIndex, this, TQT_SLOT(slotDisplayProfileChanged(int)));
  248. }
  249. }
  250. menu->insertTitle(SmallIcon("randr"), i18n("Global Configuation"));
  251. TDEAction *actColors = new TDEAction( i18n( "Configure Displays..." ),
  252. SmallIconSet( "configure" ), TDEShortcut(), TQT_TQOBJECT(this), TQT_SLOT( slotDisplayConfig() ),
  253. actionCollection() );
  254. actColors->plug( menu );
  255. // TDEAction *actPrefs = new TDEAction( i18n( "Configure Display..." ),
  256. // SmallIconSet( "configure" ), TDEShortcut(), this, TQT_SLOT( slotPrefs() ),
  257. // actionCollection() );
  258. // actPrefs->plug( menu );
  259. TDEAction *actSKeys = new TDEAction( i18n( "Configure Shortcut Keys..." ),
  260. SmallIconSet( "configure" ), TDEShortcut(), TQT_TQOBJECT(this), TQT_SLOT( slotSKeys() ),
  261. actionCollection() );
  262. actSKeys->plug( menu );
  263. menu->insertItem(SmallIcon("help"),KStdGuiItem::help().text(), m_help->menu());
  264. TDEAction *quitAction = actionCollection()->action(KStdAction::name(KStdAction::Quit));
  265. quitAction->plug(menu);
  266. m_menu = menu;
  267. }
  268. void KRandRSystemTray::slotScreenActivated()
  269. {
  270. setCurrentScreen(m_screenPopups.find(static_cast<const TDEPopupMenu*>(sender())));
  271. }
  272. void KRandRSystemTray::configChanged()
  273. {
  274. refresh();
  275. static bool first = true;
  276. if ((last_known_x == currentScreen()->currentPixelWidth()) && \
  277. (last_known_y == currentScreen()->currentPixelHeight())) {
  278. first = true;
  279. }
  280. last_known_x = currentScreen()->currentPixelWidth();
  281. last_known_y = currentScreen()->currentPixelHeight();
  282. if (!first) {
  283. emit (screenSizeChanged(currentScreen()->currentPixelWidth(), currentScreen()->currentPixelHeight()));
  284. KRandrPassivePopup::message(
  285. i18n("Screen configuration has changed"),
  286. currentScreen()->changedMessage(), SmallIcon("window_fullscreen"),
  287. this, "ScreenChangeNotification");
  288. }
  289. first = false;
  290. TQString cur_profile;
  291. cur_profile = getCurrentProfile();
  292. if (cur_profile != "") {
  293. applyIccConfiguration(cur_profile, NULL);
  294. }
  295. }
  296. int KRandRSystemTray::GetDefaultResolutionParameter()
  297. {
  298. int returnIndex = 0;
  299. int numSizes = currentScreen()->numSizes();
  300. int* sizeSort = new int[numSizes];
  301. for (int i = 0; i < numSizes; i++) {
  302. sizeSort[i] = currentScreen()->pixelCount(i);
  303. }
  304. int highest = -1, highestIndex = -1;
  305. for (int i = 0; i < numSizes; i++) {
  306. if (sizeSort[i] && sizeSort[i] > highest) {
  307. highest = sizeSort[i];
  308. highestIndex = i;
  309. }
  310. }
  311. sizeSort[highestIndex] = -1;
  312. Q_ASSERT(highestIndex != -1);
  313. returnIndex = highestIndex;
  314. delete [] sizeSort;
  315. sizeSort = 0L;
  316. return returnIndex;
  317. }
  318. int KRandRSystemTray::GetHackResolutionParameter() {
  319. int resparm;
  320. resparm = GetDefaultResolutionParameter();
  321. resparm++;
  322. return resparm;
  323. }
  324. void KRandRSystemTray::populateMenu(TDEPopupMenu* menu)
  325. {
  326. int lastIndex = 0;
  327. menu->insertTitle(SmallIcon("window_fullscreen"), i18n("Screen Size"));
  328. int numSizes = currentScreen()->numSizes();
  329. int* sizeSort = new int[numSizes];
  330. for (int i = 0; i < numSizes; i++) {
  331. sizeSort[i] = currentScreen()->pixelCount(i);
  332. }
  333. for (int j = 0; j < numSizes; j++) {
  334. int highest = -1, highestIndex = -1;
  335. for (int i = 0; i < numSizes; i++) {
  336. if (sizeSort[i] && sizeSort[i] > highest) {
  337. highest = sizeSort[i];
  338. highestIndex = i;
  339. }
  340. }
  341. sizeSort[highestIndex] = -1;
  342. Q_ASSERT(highestIndex != -1);
  343. lastIndex = menu->insertItem(i18n("%1 x %2").arg(currentScreen()->pixelSize(highestIndex).width()).arg(currentScreen()->pixelSize(highestIndex).height()));
  344. if (currentScreen()->proposedSize() == highestIndex)
  345. menu->setItemChecked(lastIndex, true);
  346. menu->setItemParameter(lastIndex, highestIndex);
  347. menu->connectItem(lastIndex, this, TQT_SLOT(slotResolutionChanged(int)));
  348. }
  349. delete [] sizeSort;
  350. sizeSort = 0L;
  351. // Don't display the rotation options if there is no point (ie. none are supported)
  352. // XFree86 4.3 does not include rotation support.
  353. if (currentScreen()->rotations() != RandRScreen::Rotate0) {
  354. menu->insertTitle(SmallIcon("reload"), i18n("Orientation"));
  355. for (int i = 0; i < 6; i++) {
  356. if ((1 << i) & currentScreen()->rotations()) {
  357. lastIndex = menu->insertItem(currentScreen()->rotationIcon(1 << i), RandRScreen::rotationName(1 << i));
  358. if (currentScreen()->proposedRotation() & (1 << i))
  359. menu->setItemChecked(lastIndex, true);
  360. menu->setItemParameter(lastIndex, 1 << i);
  361. menu->connectItem(lastIndex, this, TQT_SLOT(slotOrientationChanged(int)));
  362. }
  363. }
  364. }
  365. TQStringList rr = currentScreen()->refreshRates(currentScreen()->proposedSize());
  366. if (rr.count())
  367. menu->insertTitle(SmallIcon("clock"), i18n("Refresh Rate"));
  368. int i = 0;
  369. for (TQStringList::Iterator it = rr.begin(); it != rr.end(); ++it, i++) {
  370. lastIndex = menu->insertItem(*it);
  371. if (currentScreen()->proposedRefreshRate() == i)
  372. menu->setItemChecked(lastIndex, true);
  373. menu->setItemParameter(lastIndex, i);
  374. menu->connectItem(lastIndex, this, TQT_SLOT(slotRefreshRateChanged(int)));
  375. }
  376. }
  377. void KRandRSystemTray::slotResolutionChanged(int parameter)
  378. {
  379. if (currentScreen()->currentSize() == parameter) {
  380. //printf("This resolution is already in use; applying again...\n");
  381. currentScreen()->proposeSize(parameter);
  382. currentScreen()->applyProposed();
  383. return;
  384. }
  385. currentScreen()->proposeSize(parameter);
  386. currentScreen()->proposeRefreshRate(-1);
  387. if (currentScreen()->applyProposedAndConfirm()) {
  388. TDEConfig config("kcmrandrrc");
  389. if (syncTrayApp(config))
  390. currentScreen()->save(config);
  391. }
  392. }
  393. void KRandRSystemTray::slotOrientationChanged(int parameter)
  394. {
  395. int propose = currentScreen()->currentRotation();
  396. if (parameter & RandRScreen::RotateMask)
  397. propose &= RandRScreen::ReflectMask;
  398. propose ^= parameter;
  399. if (currentScreen()->currentRotation() == propose)
  400. return;
  401. currentScreen()->proposeRotation(propose);
  402. if (currentScreen()->applyProposedAndConfirm()) {
  403. TDEConfig config("kcmrandrrc");
  404. if (syncTrayApp(config))
  405. currentScreen()->save(config);
  406. }
  407. }
  408. void KRandRSystemTray::slotRefreshRateChanged(int parameter)
  409. {
  410. if (currentScreen()->currentRefreshRate() == parameter)
  411. return;
  412. currentScreen()->proposeRefreshRate(parameter);
  413. if (currentScreen()->applyProposedAndConfirm()) {
  414. TDEConfig config("kcmrandrrc");
  415. if (syncTrayApp(config))
  416. currentScreen()->save(config);
  417. }
  418. }
  419. void KRandRSystemTray::slotPrefs()
  420. {
  421. KCMultiDialog *kcm = new KCMultiDialog( KDialogBase::Plain, i18n( "Configure" ), this );
  422. kcm->addModule( "displayconfig" );
  423. kcm->setPlainCaption( i18n( "Configure Display" ) );
  424. kcm->exec();
  425. }
  426. void KRandRSystemTray::slotDisplayConfig()
  427. {
  428. KCMultiDialog *kcm = new KCMultiDialog( KDialogBase::Plain, i18n( "Configure" ), this );
  429. kcm->addModule( "displayconfig" );
  430. kcm->setPlainCaption( i18n( "Configure Displays" ) );
  431. kcm->exec();
  432. }
  433. void KRandRSystemTray::slotSettingsChanged(int category)
  434. {
  435. if ( category == (int) TDEApplication::SETTINGS_SHORTCUTS ) {
  436. globalKeys->readSettings();
  437. globalKeys->updateConnections();
  438. }
  439. }
  440. void KRandRSystemTray::slotSKeys()
  441. {
  442. ConfigDialog *dlg = new ConfigDialog(globalKeys, true);
  443. if ( dlg->exec() == TQDialog::Accepted ) {
  444. dlg->commitShortcuts();
  445. globalKeys->writeSettings(0, true);
  446. globalKeys->updateConnections();
  447. }
  448. delete dlg;
  449. }
  450. void KRandRSystemTray::slotCycleDisplays()
  451. {
  452. XRROutputInfo *output_info;
  453. char *output_name;
  454. int i;
  455. int current_on_index = -1;
  456. int max_index = -1;
  457. int prev_on_index;
  458. randr_screen_info = read_screen_info(randr_display);
  459. for (i = 0; i < randr_screen_info->n_output; i++) {
  460. output_info = randr_screen_info->outputs[i]->info;
  461. // Look for ON outputs...
  462. if (!randr_screen_info->outputs[i]->cur_crtc) {
  463. continue;
  464. }
  465. // ...that are connected
  466. if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
  467. continue;
  468. }
  469. output_name = output_info->name;
  470. current_on_index = i;
  471. if (i > max_index) {
  472. max_index = i;
  473. }
  474. }
  475. for (i = 0; i < randr_screen_info->n_output; i++) {
  476. output_info = randr_screen_info->outputs[i]->info;
  477. // Look for CONNECTED outputs....
  478. if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
  479. continue;
  480. }
  481. // ...that are not ON
  482. if (randr_screen_info->outputs[i]->cur_crtc) {
  483. continue;
  484. }
  485. output_name = output_info->name;
  486. if (i > max_index) {
  487. max_index = i;
  488. }
  489. }
  490. for (i = 0; i < randr_screen_info->n_output; i++) {
  491. output_info = randr_screen_info->outputs[i]->info;
  492. // Look for ALL outputs that are not connected....
  493. if (RR_Disconnected != randr_screen_info->outputs[i]->info->connection) {
  494. continue;
  495. }
  496. // ...or ON
  497. if (randr_screen_info->outputs[i]->cur_crtc) {
  498. continue;
  499. }
  500. output_name = output_info->name;
  501. if (i > max_index) {
  502. max_index = i;
  503. }
  504. }
  505. //printf("Active: %d\n", current_on_index);
  506. //printf("Max: %d\n", max_index);
  507. if ((current_on_index == -1) && (max_index == -1)) {
  508. // There is no connected display available! ABORT
  509. return;
  510. }
  511. prev_on_index = current_on_index;
  512. current_on_index = current_on_index + 1;
  513. if (current_on_index > max_index) {
  514. current_on_index = 0;
  515. }
  516. while (RR_Disconnected == randr_screen_info->outputs[current_on_index]->info->connection) {
  517. current_on_index = current_on_index + 1;
  518. if (current_on_index > max_index) {
  519. current_on_index = 0;
  520. }
  521. }
  522. if (prev_on_index != current_on_index) {
  523. randr_screen_info->cur_crtc = randr_screen_info->outputs[current_on_index]->cur_crtc;
  524. randr_screen_info->cur_output = randr_screen_info->outputs[current_on_index];
  525. randr_screen_info->cur_output->auto_set = 1;
  526. randr_screen_info->cur_output->off_set = 0;
  527. output_auto (randr_screen_info, randr_screen_info->cur_output);
  528. i=main_low_apply(randr_screen_info);
  529. if (randr_screen_info->outputs[current_on_index]->cur_crtc) {
  530. // Output successfully activated!
  531. set_primary_output(randr_screen_info, randr_screen_info->cur_output->id);
  532. if (prev_on_index != -1) {
  533. if (randr_screen_info->outputs[prev_on_index]->cur_crtc != NULL) {
  534. if (RR_Disconnected != randr_screen_info->outputs[prev_on_index]->info->connection) {
  535. randr_screen_info->cur_crtc = randr_screen_info->outputs[prev_on_index]->cur_crtc;
  536. randr_screen_info->cur_output = randr_screen_info->outputs[prev_on_index];
  537. randr_screen_info->cur_output->auto_set = 0;
  538. randr_screen_info->cur_output->off_set = 1;
  539. output_off(randr_screen_info, randr_screen_info->cur_output);
  540. i=main_low_apply(randr_screen_info);
  541. }
  542. }
  543. }
  544. // Do something about the disconnected outputs
  545. for (i = 0; i < randr_screen_info->n_output; i++) {
  546. output_info = randr_screen_info->outputs[i]->info;
  547. // Look for ON outputs
  548. if (!randr_screen_info->outputs[i]->cur_crtc) {
  549. continue;
  550. }
  551. if (RR_Disconnected != randr_screen_info->outputs[i]->info->connection) {
  552. continue;
  553. }
  554. output_name = output_info->name;
  555. // Deactivate this display to avoid a crash!
  556. randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
  557. randr_screen_info->cur_output = randr_screen_info->outputs[i];
  558. randr_screen_info->cur_output->auto_set = 0;
  559. randr_screen_info->cur_output->off_set = 1;
  560. output_off(randr_screen_info, randr_screen_info->cur_output);
  561. main_low_apply(randr_screen_info);
  562. }
  563. findPrimaryDisplay();
  564. refresh();
  565. currentScreen()->proposeSize(GetDefaultResolutionParameter());
  566. currentScreen()->applyProposed();
  567. }
  568. else {
  569. output_name = randr_screen_info->outputs[current_on_index]->info->name;
  570. KMessageBox::sorry(my_parent, i18n("<b>Unable to activate output %1</b><p>Either the output is not connected to a display,<br>or the display configuration is not detectable").arg(output_name), i18n("Output Unavailable"));
  571. }
  572. }
  573. }
  574. void KRandRSystemTray::findPrimaryDisplay()
  575. {
  576. int i;
  577. for (i = 0; i < randr_screen_info->n_output; i++) {
  578. // Look for ON outputs...
  579. if (!randr_screen_info->outputs[i]->cur_crtc) {
  580. continue;
  581. }
  582. // ...that are connected
  583. if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
  584. continue;
  585. }
  586. randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
  587. randr_screen_info->cur_output = randr_screen_info->outputs[i];
  588. }
  589. }
  590. void KRandRSystemTray::addOutputMenu(TDEPopupMenu* menu)
  591. {
  592. XRROutputInfo *output_info;
  593. char *output_name;
  594. int i;
  595. int lastIndex = 0;
  596. int connected_displays = 0;
  597. if (isValid() == true) {
  598. menu->insertTitle(SmallIcon("kcmkwm"), i18n("Output Port"));
  599. for (i = 0; i < randr_screen_info->n_output; i++) {
  600. output_info = randr_screen_info->outputs[i]->info;
  601. // Look for ON outputs
  602. if (!randr_screen_info->outputs[i]->cur_crtc) {
  603. continue;
  604. }
  605. if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
  606. continue;
  607. }
  608. output_name = output_info->name;
  609. //printf("ON: Found output %s\n", output_name);
  610. lastIndex = menu->insertItem(i18n("%1 (Active)").arg(output_name));
  611. menu->setItemChecked(lastIndex, true);
  612. menu->connectItem(lastIndex, this, TQT_SLOT(slotOutputChanged(int)));
  613. menu->setItemParameter(lastIndex, i);
  614. connected_displays++;
  615. }
  616. for (i = 0; i < randr_screen_info->n_output; i++) {
  617. output_info = randr_screen_info->outputs[i]->info;
  618. // Look for CONNECTED outputs....
  619. if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
  620. continue;
  621. }
  622. // ...that are not ON
  623. if (randr_screen_info->outputs[i]->cur_crtc) {
  624. continue;
  625. }
  626. output_name = output_info->name;
  627. //printf("CONNECTED, NOT ON: Found output %s\n", output_name);
  628. lastIndex = menu->insertItem(i18n("%1 (Connected, Inactive)").arg(output_name));
  629. menu->setItemChecked(lastIndex, false);
  630. menu->connectItem(lastIndex, this, TQT_SLOT(slotOutputChanged(int)));
  631. menu->setItemParameter(lastIndex, i);
  632. connected_displays++;
  633. }
  634. for (i = 0; i < randr_screen_info->n_output; i++) {
  635. output_info = randr_screen_info->outputs[i]->info;
  636. // Look for ALL outputs that are not connected....
  637. if (RR_Disconnected != randr_screen_info->outputs[i]->info->connection) {
  638. continue;
  639. }
  640. // ...or ON
  641. if (randr_screen_info->outputs[i]->cur_crtc) {
  642. continue;
  643. }
  644. output_name = output_info->name;
  645. //printf("DISCONNECTED, NOT ON: Found output %s\n", output_name);
  646. lastIndex = menu->insertItem(i18n("%1 (Disconnected, Inactive)").arg(output_name));
  647. menu->setItemChecked(lastIndex, false);
  648. menu->setItemEnabled(lastIndex, false);
  649. menu->connectItem(lastIndex, this, TQT_SLOT(slotOutputChanged(int)));
  650. menu->setItemParameter(lastIndex, i);
  651. }
  652. lastIndex = menu->insertItem(SmallIcon("forward"), i18n("Next available output"));
  653. if (connected_displays < 2) {
  654. menu->setItemEnabled(lastIndex, false);
  655. }
  656. menu->connectItem(lastIndex, this, TQT_SLOT(slotCycleDisplays()));
  657. }
  658. }
  659. void KRandRSystemTray::slotColorProfileChanged(int parameter)
  660. {
  661. t_config->writeEntry("CurrentProfile", m_menu->text(parameter));
  662. applyIccConfiguration(m_menu->text(parameter), NULL);
  663. }
  664. void KRandRSystemTray::slotDisplayProfileChanged(int parameter)
  665. {
  666. TQString profileName = m_menu->text(parameter);
  667. if (profileName == "<default>") {
  668. profileName = "";
  669. }
  670. TQPtrList<SingleScreenData> profileData = loadDisplayConfiguration(profileName, locateLocal("config", "/", true));
  671. applyDisplayConfiguration(profileData, TRUE, locateLocal("config", "/", true));
  672. destroyScreenInformationObject(profileData);
  673. }
  674. void KRandRSystemTray::slotOutputChanged(int parameter)
  675. {
  676. char *output_name;
  677. int i;
  678. int num_outputs_on;
  679. num_outputs_on = 0;
  680. for (i = 0; i < randr_screen_info->n_output; i++) {
  681. // Look for ON outputs
  682. if (!randr_screen_info->outputs[i]->cur_crtc) {
  683. continue;
  684. }
  685. num_outputs_on++;
  686. }
  687. if (!randr_screen_info->outputs[parameter]->cur_crtc) {
  688. //printf("Screen was off, turning it on...\n");
  689. randr_screen_info->cur_crtc = randr_screen_info->outputs[parameter]->cur_crtc;
  690. randr_screen_info->cur_output = randr_screen_info->outputs[parameter];
  691. randr_screen_info->cur_output->auto_set = 1;
  692. randr_screen_info->cur_output->off_set = 0;
  693. output_auto (randr_screen_info, randr_screen_info->cur_output);
  694. i=main_low_apply(randr_screen_info);
  695. if (!randr_screen_info->outputs[parameter]->cur_crtc) {
  696. output_name = randr_screen_info->outputs[parameter]->info->name;
  697. KMessageBox::sorry(my_parent, i18n("<b>Unable to activate output %1</b><p>Either the output is not connected to a display,<br>or the display configuration is not detectable").arg(output_name), i18n("Output Unavailable"));
  698. }
  699. }
  700. else {
  701. if (num_outputs_on > 1) {
  702. //printf("Screen was on, turning it off...\n");
  703. randr_screen_info->cur_crtc = randr_screen_info->outputs[parameter]->cur_crtc;
  704. randr_screen_info->cur_output = randr_screen_info->outputs[parameter];
  705. randr_screen_info->cur_output->auto_set = 0;
  706. randr_screen_info->cur_output->off_set = 1;
  707. output_off(randr_screen_info, randr_screen_info->cur_output);
  708. i=main_low_apply(randr_screen_info);
  709. findPrimaryDisplay();
  710. refresh();
  711. currentScreen()->proposeSize(GetDefaultResolutionParameter());
  712. currentScreen()->applyProposed();
  713. }
  714. else {
  715. KMessageBox::sorry(my_parent, i18n("<b>You are attempting to deactivate the only active output</b><p>You must keep at least one display output active at all times!"), i18n("Invalid Operation Requested"));
  716. }
  717. }
  718. }
  719. void KRandRSystemTray::deviceChanged (TDEGenericDevice* device) {
  720. if (device->type() == TDEGenericDeviceType::Monitor) {
  721. KRandrPassivePopup::message(
  722. i18n("New display output options are available!"),
  723. i18n("A screen has been added, removed, or changed"), SmallIcon("window_fullscreen"),
  724. this, "ScreenChangeNotification");
  725. reloadDisplayConfiguration();
  726. applyHotplugRules(locateLocal("config", "/", true));
  727. }
  728. }