diff options
Diffstat (limited to 'kicker/extensions/dockbar')
-rw-r--r-- | kicker/extensions/dockbar/Makefile.am | 18 | ||||
-rw-r--r-- | kicker/extensions/dockbar/dockbarextension.cpp | 423 | ||||
-rw-r--r-- | kicker/extensions/dockbar/dockbarextension.desktop | 148 | ||||
-rw-r--r-- | kicker/extensions/dockbar/dockbarextension.h | 73 | ||||
-rw-r--r-- | kicker/extensions/dockbar/dockcontainer.cpp | 198 | ||||
-rw-r--r-- | kicker/extensions/dockbar/dockcontainer.h | 90 |
6 files changed, 950 insertions, 0 deletions
diff --git a/kicker/extensions/dockbar/Makefile.am b/kicker/extensions/dockbar/Makefile.am new file mode 100644 index 000000000..6d2f20546 --- /dev/null +++ b/kicker/extensions/dockbar/Makefile.am @@ -0,0 +1,18 @@ +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = dockbar_panelextension.la + +dockbar_panelextension_la_SOURCES = dockcontainer.cpp dockbarextension.cpp +dockbar_panelextension_la_METASOURCES = AUTO +dockbar_panelextension_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +dockbar_panelextension_la_LIBADD = $(LIB_KDEUI) + +noinst_HEADERS = dockcontainer.h dockbarextension.h + +lnkdir = $(kde_datadir)/kicker/extensions +lnk_DATA = dockbarextension.desktop + +EXTRA_DIST = $(lnk_DATA) + +messages: + $(XGETTEXT) *.cpp *.h -o $(podir)/dockbarextension.pot diff --git a/kicker/extensions/dockbar/dockbarextension.cpp b/kicker/extensions/dockbar/dockbarextension.cpp new file mode 100644 index 000000000..71b583f35 --- /dev/null +++ b/kicker/extensions/dockbar/dockbarextension.cpp @@ -0,0 +1,423 @@ +/***************************************************************** + +Copyright (c) 2000 Matthias Elter + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#undef Bool // For enable-final +#include <klocale.h> +#include <kwinmodule.h> +#include <kdebug.h> +#include <kconfig.h> +#include <kprocess.h> +#include <kshell.h> +#include <kwin.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> +#include <kapplication.h> +#include <dcopclient.h> +#include <kglobal.h> + +#include "dockbarextension.h" +#include "dockbarextension.moc" + +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +extern "C" +{ + KDE_EXPORT KPanelExtension* init(QWidget *parent, const QString& configFile) + { + KGlobal::locale()->insertCatalogue("dockbarextension"); + return new DockBarExtension(configFile, KPanelExtension::Normal, + 0, parent, "dockbarextension"); + } +} + +DockBarExtension::DockBarExtension(const QString& configFile, Type type, + int actions, QWidget *parent, const char *name) + : KPanelExtension(configFile, type, actions, parent, name) +{ + dragging_container = 0; + kwin_module = new KWinModule(this); + connect( kwin_module, SIGNAL( windowAdded(WId) ), SLOT( windowAdded(WId) ) ); + setMinimumSize(DockContainer::sz(), DockContainer::sz()); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + loadContainerConfig(); +} + +DockBarExtension::~DockBarExtension() +{ + // kill nicely the applets + for (DockContainer::Vector::const_iterator it = containers.constBegin(); + it != containers.constEnd(); + ++it) + { + (*it)->kill(); + } + + if (dragging_container) delete dragging_container; +} + +QSize DockBarExtension::sizeHint(Position p, QSize) const +{ + if (p == Left || p == Right) + return QSize(DockContainer::sz(), DockContainer::sz() * containers.count()); + else + return QSize(DockContainer::sz() * containers.count(), DockContainer::sz()); +} + +void DockBarExtension::resizeEvent(QResizeEvent*) +{ + layoutContainers(); +} + + +void DockBarExtension::windowAdded(WId win) +{ + // try to read WM_COMMAND + int argc; + char **argv; + QString command; + if (XGetCommand(qt_xdisplay(), win, &argv, &argc)) { + command = KShell::joinArgs(argv, argc); + XFreeStringList(argv); + } + + // try to read wm hints + WId resIconwin = 0; + XWMHints *wmhints = XGetWMHints(qt_xdisplay(), win); + if (0 != wmhints) { // we managed to read wm hints + // read IconWindowHint + bool is_valid = false; + /* a good dockapp set the icon hint and the state hint, + if it uses its icon, the window initial state must be "withdrawn" + if not, then the initial state must be "normal" + this filters the problematic Eterm whose initial state is "normal" + and which has an iconwin. + */ + if ((wmhints->flags & IconWindowHint) && + (wmhints->flags & StateHint)) { + resIconwin = wmhints->icon_window; + is_valid = (resIconwin && wmhints->initial_state == 0) || + (resIconwin == 0 && wmhints->initial_state == 1); + + /* an alternative is a window who does not have an icon, + but whose initial state is set to "withdrawn". This has been + added for wmxmms... I hope it won't swallow to much windows :-/ + */ + } else if ((wmhints->flags & IconWindowHint) == 0 && + (wmhints->flags & StateHint)) { + is_valid = (wmhints->initial_state == 0); + } + XFree(wmhints); + if (!is_valid) + return; // we won't swallow this one + } + else + return; + + // The following if statement was at one point commented out, + // without a comment as to why. This caused problems like + // Eterm windows getting swallowed whole. So, perhaps now I'll + // get bug reports about whatever commenting it out was supposed + // to fix. + if (resIconwin == 0) + resIconwin = win; + + // try to read class hint + XClassHint hint; + QString resClass, resName; + if (XGetClassHint(qt_xdisplay(), win, &hint)) { + resName = hint.res_name; + resClass = hint.res_class; + } + else { + kdDebug() << "Could not read XClassHint of window " << win << endl; + return; + } + /* withdrawing the window prevents kwin from managing the window, + which causes the double-launch bug (one instance from the kwin + session, and one from the dockbar) bug when kde is restarted */ + if (resIconwin != win) { + XWithdrawWindow( qt_xdisplay(), win, qt_xscreen() ); + while( KWin::windowInfo(win, NET::XAWMState).mappingState() != NET::Withdrawn ); + } + + // add a container + embedWindow(resIconwin, command, resName, resClass); + saveContainerConfig(); +} + +void DockBarExtension::layoutContainers() +{ + int i = 0; + for (DockContainer::Vector::const_iterator it = containers.constBegin(); + it != containers.constEnd(); + ++it) + { + if (orientation() == Horizontal) + (*it)->move(DockContainer::sz() * i, 0); + else + (*it)->move(0, DockContainer::sz() * i); + i++; + } +} + +void DockBarExtension::embedWindow(WId win, QString command, QString resName, QString resClass) +{ + if (win == 0) return; + DockContainer* container = 0; + bool ncmd = false; + + for (DockContainer::Vector::const_iterator it = containers.constBegin(); + it != containers.constEnd(); + ++it) + { + DockContainer* c = *it; + if (c->embeddedWinId() == 0 && + c->resName() == resName && + c->resClass() == resClass && + (command.isNull() || c->command() == command)) + { + container = c; + break; + } + } + + if (container == 0) { + QString cmd = command.isNull() ? resClass : command; + if (KStandardDirs::findExe(KShell::splitArgs(cmd).front()).isEmpty()) + ncmd = true; + container = new DockContainer(cmd, this, resName, resClass); + addContainer(container); + } + + container->embed(win); + layoutContainers(); + emit updateLayout(); + if (ncmd) + container->askNewCommand(); + } + +void DockBarExtension::addContainer(DockContainer* c, int pos) +{ + if (pos == -1) + { + containers.append(c); + } + else + { + DockContainer::Vector::iterator it = containers.begin(); + + for (int i = 0; i < pos && it != containers.end(); ++i) + { + ++it; + } + ++it; + + containers.insert(it, c); + } + connect(c, SIGNAL(embeddedWindowDestroyed(DockContainer*)), + SLOT(embeddedWindowDestroyed(DockContainer*))); + connect(c, SIGNAL(settingsChanged(DockContainer*)), + SLOT(settingsChanged(DockContainer*))); + c->resize(DockContainer::sz(), DockContainer::sz()); + c->show(); +} + +void DockBarExtension::removeContainer(DockContainer* c) +{ + DockContainer::Vector::iterator it = qFind(containers.begin(), containers.end(), c); + + if (it == containers.end()) + { + return; + } + + containers.erase(it); + delete c; + layoutContainers(); +} + +void DockBarExtension::embeddedWindowDestroyed(DockContainer* c) +{ + removeContainer(c); + saveContainerConfig(); + emit updateLayout(); +} + +void DockBarExtension::settingsChanged(DockContainer *) +{ + saveContainerConfig(); +} + +void DockBarExtension::saveContainerConfig() +{ + QStringList applet_list; + KConfig *conf = config(); + unsigned count = 0; + + for (DockContainer::Vector::const_iterator it = containers.constBegin(); + it != containers.constEnd(); + ++it) + { + DockContainer* c = *it; + if (!c->command().isEmpty()) + { + QString applet_gid = QString("Applet_%1").arg(QString::number(count)); + applet_list.append(applet_gid); + conf->setGroup(applet_gid); + conf->writePathEntry("Command", c->command()); + conf->writePathEntry("resName", c->resName()); + conf->writeEntry("resClass", c->resClass()); + ++count; + } + } + conf->setGroup("General"); + conf->writeEntry("Applets", applet_list); + conf->deleteEntry("Commands"); // cleanup old config + conf->sync(); +} + +void DockBarExtension::loadContainerConfig() +{ + KConfig *conf = config(); + conf->setGroup("General"); + QStringList applets = conf->readListEntry("Applets"); + + QStringList fail_list; + for (QStringList::Iterator it = applets.begin(); it != applets.end(); ++it) { + if (!conf->hasGroup(*it)) continue; + conf->setGroup(*it); + QString cmd = conf->readPathEntry("Command"); + QString resName = conf->readPathEntry("resName"); + QString resClass = conf->readEntry("resClass"); + if (cmd.isEmpty() || resName.isEmpty() || resClass.isEmpty()) continue; + + DockContainer* c = new DockContainer(cmd, this, resName, resClass ); + addContainer(c); + + KProcess proc; + proc << KShell::splitArgs( cmd ); + if (!proc.start(KProcess::DontCare)) { + fail_list.append(cmd); + removeContainer(c); + } + } + if (!fail_list.isEmpty()) + KMessageBox::queuedMessageBox(0, KMessageBox::Information, i18n("The following dockbar applets could not be started: %1").arg(fail_list.join(", ")), i18n("kicker: information"), 0); + saveContainerConfig(); +} + +int DockBarExtension::findContainerAtPoint(const QPoint& p) +{ + int i = 0; + for (DockContainer::Vector::const_iterator it = containers.constBegin(); + it != containers.constEnd(); + ++it, ++i) + { + if ((*it)->geometry().contains(p)) + { + return i; + } + } + + return -1; +} + +void DockBarExtension::mousePressEvent(QMouseEvent *e ) { + if (e->button() == LeftButton) { + // Store the position of the mouse clic. + mclic_pos = e->pos(); + } else if (e->button() == RightButton) { + int pos = findContainerAtPoint(e->pos()); + if (pos != -1) containers.at(pos)->popupMenu(e->globalPos()); + } +} + +void DockBarExtension::mouseReleaseEvent(QMouseEvent *e ) { + if (e->button() != LeftButton) return; + if (dragging_container) { + releaseMouse(); + original_container->embed(dragging_container->embeddedWinId()); + delete dragging_container; dragging_container = 0; + layoutContainers(); + saveContainerConfig(); + } +} + +void DockBarExtension::mouseMoveEvent(QMouseEvent *e) { + if (! (e->state() & LeftButton) ) return; + if (dragging_container == 0) { + // Check whether the user has moved far enough. + int delay = QApplication::startDragDistance(); + if ( (mclic_pos - e->pos()).manhattanLength() > delay ) { + int pos = findContainerAtPoint(e->pos()); + original_container = 0; + if (pos > -1) { + original_container = containers.at(pos); + mclic_dock_pos = e->pos() - original_container->pos(); + dragged_container_original_pos = pos; + dragging_container = new DockContainer(original_container->command(), 0, original_container->resName(), original_container->resClass(), true); + dragging_container->show(); + dragging_container->embed(original_container->embeddedWinId()); + grabMouse(); + } + } + } + if (dragging_container) { + dragging_container->move(e->globalPos() - mclic_dock_pos); + + // change layout of other containers + QPoint dragpos(dragging_container->pos()), + barpos(mapToGlobal(pos())); + int pdrag1,pdrag2,psz; + pdrag1 = dragpos.x() - barpos.x() + DockContainer::sz()/2; + pdrag2 = dragpos.y() - barpos.y() + DockContainer::sz()/2; + if (orientation() == Vertical) { + int tmp = pdrag1; pdrag1 = pdrag2; pdrag2 = tmp; + psz = height(); + } else psz = width(); + if (pdrag2 >= 0 && pdrag2 < DockContainer::sz() && pdrag1 >= 0 && pdrag1 < psz) + pdrag1 /= DockContainer::sz(); + else + pdrag1 = dragged_container_original_pos; + + + DockContainer::Vector::iterator it = qFind(containers.begin(), containers.end(), original_container); + + if (it == containers.end()) + { + return; + } + + DockContainer::Vector::iterator target = containers.begin(); + for (int i = 0; i < pdrag1 && target != containers.end(); ++i) + { + ++target; + } + + containers.erase(it); + containers.insert(target, original_container); + layoutContainers(); + } +} diff --git a/kicker/extensions/dockbar/dockbarextension.desktop b/kicker/extensions/dockbar/dockbarextension.desktop new file mode 100644 index 000000000..53dff4bb0 --- /dev/null +++ b/kicker/extensions/dockbar/dockbarextension.desktop @@ -0,0 +1,148 @@ +[Desktop Entry] +Name=Dock Application Bar +Name[af]=Vasmeer Program Balk +Name[az]=Proqram Çubuğunu Yapışdır +Name[be]=Аплет убудоўвання праграмаў +Name[bg]=Допълнителен панел +Name[bn]=ডক অ্যাপলিকেশন বার +Name[bs]=Traka za dokiranje aplikacija +Name[ca]=Barra per ancorar aplicacions +Name[cs]=Lišta pro dokování aplikací +Name[csb]=Lëstew przërzeszaniô programów +Name[cy]=Docio'r Bar Cymhwysiad +Name[da]=Dok programlinje +Name[de]=Programm-Andockleiste +Name[el]=Γραμμή προσαρτημένων εφαρμογών +Name[eo]=Aplikaĵostrio +Name[es]=Barra para anclar aplicaciones +Name[et]=Dokitavate rakenduste riba +Name[eu]=Aplikazioak ainguratzeko barra +Name[fa]=میله کاربرد پیوند +Name[fi]=Upotettava ohjelmapalkki +Name[fr]=Barre de stockage des applications +Name[fy]=Ekstra systeemfak +Name[gl]=Acoplar Barra de Aplicación +Name[he]=מעגן יישומים +Name[hi]=अनुप्रयोग पट्टी डॉक करें +Name[hr]=Usidravanje trake aplikacija +Name[hu]=Alkalmazásdokkoló +Name[id]=Aplikasi Dock bar +Name[is]=Kví fyrir forrit +Name[it]=Barra per le applicazioni Dock +Name[ja]=ドックアプリケーションバー +Name[kk]=Қолданбаларды тіркеу панелі +Name[km]=របារកម្មវិធីចូលផែ +Name[ko]=KDE 응용 프로그램 +Name[lo]=ແຖບພັກແອບພີເຄຊັ້ນ +Name[lt]=Pritvirtintų programų juosta +Name[lv]=Dokot Aplikāciju Joslu +Name[mk]=Лента за вкотвување на апликации +Name[mn]=Програм-шигтгэх самбар +Name[ms]=Bar Aplikasi Dok +Name[mt]=Waħħal il-bar tal-programmi +Name[nb]=Festet programlinje +Name[nds]=Andockbalken +Name[ne]=डक अनुप्रयोगपट्टी +Name[nl]=Extra systeemvak +Name[nn]=Dokka programlinje +Name[nso]=Bar ya Tshomiso ya Dock +Name[pa]=ਡੋਕ ਕਾਰਜ ਪੱਟੀ +Name[pl]=Pasek dokowania programów +Name[pt]=Barra de Aplicações Acopláveis +Name[pt_BR]=Barra de aplicativos integrados +Name[ro]=Bară de docare aplicații +Name[ru]=Панель для встраивания приложений +Name[rw]=Umurongo Porogaramu Bikomatanye +Name[se]=Vuojuhuvvon prográmmaid holga +Name[sk]=Panel na dokovanie aplikácií +Name[sl]=Vrstica za zasidranje programov +Name[sr]=Трака за пристајање програма +Name[sr@Latn]=Traka za pristajanje programa +Name[sv]=Programdocka +Name[ta]=டாக் பயன்பாட்டு பட்டி +Name[tg]=Навори барномаи обзор +Name[th]=แถบพักแอพพลิเคชัน +Name[tr]=Uygulama çubuğunu gizle +Name[tt]=Yazılım Utırtu Taqtası +Name[uk]=Док-панель для програм +Name[vi]=Bến đỗ Thanh Chương trình +Name[wa]=Bår di wårdaedje des programes +Name[xh]=Ibar Yesicelo ye Dock +Name[zh_CN]=停靠应用程序栏 +Name[zh_TW]=嵌入程式工具列 +Name[zu]=Ibha Yomyaleli we-Dock +Comment=Dock application bar extension. +Comment[af]=Vasmeer program balk uitbreidings +Comment[az]=Proqram çubuğu uzantısını gizlət. +Comment[be]=Пашырэнне для ўбудавання праграмаў у панэль. +Comment[bg]=Разширение на системния панел +Comment[bn]=ডক অ্যাপলিকেশন বার এক্সটেনশন +Comment[bs]=Proširenje za dokiranje aplikacija +Comment[ca]=Una extensió de la barra per ancorar aplicacions. +Comment[cs]=Rozšíření lišty pro dokování aplikací. +Comment[csb]=Rozszérzenié do przërzeszaniô programów. +Comment[cy]=Docio estyniad y bar cymhwysiad +Comment[da]=Udvidelse - dok programlinje. +Comment[de]=Eine Andockleiste für Programme +Comment[el]=Επέκταση γραμμής προσαρτημένων εφαρμογών. +Comment[eo]=Aplikaĵostria aldono +Comment[es]=Extensión Barra para anclar aplicaciones. +Comment[et]=Paneeli laiendus dokitavate rakenduste hoidmiseks +Comment[eu]=Aplikazioak ainguratzeko barraren hedapena +Comment[fa]=پسوند میله کاربرد پیوند. +Comment[fi]=Upota ohjelmapalkkilaajennus +Comment[fr]=Stockage des applications dans une barre. +Comment[fy]=In balke wêryn tapassingen hun byldkaike kinne pleatse +Comment[gl]=Extensión de acoplamento de barras de aplicación +Comment[he]=הרחבת מעגן יישומים +Comment[hi]=अनुप्रयोग पट्टी विस्तार डॉक करें +Comment[hr]=Proširenje za usidravanje aplikacija +Comment[hu]=Alkalmazásdokkoló kiterjesztés. +Comment[id]=Panel dock ektensi untuk aplikasi +Comment[is]=Útvíkkun kvíar fyrir ísett forrit. +Comment[it]=Estensione per la barra delle applicazioni Dock. +Comment[ja]=アプリケーション用のドックパネル +Comment[kk]=Қолданбаларды тіркеу үшін панель. +Comment[km]=ផ្នែកបន្ថែមរបារកម្មវិធីចូលផែ ។ +Comment[lo]=ສ່ວນຂະຫຍາຍເພີ້ນຕື່ມພາເນລແຖລພັກແອລພີເຄຊັ້ນ +Comment[lt]=Pritvirtintų programų juostos plėtinys. +Comment[lv]=Doko aplikāciju joslas paplašinājumu. +Comment[mk]=Екстензија за вкотвување на апликации. +Comment[mn]=Програмын шигтгээ самбар өргөтгөл +Comment[ms]=Lanjutan bar aplikasi dok. +Comment[mt]=Estensjoni biex twaħħal il-bar tal-programmi. +Comment[nb]=Festepanel for programmer +Comment[nds]=Andockbalken för Programmen +Comment[ne]=डक अनुप्रयोगपट्टी विस्तार +Comment[nl]=Een balk waarin toepassingen hun pictogram kunnen plaatsen +Comment[nn]=Dokkingspanel for program +Comment[nso]=Koketso ya bar ya tshomiso ya dock. +Comment[pa]=ਡੋਕ ਕਾਰਜ ਪੱਟੀ ਵਧਾਰਾ ਹੈ। +Comment[pl]=Rozszerzenie do dokowania programów. +Comment[pt]=Uma extensão de barra de aplicações acopláveis. +Comment[pt_BR]=Extensão da barra de aplicativos embutidos. +Comment[ro]=Extensie bară de docare aplicații. +Comment[ru]=Расширение панели для встраивания приложений. +Comment[rw]=Iyagura ry'umurongo w'ikomatanya porogaramu +Comment[se]=Prográmmaid vuojuhanpanela +Comment[sk]=Rozšírenie pre dokovací panel aplikácií +Comment[sl]=Razširitev za sidrišče programov. +Comment[sr]=Проширење траке за пристајање програма. +Comment[sr@Latn]=Proširenje trake za pristajanje programa. +Comment[sv]=Bygger ut med en programdocka +Comment[ta]=டாக் பயன்பாடு பட்டி விரிவாக்கம் +Comment[tg]=Кушодкунии панел барои бино кунӣ. +Comment[th]=ส่วนขยายเพิ่มเติมพาเนล แถบพักแอพพลิเคชัน +Comment[tr]=Uygulama çubuğu uzantısını gizle. +Comment[tt]=Yazılım utırtuçı taqta östämäse. +Comment[uk]=Розширення док-панелі для програм. +Comment[vi]=Bến đỗ các thanh chương trình mở rộng +Comment[wa]=Module di bår di wårdaedje des programes +Comment[xh]=Ulwandiso lwe bar yesicelo se Dock. +Comment[zh_CN]=停靠应用程序栏扩展。 +Comment[zh_TW]=嵌入延伸程式工具列 +Comment[zu]=Isandiso sebha Yomyaleli we-Dock + +Icon=dockbar +X-KDE-Library=dockbar_panelextension +X-KDE-UniqueApplet=true diff --git a/kicker/extensions/dockbar/dockbarextension.h b/kicker/extensions/dockbar/dockbarextension.h new file mode 100644 index 000000000..0003ec6fa --- /dev/null +++ b/kicker/extensions/dockbar/dockbarextension.h @@ -0,0 +1,73 @@ +/***************************************************************** + +Copyright (c) 2000 Matthias Elter + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef __dockbarextension_h__ +#define __dockbarextension_h__ + +#include <qvaluevector.h> +#include <kpanelextension.h> +#include "dockcontainer.h" + +class KWinModule; + +class DockBarExtension : public KPanelExtension +{ + Q_OBJECT + +public: + DockBarExtension(const QString& configFile, Type t = Normal, + int actions = 0, QWidget *parent = 0, const char *name = 0); + + virtual ~DockBarExtension(); + + QSize sizeHint(Position, QSize maxSize) const; + Position preferedPosition() const { return Right; } + +protected slots: + void windowAdded(WId); + void embeddedWindowDestroyed(DockContainer*); + void settingsChanged(DockContainer*); + +protected: + void resizeEvent(QResizeEvent*); + void embedWindow(WId win, QString command, QString resName, QString resClass); + void addContainer(DockContainer*, int pos=-1); + void removeContainer(DockContainer*); + void saveContainerConfig(); + void loadContainerConfig(); + void layoutContainers(); + int findContainerAtPoint(const QPoint&); + void mousePressEvent(QMouseEvent *); + void mouseReleaseEvent(QMouseEvent *); + void mouseMoveEvent(QMouseEvent *); +private: + KWinModule* kwin_module; + DockContainer::Vector containers; + + // handle the dragging of applets + DockContainer *dragging_container, *original_container; + QPoint mclic_pos, mclic_dock_pos; + int dragged_container_original_pos; +}; + +#endif diff --git a/kicker/extensions/dockbar/dockcontainer.cpp b/kicker/extensions/dockbar/dockcontainer.cpp new file mode 100644 index 000000000..f2117346d --- /dev/null +++ b/kicker/extensions/dockbar/dockcontainer.cpp @@ -0,0 +1,198 @@ +/***************************************************************** + +Copyright (c) 2000 Matthias Elter <elter@kde.org> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#include <qwidget.h> +#include <qtooltip.h> +#include <kwin.h> +#include <qvalidator.h> +#include <kinputdialog.h> +#include <klocale.h> +#include <kpopupmenu.h> +#include <kdebug.h> + +#include "dockcontainer.h" +#include "dockcontainer.moc" + +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> + + +DockContainer::DockContainer( QString command, QWidget *parent, + QString resname, QString resclass, bool undocked_style ) + : QFrame( parent, resname.ascii(), + undocked_style ? WStyle_Customize | + WStyle_StaysOnTop | WStyle_Tool | + WStyle_NoBorder | WX11BypassWM : 0 ), + _embeddedWinId(0), + _command(command), + _resName(resname), + _resClass(resclass) +{ + XSelectInput( qt_xdisplay(), winId(), + KeyPressMask | KeyReleaseMask | + ButtonPressMask | ButtonReleaseMask | + KeymapStateMask | + ButtonMotionMask | + PointerMotionMask | + EnterWindowMask | LeaveWindowMask | + FocusChangeMask | + ExposureMask | + StructureNotifyMask | + SubstructureRedirectMask | + SubstructureNotifyMask ); + if (!undocked_style) { + setFrameStyle(StyledPanel | Raised); + setLineWidth(border()); + QToolTip::add(this, command); + } else { + setFrameStyle(StyledPanel | Plain); + setLineWidth(1); + } + resize(sz(),sz()); +} + +void DockContainer::embed( WId id ) +{ + if( id == _embeddedWinId || id == 0) + return; + QRect geom = KWin::windowInfo(id,NET::WMKDEFrameStrut).frameGeometry(); + + // does the same as KWM::prepareForSwallowing() + XWithdrawWindow( qt_xdisplay(), id, qt_xscreen() ); + while( KWin::windowInfo(id, NET::XAWMState).mappingState() != NET::Withdrawn ); + + XReparentWindow( qt_xdisplay(), id, winId(), 0, 0 ); + + // resize if window is bigger than frame + if( (geom.width() > width()) || + (geom.height() > height()) ) + XResizeWindow( qt_xdisplay(), id, width(), height() ); + else + XMoveWindow(qt_xdisplay(), id, + (sz() - geom.width())/2 - border(), + (sz() - geom.height())/2 - border()); + XMapWindow( qt_xdisplay(), id ); + XUngrabButton( qt_xdisplay(), AnyButton, AnyModifier, winId() ); + + _embeddedWinId = id; +} + +void DockContainer::unembed() +{ + if( _embeddedWinId ) + XReparentWindow( qt_xdisplay(), _embeddedWinId, qt_xrootwin(), 0, 0 ); +} + +void DockContainer::kill() +{ + if ( _embeddedWinId ) { + XKillClient( qt_xdisplay(), _embeddedWinId ); + _embeddedWinId = 0; // in case the window does not exist anymore.. + } + else emit embeddedWindowDestroyed(this); /* enable killing of empty windows.. */ +} + +bool DockContainer::x11Event( XEvent *e ) +{ + switch( e->type ) { + case DestroyNotify: + if( e->xdestroywindow.window == _embeddedWinId || _embeddedWinId == 0) { + _embeddedWinId = 0; + emit embeddedWindowDestroyed(this); + } + break; + case UnmapNotify: + if ( e->xunmap.window == _embeddedWinId ) { + kdDebug() << "Unmap Notify !!! I hate smart dockapps as wmpinboard " << command() << endl; + _embeddedWinId = 0; + } + break; + case ReparentNotify: + if( _embeddedWinId && + (e->xreparent.window == _embeddedWinId) && + (e->xreparent.parent != winId()) ) { + _embeddedWinId = 0; + } + else if( e->xreparent.parent == winId() ) { + _embeddedWinId = e->xreparent.window; + embed( _embeddedWinId ); + } + break; + } + + return false; +} + +void DockContainer::askNewCommand(bool bad_command) +{ + bool ok; + QString title( i18n("Enter Command Line for Applet %1.%2").arg(resName()).arg(resClass()) ); + QString description( i18n("This applet does not behave correctly and the dockbar was unable to " + "find the command line necessary to launch it the next time KDE starts up") ); + QString cmd; + + /* + I was not able to figure out why valgrind complains inside the getText call.. + (invalid read of size 1 in Xmb.. functions) + */ + if (bad_command) { + cmd = KInputDialog::getText( title, description, + command(), &ok, this ); + } else { + cmd = KInputDialog::getText( title, QString::null, + command(), &ok, this ); + } + if (ok) { _command = cmd; emit settingsChanged(this); } +} + +void DockContainer::popupMenu(QPoint p) +{ + int r; + { + KPopupMenu pm(this); + pm.insertItem( i18n("Kill This Applet"), 0); + pm.insertItem( i18n("Change Command"), 1); + r = pm.exec(p); + /* pm is destroyed now .. if it is destroyed later, + there is a risk that kill() double-frees it */ + } + switch (r) { + case 0: { + kill(); + } break; + case 1: { + askNewCommand(false); + } break; + } +} + +int& DockContainer::sz() { + static int _sz = 66; + return _sz; +} + +int& DockContainer::border() { + static int _border = 1; + return _border; +} diff --git a/kicker/extensions/dockbar/dockcontainer.h b/kicker/extensions/dockbar/dockcontainer.h new file mode 100644 index 000000000..bc9962290 --- /dev/null +++ b/kicker/extensions/dockbar/dockcontainer.h @@ -0,0 +1,90 @@ +/***************************************************************** + +Copyright (c) 2000 Matthias Elter <elter@kde.org> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef __dockcontainer_h__ +#define __dockcontainer_h__ + +#include <qframe.h> +#include <qvaluevector.h> + +class DockContainer : public QFrame +{ + Q_OBJECT + +public: + typedef QValueVector<DockContainer*> Vector; + + DockContainer( QString command, QWidget *parent, + QString resname, + QString resclass, + bool undocked_style=false); + + void embed(WId); + void unembed(); + void kill(); + + WId embeddedWinId() const; + QString command() const; + QString resClass() const; + QString resName() const; + void askNewCommand(bool bad_command=true); + void popupMenu(QPoint p); + static int& sz(); + static int& border(); +signals: + void embeddedWindowDestroyed(DockContainer*); + void settingsChanged(DockContainer*); + +protected: + bool x11Event( XEvent * ); + +private: + WId _embeddedWinId; + QString _command; + QString _resName, _resClass; +}; + + +inline WId DockContainer::embeddedWinId() const +{ + return _embeddedWinId; +} + +inline QString DockContainer::command() const +{ + return _command; +} + +inline QString DockContainer::resClass() const +{ + return _resClass; +} + +inline QString DockContainer::resName() const +{ + return _resName; +} + + +#endif + |