diff options
Diffstat (limited to 'kdesktop')
152 files changed, 25399 insertions, 0 deletions
diff --git a/kdesktop/AUTHORS b/kdesktop/AUTHORS new file mode 100644 index 000000000..05bcfd697 --- /dev/null +++ b/kdesktop/AUTHORS @@ -0,0 +1,4 @@ +Torben Weis <[email protected]> +David Faure <[email protected]> +Martin R. Jones <[email protected]> +Geert Jansen <[email protected]> diff --git a/kdesktop/CMakeLists.txt b/kdesktop/CMakeLists.txt new file mode 100644 index 000000000..80ea9c21a --- /dev/null +++ b/kdesktop/CMakeLists.txt @@ -0,0 +1,109 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include( ConfigureChecks.cmake ) + +add_subdirectory( lock ) +add_subdirectory( pics ) +add_subdirectory( patterns ) +add_subdirectory( programs ) +add_subdirectory( init ) +add_subdirectory( kwebdesktop ) + + +if( NOT BUILD_LIBKONQ ) + include( "${TDE_CMAKE_DIR}/libkonq.cmake" ) +endif( NOT BUILD_LIBKONQ ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/tdmlib + ${CMAKE_SOURCE_DIR}/kcontrol/background + ${CMAKE_SOURCE_DIR}/libkonq + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} + ${DBUS_INCLUDE_DIRS} + ${DBUS_1_TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} + ${LIBART_LIBRARY_DIRS} + ${DBUS_1_TQT_LIBRARY_DIRS} +) + + +##### headers ################################### + +install( FILES + KDesktopIface.h KScreensaverIface.h KBackgroundIface.h + DESTINATION ${INCLUDE_INSTALL_DIR} ) + + +##### other data ################################ + +configure_file( kdesktop.desktop.cmake kdesktop.desktop @ONLY ) + +install( FILES ${CMAKE_CURRENT_BINARY_DIR}/kdesktop.desktop DESTINATION ${AUTOSTART_INSTALL_DIR} ) +install( FILES kdesktop_custom_menu1 kdesktop_custom_menu2 DESTINATION ${CONFIG_INSTALL_DIR} ) +install( FILES kdesktopSetAsBackground.desktop DESTINATION ${DATA_INSTALL_DIR}/konqueror/servicemenus ) +install( FILES kdesktop.kcfg tdelaunch.kcfg DESTINATION ${KCFG_INSTALL_DIR} ) + + +##### kcheckrunning (executable) ################ + +tde_add_executable( kcheckrunning + SOURCES kcheckrunning.cpp + LINK ${TQT_LIBRARIES} X11 + DESTINATION ${BIN_INSTALL_DIR} +) + + +##### kxdglauncher (executable) ################# + +tde_add_executable( kxdglauncher + SOURCES kxdglauncher.cpp + LINK tdeutils-shared + DESTINATION ${BIN_INSTALL_DIR} +) + + +##### kdesktop (tdeinit) ######################## + +set( target kdesktop ) + +set( ${target}_SRCS + main.cc krootwm.cc xautolock.cc kdiconview.cc init.cc + desktop.cc lockeng.cc KDesktopIface.skel bgmanager.cc + KScreensaverIface.skel minicli.cpp KBackgroundIface.skel + pixmapserver.cc kcustommenu.cc startupid.cpp minicli_ui.ui + xautolock_diy.c xautolock_engine.c kshadowengine.cpp + kshadowsettings.cpp kdesktopshadowsettings.cpp + tdefileividesktop.cpp kdesktopapp.cpp +) + +tde_add_tdeinit_executable( ${target} AUTOMOC + SOURCES ${${target}_SRCS} + LINK + kdesktopsettings-static bgnd-static dmctl-static + konq-shared tdeutils-shared + ${XRENDER_LIBRARIES} ${XCURSOR_LIBRARIES} Xext dl + ${XSS_LIBRARIES} ${DBUS_1_TQT_LIBRARIES} +) + + +##### kdesktopsettings (static) ################# + +tde_add_library( kdesktopsettings STATIC_PIC + SOURCES kdesktopsettings.kcfgc tdelaunchsettings.kcfgc +) diff --git a/kdesktop/ConfigureChecks.cmake b/kdesktop/ConfigureChecks.cmake new file mode 100644 index 000000000..bc53ec698 --- /dev/null +++ b/kdesktop/ConfigureChecks.cmake @@ -0,0 +1,14 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +if( WITH_PAM ) + set( TDESCREENSAVER_PAM_SERVICE "kde" CACHE INTERNAL "" ) +endif( ) diff --git a/kdesktop/DESIGN b/kdesktop/DESIGN new file mode 100644 index 000000000..f69ee2198 --- /dev/null +++ b/kdesktop/DESIGN @@ -0,0 +1,94 @@ +KDesktop Design Document + +Author : + David Faure, [email protected] + Martin R. Jones, [email protected] (screensaver) + Geert Jansen, [email protected] (background code) + +Last modified: 24 Oct 1999 + +Overall design of KDesktop : +============================= + +KDesktop is the program that handles the desktop icons, +the popup menus for the desktop, the mac menubar, and the +screensaver system. + +Files : +======= + +main.* : main +desktop.* : the icon container for the desktop icons +krootwm.* : right and middle mouse button popup menus, Mac menubar +bg*.*: Background renderer/manager. + +icons.* : old code, not used anymore. + We need to borrow ideas from it for positioning icons after a DnD + (in kiconcontainer so that it works with konqueror as well) + - well, only if we want dropped icons to remain where they have been + dropped :) + We also need to store the desktop icons position, like was done in kfm. + and we need to do it for konqy as well. + +KDesktopIface* : DCOP interface for kdesktop, used by kfmclient + +lock* : screen saver/locker + +Libs used by KDesktop +====================== + +tdecore, tdeui, tdefile - usual stuff :) +libtdeio - I/O stuff, mimetypes, services, registry +libkonq - properties dialog, templates ("new") menu, dir lister, settings + +Screensaver +=========== + +The screensaver now works in a similar way to xscreensaver, i.e. a driver +(kdesktop) provides the timeout, locking, and blanking functionality, but +does no actual drawing. A separate stand-alone program capable of +drawing on a supplied window is used to do the actual fancy graphics. +xscreensaver's "hacks" will work with the KDE screensaver engine. + +This makes adding new screensavers trivial, and means one less process that +must always be running (compared to KDE 1.x). + +The screensaver is controlled via DCOP: + +KScreensaverIface::configure() Reloads the screensaver config from desktoprc. +KScreensaverIface::lock() Locks the screen immediately. +KScreensaverIface::save() Saves the screen immediately. +KScreensaverIface::isEnabled() returns true if the screensaver is enabled. +KScreensaverIface::isBlanked() returns true if the screen is currently blank. + +Backgrounds +=========== + +The new background code is in bgrender.cpp and bgmanager.cpp. Some features: + +* Support for xearth like programs. +* Can export a pixmap of the desktop background for pseudo transparency. + +Multiple monitors +================= +Two monitors showing different things (not a mirror-setup) can be configured +in X to either use one X screen, or 2 X screens. Difference is that if I +drag a window from one monitor to the other the application gets asked to +repaint itself on a 2 screen setup and a simple move of the window will be +done in memory (by XFree) if you have a 1 screen setup. + +Monitors example: + +----+ +-----+ 2 monitors, with same resolution to keep it simple. + | | | | + +----+ +-----+ + +In case of 1 screen (xinerama) + +------------+ + | + desktopGeometry == screenGeometry == 3200 x 1200 + +------------+ + +In case of 2 screen (multihead) + +----+ +-----+ + | | | | desktopGeometry = 3200 x 1200 + +----+ +-----+ screenGeometry = 1600 x 1200 (for each monitor) + diff --git a/kdesktop/KBackgroundIface.h b/kdesktop/KBackgroundIface.h new file mode 100644 index 000000000..0753b54aa --- /dev/null +++ b/kdesktop/KBackgroundIface.h @@ -0,0 +1,77 @@ +/** + * DCOP interface for the background manager. + */ + +#ifndef __KBackgroundIface_h__ +#define __KBackgroundIface_h__ + +#include <dcopobject.h> +#include <tqcolor.h> + +class KBackgroundIface : public DCOPObject +{ + K_DCOP +public: + + KBackgroundIface() : DCOPObject("KBackgroundIface") {} + +k_dcop: + /** Reread the configuration */ + virtual void configure() = 0; + + /** Enable/disable export of the background pixmap. */ + virtual void setExport(int xport) = 0; + + /** Returns the export desktop pixmap state. */ + virtual bool isExport() = 0; + + /** Enable/disable common desktop background. */ + virtual void setCommon(int common) = 0; + + /** Returns the common desktop background state. */ + virtual bool isCommon() = 0; + + /** Change caching behaviour. + * @param bLimit Limit cache if not equal to zero. + * @param size Cache size in kilobytes. */ + virtual void setCache(int bLimit, int size) = 0; + + /** Change the wallpaper. + * @param desk desktop number, or 0 for the current visible desktop. + * @param wallpaper The (local) path to the wallpaper. + * @param mode The tiling mode. */ + virtual void setWallpaper(int desk, TQString wallpaper, int mode) = 0; + + /** Change the wallpaper. + * @param wallpaper The (local) path to the wallpaper. + * @param mode The tiling mode. */ + virtual void setWallpaper(TQString wallpaper, int mode) = 0; + + /** Set color. + * @param c The color. + * @param isColorA true for foreground and false for background color. */ + virtual void setColor(const TQColor &c, bool isColorA) = 0; + + /** Change the wallpaper in "multi mode". */ + virtual void changeWallpaper() = 0; + + /** Enable/disable desktop background. */ + virtual void setBackgroundEnabled(const bool enable) = 0; + + /** Return the current wallpaper for specified desk. + * @param desk desktop number, or 0 for the current visible desktop. + */ + virtual TQString currentWallpaper( int desk ) = 0; + + /** Return the wallpaper list for specified desk. + * @param desk desktop number, or 0 for the current visible desktop. + */ + virtual TQStringList wallpaperList(int desk) = 0; + + /** Return the wallpaper files for specified desk. + * @param desk desktop number, or 0 for the current visible desktop. + */ + virtual TQStringList wallpaperFiles(int desk) = 0; +}; + +#endif // __KBackgroundIface_h__ diff --git a/kdesktop/KDesktopIface.h b/kdesktop/KDesktopIface.h new file mode 100644 index 000000000..945fb4ca8 --- /dev/null +++ b/kdesktop/KDesktopIface.h @@ -0,0 +1,156 @@ + +#ifndef __KDesktopIface_h__ +#define __KDesktopIface_h__ + +#include <tqstringlist.h> +#include <dcopobject.h> +#include <dcopref.h> + +class KDesktopIface : public DCOPObject +{ + K_DCOP +public: + + KDesktopIface() : DCOPObject("KDesktopIface") {} + +k_dcop: + /** + * @internal + */ + virtual void runAutoStart() = 0; + + /** + * Re-arrange the desktop icons. + */ + virtual void rearrangeIcons() = 0; + /** + * @deprecated + */ + void rearrangeIcons( bool ) { rearrangeIcons(); } + /** + * Lineup the desktop icons. + */ + virtual void lineupIcons() = 0; + /** + * Select all icons + */ + virtual void selectAll() = 0; + /** + * Unselect all icons + */ + virtual void unselectAll() = 0; + /** + * Refresh all icons + */ + virtual void refreshIcons() = 0; + /** + * Set show desktop state + */ + virtual void setShowDesktop( bool b ) = 0; + /** + * @return the show desktop state + */ + virtual bool showDesktopState() = 0; + /** + * Toggle show desktop state + */ + virtual void toggleShowDesktop() = 0; + /** + * @return the urls of selected icons + */ + virtual TQStringList selectedURLs() = 0; + + /** + * Re-read KDesktop's configuration + */ + virtual void configure() = 0; + /** + * Display the "Run Command" dialog (minicli) + */ + virtual void popupExecuteCommand() = 0; + /** + * Display the "Run Command" dialog (minicli) and prefill + * @since 3.4 + */ + virtual void popupExecuteCommand(const TQString& command) = 0; + /** + * Get the background dcop interface (KBackgroundIface) + */ + DCOPRef background() { return DCOPRef( "kdesktop", "KBackgroundIface" ); } + /** + * Get the screensaver dcop interface (KScreensaverIface) + */ + DCOPRef screenSaver() { return DCOPRef( "kdesktop", "KScreensaverIface" ); } + /** + * Full refresh + */ + virtual void refresh() = 0; + /** + * Bye bye + */ + virtual void logout() = 0; + /** + * Returns whether KDesktop uses a virtual root. + */ + virtual bool isVRoot() = 0; + /** + * Set whether KDesktop should use a virtual root. + */ + virtual void setVRoot( bool enable )= 0; + /** + * Clears the command history and completion items + */ + virtual void clearCommandHistory() = 0; + /** + * Returns whether icons are enabled on the desktop + */ + virtual bool isIconsEnabled() = 0; + /** + * Disable icons on the desktop. + */ + virtual void setIconsEnabled( bool enable )= 0; + + /** + * Should be called by any application that wants to tell KDesktop + * to switch desktops e.g. the minipager applet on kicker. + */ + virtual void switchDesktops( int delta ) = 0; + + /** + * slot for kicker; called when the number or size of panels change the available + * space for desktop icons + */ + virtual void desktopIconsAreaChanged(const TQRect &area, int screen) = 0; + + /** + * Find the next free place for a not yet existing icon, so it fits + * in the user arrangement. Basicly prepare for icons to be moved in. + * It will try to find a place in the virtual grid near col,row + * where no other icon is. + * + * If you specify -1 for row or column, it will try to find the next + * free room where no other icon follows. E.g. if you specify column + * = -1 and row = 0, kdesktop will find the next vertical placement + * so that the icon appears at the end of the existing icons preferable + * in the first column. If the first column is full, it will find the + * next free room in the second column. + * + * If you specify both column and row, kdesktop won't care for aligning, + * or surrounding icons, but try to find the free place near the given + * grid place (e.g. specify 0,0 to find the nearest place in the left + * upper corner). + */ + virtual TQPoint findPlaceForIcon( int column, int row) = 0; + + /// copy the desktop file in the Desktop and place it at x, y + virtual void addIcon(const TQString &url, int x, int y) = 0; + + /// same with specific destination + virtual void addIcon(const TQString &url, const TQString &dest, int x, int y) = 0; + + /// remove the desktop file (either full path or relative) + virtual void removeIcon(const TQString &dest) = 0; +}; + +#endif + diff --git a/kdesktop/KScreensaverIface.h b/kdesktop/KScreensaverIface.h new file mode 100644 index 000000000..de5c19f2b --- /dev/null +++ b/kdesktop/KScreensaverIface.h @@ -0,0 +1,51 @@ + +#ifndef __KScreensaverIface_h__ +#define __KScreensaverIface_h__ + +#include <dcopobject.h> + +class KScreensaverIface : public DCOPObject +{ + K_DCOP +public: + + KScreensaverIface() : DCOPObject("KScreensaverIface") {} + +k_dcop: + /** Lock the screen now even if the screensaver does not lock by default. */ + virtual void lock() = 0; + + /** Save the screen now. If the user has locking enabled, the screen is + * locked also. */ + virtual void save() = 0; + + /** Quit the screensaver if it is running */ + virtual void quit() = 0; + + /** Is the screensaver enabled? */ + virtual bool isEnabled() = 0; + + /** + * Enable/disable the screensaver + * returns true if the action succeeded + */ + virtual bool enable( bool e ) = 0; + + /** Is the screen currently blanked? */ + virtual bool isBlanked() = 0; + + /** Reload the screensaver configuration. */ + virtual void configure() = 0; + + /** Only blank the screen (and possibly lock). Do not use a custom + * screen saver in the interest of saving battery. + */ + virtual void setBlankOnly( bool blankOnly ) = 0; + + /*** + * @internal + */ + virtual void saverLockReady() = 0; +}; + +#endif diff --git a/kdesktop/Makefile.am b/kdesktop/Makefile.am new file mode 100644 index 000000000..539db39f1 --- /dev/null +++ b/kdesktop/Makefile.am @@ -0,0 +1,77 @@ +## Makefile.am of tdebase/kdesktop + +INCLUDES = -I$(top_srcdir)/kcontrol/background -I$(top_srcdir)/libkonq -I$(top_srcdir)/tdmlib $(all_includes) +kdesktop_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kdesktop_la_LIBADD = libkdesktopsettings.la $(top_builddir)/libkonq/libkonq.la $(top_builddir)/kcontrol/background/libbgnd.la $(top_builddir)/tdmlib/libdmctl.la $(LIB_XSS) $(LIB_TDEUTILS) $(LIB_XCURSOR) + +SUBDIRS = . lock pics patterns programs init kwebdesktop + +####### Files + +bin_PROGRAMS = kcheckrunning kxdglauncher +lib_LTLIBRARIES = +tdeinit_LTLIBRARIES = kdesktop.la +noinst_LTLIBRARIES = libkdesktopsettings.la + +libkdesktopsettings_la_LDFLAGS = $(all_libraries) -no-undefined +libkdesktopsettings_la_LIBADD = $(LIB_TDECORE) +libkdesktopsettings_la_SOURCES = kdesktopsettings.kcfgc tdelaunchsettings.kcfgc + +kdesktop_la_SOURCES = main.cc krootwm.cc xautolock.cc kdiconview.cc desktop.cc \ + lockeng.cc KDesktopIface.skel \ + bgmanager.cc init.cc KScreensaverIface.skel \ + minicli.cpp KBackgroundIface.skel pixmapserver.cc kcustommenu.cc \ + startupid.cpp minicli_ui.ui xautolock_diy.c xautolock_engine.c \ + kshadowengine.cpp kshadowsettings.cpp \ + kdesktopshadowsettings.cpp tdefileividesktop.cpp \ + kdesktopapp.cpp + +include_HEADERS = KDesktopIface.h KScreensaverIface.h KBackgroundIface.h + +noinst_HEADERS = desktop.h bgmanager.h krootwm.h \ + xautolock.h lockeng.h init.h minicli.h \ + pixmapserver.h startupid.h xautolock_c.h \ + kdesktopapp.h kxdglauncher.h + +kcheckrunning_SOURCES = kcheckrunning.cpp +kcheckrunning_LDFLAGS = $(all_libraries) +kcheckrunning_LDADD = $(LIB_X11) $(LIB_QT) + +kxdglauncher_SOURCES = kxdglauncher.cpp +kxdglauncher_LDFLAGS = $(all_libraries) +kxdglauncher_LDADD = $(LIB_TDEUTILS) + +METASOURCES = AUTO + +####### Build rules + +# List made with: grep -l kdesktopsettings.h *[pc] | sed -e 's/\.c.*$/.lo: kdesktopsettings.h/' +bgmanager.lo: kdesktopsettings.h +desktop.lo: kdesktopsettings.h +init.lo: kdesktopsettings.h +kdesktopsettings.lo: kdesktopsettings.h +kdiconview.lo: kdesktopsettings.h +krootwm.lo: kdesktopsettings.h +lockeng.lo: kdesktopsettings.h +main.lo: kdesktopsettings.h +minicli.lo: kdesktopsettings.h + +# List made with: grep -l tdelaunchsettings.h *[pc] | sed -e 's/\.c.*$/.lo: tdelaunchsettings.h/' +desktop.lo: tdelaunchsettings.h +tdelaunchsettings.lo: tdelaunchsettings.h +startupid.lo: tdelaunchsettings.h + +messages: rc.cpp + $(EXTRACTRC) lock/*.ui >> rc.cpp + $(XGETTEXT) lock/*.cc *.cc *.cpp *.h -o $(podir)/kdesktop.pot + +menu_DATA = kdesktop_custom_menu1 kdesktop_custom_menu2 +menudir = $(kde_confdir) + +autostart_DATA = kdesktop.desktop +autostartdir = $(datadir)/autostart + +konqservice_DATA = kdesktopSetAsBackground.desktop +konqservicedir = $(kde_datadir)/konqueror/servicemenus + +kde_kcfg_DATA = kdesktop.kcfg tdelaunch.kcfg diff --git a/kdesktop/bgmanager.cc b/kdesktop/bgmanager.cc new file mode 100644 index 000000000..ddb95c9e7 --- /dev/null +++ b/kdesktop/bgmanager.cc @@ -0,0 +1,1025 @@ +/* vi: ts=8 sts=4 sw=4 + * kate: space-indent on; tab-width 8; indent-width 4; indent-mode cstyle; + * + * This file is part of the KDE project, module kdesktop. + * Copyright (C) 1999,2000 Geert Jansen <[email protected]> + * + * You can Freely distribute this program under the GNU General Public + * License. See the file "COPYING" for the exact licensing terms. + */ + +#include <config.h> +#include "bgrender.h" +#include "bgmanager.h" +#include "bgdefaults.h" +#include "kdesktopsettings.h" +#include "bgsettings.h" +#include "kdesktopapp.h" + +#include <assert.h> + +#include <tqtimer.h> +#include <tqscrollview.h> + +#include <kiconloader.h> +#include <tdeconfig.h> +#include <twin.h> +#include <tdeapplication.h> +#include <kdebug.h> +#include <kipc.h> +#include <tdepopupmenu.h> +#include <twinmodule.h> +#include <krootpixmap.h> + +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xatom.h> + +#ifndef None +#define None 0L +#endif + +#ifdef COMPOSITE +# include <X11/Xlib.h> +# include <X11/extensions/Xrender.h> +# include <fixx11h.h> +#endif + +#include "pixmapserver.h" + +template class TQPtrVector<KBackgroundRenderer>; +template class TQPtrVector<KBackgroundCacheEntry>; +template class TQMemArray<int>; + +static Atom prop_root; +static bool properties_inited = false; + +extern bool argb_visual; +extern KDesktopApp *myApp; + +/**** KBackgroundManager ****/ + +KBackgroundManager::KBackgroundManager(TQWidget *desktop, KWinModule* twinModule) + : KBackgroundIface() +{ + if( !properties_inited ) + { + prop_root = XInternAtom(tqt_xdisplay(), "_XROOTPMAP_ID", False); + properties_inited = true; + } + m_bBgInitDone = false; + m_bEnabled = true; + + m_pDesktop = desktop; + if (desktop == 0L) + desktop = TQT_TQWIDGET(TDEApplication::desktop()->screen()); + + m_Renderer.resize( 1 ); + m_Cache.resize( 1 ); + + m_Serial = 0; m_Hash = 0; + m_pConfig = TDEGlobal::config(); + m_bExport = m_bCommon = m_bInit = false; + m_pKwinmodule = twinModule; + m_pPixmapServer = new KPixmapServer(); + m_xrootpmap = None; + + for (unsigned i=0; i<m_Renderer.size(); i++) + { + m_Cache.insert(i, new KBackgroundCacheEntry); + m_Cache[i]->pixmap = 0L; + m_Cache[i]->hash = 0; + m_Cache[i]->exp_from = -1; + m_Renderer.insert (i, new KVirtualBGRenderer(i,m_pConfig)); + connect(m_Renderer[i], TQT_SIGNAL(imageDone(int)), TQT_SLOT(slotImageDone(int))); + m_Renderer[i]->enableTiling( true ); // optimize + } + +#ifdef COMPOSITE + m_tPixmap = new KPixmap(kapp->desktop()->size()); + m_tPixmap->fill(TQColor(0, 0x0)); + connect(myApp, TQT_SIGNAL(cmBackgroundChanged( bool )), + TQT_SLOT(slotCmBackgroundChanged( bool ))); +#endif + + configure(); + + m_pTimer = new TQTimer(this); + connect(m_pTimer, TQT_SIGNAL(timeout()), TQT_SLOT(slotTimeout())); + m_pTimer->start( 60000 ); + + connect(m_pKwinmodule, TQT_SIGNAL(currentDesktopChanged(int)), + TQT_SLOT(slotChangeDesktop(int))); + connect(m_pKwinmodule, TQT_SIGNAL(numberOfDesktopsChanged(int)), + TQT_SLOT(slotChangeNumberOfDesktops(int))); + connect(m_pKwinmodule, TQT_SIGNAL(currentDesktopViewportChanged(int, const TQPoint&)), + TQT_SLOT(slotChangeViewport(int, const TQPoint&))); + + +#if (TQT_VERSION-0 >= 0x030200) + connect( kapp->desktop(), TQT_SIGNAL( resized( int )), TQT_SLOT( desktopResized())); // RANDR support +#endif + + TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop())); + m_numberOfViewports = s.width() * s.height(); + if (m_numberOfViewports < 1) { + m_numberOfViewports = 1; + } + for (signed j=0;j<(m_pKwinmodule->numberOfDesktops() * m_numberOfViewports);j++) { + renderBackground(j); + } +} + + +KBackgroundManager::~KBackgroundManager() +{ + for (unsigned i=0; i<m_Renderer.size(); i++) + delete m_Renderer[i]; + + //delete m_pConfig; Very bad idea, this is TDEGlobal::config ! + delete m_pPixmapServer; + delete m_pTimer; + + // clear the Esetroot properties, as the pixmaps they refer to are going away... + Pixmap pm = None; + Atom type; + int format; + unsigned long length, after; + unsigned char* data_root; + if( XGetWindowProperty( tqt_xdisplay(), tqt_xrootwin(), prop_root, 0L, 1L, False, AnyPropertyType, + &type, &format, &length, &after, &data_root) == Success && data_root != NULL ) + { + if (type == XA_PIXMAP) + pm = *((Pixmap*)data_root); + XFree( data_root ); + } + // only if it's our pixmap + if( pm == m_xrootpmap ) + XDeleteProperty(tqt_xdisplay(), tqt_xrootwin(), prop_root); + m_xrootpmap = None; + + if (m_bExport) + return; + + for (unsigned i=0; i<m_Cache.size(); i++) + { + delete m_Cache[i]->pixmap; + delete m_Cache[i]; + } +} + + +void KBackgroundManager::applyExport(bool exp) +{ + if (exp == m_bExport) + return; + + // If export mode changed from true -> false, remove all shared pixmaps. + // If it changed false -> true force a redraw because the current screen + // image might not have an associated pixmap in the cache. + if (!exp) + { + for (unsigned i=0; i<m_Cache.size(); i++) + removeCache(i); + } else + m_Hash = 0; + + m_bExport = exp; +} + + +void KBackgroundManager::applyCommon(bool common) +{ + if (common == m_bCommon) + return; + m_bCommon = common; + + // If common changed from false -> true, remove all cache entries, except + // at index 0 if exports are on. + if (m_bCommon) + { + if (!m_bExport) + removeCache(0); + for (unsigned i=1; i<m_Cache.size(); i++) + removeCache(i); + } +} + + +void KBackgroundManager::applyCache(bool limit, int size) +{ + m_bLimitCache = limit; + m_CacheLimit = size; + freeCache(0); +} + + +/* + * Call this when the configuration has changed. + * This method is exported with DCOP. + */ +void KBackgroundManager::configure() +{ + // Global settings + m_pConfig->reparseConfiguration(); + KDesktopSettings::self()->readConfig(); + + // Read individual settings + KVirtualBGRenderer *r; + for (unsigned i=0; i<m_Renderer.size(); i++) + { + r = m_Renderer[i]; + int ohash = r->hash(); + r->load(i,false); + if ((r->hash() != ohash)) + removeCache(i); + } + + applyCommon(KDesktopSettings::commonDesktop()); + + bool limit = KDesktopSettings::limitCache(); + int size = KDesktopSettings::cacheSize() * 1024; + applyCache(limit, size); + + // Repaint desktop + slotChangeDesktop(0); + + // Redraw all desktops so that applications relying on exported data, e.g. kpager, continue to work properly + TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop())); + m_numberOfViewports = s.width() * s.height(); + if (m_numberOfViewports < 1) { + m_numberOfViewports = 1; + } + for (signed j=0;j<(m_pKwinmodule->numberOfDesktops() * m_numberOfViewports);j++) { + renderBackground(j); + } +} + + +int KBackgroundManager::realDesktop() +{ + int desk = m_pKwinmodule->currentDesktop(); + if (desk) desk--; + return desk; +} + + +int KBackgroundManager::effectiveDesktop() +{ + TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop())); + m_numberOfViewports = s.width() * s.height(); + + if (m_numberOfViewports > 1) { + if (m_bCommon) { + return 0; + } + else { + TQPoint vx(m_pKwinmodule->currentViewport(m_pKwinmodule->currentDesktop())); + return (realDesktop() * m_numberOfViewports) + ((vx.x() * vx.y()) - 1); + } + } + else { + return m_bCommon ? 0 : realDesktop(); + } +} + + +/* + * Number of desktops changed + */ +void KBackgroundManager::slotChangeNumberOfDesktops(int num) +{ + TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop())); + m_numberOfViewports = s.width() * s.height(); + if (m_numberOfViewports < 1) { + m_numberOfViewports = 1; + } + num = (num * m_numberOfViewports); + + if (m_Renderer.size() == (unsigned) num) + return; + + if (m_Renderer.size() > (unsigned) num) + { + for (unsigned i=num; i<m_Renderer.size(); i++) + { + if (m_Renderer[i]->isActive()) + m_Renderer[i]->stop(); + delete m_Renderer[i]; + removeCache(i); + } + for (unsigned i=num; i<m_Renderer.size(); i++) + delete m_Cache[i]; + m_Renderer.resize(num); + m_Cache.resize(num); + } else + { + // allocate new renderers and caches + int oldsz = m_Renderer.size(); + m_Renderer.resize(num); + m_Cache.resize(num); + for (int i=oldsz; i<num; i++) + { + m_Cache.insert(i, new KBackgroundCacheEntry); + m_Cache[i]->pixmap = 0L; + m_Cache[i]->hash = 0; + m_Cache[i]->exp_from = -1; + m_Renderer.insert(i, new KVirtualBGRenderer(i,m_pConfig)); + connect(m_Renderer[i], TQT_SIGNAL(imageDone(int)), TQT_SLOT(slotImageDone(int))); + m_Renderer[i]->enableTiling( true ); // optimize + } + } +} + +/* + * Call this when the desktop has been changed. + * Desk is in KWin convention: [1..desks], instead of [0..desks-1]. + * 0 repaints the current desktop. + */ +void KBackgroundManager::slotChangeDesktop(int desk) +{ + TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop())); + m_numberOfViewports = s.width() * s.height(); + if (m_numberOfViewports < 1) { + m_numberOfViewports = 1; + } + + if (desk == 0) + desk = realDesktop(); + else + desk--; + + // Lazy initialisation of # of desktops + if ((unsigned)(m_pKwinmodule->numberOfDesktops() * m_numberOfViewports) >= m_Renderer.size()) + slotChangeNumberOfDesktops( m_pKwinmodule->numberOfDesktops() * m_numberOfViewports); + + int edesk = effectiveDesktop(); + m_Serial++; + + // If the background is the same: do nothing + if ((m_Hash == m_Renderer[edesk]->hash()) && (desk != 0)) + { + exportBackground(m_Current, desk); + return; + } + m_Renderer[edesk]->stop(); + m_Renderer[edesk]->cleanup(); + + // If we have the background already rendered: set it + for (unsigned i=0; i<m_Cache.size(); i++) + { + if (!m_Cache[i]->pixmap) + continue; + if (m_Cache[i]->hash != m_Renderer[edesk]->hash()) + continue; + if (desk == 0) + continue; +// kdDebug() << "slotChangeDesktop i=" << i << endl; + setPixmap(m_Cache[i]->pixmap, m_Cache[i]->hash, i); + m_Cache[i]->atime = m_Serial; + exportBackground(i, desk); + return; + } + + // Do we have this or an identical config already running? + for (unsigned i=0; i<m_Renderer.size(); i++) + { + if (((m_Renderer[i]->hash() == m_Renderer[edesk]->hash()) && (m_Renderer[i]->isActive())) && (desk != 0)) + return; + } + + renderBackground(edesk); +} + +/* + * Call this when the viewport has been changed. + * Desk is in KWin convention: [1..desks], instead of [0..desks-1]. + * 0 repaints the current viewport. + */ +void KBackgroundManager::slotChangeViewport(int desk, const TQPoint& viewport) +{ + TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop())); + m_numberOfViewports = s.width() * s.height(); + if (m_numberOfViewports < 1) { + m_numberOfViewports = 1; + } + + if (desk == 0) + desk = realDesktop(); + else + desk--; + + // Lazy initialisation of # of desktops + if ((unsigned)(m_pKwinmodule->numberOfDesktops() * m_numberOfViewports) >= m_Renderer.size()) + slotChangeNumberOfDesktops( m_pKwinmodule->numberOfDesktops() * m_numberOfViewports ); + + int edesk = effectiveDesktop(); + m_Serial++; + + // If the background is the same: do nothing + if ((m_Hash == m_Renderer[edesk]->hash()) && (desk != 0)) + { + exportBackground(m_Current, desk); + return; + } + m_Renderer[edesk]->stop(); + m_Renderer[edesk]->cleanup(); + + // If we have the background already rendered: set it + for (unsigned i=0; i<m_Cache.size(); i++) + { + if (!m_Cache[i]->pixmap) + continue; + if (m_Cache[i]->hash != m_Renderer[edesk]->hash()) + continue; + if (desk == 0) + continue; +// kdDebug() << "slotChangeDesktop i=" << i << endl; + + //KPixmap * viewport_background = new KPixmap(TQPixmap(m_Cache[i]->pixmap->width()*s.width(), m_Cache[i]->pixmap->height()*s.height())); + //setPixmap(viewport_background, m_Cache[i]->hash, i); + //delete viewport_background; + + setPixmap(m_Cache[i]->pixmap, m_Cache[i]->hash, i); + m_Cache[i]->atime = m_Serial; + exportBackground(i, desk); + return; + } + + // Do we have this or an identical config already running? + for (unsigned i=0; i<m_Renderer.size(); i++) + { + if (((m_Renderer[i]->hash() == m_Renderer[edesk]->hash()) && (m_Renderer[i]->isActive())) && (desk != 0)) + return; + } + + renderBackground(edesk); +} + + +/* + * Share a desktop pixmap. + */ +void KBackgroundManager::exportBackground(int pixmap, int desk) +{ + if (!m_bExport || (m_Cache[desk]->exp_from == pixmap)) + return; + + m_Cache[desk]->exp_from = pixmap; + m_pPixmapServer->add(KRootPixmap::pixmapName(desk+1), + m_Cache[pixmap]->pixmap); + KIPC::sendMessageAll(KIPC::BackgroundChanged, desk+1); +} + + +/* + * Paint the pixmap to the root window. + */ +void KBackgroundManager::setPixmap(KPixmap *pm, int hash, int desk) +{ + KPixmap *ep = pm; + +#ifdef COMPOSITE + if (argb_visual && (KDesktopSettings::backgroundOpacity() < 100 + || myApp->cmBackground())) + { + ep = m_tPixmap; + if (KDesktopSettings::backgroundOpacity() > 0 && pm + && !myApp->cmBackground()) + { + XRenderPictFormat *format; + format = XRenderFindStandardFormat (tqt_xdisplay(), PictStandardARGB32); + + XRenderColor fillColor; + + int color = KDesktopSettings::backgroundOpacity() * 0xffff / 100; + fillColor.red = color; + fillColor.green = color; + fillColor.blue = color; + fillColor.alpha = color; + + Picture fill = XRenderCreateSolidFill (tqt_xdisplay(), &fillColor); + Picture src = XRenderCreatePicture(tqt_xdisplay(), pm->handle(), + format, 0, NULL); + Picture dst = XRenderCreatePicture(tqt_xdisplay(), ep->handle(), + format, 0, NULL); + + XRenderComposite (tqt_xdisplay(), PictOpSrc, src, fill, dst, 0, 0, 0, + 0, 0, 0, pm->width(), pm->height()); + + XRenderFreePicture (tqt_xdisplay(), fill); + XRenderFreePicture (tqt_xdisplay(), src); + XRenderFreePicture (tqt_xdisplay(), dst); + } + } +#endif + + if (m_pDesktop) + { + TQScrollView* sv = dynamic_cast<TQScrollView*>( m_pDesktop ); + if ( sv ) { + // Qt eats repaint events in this case :-(( + sv->viewport()->update(); + } + m_pDesktop->setErasePixmap(*ep); + m_pDesktop->repaint(); + static bool root_cleared = false; + if( !root_cleared ) + { // clear the root window pixmap set by tdm + root_cleared = true; + TQTimer::singleShot( 0, this, TQT_SLOT( clearRoot())); + // but make the pixmap visible until m_pDesktop is visible + TQT_TQWIDGET(TDEApplication::desktop()->screen())->setErasePixmap(*ep); + TQT_TQWIDGET(TDEApplication::desktop()->screen())->erase(); + } + } + else + { + TQT_TQWIDGET(TDEApplication::desktop()->screen())->setErasePixmap(*ep); + TQT_TQWIDGET(TDEApplication::desktop()->screen())->erase(); + } + + // and export it via Esetroot-style for gnome/GTK apps to share in the pretties + Pixmap bgPm = pm->handle(); // fetch the actual X handle to it + //kdDebug() << "Esetroot compat: setting pixmap to " << bgPm << endl; + + // don't set the ESETROOT_PMAP_ID property - that would result in possible XKillClient() + // done on kdesktop + + XChangeProperty(tqt_xdisplay(), tqt_xrootwin(), prop_root, XA_PIXMAP, 32, PropModeReplace, + (unsigned char *) &bgPm, 1); + m_xrootpmap = bgPm; + + m_Hash = hash; + m_Current = desk; +} + +void KBackgroundManager::clearRoot() +{ + TQT_TQWIDGET(TDEApplication::desktop()->screen())->setErasePixmap( TQPixmap()); + TQT_TQWIDGET(TDEApplication::desktop()->screen())->erase(); +} + +/* + * Start the render of a desktop background. + */ +void KBackgroundManager::renderBackground(int desk) +{ + KVirtualBGRenderer *r = m_Renderer[desk]; + if (r->isActive()) + { + kdDebug() << "renderer " << desk << " already active" << endl; + return; + } + + r->start(); +} + + +/* + * This slot is called when a renderer is done. + */ +void KBackgroundManager::slotImageDone(int desk) +{ + bool t_useViewports = 1; + TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop())); + m_numberOfViewports = s.width() * s.height(); + if (m_numberOfViewports < 1) { + m_numberOfViewports = 1; + t_useViewports = 0; + } + + KPixmap *pm = new KPixmap(); + KVirtualBGRenderer *r = m_Renderer[desk]; + bool do_cleanup = true; + + *pm = r->pixmap(); + // If current: paint it + bool current = (r->hash() == m_Renderer[effectiveDesktop()]->hash()); + if (current) + { + //KPixmap * viewport_background = new KPixmap(TQPixmap(pm->width()*s.width(), pm->height()*s.height())); + //printf("slotImageDone(): x: %d y: %d\n", viewport_background->size().width(), viewport_background->size().height()); + //setPixmap(viewport_background, r->hash(), desk); + //delete viewport_background; + + setPixmap(pm, r->hash(), desk); + if (!m_bBgInitDone) + { + m_bBgInitDone = true; + emit initDone(); + TQTimer::singleShot( 30000, this, TQT_SLOT( saveImages())); + do_cleanup = false; + } + } + if (m_bExport || !m_bCommon) + addCache(pm, r->hash(), desk); + else + delete pm; + + if (current) + //exportBackground(desk, realDesktop()); + exportBackground(desk, desk); + + if( do_cleanup ) + { + r->saveCacheFile(); + r->cleanup(); + } +} + + +void KBackgroundManager::saveImages() +{ + for (unsigned i=0; i<m_Renderer.size(); i++) + { + m_Renderer[i]->saveCacheFile(); + m_Renderer[i]->cleanup(); + } +} + +/* + * Size in bytes of a TQPixmap. For use in the pixmap cache. + */ +int KBackgroundManager::pixmapSize(TQPixmap *pm) +{ + return (pm->width() * pm->height()) * ((pm->depth() + 7) / 8); +} + + +/* + * Total size of the pixmap cache. + */ +int KBackgroundManager::cacheSize() +{ + int total = 0; + for (unsigned i=0; i<m_Cache.size(); i++) + { + if (m_Cache[i]->pixmap) + total += pixmapSize(m_Cache[i]->pixmap); + } + return total; +} + + +/* + * Remove an entry from the pixmap cache. + */ +void KBackgroundManager::removeCache(int desk) +{ + if (m_bExport) + m_pPixmapServer->remove(KRootPixmap::pixmapName(desk+1)); + else + delete m_Cache[desk]->pixmap; + m_Cache[desk]->pixmap = 0L; + m_Cache[desk]->hash = 0; + m_Cache[desk]->exp_from = -1; + m_Cache[desk]->atime = 0; + + // Remove cache entries pointing to the removed entry + for (unsigned i=0; i<m_Cache.size(); i++) + { + if (m_Cache[i]->exp_from == desk) + { + assert(m_bExport); + m_Cache[i]->exp_from = -1; + m_pPixmapServer->remove(KRootPixmap::pixmapName(i+1)); + } + } +} + + +/* + * Try to free up to size bytes from the cache. + */ +bool KBackgroundManager::freeCache(int size) +{ + if (m_bExport || !m_bLimitCache) + return true; + + // If it doesn't fit at all, return now. + if (size > m_CacheLimit) + return false; + + // If cache is too full, purge it (LRU) + while (size+cacheSize() > m_CacheLimit) + { + int j, min; + min = m_Serial+1; j = 0; + for (unsigned i=0; i<m_Cache.size(); i++) + { + if (m_Cache[i]->pixmap && (m_Cache[i]->atime < min)) + { + min = m_Cache[i]->atime; + j = i; + } + } + removeCache(j); + } + return true; +} + + +/* + * Try to add a pixmap to the pixmap cache. We don't use TQPixmapCache here + * because if we're exporting pixmaps, this needs special care. + */ +void KBackgroundManager::addCache(KPixmap *pm, int hash, int desk) +{ + if (m_Cache[desk]->pixmap) + removeCache(desk); + + if (m_bLimitCache && !m_bExport && !freeCache(pixmapSize(pm))) + { + // pixmap does not fit in cache + delete pm; + return; + } + + m_Cache[desk]->pixmap = pm; + m_Cache[desk]->hash = hash; + m_Cache[desk]->atime = m_Serial; + m_Cache[desk]->exp_from = -1; + exportBackground(desk, desk); +} + +/* + * Called every minute to check if we need to rerun a background program. + * or change a wallpaper. + */ +void KBackgroundManager::slotTimeout() +{ + TQMemArray<int> running(m_Renderer.size()); + running.fill(0); + + int NumDesks = m_Renderer.size(); + if (m_bCommon) + NumDesks = 1; + + int edesk = effectiveDesktop(); + + for (int i=0; i<NumDesks; i++) + { + KVirtualBGRenderer *r = m_Renderer[i]; + bool change = false; + + if (r->needProgramUpdate()) + { + r->programUpdate(); + change = true; + } + + if (r->needWallpaperChange()) + { + r->changeWallpaper(); + change = true; + } + + if (change && (i == edesk)) + { + running[i] = r->hash(); + r->start(); + } + } +} + +// Return a valid desk number. +int KBackgroundManager::validateDesk(int desk) +{ + if (desk > (int)m_Renderer.size()) + slotChangeNumberOfDesktops( m_pKwinmodule->numberOfDesktops() ); + + if ( (desk <= 0) || (desk > (int)m_Renderer.size()) ) + return realDesktop(); + + return desk - 1; +} + +// DCOP exported +// Return current wallpaper for specified desk. +// 0 is for the current visible desktop. +TQString KBackgroundManager::currentWallpaper(int desk) +{ + //TODO Is the behaviour of this function appropriate for multiple screens? + KBackgroundRenderer *r = m_Renderer[validateDesk(desk)]->renderer(0); + + return r->currentWallpaper(); +} + +// DCOP exported +void KBackgroundManager::changeWallpaper() +{ + KVirtualBGRenderer *r = m_Renderer[effectiveDesktop()]; + + r->changeWallpaper(); + slotChangeDesktop(0); +} + +// DCOP exported +void KBackgroundManager::setExport(int _export) +{ + kdDebug() << "KBackgroundManager enabling exports.\n"; + applyExport(_export); + slotChangeDesktop(0); +} + +// DCOP exported +void KBackgroundManager::setCommon(int common) +{ + applyCommon(common); + KDesktopSettings::setCommonDesktop( m_bCommon ); + KDesktopSettings::writeConfig(); + slotChangeDesktop(0); +} + +// DCOP exported +void KBackgroundManager::setWallpaper(TQString wallpaper, int mode) +{ + if (mode < 0 || mode >= KBackgroundSettings::lastWallpaperMode) { + kdDebug() << "Invalid background mode " << mode << " passed to " << k_funcinfo << "\n"; + return; + } + + //TODO Is the behaviour of this function appropriate for multiple screens? + for (unsigned i=0; i < m_Renderer[effectiveDesktop()]->numRenderers(); ++i) + { + KBackgroundRenderer *r = m_Renderer[effectiveDesktop()]->renderer(i); + r->stop(); + r->setWallpaperMode(mode); + r->setMultiWallpaperMode(KBackgroundSettings::NoMulti); + r->setWallpaper(wallpaper); + r->writeSettings(); + } + slotChangeDesktop(0); +} + +void KBackgroundManager::setWallpaper(TQString wallpaper) +{ + //TODO Is the behaviour of this function appropriate for multiple screens? + KBackgroundRenderer *r = m_Renderer[effectiveDesktop()]->renderer(0); + int mode = r->wallpaperMode(); + if (mode == KBackgroundSettings::NoWallpaper) + mode = KBackgroundSettings::Tiled; + setWallpaper(wallpaper, mode); +} + +// DCOP exported +// Returns the filenames of all wallpaper entries for specified desk +// 0 is for current visible desktop. +TQStringList KBackgroundManager::wallpaperFiles(int desk) +{ + //TODO Is the behaviour of this function appropriate for multiple screens? + KBackgroundRenderer *r = m_Renderer[validateDesk(desk)]->renderer(0); + + return r->wallpaperFiles(); +} + +// DCOP exported +// Returns the list of wallpaper entries (viewable in background slide +// show window) for specified desk. 0 is for current visible desktop. +TQStringList KBackgroundManager::wallpaperList(int desk) +{ + //TODO Is the behaviour of this function appropriate for multiple screens? + KBackgroundRenderer *r = m_Renderer[validateDesk(desk)]->renderer(0);; + + return r->wallpaperList(); +} + +// DCOP exported +void KBackgroundManager::setCache( int bLimit, int size ) +{ + applyCache( bLimit, size*1024 ); + KDesktopSettings::setLimitCache( (bool) bLimit ); + KDesktopSettings::setCacheSize( size ); + KDesktopSettings::writeConfig(); +} + +// DCOP exported +void KBackgroundManager::setWallpaper(int desk, TQString wallpaper, int mode) +{ + if (mode < 0 || mode >= KBackgroundSettings::lastWallpaperMode) { + kdDebug() << "Invalid background mode " << mode << " passed to " << k_funcinfo << "\n"; + return; + } + + int sdesk = validateDesk(desk); + + //TODO Is the behaviour of this function appropriate for multiple screens? + for (unsigned i=0; i < m_Renderer[sdesk]->numRenderers(); ++i) + { + KBackgroundRenderer *r = m_Renderer[sdesk]->renderer(i); + + setCommon(false); // Force each desktop to have it's own wallpaper + + r->stop(); + r->setWallpaperMode(mode); + r->setMultiWallpaperMode(KBackgroundSettings::NoMulti); + r->setWallpaper(wallpaper); + r->writeSettings(); + } + slotChangeDesktop(sdesk); +} + +void KBackgroundManager::repaintBackground() +{ + if (m_pDesktop) + m_pDesktop->repaint(); + else + TQT_TQWIDGET(TDEApplication::desktop()->screen())->erase(); +} + +void KBackgroundManager::desktopResized() +{ + for (unsigned i=0; i<m_Renderer.size(); i++) + { + KVirtualBGRenderer * r = m_Renderer[i]; + if( r->isActive()) + r->stop(); + removeCache(i); + // make the renderer update its desktop size + r->desktopResized(); + for (unsigned j=0; j<(r->numRenderers()); ++j) { + r->renderer(j)->desktopResized(); + } + } + +#ifdef COMPOSITE + if (m_tPixmap) + delete m_tPixmap; + m_tPixmap = new KPixmap(kapp->desktop()->size()); + m_tPixmap->fill(TQColor(0, 0x0)); +#endif + + m_Hash = 0; + if( m_pDesktop ) + m_pDesktop->resize( kapp->desktop()->geometry().size()); + // Repaint desktop + slotChangeDesktop(0); + repaintBackground(); + + // Redraw all desktops so that applications relying on exported data, e.g. kpager, continue to work properly + TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop())); + m_numberOfViewports = s.width() * s.height(); + if (m_numberOfViewports < 1) { + m_numberOfViewports = 1; + } + for (signed j=0;j<(m_pKwinmodule->numberOfDesktops() * m_numberOfViewports);j++) { + renderBackground(j); + } +} + +// DCOP exported +void KBackgroundManager::setColor(const TQColor & c, bool isColorA) +{ + //TODO Is the behaviour of this function appropriate for multiple screens? + for (unsigned i=0; i < m_Renderer[effectiveDesktop()]->numRenderers(); ++i) + { + KBackgroundRenderer *r = m_Renderer[effectiveDesktop()]->renderer(i); + r->stop(); + + if (isColorA) + r->setColorA(c); + else + r->setColorB(c); + + int mode = r->backgroundMode(); + if (mode == KBackgroundSettings::Program) + mode = KBackgroundSettings::Flat; + + if (!isColorA && (mode == KBackgroundSettings::Flat)) + mode = KBackgroundSettings::VerticalGradient; + r->setBackgroundMode(mode); + + r->writeSettings(); + } + slotChangeDesktop(0); +} + +void KBackgroundManager::setBackgroundEnabled( const bool enable ) +{ + if (m_bEnabled == enable) + return; + + m_bEnabled= enable; + + int NumDesks = m_Renderer.size(); + if (m_bCommon) + NumDesks = 1; + + for (int i=0; i<NumDesks; i++) + { + m_Renderer[i]->setEnabled(enable); + } + slotChangeDesktop(0); +} + +#ifdef COMPOSITE +void KBackgroundManager::slotCmBackgroundChanged( bool ) +{ + m_tPixmap->fill(TQColor(0, 0x0)); + m_Hash = 0; + slotChangeDesktop(0); +} +#endif + +#include "bgmanager.moc" diff --git a/kdesktop/bgmanager.h b/kdesktop/bgmanager.h new file mode 100644 index 000000000..2d29278f7 --- /dev/null +++ b/kdesktop/bgmanager.h @@ -0,0 +1,136 @@ +/* vi: ts=8 sts=4 sw=4 + * + * This file is part of the KDE project, module kdesktop. + * Copyright (C) 1999,2000 Geert Jansen <[email protected]> + * + * You can Freely distribute this program under the GNU General Public + * License. See the file "COPYING" for the exact licensing terms. + */ + +#ifndef __BGManager_h_Included__ +#define __BGManager_h_Included__ + +#include <tqstring.h> +#include <tqptrvector.h> + +#include <KBackgroundIface.h> + +#if defined(Q_WS_X11) && defined(HAVE_XRENDER) && TQT_VERSION >= 0x030300 +#define COMPOSITE +#endif + +class TDEConfig; +class TQTimer; +class TQPixmap; +class TDEPopupMenu; +class KWinModule; +class KPixmap; +class KVirtualBGRenderer; +class KPixmapServer; + +/** + * Internal struct for KBackgroundManager. + */ +struct KBackgroundCacheEntry +{ + int hash; + int atime; + int exp_from; + KPixmap *pixmap; +}; + + +/** + * Background manager for KDE. This class is to be used in kdesktop. Usage is + * very simple: instantiate this class once and the desktop background will + * be painted automatically from now on. + * + * The background manager also has a DCOP interface to remotely control its + * operation. See KBackgroundIface.h for details. + */ + +class KBackgroundManager + : public TQObject, + public KBackgroundIface +{ + Q_OBJECT + + +public: + KBackgroundManager(TQWidget *desktop, KWinModule* twinModule); + ~KBackgroundManager(); + + void configure(); + void setCommon(int); + bool isCommon() { return m_bCommon; }; + void setExport(int); + bool isExport() { return m_bExport; }; + void setCache(int, int); + void setWallpaper(int desk, TQString wallpaper, int mode); + void setWallpaper(TQString wallpaper, int mode); + void setWallpaper(TQString wallpaper); + void changeWallpaper(); + TQString currentWallpaper(int desk); + void setColor(const TQColor & c, bool isColorA = true); + void setBackgroundEnabled(const bool enable); + TQStringList wallpaperList(int desk); + TQStringList wallpaperFiles(int desk); + +signals: + void initDone(); + +private slots: + void slotTimeout(); + void slotImageDone(int desk); + void slotChangeDesktop(int); + void slotChangeViewport(int, const TQPoint&); + void slotChangeNumberOfDesktops(int); + void repaintBackground(); + void desktopResized(); + void clearRoot(); + void saveImages(); + void slotCmBackgroundChanged(bool); + +private: + void applyCommon(bool common); + void applyExport(bool _export); + void applyCache(bool limit, int size); + + int realDesktop(); + int effectiveDesktop(); + int validateDesk(int desk); + int m_numberOfViewports; + + void renderBackground(int desk); + void exportBackground(int pixmap, int desk); + int pixmapSize(TQPixmap *pm); + int cacheSize(); + void removeCache(int desk); + bool freeCache(int size); + void addCache(KPixmap *pm, int hash, int desk); + void setPixmap(KPixmap *pm, int hash, int desk); + + bool m_bExport, m_bCommon; + bool m_bLimitCache, m_bInit; + bool m_bBgInitDone; + bool m_bEnabled; + + int m_CacheLimit; + int m_Serial, m_Hash, m_Current; + + TDEConfig *m_pConfig; + TQWidget *m_pDesktop; + TQTimer *m_pTimer; + + KPixmap *m_tPixmap; + + TQPtrVector<KVirtualBGRenderer> m_Renderer; + TQPtrVector<KBackgroundCacheEntry> m_Cache; + + KWinModule *m_pKwinmodule; + KPixmapServer *m_pPixmapServer; + + unsigned long m_xrootpmap; +}; + +#endif // __BGManager_h_Included__ diff --git a/kdesktop/configure.in.in b/kdesktop/configure.in.in new file mode 100644 index 000000000..fcc161c1e --- /dev/null +++ b/kdesktop/configure.in.in @@ -0,0 +1,39 @@ +xss_save_ldflags="$LDFLAGS" +LDFLAGS="$X_LDFLAGS" + +LIB_XSS= + +AC_ARG_WITH([xscreensaver], + AC_HELP_STRING([--without-xscreensaver], [Disable XScreenSaver support (default: check)]) ) + +if test "x$with_xscreensaver" != "xno"; then + KDE_CHECK_HEADER(X11/extensions/scrnsaver.h, + [ + AC_CHECK_LIB(Xext,XScreenSaverQueryInfo, + [ + AC_DEFINE(HAVE_XSCREENSAVER, 1, [Define if you have the XScreenSaver extension]) + LIB_XSS="-lXext" + ], + [ + ld_shared_flag= + xss_save_cxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $lt_prog_compiler_pic_CXX" + KDE_CHECK_COMPILER_FLAG(shared, [ld_shared_flag="-shared"]) + AC_CHECK_LIB(Xss,XScreenSaverQueryInfo, + [ + AC_DEFINE(HAVE_XSCREENSAVER, 1, [Define if you have the XScreenSaver extension]) + LIB_XSS="-lXss" + ], + [], + [ $ld_shared_flag $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS ]) + CXXFLAGS="$xss_save_cxxflags" + ], + [ $X_PRE_LIBS -lX11 $X_EXTRA_LIBS ]) + ], [], + [ + #include <X11/Xlib.h> + ] ) +fi + +AC_SUBST(LIB_XSS) +LDFLAGS="$xss_save_ldflags" diff --git a/kdesktop/desktop.cc b/kdesktop/desktop.cc new file mode 100644 index 000000000..b3893c029 --- /dev/null +++ b/kdesktop/desktop.cc @@ -0,0 +1,1195 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 Torben Weis <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +#include "desktop.h" +#include "krootwm.h" +#include "bgmanager.h" +#include "bgsettings.h" +#include "startupid.h" +#include "kdiconview.h" +#include "minicli.h" +#include "kdesktopsettings.h" +#include "tdelaunchsettings.h" + +#include <string.h> +#include <unistd.h> +#include <kcolordrag.h> +#include <kurldrag.h> +#include <stdlib.h> +#include <tdeio/job.h> +#include <tqfile.h> + +#include <tqdir.h> +#include <tqevent.h> +#include <tqtooltip.h> + +#include <netwm.h> +#include <dcopclient.h> +#include <kcursor.h> +#include <kdebug.h> +#include <kstandarddirs.h> +#include <kimageio.h> +#include <kinputdialog.h> +#include <kipc.h> +#include <tdelocale.h> +#include <tdeio/netaccess.h> +#include <kprocess.h> +#include <tdesycoca.h> +#include <tdetempfile.h> +#include <tdemessagebox.h> +#include <kglobalaccel.h> +#include <twinmodule.h> +#include <krun.h> +#include <twin.h> +#include <tdeglobalsettings.h> +#include <tdepopupmenu.h> +#include <tdeapplication.h> +#include <kdirlister.h> +// Create the equivalent of TDEAccelBase::connectItem +// and then remove this include and fix reconnects in initRoot() -- ellis +//#include <tdeaccelbase.h> + +extern int kdesktop_screen_number; +extern TQCString kdesktop_name, kicker_name, twin_name; + +KRootWidget::KRootWidget() : TQObject() +{ + kapp->desktop()->installEventFilter(this); + kapp->desktop()->setAcceptDrops( true ); +} + +bool KRootWidget::eventFilter ( TQObject *, TQEvent * e ) +{ + if (e->type() == TQEvent::MouseButtonPress) + { + TQMouseEvent *me = TQT_TQMOUSEEVENT(e); + KRootWm::self()->mousePressed( me->globalPos(), me->button() ); + return true; + } + else if (e->type() == TQEvent::Wheel) + { + TQWheelEvent *we = TQT_TQWHEELEVENT(e); + emit wheelRolled(we->delta()); + return true; + } + else if ( e->type() == TQEvent::DragEnter ) + { + TQDragEnterEvent* de = static_cast<TQDragEnterEvent*>( e ); + bool b = !TDEGlobal::config()->isImmutable() && !TDEGlobal::dirs()->isRestrictedResource( "wallpaper" ); + + bool imageURL = false; + if ( KURLDrag::canDecode( de ) ) + { + KURL::List list; + KURLDrag::decode( de, list ); + KURL url = list.first(); + KMimeType::Ptr mime = KMimeType::findByURL( url ); + if ( !KImageIO::type( url.path() ).isEmpty() || + KImageIO::isSupported( mime->name(), KImageIO::Reading ) || mime->is( "image/svg+xml" ) ) + imageURL = true; + } + + b = b && ( KColorDrag::canDecode( de ) || TQImageDrag::canDecode( de ) || imageURL ); + de->accept( b ); + return true; + } + else if ( e->type() == TQEvent::Drop ) + { + TQDropEvent* de = static_cast<TQDropEvent*>( e ); + if ( KColorDrag::canDecode( de ) ) + emit colorDropEvent( de ); + else if ( TQImageDrag::canDecode( de ) ) + emit imageDropEvent( de ); + else if ( KURLDrag::canDecode( de ) ) { + KURL::List list; + KURLDrag::decode( de, list ); + KURL url = list.first(); + emit newWallpaper( url ); + } + return true; + } + return false; // Don't filter. +} + +// ----------------------------------------------------------------------------- +#define DEFAULT_DELETEACTION 1 + +KDesktop::WheelDirection KDesktop::m_eWheelDirection = KDesktop::m_eDefaultWheelDirection; +const char* KDesktop::m_wheelDirectionStrings[2] = { "Forward", "Reverse" }; + +KDesktop::KDesktop( bool x_root_hack, bool wait_for_kded ) : + TQWidget( 0L, "desktop", (WFlags)(WResizeNoErase | ( x_root_hack ? (WStyle_Customize | WStyle_NoBorder) : 0)) ), + KDesktopIface(), + // those two WStyle_ break kdesktop when the root-hack isn't used (no Dnd) + startup_id( NULL ), m_waitForKicker(0) +{ + NETRootInfo i( tqt_xdisplay(), NET::Supported ); + m_wmSupport = i.isSupported( NET::WM2ShowingDesktop ); + + m_bWaitForKded = wait_for_kded; + m_miniCli = 0; // created on demand + keys = 0; // created later + TDEGlobal::locale()->insertCatalogue("kdesktop"); + TDEGlobal::locale()->insertCatalogue("libkonq"); // needed for apps using libkonq + TDEGlobal::locale()->insertCatalogue("libdmctl"); + + setCaption( "KDE Desktop"); + + setAcceptDrops(true); // WStyle_Customize seems to disable that + m_pKwinmodule = new KWinModule( TQT_TQOBJECT(this) ); + + kapp->dcopClient()->setNotifications(true); + kapp->dcopClient()->connectDCOPSignal(kicker_name, kicker_name, "desktopIconsAreaChanged(TQRect, int)", + "KDesktopIface", "desktopIconsAreaChanged(TQRect, int)", false); + + // Dont repaint on configuration changes during construction + m_bInit = true; + + // It's the child widget that gets the focus, not us + setFocusPolicy( TQ_NoFocus ); + + if ( x_root_hack ) + { + // this is a ugly hack to make Dnd work + // Matthias told me that it won't be necessary with twin + // actually my first try with ICCCM (Dirk) :-) + unsigned long data[2]; + data[0] = (unsigned long) 1; + data[1] = (unsigned long) 0; // None; (Werner) + Atom wm_state = XInternAtom(tqt_xdisplay(), "WM_STATE", False); + XChangeProperty(tqt_xdisplay(), winId(), wm_state, wm_state, 32, + PropModeReplace, (unsigned char *)data, 2); + + } + + setGeometry( TQApplication::desktop()->geometry() ); + lower(); + + connect( kapp, TQT_SIGNAL( shutDown() ), + this, TQT_SLOT( slotShutdown() ) ); + + connect(kapp, TQT_SIGNAL(settingsChanged(int)), + this, TQT_SLOT(slotSettingsChanged(int))); + kapp->addKipcEventMask(KIPC::SettingsChanged); + + kapp->addKipcEventMask(KIPC::IconChanged); + connect(kapp, TQT_SIGNAL(iconChanged(int)), this, TQT_SLOT(slotIconChanged(int))); + + connect(KSycoca::self(), TQT_SIGNAL(databaseChanged()), + this, TQT_SLOT(slotDatabaseChanged())); + + m_pIconView = 0; + m_pRootWidget = 0; + bgMgr = 0; + initRoot(); + + TQTimer::singleShot(0, this, TQT_SLOT( slotStart() )); + +#if (TQT_VERSION-0 >= 0x030200) // XRANDR support + connect( kapp->desktop(), TQT_SIGNAL( resized( int )), TQT_SLOT( desktopResized())); +#endif +} + +void +KDesktop::initRoot() +{ + Display *dpy = tqt_xdisplay(); + Window root = RootWindow(dpy, kdesktop_screen_number); + XDefineCursor(dpy, root, cursor().handle()); + + m_bDesktopEnabled = KDesktopSettings::desktopEnabled(); + if ( !m_bDesktopEnabled && !m_pRootWidget ) + { + hide(); + delete bgMgr; + bgMgr = 0; + if ( m_pIconView ) + m_pIconView->saveIconPositions(); + delete m_pIconView; + m_pIconView = 0; + + { // trigger creation of QToolTipManager, it does XSelectInput() on the root window + TQWidget w; + TQToolTip::add( &w, "foo" ); + } + // NOTE: If mouse clicks stop working again, it's most probably something doing XSelectInput() + // on the root window after this, and setting it to some fixed value instead of adding its mask. + XWindowAttributes attrs; + XGetWindowAttributes(dpy, root, &attrs); + XSelectInput(dpy, root, attrs.your_event_mask | ButtonPressMask); + + m_pRootWidget = new KRootWidget; + connect(m_pRootWidget, TQT_SIGNAL(wheelRolled(int)), this, TQT_SLOT(slotSwitchDesktops(int))); + connect(m_pRootWidget, TQT_SIGNAL(colorDropEvent(TQDropEvent*)), this, TQT_SLOT(handleColorDropEvent(TQDropEvent*)) ); + connect(m_pRootWidget, TQT_SIGNAL(imageDropEvent(TQDropEvent*)), this, TQT_SLOT(handleImageDropEvent(TQDropEvent*)) ); + connect(m_pRootWidget, TQT_SIGNAL(newWallpaper(const KURL&)), this, TQT_SLOT(slotNewWallpaper(const KURL&)) ); + + // Geert Jansen: backgroundmanager belongs here + // TODO tell KBackgroundManager if we change widget() + bgMgr = new KBackgroundManager( m_pIconView, m_pKwinmodule ); + bgMgr->setExport(1); + connect( bgMgr, TQT_SIGNAL( initDone()), TQT_SLOT( backgroundInitDone())); + if (!m_bInit) + { + delete KRootWm::self(); + KRootWm* krootwm = new KRootWm( this ); // handler for root menu (used by kdesktop on RMB click) + keys->setSlot("Lock Session", krootwm, TQT_SLOT(slotLock())); + keys->updateConnections(); + } + } + else if (m_bDesktopEnabled && !m_pIconView) + { + delete bgMgr; + bgMgr = 0; + delete m_pRootWidget; + m_pRootWidget = 0; + m_pIconView = new KDIconView( this, 0 ); + connect( m_pIconView, TQT_SIGNAL( imageDropEvent( TQDropEvent * ) ), + this, TQT_SLOT( handleImageDropEvent( TQDropEvent * ) ) ); + connect( m_pIconView, TQT_SIGNAL( colorDropEvent( TQDropEvent * ) ), + this, TQT_SLOT( handleColorDropEvent( TQDropEvent * ) ) ); + connect( m_pIconView, TQT_SIGNAL( newWallpaper( const KURL & ) ), + this, TQT_SLOT( slotNewWallpaper( const KURL & ) ) ); + connect( m_pIconView, TQT_SIGNAL( wheelRolled( int ) ), + this, TQT_SLOT( slotSwitchDesktops( int ) ) ); + + // All the QScrollView/QWidget-specific stuff should go here, so that we can use + // another qscrollview/widget instead of the iconview and use the same code + m_pIconView->setVScrollBarMode( TQScrollView::AlwaysOff ); + m_pIconView->setHScrollBarMode( TQScrollView::AlwaysOff ); + m_pIconView->setDragAutoScroll( false ); + m_pIconView->setFrameStyle( TQFrame::NoFrame ); + m_pIconView->viewport()->setBackgroundMode( X11ParentRelative ); + m_pIconView->setFocusPolicy( TQ_StrongFocus ); + m_pIconView->viewport()->setFocusPolicy( TQ_StrongFocus ); + m_pIconView->setGeometry( geometry() ); + m_pIconView->show(); + + // Geert Jansen: backgroundmanager belongs here + // TODO tell KBackgroundManager if we change widget() + bgMgr = new KBackgroundManager( m_pIconView, m_pKwinmodule ); + bgMgr->setExport(1); + connect( bgMgr, TQT_SIGNAL( initDone()), TQT_SLOT( backgroundInitDone())); + + // make sure it is initialized before we first call updateWorkArea() + m_pIconView->initConfig( m_bInit ); + + // set the size of the area for desktop icons placement + { + TQByteArray data, result; + TQDataStream arg(data, IO_WriteOnly); + arg << kdesktop_screen_number; + TQCString replyType; + TQRect area; + + if ( kapp->dcopClient()->call(kicker_name, kicker_name, "desktopIconsArea(int)", + data, replyType, result, false, 2000) ) + { + TQDataStream res(result, IO_ReadOnly); + res >> area; + + m_pIconView->updateWorkArea(area); + } + else + if ( m_bInit ) + { + // if we failed to get the information from kicker wait a little - probably + // this is the KDE startup and kicker is simply not running yet + m_waitForKicker = new TQTimer(this); + connect(m_waitForKicker, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotNoKicker())); + m_waitForKicker->start(15000, true); + } + else // we are not called from the ctor, so kicker should already run + { + area = twinModule()->workArea(twinModule()->currentDesktop()); + m_pIconView->updateWorkArea(area); + } + } + + if (!m_bInit) + { + m_pIconView->start(); + delete KRootWm::self(); + KRootWm* krootwm = new KRootWm( this ); // handler for root menu (used by kdesktop on RMB click) + keys->setSlot("Lock Session", krootwm, TQT_SLOT(slotLock())); + keys->updateConnections(); + } + } else { + DCOPRef r( "ksmserver", "ksmserver" ); + r.send( "resumeStartup", TQCString( "kdesktop" )); + } + + KWin::setType( winId(), NET::Desktop ); + KWin::setState( winId(), NET::SkipPager ); + KWin::setOnAllDesktops( winId(), true ); +} + +void KDesktop::slotNoKicker() +{ + kdDebug(1204) << "KDesktop::slotNoKicker ... kicker did not respond" << endl; + // up till now, we got no desktopIconsArea from kicker - probably + // it's not running, so use the area from KWinModule + TQRect area = twinModule()->workArea(twinModule()->currentDesktop()); + m_pIconView->updateWorkArea(area); +} + +void +KDesktop::backgroundInitDone() +{ + //kdDebug(1204) << "KDesktop::backgroundInitDone" << endl; + // avoid flicker + if (m_bDesktopEnabled) + { + const TQPixmap *bg = TQT_TQWIDGET(TQApplication::desktop()->screen())->backgroundPixmap(); + if ( bg ) + m_pIconView->setErasePixmap( *bg ); + + show(); + kapp->sendPostedEvents(); + } + + DCOPRef r( "ksmserver", "ksmserver" ); + r.send( "resumeStartup", TQCString( "kdesktop" )); +} + +void +KDesktop::slotStart() +{ + //kdDebug(1204) << "KDesktop::slotStart" << endl; + if (!m_bInit) return; + + // In case we started without database + KImageIO::registerFormats(); + + initConfig(); + +// if (m_bDesktopEnabled) +// { +// // We need to be visible in order to insert icons, even if the background isn't ready yet... + +// show(); +// } + + // Now we may react to configuration changes + m_bInit = false; + + if (m_pIconView) + m_pIconView->start(); + + // Global keys + keys = new TDEGlobalAccel( TQT_TQOBJECT(this) ); + (void) new KRootWm( this ); + +#include "kdesktopbindings.cpp" + + keys->readSettings(); + keys->updateConnections(); + + connect(kapp, TQT_SIGNAL(appearanceChanged()), TQT_SLOT(slotConfigure())); + + TQTimer::singleShot(300, this, TQT_SLOT( slotUpAndRunning() )); +} + +void +KDesktop::runAutoStart() +{ + // now let's execute all the stuff in the autostart folder. + // the stuff will actually be really executed when the event loop is + // entered, since KRun internally uses a QTimer + TQDir dir( TDEGlobalSettings::autostartPath() ); + TQStringList entries = dir.entryList( TQDir::Files ); + TQStringList::Iterator it = entries.begin(); + TQStringList::Iterator end = entries.end(); + for (; it != end; ++it ) + { + // Don't execute backup files + if ( (*it).right(1) != "~" && (*it).right(4) != ".bak" && + ( (*it)[0] != '%' || (*it).right(1) != "%" ) && + ( (*it)[0] != '#' || (*it).right(1) != "#" ) ) + { + KURL url; + url.setPath( dir.absPath() + '/' + (*it) ); + (void) new KRun( url, 0, true ); + } + } +} + +// ----------------------------------------------------------------------------- + +KDesktop::~KDesktop() +{ + delete m_miniCli; + m_miniCli = 0; // see #120382 + delete bgMgr; + bgMgr = 0; + delete startup_id; +} + +// ----------------------------------------------------------------------------- + +void KDesktop::initConfig() +{ + if (m_pIconView) + m_pIconView->initConfig( m_bInit ); + + if ( keys ) + { + keys->readSettings(); + keys->updateConnections(); + } + + TDELaunchSettings::self()->readConfig(); + if( !TDELaunchSettings::busyCursor() ) + { + delete startup_id; + startup_id = NULL; + } + else + { + if( startup_id == NULL ) + startup_id = new StartupId; + startup_id->configure(); + } + + set_vroot = KDesktopSettings::setVRoot(); + slotSetVRoot(); // start timer + + m_bWheelSwitchesWorkspace = KDesktopSettings::wheelSwitchesWorkspace(); + + const char* forward_string = m_wheelDirectionStrings[Forward]; + m_eWheelDirection = + (KDesktopSettings::wheelDirection() == forward_string) ? Forward : Reverse; +} + +// ----------------------------------------------------------------------------- + +void KDesktop::slotExecuteCommand() +{ + // this function needs to be duplicated since it appears that one + // cannot have a 'slot' be a DCOP method. if this changes in the + // future, then 'slotExecuteCommand' and 'popupExecuteCommand' can + // merge into one slot. + popupExecuteCommand(); +} + +/* + Shows minicli + */ +void KDesktop::popupExecuteCommand() +{ + popupExecuteCommand(""); +} + +void KDesktop::popupExecuteCommand(const TQString& command) +{ + if (m_bInit) + return; + + if (!kapp->authorize("run_command")) + return; + + // Created on demand + if ( !m_miniCli ) + { + m_miniCli = new Minicli( this ); + m_miniCli->adjustSize(); // for the centering below + } + + if (!command.isEmpty()) + m_miniCli->setCommand(command); + + // Move minicli to the current desktop + NETWinInfo info( tqt_xdisplay(), m_miniCli->winId(), tqt_xrootwin(), NET::WMDesktop ); + int currentDesktop = twinModule()->currentDesktop(); + if ( info.desktop() != currentDesktop ) + info.setDesktop( currentDesktop ); + + if ( m_miniCli->isVisible() ) { + KWin::forceActiveWindow( m_miniCli->winId() ); + } else { + NETRootInfo i( tqt_xdisplay(), NET::Supported ); + if( !i.isSupported( NET::WM2FullPlacement )) { + TQRect rect = TDEGlobalSettings::desktopGeometry(TQCursor::pos()); + m_miniCli->move(rect.x() + (rect.width() - m_miniCli->width())/2, + rect.y() + (rect.height() - m_miniCli->height())/2); + } + m_miniCli->show(); // non-modal + } +} + +void KDesktop::slotSwitchUser() +{ + KRootWm::self()->slotSwitchUser(); +} + +void KDesktop::slotShowWindowList() +{ + KRootWm::self()->slotWindowList(); +} + +void KDesktop::slotShowTaskManager() +{ + //kdDebug(1204) << "Launching KSysGuard..." << endl; + TDEProcess* p = new TDEProcess; + TQ_CHECK_PTR(p); + + *p << "ksysguard"; + *p << "--showprocesses"; + + p->start(TDEProcess::DontCare); + + delete p; +} + +// ----------------------------------------------------------------------------- + +void KDesktop::rearrangeIcons() +{ + if (m_pIconView) + m_pIconView->rearrangeIcons(); +} + +void KDesktop::lineupIcons() +{ + if (m_pIconView) + m_pIconView->lineupIcons(); +} + +void KDesktop::selectAll() +{ + if (m_pIconView) + m_pIconView->selectAll( true ); +} + +void KDesktop::unselectAll() +{ + if (m_pIconView) + m_pIconView->selectAll( false ); +} + +TQStringList KDesktop::selectedURLs() +{ + if (m_pIconView) + return m_pIconView->selectedURLs(); + return TQStringList(); +} + +void KDesktop::refreshIcons() +{ + if (m_pIconView) + m_pIconView->refreshIcons(); +} + +void KDesktop::setShowDesktop( bool b ) +{ + bool m_showingDesktop = showDesktopState(); + + if (b == m_showingDesktop) + { + return; + } + + if( m_wmSupport ) + { + NETRootInfo i( tqt_xdisplay(), 0 ); + i.setShowingDesktop( b ); + return; + } + + if (b) + { + m_activeWindow = twinModule()->activeWindow(); + m_iconifiedList.clear(); + + const TQValueList<WId> windows = twinModule()->windows(); + for (TQValueList<WId>::ConstIterator it = windows.begin(); + it != windows.end(); + ++it) + { + WId w = *it; + + NETWinInfo info( tqt_xdisplay(), w, tqt_xrootwin(), + NET::XAWMState | NET::WMDesktop ); + + if (info.mappingState() == NET::Visible && + (info.desktop() == NETWinInfo::OnAllDesktops || + info.desktop() == (int)twinModule()->currentDesktop())) + { + m_iconifiedList.append( w ); + } + } + + // find first, hide later, otherwise transients may get minimized + // with the window they're transient for + for (TQValueVector<WId>::Iterator it = m_iconifiedList.begin(); + it != m_iconifiedList.end(); + ++it) + { + KWin::iconifyWindow( *it, false ); + } + + // on desktop changes or when a window is deiconified, we abort the show desktop mode + connect(twinModule(), TQT_SIGNAL(currentDesktopChanged(int)), + TQT_SLOT(slotCurrentDesktopChanged(int))); + connect(twinModule(), TQT_SIGNAL(windowChanged(WId,unsigned int)), + TQT_SLOT(slotWindowChanged(WId,unsigned int))); + connect(twinModule(), TQT_SIGNAL(windowAdded(WId)), + TQT_SLOT(slotWindowAdded(WId))); + } + else + { + disconnect(twinModule(), TQT_SIGNAL(currentDesktopChanged(int)), + this, TQT_SLOT(slotCurrentDesktopChanged(int))); + disconnect(twinModule(), TQT_SIGNAL(windowChanged(WId,unsigned int)), + this, TQT_SLOT(slotWindowChanged(WId,unsigned int))); + disconnect(twinModule(), TQT_SIGNAL(windowAdded(WId)), + this, TQT_SLOT(slotWindowAdded(WId))); + + for (TQValueVector<WId>::ConstIterator it = m_iconifiedList.begin(); + it != m_iconifiedList.end(); + ++it) + { + KWin::deIconifyWindow(*it, false); + } + + KWin::forceActiveWindow(m_activeWindow); + } + + m_showingDesktop = b; + emit desktopShown(m_showingDesktop); +} + +void KDesktop::slotCurrentDesktopChanged(int) +{ + setShowDesktop( false ); +} + +void KDesktop::slotWindowAdded(WId w) +{ + bool m_showingDesktop = showDesktopState(); + + if (!m_showingDesktop) + { + return; + } + + NETWinInfo inf(tqt_xdisplay(), w, tqt_xrootwin(), + NET::XAWMState | NET::WMWindowType); + NET::WindowType windowType = inf.windowType(NET::AllTypesMask); + + if ((windowType == NET::Normal || windowType == NET::Unknown) && + inf.mappingState() == NET::Visible) + { + TDEConfig twincfg( "twinrc", true ); // see in twin + twincfg.setGroup( "Windows" ); + if( twincfg.readBoolEntry( "ShowDesktopIsMinimizeAll", false )) + { + m_iconifiedList.clear(); + m_showingDesktop = false; + emit desktopShown(false); + } + else + { + m_activeWindow = w; + setShowDesktop(false); + } + } +} + +void KDesktop::slotWindowChanged(WId w, unsigned int dirty) +{ + bool m_showingDesktop = showDesktopState(); + + if (!m_showingDesktop) + { + return; + } + + if (dirty & NET::XAWMState) + { + NETWinInfo inf(tqt_xdisplay(), w, tqt_xrootwin(), + NET::XAWMState | NET::WMWindowType); + NET::WindowType windowType = inf.windowType(NET::AllTypesMask); + + if ((windowType == NET::Normal || windowType == NET::Unknown) && + inf.mappingState() == NET::Visible) + { + // a window was deiconified, abort the show desktop mode. + m_iconifiedList.clear(); + m_showingDesktop = false; + emit desktopShown(false); + } + } +} + +bool KDesktop::showDesktopState() +{ + return twinModule()->showingDesktop(); +} + +void KDesktop::toggleShowDesktop() +{ + setShowDesktop(!showDesktopState()); +} + +TDEActionCollection * KDesktop::actionCollection() +{ + if (!m_pIconView) + return 0; + return m_pIconView->actionCollection(); +} + +KURL KDesktop::url() const +{ + if (m_pIconView) + return m_pIconView->url(); + return KURL(); +} + +// ----------------------------------------------------------------------------- + +void KDesktop::slotConfigure() +{ + configure(); +} + +void KDesktop::configure() +{ + // re-read configuration and apply it + TDEGlobal::config()->reparseConfiguration(); + KDesktopSettings::self()->readConfig(); + + // If we have done start() already, then re-configure. + // Otherwise, start() will call initConfig anyway + if (!m_bInit) + { + initRoot(); + initConfig(); + KRootWm::self()->initConfig(); + } + + if (keys) + { + keys->readSettings(); + keys->updateConnections(); + } +} + +void KDesktop::slotSettingsChanged(int category) +{ + //kdDebug(1204) << "KDesktop::slotSettingsChanged" << endl; + if (category == TDEApplication::SETTINGS_PATHS) + { + kdDebug(1204) << "KDesktop::slotSettingsChanged SETTINGS_PATHS" << endl; + if (m_pIconView) + m_pIconView->recheckDesktopURL(); + } + else if (category == TDEApplication::SETTINGS_SHORTCUTS) + { + kdDebug(1204) << "KDesktop::slotSettingsChanged SETTINGS_SHORTCUTS" << endl; + keys->readSettings(); + keys->updateConnections(); + } +} + +void KDesktop::slotIconChanged(int group) +{ + if ( group == TDEIcon::Desktop ) + { + kdDebug(1204) << "KDesktop::slotIconChanged" << endl; + refresh(); + } +} + +void KDesktop::slotDatabaseChanged() +{ + //kdDebug(1204) << "KDesktop::slotDatabaseChanged" << endl; + if (m_bInit) // kded is done, now we can "start" for real + slotStart(); + if (m_pIconView && KSycoca::isChanged("mimetypes")) + m_pIconView->refreshMimeTypes(); +} + +void KDesktop::refresh() +{ + // George Staikos 3/14/01 + // This bit will just refresh the desktop and icons. Now I have code + // in KWin to do a complete refresh so this isn't really needed. + // I'll leave it in here incase the plan is changed again +#if 0 + m_bNeedRepaint |= 1; + updateWorkArea(); +#endif + kapp->dcopClient()->send( twin_name, "", "refresh()", TQString("")); + refreshIcons(); +} + +// ----------------------------------------------------------------------------- + +void KDesktop::slotSetVRoot() +{ + if (!m_pIconView) + return; + + if (KWin::windowInfo(winId()).mappingState() == NET::Withdrawn) { + TQTimer::singleShot(100, this, TQT_SLOT(slotSetVRoot())); + return; + } + + unsigned long rw = RootWindowOfScreen(ScreenOfDisplay(tqt_xdisplay(), tqt_xscreen())); + unsigned long vroot_data[1] = { m_pIconView->viewport()->winId() }; + static Atom vroot = XInternAtom(tqt_xdisplay(), "__SWM_VROOT", False); + + Window rootReturn, parentReturn, *children; + unsigned int numChildren; + Window top = winId(); + while (1) { + /*int ret = */XQueryTree(tqt_xdisplay(), top , &rootReturn, &parentReturn, + &children, &numChildren); + if (children) + XFree((char *)children); + if (parentReturn == rw) { + break; + } else + top = parentReturn; + } + if ( set_vroot ) + XChangeProperty(tqt_xdisplay(), top, vroot, XA_WINDOW, 32, + PropModeReplace, (unsigned char *)vroot_data, 1); + else + XDeleteProperty (tqt_xdisplay(), top, vroot); +} + +// ----------------------------------------------------------------------------- + +void KDesktop::slotShutdown() +{ + if ( m_pIconView ) + m_pIconView->saveIconPositions(); + if ( m_miniCli ) + m_miniCli->saveConfig(); +} + +// don't hide when someone presses Alt-F4 on us +void KDesktop::closeEvent(TQCloseEvent *e) +{ + e->ignore(); +} + +void KDesktop::desktopIconsAreaChanged(const TQRect &area, int screen) +{ + // hurra! kicker is alive + if ( m_waitForKicker ) m_waitForKicker->stop(); + + // -2: all screens + // -1: primary screen + // else: screen number + + if (screen <= -2) + screen = kdesktop_screen_number; + else if (screen == -1) + screen = kapp->desktop()->primaryScreen(); + + // This is pretty broken, mixes Xinerama and non-Xinerama multihead + // and generally doesn't seem to be required anyway => ignore screen. + if ( /*(screen == kdesktop_screen_number) &&*/ m_pIconView ) { + m_pIconView->updateWorkArea(area); + } +} + +void KDesktop::slotSwitchDesktops(int delta) +{ + if(m_bWheelSwitchesWorkspace && KWin::numberOfDesktops() > 1) + { + int newDesk, curDesk = KWin::currentDesktop(); + + if( (delta < 0 && m_eWheelDirection == Forward) || (delta > 0 && m_eWheelDirection == Reverse) ) + newDesk = curDesk % KWin::numberOfDesktops() + 1; + else + newDesk = ( KWin::numberOfDesktops() + curDesk - 2 ) % KWin::numberOfDesktops() + 1; + + KWin::setCurrentDesktop( newDesk ); + } +} + +void KDesktop::handleColorDropEvent(TQDropEvent * e) +{ + TDEPopupMenu popup; + popup.insertItem(SmallIconSet("colors"),i18n("Set as Primary Background Color"), 1); + popup.insertItem(SmallIconSet("colors"),i18n("Set as Secondary Background Color"), 2); + int result = popup.exec(e->pos()); + + TQColor c; + KColorDrag::decode(e, c); + switch (result) { + case 1: bgMgr->setColor(c, true); break; + case 2: bgMgr->setColor(c, false); break; + default: return; + } + bgMgr->setWallpaper(0,0); +} + +void KDesktop::handleImageDropEvent(TQDropEvent * e) +{ + TDEPopupMenu popup; + if ( m_pIconView ) + popup.insertItem(SmallIconSet("filesave"),i18n("&Save to Desktop..."), 1); + if ( ( m_pIconView && m_pIconView->maySetWallpaper() ) || m_pRootWidget ) + popup.insertItem(SmallIconSet("background"),i18n("Set as &Wallpaper"), 2); + popup.insertSeparator(); + popup.insertItem(SmallIconSet("cancel"), i18n("&Cancel")); + int result = popup.exec(e->pos()); + + if (result == 1) + { + bool ok = true; + TQString filename = KInputDialog::getText(TQString::null, i18n("Enter a name for the image below:"), TQString::null, &ok, m_pIconView); + + if (!ok) + { + return; + } + + if (filename.isEmpty()) + { + filename = i18n("image.png"); + } + else if (filename.right(4).lower() != ".png") + { + filename += ".png"; + } + + TQImage i; + TQImageDrag::decode(e, i); + KTempFile tmpFile(TQString::null, filename); + i.save(tmpFile.name(), "PNG"); + // We pass 0 as parent window because passing the desktop is not a good idea + KURL src; + src.setPath( tmpFile.name() ); + KURL dest( KDIconView::desktopURL() ); + dest.addPath( filename ); + TDEIO::NetAccess::copy( src, dest, 0 ); + tmpFile.unlink(); + } + else if (result == 2) + { + TQImage i; + TQImageDrag::decode(e, i); + KTempFile tmpFile(TDEGlobal::dirs()->saveLocation("wallpaper"), ".png"); + i.save(tmpFile.name(), "PNG"); + kdDebug(1204) << "KDesktop::contentsDropEvent " << tmpFile.name() << endl; + bgMgr->setWallpaper(tmpFile.name()); + } +} + +void KDesktop::slotNewWallpaper(const KURL &url) +{ + // This is called when a file containing an image is dropped + // (called by KonqOperations) + if ( url.isLocalFile() ) + bgMgr->setWallpaper( url.path() ); + else + { + // Figure out extension + TQString fileName = url.fileName(); + TQFileInfo fileInfo( fileName ); + TQString ext = fileInfo.extension(); + // Store tempfile in a place where it will still be available after a reboot + KTempFile tmpFile( TDEGlobal::dirs()->saveLocation("wallpaper"), "." + ext ); + KURL localURL; localURL.setPath( tmpFile.name() ); + // We pass 0 as parent window because passing the desktop is not a good idea + TDEIO::NetAccess::file_copy( url, localURL, -1, true /*overwrite*/ ); + bgMgr->setWallpaper( localURL.path() ); + } +} + +// for dcop interface backward compatibility +void KDesktop::logout() +{ + logout( TDEApplication::ShutdownConfirmDefault, + TDEApplication::ShutdownTypeNone ); +} + +void KDesktop::logout( TDEApplication::ShutdownConfirm confirm, + TDEApplication::ShutdownType sdtype ) +{ + if( !kapp->requestShutDown( confirm, sdtype ) ) + // this i18n string is also in kicker/applets/run/runapplet + KMessageBox::error( this, i18n("Could not log out properly.\nThe session manager cannot " + "be contacted. You can try to force a shutdown by pressing " + "Ctrl+Alt+Backspace; note, however, that your current session " + "will not be saved with a forced shutdown." ) ); +} + +void KDesktop::slotLogout() +{ + logout( TDEApplication::ShutdownConfirmDefault, + TDEApplication::ShutdownTypeDefault ); +} + +void KDesktop::slotLogoutNoCnf() +{ + logout( TDEApplication::ShutdownConfirmNo, + TDEApplication::ShutdownTypeNone ); +} + +void KDesktop::slotHaltNoCnf() +{ + logout( TDEApplication::ShutdownConfirmNo, + TDEApplication::ShutdownTypeHalt ); +} + +void KDesktop::slotRebootNoCnf() +{ + logout( TDEApplication::ShutdownConfirmNo, + TDEApplication::ShutdownTypeReboot ); +} + +void KDesktop::setVRoot( bool enable ) +{ + if ( enable == set_vroot ) + return; + + set_vroot = enable; + kdDebug(1204) << "setVRoot " << enable << endl; + KDesktopSettings::setSetVRoot( set_vroot ); + KDesktopSettings::writeConfig(); + slotSetVRoot(); +} + +void KDesktop::clearCommandHistory() +{ + if ( m_miniCli ) + m_miniCli->clearHistory(); +} + +void KDesktop::setIconsEnabled( bool enable ) +{ + if ( enable == m_bDesktopEnabled ) + return; + + m_bDesktopEnabled = enable; + kdDebug(1204) << "setIcons " << enable << endl; + KDesktopSettings::setDesktopEnabled( m_bDesktopEnabled ); + KDesktopSettings::writeConfig(); + if (!enable) { + delete m_pIconView; + m_pIconView = 0; + } + configure(); +} + +void KDesktop::desktopResized() +{ + resize(kapp->desktop()->size()); + + if ( m_pIconView ) + { + // the sequence of actions is important: + // remove all icons, resize desktop, tell kdiconview new iconsArea size + // tell kdiconview to reget all icons + m_pIconView->slotClear(); + m_pIconView->resize(kapp->desktop()->size()); + + // get new desktopIconsArea from kicker + TQByteArray data, result; + TQDataStream arg(data, IO_WriteOnly); + arg << kdesktop_screen_number; + TQCString replyType; + TQRect area; + + if ( kapp->dcopClient()->call(kicker_name, kicker_name, "desktopIconsArea(int)", + data, replyType, result, false, 2000) ) + { + TQDataStream res(result, IO_ReadOnly); + res >> area; + } + else + { + area = twinModule()->workArea(twinModule()->currentDesktop()); + } + + m_pIconView->updateWorkArea(area); + m_pIconView->startDirLister(); + } +} + +void KDesktop::switchDesktops( int delta ) +{ + bool old = m_bWheelSwitchesWorkspace; + m_bWheelSwitchesWorkspace = true; + slotSwitchDesktops(delta); + m_bWheelSwitchesWorkspace = old; +} + +bool KDesktop::event(TQEvent * e) +{ + if ( e->type() == TQEvent::WindowDeactivate) + { + if (m_pIconView) + m_pIconView->clearSelection(); + } + return TQWidget::event(e); +} + +TQPoint KDesktop::findPlaceForIcon( int column, int row ) +{ + if (m_pIconView) + return m_pIconView->findPlaceForIcon(column, row); + else + return TQPoint(-1, -1); +} + +void KDesktop::addIcon(const TQString & _url, int x, int y) +{ + addIcon( _url, TDEGlobalSettings::desktopPath(), x, y ); +} + +void KDesktop::addIcon(const TQString & _url, const TQString & _dest, int x, int y) +{ + TQString filename = _url.mid(_url.findRev('/') + 1); + + TQValueList<TDEIO::CopyInfo> files; + TDEIO::CopyInfo i; + i.uSource = KURL::fromPathOrURL( _url ); + i.uDest = KURL::fromPathOrURL( _dest ); + i.uDest.addPath( filename ); + files.append(i); + if (!TQFile::exists(i.uDest.prettyURL().replace("file://",TQString()))) { m_pIconView->slotAboutToCreate( TQPoint( x, y ), files ); + TDEIO::copy( i.uSource, i.uDest, false ); } + +// m_pIconView->addFuturePosition(filename, x, y); + // tqDebug("addIcon %s %s %d %d", _url.latin1(), _dest.latin1(), x, y); +// system(TQString("cp \"%1\" \"%2/%3\"").arg(KURL(_url).path()).arg(KURL(_dest).path()).arg(filename).latin1()); +// m_pIconView->update( _dest ); +} + +void KDesktop::removeIcon(const TQString &_url) +{ + if (_url.at(0) != '/') { + tqDebug("removeIcon with relative path not supported for now"); + return; + } + unlink(KURL(_url).path().latin1()); + TQString dest = _url.left(_url.findRev('/') + 1); + m_pIconView->update( dest ); +} + +#include "desktop.moc" diff --git a/kdesktop/desktop.h b/kdesktop/desktop.h new file mode 100644 index 000000000..6d8015f31 --- /dev/null +++ b/kdesktop/desktop.h @@ -0,0 +1,234 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 Torben Weis <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __desktop_h__ +#define __desktop_h__ + +#include "KDesktopIface.h" + +#include <tqwidget.h> +#include <tqstringlist.h> +#include <tqvaluevector.h> + +#include <tdeapplication.h> // for logout parameters + +class KURL; +class TQCloseEvent; +class TQDropEvent; +class TQPopupMenu; +class TDEGlobalAccel; +class KWinModule; +class KBackgroundManager; +class TQTimer; +class StartupId; +class KDIconView; +class Minicli; +class TDEActionCollection; + +class KRootWidget : public TQObject +{ + Q_OBJECT +public: + KRootWidget(); + bool eventFilter( TQObject *, TQEvent * e ); +signals: + void wheelRolled( int delta ); + void colorDropEvent( TQDropEvent* e ); + void imageDropEvent( TQDropEvent* e ); + void newWallpaper( const KURL& url ); +}; + +/** + * KDesktop is the toplevel widget that is the desktop. + * It handles the background, the screensaver and all the rest of the global stuff. + * The icon view is a child widget of KDesktop. + */ +class KDesktop : public TQWidget, + public KDesktopIface +{ + Q_OBJECT + +public: + + enum WheelDirection { Forward = 0, Reverse }; + + KDesktop(bool x_root_hack, bool wait_for_kded ); + ~KDesktop(); + + // Implementation of the DCOP interface + virtual void rearrangeIcons(); + virtual void lineupIcons(); + virtual void selectAll(); + virtual void unselectAll(); + virtual void refreshIcons(); + virtual void setShowDesktop( bool b ); + virtual bool showDesktopState(); + virtual void toggleShowDesktop(); + virtual TQStringList selectedURLs(); + + virtual void configure(); + virtual void popupExecuteCommand(); + virtual void popupExecuteCommand(const TQString& content); + virtual void refresh(); + virtual void logout(); + virtual void clearCommandHistory(); + virtual void runAutoStart(); + + virtual void switchDesktops( int delta ); + + virtual void desktopIconsAreaChanged(const TQRect &area, int screen); + + void logout( TDEApplication::ShutdownConfirm confirm, TDEApplication::ShutdownType sdtype ); + + KWinModule* twinModule() const { return m_pKwinmodule; } + + // The action collection of the active widget + TDEActionCollection *actionCollection(); + + // The URL (for the File/New menu) + KURL url() const; + + // ## hack ## + KDIconView *iconView() const { return m_pIconView; } + +private slots: + /** Background is ready. */ + void backgroundInitDone(); + + /** Activate the desktop. */ + void slotStart(); + + /** Activate crash recovery. */ + void slotUpAndRunning(); + + /** Reconfigures */ + void slotConfigure(); + + /** Show minicli,. the KDE command line interface */ + void slotExecuteCommand(); + + /** Show taskmanager (calls KSysGuard with --showprocesses option) */ + void slotShowTaskManager(); + + void slotShowWindowList(); + + void slotSwitchUser(); + + void slotLogout(); + void slotLogoutNoCnf(); + void slotHaltNoCnf(); + void slotRebootNoCnf(); + + /** Connected to KSycoca */ + void slotDatabaseChanged(); + + void slotShutdown(); + void slotSettingsChanged(int); + void slotIconChanged(int); + + /** set the vroot atom for e.g. xsnow */ + void slotSetVRoot(); + + /** Connected to KDIconView */ + void handleImageDropEvent( TQDropEvent * ); + void handleColorDropEvent( TQDropEvent * ); + void slotNewWallpaper(const KURL &url); + + /** Connected to KDIconView and KRootWidget */ + void slotSwitchDesktops(int delta); + + // when there seems to be no kicker, we have to get desktopIconsArea from twinModule + void slotNoKicker(); + + /** Used for desktop show/hide functionality */ + void slotCurrentDesktopChanged(int); + void slotWindowAdded(WId w); + void slotWindowChanged(WId w, unsigned int dirty); + +protected: + void initConfig(); + void initRoot(); + + virtual void closeEvent(TQCloseEvent *e); + + virtual bool isVRoot() { return set_vroot; } + virtual void setVRoot( bool enable ); + + virtual bool isIconsEnabled() { return m_bDesktopEnabled; } + virtual void setIconsEnabled( bool enable ); + virtual bool event ( TQEvent * e ); + + virtual TQPoint findPlaceForIcon( int column, int row); + virtual void addIcon(const TQString &url, int x, int y); + virtual void addIcon(const TQString &url, const TQString &dest, int x, int y); + virtual void removeIcon(const TQString &url); + +private slots: + void desktopResized(); + +signals: + void desktopShown(bool shown); + +private: + + TDEGlobalAccel *keys; + + KWinModule* m_pKwinmodule; + + KBackgroundManager* bgMgr; + + KDIconView *m_pIconView; + KRootWidget *m_pRootWidget; + + Minicli *m_miniCli; + + StartupId* startup_id; + bool set_vroot; + + /** Set to true until start() has been called */ + bool m_bInit; + + /** Wait for kded to finish building database? */ + bool m_bWaitForKded; + + /** Desktop enabled / disabled **/ + bool m_bDesktopEnabled; + + /** Whether or not to switch desktops when mouse wheel is rolled */ + bool m_bWheelSwitchesWorkspace; + + TQTimer *m_waitForKicker; + + /** Default mouse wheel direction (Fwd means mwheel up switches to + lower desktop) + */ + static const WheelDirection m_eDefaultWheelDirection = Forward; + + /** Mouse wheel/desktop switching direction */ + static WheelDirection m_eWheelDirection; + + /** Possible values for "kdesktoprc"->"Mouse Buttons"->"WheelDirection" */ + static const char* m_wheelDirectionStrings[2]; + + bool m_wmSupport; + WId m_activeWindow; + TQValueVector<WId> m_iconifiedList; +}; + +#endif diff --git a/kdesktop/init.cc b/kdesktop/init.cc new file mode 100644 index 000000000..6bf87f333 --- /dev/null +++ b/kdesktop/init.cc @@ -0,0 +1,247 @@ +/* This file is part of the KDE project + Copyright (C) 1999 David Faure <[email protected]> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <tdeio/job.h> +#include <tdeio/netaccess.h> +#include <kstandarddirs.h> +#include <kdesktopfile.h> +#include <tdeglobalsettings.h> +#include <tdeapplication.h> +#include <kprocess.h> +#include <tdemessagebox.h> +#include <tdelocale.h> +#include <kdebug.h> +#include <kdesktopsettings.h> + +#include <tqdir.h> +#include <tqfile.h> +#include <tqregexp.h> + +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#include <dirent.h> +#include <stdlib.h> +#include <errno.h> +#include <ksimpleconfig.h> + +// for multihead +extern int kdesktop_screen_number; + + +/** + * Test if a directory exists, create otherwise + * @param _name full path of the directory + * @param _showMsg show a message box if we created the dir + * @return true if the dir was just created (e.g. so that we can populate it) + */ +static bool testDir( const TQString &_name ) +{ + DIR *dp; + dp = opendir( TQFile::encodeName(_name) ); + if ( dp == NULL ) + { + TQString m = _name; + if ( m.endsWith( "/" ) ) + m.truncate( m.length() - 1 ); + TQCString path = TQFile::encodeName(m); + + bool ok = ::mkdir( path, S_IRWXU ) == 0; + if ( !ok && errno == EEXIST ) { + int ret = KMessageBox::warningYesNo( 0, i18n("%1 is a file, but TDE needs it to be a directory; move it to %2.orig and create directory?").arg(m).arg(m), TQString::null, i18n("Move It"), i18n("Do Not Move") ); + if ( ret == KMessageBox::Yes ) { + if ( ::rename( path, path + ".orig" ) == 0 ) { + ok = ::mkdir( path, S_IRWXU ) == 0; + } else { + // foo.orig existed already. How likely is that? + ok = false; + } + } else { + return false; + } + } + if ( !ok ) + { + KMessageBox::sorry( 0, i18n( "Could not create directory %1; check for permissions or reconfigure the desktop to use another path." ).arg( m ) ); + return false; + } + return true; + } + else // exists already + { + closedir( dp ); + return false; + } +} + +/** + * Copy a standard .directory file to a user's directory + * @param fileName destination file name + * @param dir destination directory + * @param force if false, don't copy if destination file already exists + */ +static void copyDirectoryFile(const TQString &fileName, const TQString& dir, bool force) +{ + if (force || !TQFile::exists(dir + "/.directory")) { + TQString cmd = "cp "; + cmd += TDEProcess::quote(locate("data", TQString("kdesktop/") + fileName)); + cmd += " "; + cmd += TDEProcess::quote(dir+"/.directory"); + system( TQFile::encodeName(cmd) ); + } +} + +static void copyFile( const TQString& src, const TQString& dest ) +{ + TQCString cmd = "cp "; + cmd += TQFile::encodeName(TDEProcess::quote(src)); + cmd += " "; + cmd += TQFile::encodeName(TDEProcess::quote(dest)); + system( cmd ); +} + +static TQString realDesktopPath() +{ + TQString desktopPath = TDEGlobalSettings::desktopPath(); + if (kdesktop_screen_number != 0) { + TQString dn = "Desktop"; + dn += TQString::number(kdesktop_screen_number); + desktopPath.replace("Desktop", dn); + } + return desktopPath; +} + +/** + * Copy all links from DesktopLinks/ to the desktop, appropriately renamed + * (to the contents of the translated Name field) + */ +static void copyDesktopLinks() +{ + TDEConfig *config = kapp->config(); + config->setGroup("General"); + if (!config->readBoolEntry("CopyDesktopLinks", true)) + return; + + TQStringList list = + TDEGlobal::dirs()->findAllResources("appdata", "DesktopLinks/*", false, true); + + TQString desktopPath = realDesktopPath(); + + for (TQStringList::ConstIterator it = list.begin(); it != list.end(); it++) { + KDesktopFile desk( *it ); + if (desk.readBoolEntry("Hidden")) + continue; + copyFile( *it, desktopPath ); + } +} + +/** + * @return true if this is the first time + * kdesktop is run for the current release + * WARNING : call only once !!! (second call will always return false !) + */ +static bool isNewRelease() +{ + bool bNewRelease = false; + + int versionMajor = KDesktopSettings::kDEVersionMajor(); + int versionMinor = KDesktopSettings::kDEVersionMinor(); + int versionRelease = KDesktopSettings::kDEVersionRelease(); + + if( versionMajor < TDE_VERSION_MAJOR ) + bNewRelease = true; + else if( versionMinor < TDE_VERSION_MINOR ) + bNewRelease = true; + else if( versionRelease < TDE_VERSION_RELEASE ) + bNewRelease = true; + + if( bNewRelease ) { + KDesktopSettings::setKDEVersionMajor( TDE_VERSION_MAJOR ); + KDesktopSettings::setKDEVersionMinor( TDE_VERSION_MINOR ); + KDesktopSettings::setKDEVersionRelease( TDE_VERSION_RELEASE ); + KDesktopSettings::writeConfig(); + } + + return bNewRelease; +} + +/** + * Create, if necessary, some directories in user's .kde/, + * copy default .directory files there, as well as templates files. + * Called by kdesktop on startup. + */ +void testLocalInstallation() +{ + const bool newRelease = isNewRelease(); + + const TQString desktopPath = realDesktopPath(); + const bool emptyDesktop = testDir( desktopPath ); + + // Do not force copying that one (it would lose the icon positions) + copyDirectoryFile("directory.desktop", desktopPath, false); + + testDir( TDEGlobalSettings::autostartPath() ); + // we force the copying in case of a new release, to install new translations.... + copyDirectoryFile("directory.autostart", TDEGlobalSettings::autostartPath(), newRelease); + + if (emptyDesktop) + copyDesktopLinks(); + + // Take care of creating or updating trash.desktop + const TQString trashDir = TDEGlobal::dirs()->localxdgdatadir() + "Trash"; + const bool firstTimeWithNewTrash = !TQFile::exists( trashDir ); + const TQString trashDesktopPath = desktopPath + "/trash.desktop"; + const bool trashDesktopExists = TQFile::exists( trashDesktopPath ); + const bool installNewTrashi18n = newRelease && trashDesktopExists; // not if deleted by user + if ( emptyDesktop || firstTimeWithNewTrash || installNewTrashi18n ) { + TQString oldIcon, oldEmptyIcon; + if ( trashDesktopExists ) { + KDesktopFile trashDesktop( trashDesktopPath, true ); + oldIcon = trashDesktop.readIcon(); + oldEmptyIcon = trashDesktop.readEntry( "EmptyIcon" ); + } + copyFile( locate( "data", "kdesktop/directory.trash" ), trashDesktopPath ); + if ( trashDesktopExists ) { + KDesktopFile trashDesktop( trashDesktopPath ); + trashDesktop.writeEntry( "Icon", oldIcon ); + trashDesktop.writeEntry( "EmptyIcon", oldEmptyIcon ); + trashDesktop.sync(); + } + } + + if ( firstTimeWithNewTrash ) { // migrate pre-kde-3.4 trash contents + TQByteArray packedArgs; + TQDataStream stream( packedArgs, IO_WriteOnly ); + stream << (int)2; + TDEIO::Job* job = TDEIO::special( "trash:/", packedArgs ); + (void)TDEIO::NetAccess::synchronousRun( job, 0 ); + + // OK the only thing missing is to convert the icon position... + KSimpleConfig cfg( locateLocal("appdata", "IconPositions") ); + if ( cfg.hasGroup( "IconPosition::Trash" ) && !cfg.hasGroup( "IconPosition::trash.desktop" ) ) { + const TQMap<TQString, TQString> entries = cfg.entryMap( "IconPosition::Trash" ); + cfg.setGroup( "IconPosition::trash.desktop" ); + for( TQMap<TQString,TQString>::ConstIterator it = entries.begin(); it != entries.end(); ++it ) { + cfg.writeEntry( it.key(), it.data() ); + } + } + } +} + diff --git a/kdesktop/init.h b/kdesktop/init.h new file mode 100644 index 000000000..8f23ac1b4 --- /dev/null +++ b/kdesktop/init.h @@ -0,0 +1,30 @@ +/* This file is part of the KDE project + Copyright (C) 1999 David Faure <[email protected]> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __init_h +#define __init_h + +/** + * Create, if necessary, some directories in user's .kde/, + * copy default .directory files there, as well as templates files. + * Called by kdesktop on startup. + */ +void testLocalInstallation(); + +#endif diff --git a/kdesktop/init/CMakeLists.txt b/kdesktop/init/CMakeLists.txt new file mode 100644 index 000000000..c771e6dfb --- /dev/null +++ b/kdesktop/init/CMakeLists.txt @@ -0,0 +1,24 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( Templates ) + +install( FILES + directory.autostart directory.templates directory.desktop + DESTINATION ${DATA_INSTALL_DIR}/kdesktop ) + +install( FILES + My_Computer My_Documents My_Network_Places Printers Trash Web_Browser + DESTINATION ${DATA_INSTALL_DIR}/kdesktop/Desktop ) + +install( FILES + Home.desktop System.desktop + DESTINATION ${DATA_INSTALL_DIR}/kdesktop/DesktopLinks ) diff --git a/kdesktop/init/Home.desktop b/kdesktop/init/Home.desktop new file mode 100644 index 000000000..58f5302c8 --- /dev/null +++ b/kdesktop/init/Home.desktop @@ -0,0 +1,166 @@ +[Desktop Entry] +Name=Home +Name[af]=Tuiste +Name[ar]=المنزل +Name[az]=Başlanğıc +Name[be]=Хатняя тэчка +Name[bg]=Домашна директория +Name[bn]=ব্যক্তিগত ফোল্ডার +Name[br]=Er-gêr +Name[bs]=Početak +Name[ca]=Inici +Name[cs]=Můj adresář +Name[csb]=Dodóm +Name[cy]=Cartref +Name[da]=Hjem +Name[de]=Persönlicher Ordner +Name[el]=Προσωπικός φάκελος +Name[eo]=Hejmo +Name[es]=Personal +Name[et]=Kodu +Name[eu]=Etxea +Name[fa]=آغازه +Name[fi]=Koti +Name[fr]=Dossier personnel +Name[fy]=Thús +Name[ga]=Baile +Name[gl]=Persoal +Name[he]=בית +Name[hi]=घर +Name[hr]=Početak +Name[hu]=Saját könyvtár +Name[id]=Rumah +Name[is]=Heimasvæðið þitt +Name[ja]=ホーム +Name[ka]=სახლში +Name[kk]=Мекен +Name[km]=ផ្ទះ +Name[ko]=홈 +Name[lo]=ພື້ນທີ່ສ່ວນຕົວ +Name[lt]=Pradžia +Name[lv]=Mājas +Name[mk]=Дома +Name[mn]=Гэр +Name[ms]=Laman Utama +Name[mt]=Direttorju Personali +Name[nb]=Hjem +Name[nds]=Tohuus +Name[ne]=गृह +Name[nn]=Heim +Name[nso]=Gae +Name[oc]=Inici +Name[pa]=ਘਰ +Name[pl]=Katalog domowy +Name[pt]=Pasta Pessoal +Name[pt_BR]=Pasta do Usuário +Name[ro]=Acasă +Name[ru]=Домой +Name[rw]=Urugo +Name[se]=Ruoktu +Name[sk]=Domov +Name[sl]=Domov +Name[sr]=Домаће +Name[sr@Latn]=Domaće +Name[ss]=Ekhaya +Name[sv]=Hem +Name[ta]=தொடக்கம் +Name[te]=ఇల్లు +Name[tg]=Компютери Ман +Name[th]=พื้นที่ส่วนตัว +Name[tr]=Başlangıç +Name[tt]=Anabit +Name[uk]=Домівка +Name[uz]=Uy +Name[uz@cyrillic]=Уй +Name[ven]=Haya +Name[vi]=Nhà +Name[wa]=Måjhon +Name[xh]=Ikhaya +Name[zh_CN]=主文件夹 +Name[zh_TW]=家目錄 +Name[zu]=Ikhaya +GenericName=Personal Files +GenericName[af]=Persoonlike Lêers +GenericName[ar]=الملفات الشخصية +GenericName[az]=Şəxsi Fayllar +GenericName[be]=Персанальныя файлы +GenericName[bg]=Лични файлове +GenericName[bn]=ব্যক্তিগত ফাইলসমূহ +GenericName[br]=Restroù deoc'h +GenericName[bs]=Osobne datoteke +GenericName[ca]=Fitxers personals +GenericName[cs]=Osobní soubory +GenericName[csb]=Swòje lopczi +GenericName[cy]=Ffeiliau Personol +GenericName[da]=Personlige filer +GenericName[de]=Eigene Dateien +GenericName[el]=Προσωπικά αρχεία +GenericName[eo]=Personaj dosieroj +GenericName[es]=Archivos personales +GenericName[et]=Isiklikud failid +GenericName[eu]=Fitxategi pertsonalak +GenericName[fa]=پروندههای شخصی +GenericName[fi]=Omat tiedostot +GenericName[fr]=Fichiers personnels +GenericName[fy]=Persoanlike map +GenericName[ga]=Comhaid Phearsanta +GenericName[gl]=Ficheiros Persoais +GenericName[he]=קבצים אישיים +GenericName[hi]=निजी फ़ाइलें +GenericName[hr]=Osobne datoteke +GenericName[hu]=Személyes fájlok +GenericName[id]=File Pribadi +GenericName[is]=Skrárnar þínar +GenericName[it]=File personali +GenericName[ja]=個人のファイル +GenericName[ka]=პირადი საქაღალდეები +GenericName[kk]=Дербес файлдар +GenericName[km]=ឯកសារផ្ទាល់ខ្លួន +GenericName[ko]=개인적인 파일 +GenericName[lo]=ທີ່ເກັບແຟ້ມແລະເອກະສານສວ່ນຕົວຫລືອື່ນຯ +GenericName[lt]=Asmeninės bylos +GenericName[lv]=Personālie Faili +GenericName[mk]=Лични датотеки +GenericName[mn]=Өөрийн файлууд +GenericName[ms]=Fail Peribadi +GenericName[mt]=Fajls Personali +GenericName[nb]=Personlige filer +GenericName[nds]=De egen Dateien +GenericName[ne]=व्यक्तिगत फाइल +GenericName[nl]=Persoonlijke map +GenericName[nn]=Personlege filer +GenericName[nso]=Difaele tsa Botho +GenericName[oc]=FiquièRs personals +GenericName[pa]=ਨਿੱਜੀ ਫਾਇਲ਼ਾਂ +GenericName[pl]=Pliki osobiste +GenericName[pt]=Ficheiros Pessoais +GenericName[pt_BR]=Arquivos Pessoais +GenericName[ro]=Fișiere personale +GenericName[ru]=Личные файлы +GenericName[rw]=Amadosiye Yihariye +GenericName[se]=Iežat fiillat +GenericName[sk]=Osobné súbory +GenericName[sl]=Osebne datoteke +GenericName[sr]=Лични фајлови +GenericName[sr@Latn]=Lični fajlovi +GenericName[sv]=Personliga filer +GenericName[ta]=சொந்த கோப்புகள் +GenericName[te]=వ్యక్తిగత దస్త్రాలు +GenericName[tg]=Файлҳои шахсӣ +GenericName[th]=แฟ้มส่วนตัว +GenericName[tr]=Kişisel Dosyalar +GenericName[tt]=Şäxsi Biremnär +GenericName[uk]=Особисті файли +GenericName[uz]=Shaxsiy fayllar +GenericName[uz@cyrillic]=Шахсий файллар +GenericName[ven]=Dzifaela dza vhune +GenericName[vi]=Tập tin Cá nhân +GenericName[wa]=Fitchîs da vosse +GenericName[xh]=Iifayile Zobuqu +GenericName[zh_CN]=个人文件 +GenericName[zh_TW]=個人檔案 +GenericName[zu]=Amafayela Omuntu siqu +URL=$HOME +Icon=kfm_home +Type=Link +OnlyShowIn=TDE; diff --git a/kdesktop/init/Makefile.am b/kdesktop/init/Makefile.am new file mode 100644 index 000000000..c997bfcb0 --- /dev/null +++ b/kdesktop/init/Makefile.am @@ -0,0 +1,11 @@ +SUBDIRS = Templates + +kdesktop_init_data_DATA = directory.autostart directory.templates directory.desktop +kdesktop_init_datadir = $(kde_datadir)/kdesktop + +kdesktop_builtin_data_DATA = My_Computer My_Documents My_Network_Places Printers Trash Web_Browser +kdesktop_builtin_datadir = $(kde_datadir)/kdesktop/Desktop + +desktoplink_DATA = Home.desktop System.desktop +desktoplinkdir = $(kde_datadir)/kdesktop/DesktopLinks + diff --git a/kdesktop/init/My_Computer b/kdesktop/init/My_Computer new file mode 100644 index 000000000..68847b649 --- /dev/null +++ b/kdesktop/init/My_Computer @@ -0,0 +1,75 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=system +Name=My Computer +Name[af]=Stoor Media +Name[ar]=وسائط التخزين +Name[be]=Носьбіты +Name[bg]=Съхраняващи устройства +Name[bn]=স্টোরেজ মিডিয়া +Name[bs]=Uređaji za smještaj podataka +Name[ca]=Suports d'emmagatzematge +Name[cs]=Úložná zařízení +Name[csb]=Zôpisowné media +Name[da]=Opbevaringsmedie +Name[de]=Speichermedien +Name[el]=Συσκευές αποθήκευσης +Name[en_US]=My Computer +Name[eo]=Enmemoriga Medio +Name[es]=Dispositivos de almacenamiento +Name[et]=Andmekandjad +Name[eu]=Biltegiratze-euskarria +Name[fa]=رسانۀ ذخیرهگاه +Name[fi]=Tallennusmedia +Name[fr]=Support de stockage +Name[fy]=Opslachapparaten +Name[ga]=Meán Stórais +Name[gl]=Medios de armacenaxe +Name[he]=התקנים +Name[hi]=भंडार मीडिया +Name[hr]=Mediji za pohranjivanje +Name[hu]=Tárolóeszközök +Name[is]=Geymslumiðlar +Name[it]=Dispositivi di archiviazione +Name[ja]=記憶メディア +Name[ka]=მონაცემთა შენახვის მოწყობილობები +Name[kk]=Жинақтаушы құрылғылар +Name[km]=ឧបករណ៍ផ្ទុក +Name[lt]=Saugojimo įrenginiai +Name[lv]=Datu nesējs +Name[mk]=Медиуми за податоци +Name[ms]=Media Storan +Name[nb]=Lagringsenheter +Name[nds]=Spiekermedien +Name[ne]=भण्डारण मिडिया +Name[nl]=Opslagapparaten +Name[nn]=Lagringsmedium +Name[pa]=ਸਟੋਰੇਜ਼ ਮੀਡਿਆ +Name[pl]=Urządzenia przechowywania danych +Name[pt]=Dispositivos de Armazenamento +Name[pt_BR]=Mídia de Armazenamento +Name[ro]=Mediu de stocare +Name[ru]=Устройства хранения данных +Name[rw]=Uburyo bwo Kubika +Name[se]=Vurkenmedia +Name[sk]=Zálohovacie médiá +Name[sl]=Nosilci za shranjevanje +Name[sr]=Складишни медијуми +Name[sr@Latn]=Skladišni medijumi +Name[sv]=Lagringsmedia +Name[ta]=சேகரிப்பு ஊடகம் +Name[tg]=Захирагоҳи маълумот +Name[th]=สื่อเก็บข้อมูล +Name[tr]=Depolama Ortamı +Name[tt]=Saqlawlı Media +Name[uk]=Пристрої зберігання інформації +Name[uz]=Saqlash uskunalari +Name[uz@cyrillic]=Сақлаш ускуналари +Name[vi]=Ổ chứa Dữ liệu +Name[wa]=Sopoirts di wårdaedje +Name[zh_CN]=存储介质 +Name[zh_TW]=儲存媒體 +OnlyShowIn=TDE; +Type=Link +URL=media:/ +X-Trinity-BuiltIn=true diff --git a/kdesktop/init/My_Documents b/kdesktop/init/My_Documents new file mode 100644 index 000000000..497f34c40 --- /dev/null +++ b/kdesktop/init/My_Documents @@ -0,0 +1,67 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=folder_wordprocessing +Name=My Documents +Name[af]=Dokument Gids +Name[ar]=مستنداتي +Name[be]=ТÑчка Ð´Ð»Ñ Ð´Ð°ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñž +Name[bg]=Ð”Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð¸ +Name[bn]=ডকà§à¦®à§‡à¦¨à§à¦Ÿ ফোলà§à¦¡à¦¾à¦° +Name[br]=Renkell an teulioù +Name[bs]=Direktorij dokumenata +Name[ca]=Carpeta de documents +Name[cs]=Složka s dokumenty +Name[csb]=Katalog dokùmentów +Name[da]=Dokumentmappe +Name[de]=Dokumente +Name[en_US]=My Documents +Name[eo]=Dokumenta dosierujo +Name[es]=Carpeta de documentos +Name[et]=Dokumentide kataloog +Name[eu]=Dokumentuen karpeta +Name[fa]=پوشۀ مستندات +Name[fi]=Asiakirjakansio +Name[fr]=Dossier des documents +Name[fy]=Ofkeppele kamera +Name[ga]=Fillteán na gCáipéisí +Name[gl]=Cartafol de Documentos +Name[hr]=Mapa dokumenata +Name[hu]=Dokumentumok könyvtár +Name[is]=Skjalamappa +Name[it]=Cartella documenti +Name[ja]=ドキュメントフォルダ +Name[kk]=Құжаттар қапшығы +Name[lt]=Dokumentų aplankai +Name[nb]=Dokumentmappe +Name[nds]=Dokmenten-Orner +Name[nl]=Documenten +Name[nn]=Dokumentmappe +Name[pa]=ਦਸਤਾਵੇਜ਼ ਫੋਲਡਰ +Name[pl]=Katalog dokumentów +Name[pt]=Pasta de Documentos +Name[pt_BR]=Pasta de Documentos +Name[ro]=Folder documente +Name[ru]=Документы +Name[se]=Dokumeantamáhppa +Name[sl]=Mapa z dokumenti +Name[sr@Latn]=Fascikla sa dokumentima +Name[sv]=Dokumentkatalog +Name[tg]=Ҳуҷҷатҳо +Name[tr]=Belgeler Dizini +Name[uk]=Тека документів +Name[uz]=Hujjatlar jildi +Name[uz@cyrillic]=Ҳужжатлар жилди +Name[vi]=Thư mục T� i liệu +Name[wa]=Ridant documints +Name[zh_CN]=文档文件夹 +Name[zh_TW]=文件目錄 +URL=$( kxdglauncher --getpath --xdgname DOCUMENTS ) +Type=Link +StartupNotify=true +MimeType= +Terminal=false +TerminalOptions= +X-DCOP-ServiceType= +X-TDE-SubstituteUID=false +X-TDE-Username= +OnlyShowIn=TDE; diff --git a/kdesktop/init/My_Network_Places b/kdesktop/init/My_Network_Places new file mode 100644 index 000000000..647db5a85 --- /dev/null +++ b/kdesktop/init/My_Network_Places @@ -0,0 +1,77 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=network +Name=My Network Places +Name[af]=Afgeleë Plekke +Name[ar]=أماكن بعيدة +Name[be]=Аддаленыя месцы +Name[bg]=Отдалечени директории +Name[bn]=দূরবর্তী অবস্থান +Name[br]=Lec'hiadurioù a-bell +Name[bs]=Udaljena mjesta +Name[ca]=Llocs remots +Name[cs]=Vzdálená umístění +Name[csb]=Daleczi place +Name[da]=Eksterne steder +Name[de]=Netzwerk +Name[el]=Απομακρυσμένες τοποθεσίες +Name[en_US]=My Network Places +Name[eo]=Foraj Lokoj +Name[es]=Lugares remotos +Name[et]=Võrgukohad +Name[eu]=Urruneko lekuak +Name[fa]=جاهای دور +Name[fi]=Etäkohteet +Name[fr]=Emplacements distants +Name[fy]=Eksterne plakken +Name[ga]=Áiteanna Cianda +Name[gl]=Comparticións Remotas +Name[he]=מקומות מרוחקים +Name[hi]=रिमोट स्थान +Name[hr]=Udaljene lokacije +Name[hu]=Hálózati helyek +Name[is]=Fjarlægir staðir +Name[it]=Indirizzi remoti +Name[ja]=リモートの場所 +Name[ka]=დაშორებული ადგილები +Name[kk]=Қашықтағы орындар +Name[km]=កន្លែងពីចម្ងាយ +Name[ko]=원격 접속 +Name[lt]=Nutolusios vietos +Name[lv]=Attālinātās vietas +Name[mk]=Оддалечени места +Name[ms]=Tempat Jauh +Name[nb]=Eksterne steder +Name[nds]=Feern Steden +Name[ne]=टाढाको स्थान +Name[nl]=Externe plekken +Name[nn]=Eksterne plassar +Name[pa]=ਰਿਮੋਟ ਥਾਂ +Name[pl]=Zdalne miejsca +Name[pt]=Locais Remotos +Name[pt_BR]=Locais Remotos +Name[ro]=Locații distante +Name[ru]=Сетевые ресурсы +Name[rw]=Imyanya ya Kure +Name[se]=Gáiddus báikkit +Name[sk]=Vzdialené miesta +Name[sl]=Oddaljena mesta +Name[sr]=Удаљена места +Name[sr@Latn]=Udaljena mesta +Name[sv]=Fjärrplatser +Name[ta]=தொலைதூர இடங்கள் +Name[te]=సుదూరపు ప్రదేశాలు +Name[th]=ทางไกล +Name[tr]=Uzak Yerler +Name[tt]=Çittäge Urınnar +Name[uk]=Віддалені місця +Name[uz]=Masofadagi joylar +Name[uz@cyrillic]=Масофадаги жойлар +Name[vi]=Địa chỉ trên mạng +Name[wa]=Plaeces då lon +Name[zh_CN]=远程位置 +Name[zh_TW]=遠端空間 +OnlyShowIn=TDE; +Type=Link +URL=remote:/ +X-Trinity-BuiltIn=true diff --git a/kdesktop/init/Printers b/kdesktop/init/Printers new file mode 100644 index 000000000..91abc3e83 --- /dev/null +++ b/kdesktop/init/Printers @@ -0,0 +1,86 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=kjobviewer +Name=Printers +Name[af]=Drukkers +Name[ar]=الطابعات +Name[be]=Друкаркі +Name[bg]=Принтери +Name[bn]=মুদ্রণ +Name[br]=Moullerezioù +Name[bs]=Štampači +Name[ca]=Impressores +Name[cs]=Tiskárny +Name[csb]=Drëkerë +Name[cy]=Argraffyddion +Name[da]=Printere +Name[de]=Drucker +Name[el]=Εκτυπωτές +Name[en_US]=Printers +Name[eo]=Printiloj +Name[es]=Impresoras +Name[et]=Printerid +Name[eu]=Inprimagailuak +Name[fa]=چاپگرها +Name[fi]=Tulostimet +Name[fr]=Imprimantes +Name[ga]=Printéirí +Name[gl]=Impresoras +Name[he]=מדפסות +Name[hi]=प्रिंटर +Name[hr]=Pisači +Name[hu]=Nyomtató +Name[is]=Prentarar +Name[it]=Stampanti +Name[ja]=プリンタ +Name[ka]=პრინტერები +Name[kk]=Принтерлер +Name[km]=ម៉ាស៊ីនបោះពុម្ព +Name[lo]=ເຄື່ອງພິມ - K +Name[lt]=Spausdintuvai +Name[lv]=Printeri +Name[mk]=Печатачи +Name[mn]=Хэвлэгч +Name[ms]=Pencetak +Name[nb]=Skrivere +Name[nds]=Druckers +Name[ne]=मुद्रक +Name[nn]=Skrivarar +Name[nso]=Digatisi +Name[pa]=ਪਰਿੰਟਰ +Name[pl]=Drukarki +Name[pt]=Impressoras +Name[pt_BR]=Impressoras +Name[ro]=Imprimante +Name[ru]=Принтеры +Name[rw]=Mucapyi +Name[se]=Čálánat +Name[sk]=Tlačiarne +Name[sl]=Tiskalniki +Name[sr]=Штампачи +Name[sr@Latn]=Štampači +Name[ss]=Tishiceleli +Name[sv]=Skrivare +Name[ta]=அச்சியந்திரம் +Name[te]=ప్రింటర్లు +Name[tg]=Чопгарҳо +Name[th]=เครื่องพิมพ์ +Name[tr]=Yazıcılar +Name[tt]=Basaqlar +Name[uk]=Принтери +Name[uz]=Printerlar +Name[uz@cyrillic]=Принтерлар +Name[ven]=Dziphirinthara +Name[vi]=Máy in +Name[wa]=Sicrireces +Name[xh]=Abashicileli +Name[zh_CN]=打印机 +Name[zh_TW]=印表機 +Name[zu]=Abashicileli +Terminal=false +Type=Application +Exec=kjobviewer --all --show %i %m +OnlyShowIn=TDE; +X-DCOP-ServiceType=Unique +X-TDE-StartupNotify=true +X-Trinity-BuiltIn=true diff --git a/kdesktop/init/System.desktop b/kdesktop/init/System.desktop new file mode 100644 index 000000000..509f1f17d --- /dev/null +++ b/kdesktop/init/System.desktop @@ -0,0 +1,149 @@ +[Desktop Entry] +Name=System +Name[af]=Stelsel +Name[ar]=النظام +Name[az]=Sistem +Name[be]=Сістэма +Name[bg]=Система +Name[bn]=সিস্টেম +Name[br]=Reizhiad +Name[bs]=Sistem +Name[ca]=Sistema +Name[cs]=Systém +Name[csb]=Systema +Name[cy]=Cysawd +Name[el]=Σύστημα +Name[eo]=Sistemo +Name[es]=Sistema +Name[et]=Süsteem +Name[eu]=Sistema +Name[fa]=سیستم +Name[fi]=Järjestelmä +Name[fo]=Kervi +Name[fr]=Système +Name[fy]=Systeem +Name[ga]=Córas +Name[gl]=Sistema +Name[he]=מערכת +Name[hi]=तंत्र +Name[hr]=Sustav +Name[hu]=Rendszer +Name[id]=Sistem +Name[is]=Kerfi +Name[it]=Sistema +Name[ja]=システム +Name[ka]=სისტემა +Name[kk]=Жүйелік +Name[km]=ប្រព័ន្ធ +Name[ko]=시스템 +Name[lo]=ຈັດການລະບົບ +Name[lt]=Sistema +Name[lv]=Sistēma +Name[mk]=Систем +Name[mn]=Систем +Name[ms]=Sistem +Name[mt]=Sistema +Name[nds]=Systeem +Name[ne]=प्रणाली +Name[nl]=Systeem +Name[oc]=Sistemo +Name[pa]=ਸਿਸਟਮ +Name[pt]=Sistema +Name[pt_BR]=Sistema +Name[ro]=Sistem +Name[ru]=Система +Name[rw]=Sisitemu +Name[se]=Vuogádat +Name[sk]=Systém +Name[sl]=Sistem +Name[sr]=Систем +Name[sr@Latn]=Sistem +Name[ss]=Umshini +Name[ta]=அமைப்பு +Name[te]=వ్యవస్థ +Name[tg]=Система +Name[th]=ระบบ +Name[tr]=Sistem +Name[tt]=Sistem +Name[uk]=Система +Name[uz]=Tizim +Name[uz@cyrillic]=Тизим +Name[ven]=Maitele +Name[vi]=Hệ thống +Name[wa]=Sistinme +Name[xh]=Indlela esestyenziswayo +Name[zh_CN]=系统 +Name[zh_TW]=系統 +Name[zu]=Isistimu +GenericName=System Locations +GenericName[af]=Stelsel Liggings +GenericName[ar]=مواقع النظام +GenericName[be]=Сістэмныя месцазнаходжанні +GenericName[bg]=Системни файлове +GenericName[bn]=সিস্টেম অবস্থানসমূহ +GenericName[bs]=Sistemske lokacije +GenericName[ca]=Localitzacions del sistema +GenericName[cs]=Systémová umístění +GenericName[csb]=Systemòwé lokalizacëje +GenericName[da]=System-steder +GenericName[de]=Systemordner +GenericName[el]=Τοποθεσίες συστήματος +GenericName[eo]=Sistemaj lokoj +GenericName[es]=Ubicaciones del sistema +GenericName[et]=Süsteemi asukohad +GenericName[eu]=Sistemaren kokapenak +GenericName[fa]=محلهای سیستم +GenericName[fi]=Järjestelmän sijainti +GenericName[fr]=Emplacements systèmes +GenericName[fy]=Systeemlokaasjes +GenericName[gl]=Lugares do Sistema +GenericName[he]=מיקומי מערכת +GenericName[hi]=तंत्र स्थान +GenericName[hr]=Sistemske lokacije +GenericName[hu]=Rendszerkönyvtárak +GenericName[is]=Staðsetningar kerfis +GenericName[it]=Indirizzi di sistema +GenericName[ja]=システム場所 +GenericName[ka]=სისტემური მისამართები +GenericName[kk]=Жүйенің орналасуы +GenericName[km]=ទីតាំងប្រព័ន្ធ +GenericName[ko]=시스템 알림 +GenericName[lt]=Sistemos vietos +GenericName[lv]=Sistēmas vietas +GenericName[mk]=Системски локации +GenericName[ms]=Lokasi Sistem +GenericName[mt]=System Monitor +GenericName[nb]=Systemplassar +GenericName[nds]=Systeemsteden +GenericName[ne]=प्रणाली स्थान +GenericName[nl]=Systeemlocaties +GenericName[nn]=Systemplassar +GenericName[pa]=ਸਿਸਟਮ ਟਿਕਾਣੇ +GenericName[pl]=Lokalizacje systemowe +GenericName[pt]=Locais do Sistema +GenericName[pt_BR]=Localizações no Sistema +GenericName[ro]=Locații de sistem +GenericName[ru]=Системные адреса +GenericName[rw]=Ahantu ha Sisitemu +GenericName[se]=Vuogádatbáikkit +GenericName[sk]=Systémové lokácie +GenericName[sl]=Sistemske lokacije +GenericName[sr]=Системске локације +GenericName[sr@Latn]=Sistemske lokacije +GenericName[sv]=Systemplatser +GenericName[ta]=அமைப்பு இடங்கள் +GenericName[tg]=Ҷойгиршавиҳои система +GenericName[th]=ที่ตั้งของระบบ +GenericName[tr]=Sistem Konumları +GenericName[tt]=Sistem Urınlaşuları +GenericName[uk]=Системні адреси +GenericName[uz]=Tizimga tegishli manzillar +GenericName[uz@cyrillic]=Тизимга тегишли манзиллар +GenericName[vi]=Đường dẫn Hệ thống +GenericName[wa]=Plaeces do sistinme +GenericName[zh_CN]=系统定位 +GenericName[zh_TW]=系統位置 +URL=system:/ +Icon=system +Type=Link +OnlyShowIn=TDE; diff --git a/kdesktop/init/Templates/CAMERA-Device.desktop b/kdesktop/init/Templates/CAMERA-Device.desktop new file mode 100644 index 000000000..524436e35 --- /dev/null +++ b/kdesktop/init/Templates/CAMERA-Device.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +MountPoint= +Dev= +ReadOnly=false +Type=FSDevice +Icon=camera_mount +UnmountIcon=camera_unmount diff --git a/kdesktop/init/Templates/CDROM-Device.desktop b/kdesktop/init/Templates/CDROM-Device.desktop new file mode 100644 index 000000000..b4201f447 --- /dev/null +++ b/kdesktop/init/Templates/CDROM-Device.desktop @@ -0,0 +1,92 @@ +[Desktop Entry] +MountPoint= +Dev= +ReadOnly=false +Type=FSDevice +Icon=cdrom_mount +UnmountIcon=cdrom_unmount +Actions=Eject; +X-TDE-Priority=TopLevel +[Desktop Action Eject] +Name=Eject +Name[af]=Uitskiet +Name[ar]=أقذف +Name[az]=Çıxart +Name[be]=Вызваліць +Name[bg]=Изваждане +Name[bn]=ইজেক্ট +Name[br]=Stlepel +Name[bs]=Izbaci +Name[ca]=Expulsa +Name[cs]=Vysunout +Name[csb]=Wësënie +Name[cy]=Allfwrw +Name[da]=Skub ud +Name[de]=Auswerfen +Name[el]=Εξαγωγή +Name[eo]=Eligo +Name[es]=Expulsar +Name[et]=Väljastamine +Name[eu]=Egotzi +Name[fa]=پس زدن +Name[fi]=Poista +Name[fr]=Éjecter +Name[fy]=Utsmytknop +Name[ga]=Díchuir +Name[gl]=Expulsar +Name[he]=הוצא +Name[hi]=बाहर +Name[hr]=Izbaci +Name[hu]=Kidobás +Name[is]=Henda út +Name[it]=Espelli +Name[ja]=取り出し +Name[ka]=CD-ს ამოღება +Name[kk]=Алып-шығару +Name[km]=ច្រានចេញ +Name[ko]=꺼내기 +Name[lo]=ເອົາແຜ່ນອອກ +Name[lt]=Išmesti +Name[lv]=Izņemt +Name[mk]=Извади +Name[mn]=Гаргах +Name[ms]=Lenting +Name[mt]=Iftaħ +Name[nb]=Løs ut +Name[nds]=Rutsmieten +Name[ne]=निकाल्नुहोस् +Name[nl]=Uitwerpen +Name[nn]=Løys ut +Name[nso]=Ntsha +Name[oc]=Expulsa +Name[pa]=ਬਾਹਰ ਕੱਢੋ +Name[pl]=Wysuń +Name[pt]=Ejectar +Name[pt_BR]=Ejetar +Name[ro]=Ejectează +Name[ru]=Извлечь CD +Name[rw]=Gusohora +Name[se]=Bálkes olggos +Name[sk]=Vysunúť +Name[sl]=Izvrzi +Name[sr]=Избаци +Name[sr@Latn]=Izbaci +Name[ss]=Khafuna +Name[sv]=Mata ut +Name[ta]=வெளித்தள் +Name[te]=ఎజెక్ట్ +Name[tg]=Ихроҷ +Name[th]=เอาแผ่นออก +Name[tr]=Çıkart +Name[tt]=Çığar +Name[uk]=Виштовхнути +Name[uz]=Chiqarish +Name[uz@cyrillic]=Чиқариш +Name[ven]=Bvisa +Name[vi]=Đẩy đĩa ra +Name[wa]=Fé rexhe +Name[xh]=Khuphela ngaphandle +Name[zh_CN]=弹出 +Name[zh_TW]=退出 +Name[zu]=Khipha +Exec=tdeeject %v diff --git a/kdesktop/init/Templates/CDWRITER-Device.desktop b/kdesktop/init/Templates/CDWRITER-Device.desktop new file mode 100644 index 000000000..77c5d0774 --- /dev/null +++ b/kdesktop/init/Templates/CDWRITER-Device.desktop @@ -0,0 +1,92 @@ +[Desktop Entry] +MountPoint= +Dev= +ReadOnly=0 +Type=FSDevice +Icon=cdwriter_mount +UnmountIcon=cdwriter_unmount +Actions=Eject; +X-TDE-Priority=TopLevel +[Desktop Action Eject] +Name=Eject +Name[af]=Uitskiet +Name[ar]=أقذف +Name[az]=Çıxart +Name[be]=Вызваліць +Name[bg]=Изваждане +Name[bn]=ইজেক্ট +Name[br]=Stlepel +Name[bs]=Izbaci +Name[ca]=Expulsa +Name[cs]=Vysunout +Name[csb]=Wësënie +Name[cy]=Allfwrw +Name[da]=Skub ud +Name[de]=Auswerfen +Name[el]=Εξαγωγή +Name[eo]=Eligo +Name[es]=Expulsar +Name[et]=Väljastamine +Name[eu]=Egotzi +Name[fa]=پس زدن +Name[fi]=Poista +Name[fr]=Éjecter +Name[fy]=Utsmytknop +Name[ga]=Díchuir +Name[gl]=Expulsar +Name[he]=הוצא +Name[hi]=बाहर +Name[hr]=Izbaci +Name[hu]=Kidobás +Name[is]=Henda út +Name[it]=Espelli +Name[ja]=取り出し +Name[ka]=CD-ს ამოღება +Name[kk]=Алып-шығару +Name[km]=ច្រានចេញ +Name[ko]=꺼내기 +Name[lo]=ເອົາແຜ່ນອອກ +Name[lt]=Išmesti +Name[lv]=Izņemt +Name[mk]=Извади +Name[mn]=Гаргах +Name[ms]=Lenting +Name[mt]=Iftaħ +Name[nb]=Løs ut +Name[nds]=Rutsmieten +Name[ne]=निकाल्नुहोस् +Name[nl]=Uitwerpen +Name[nn]=Løys ut +Name[nso]=Ntsha +Name[oc]=Expulsa +Name[pa]=ਬਾਹਰ ਕੱਢੋ +Name[pl]=Wysuń +Name[pt]=Ejectar +Name[pt_BR]=Ejetar +Name[ro]=Ejectează +Name[ru]=Извлечь CD +Name[rw]=Gusohora +Name[se]=Bálkes olggos +Name[sk]=Vysunúť +Name[sl]=Izvrzi +Name[sr]=Избаци +Name[sr@Latn]=Izbaci +Name[ss]=Khafuna +Name[sv]=Mata ut +Name[ta]=வெளித்தள் +Name[te]=ఎజెక్ట్ +Name[tg]=Ихроҷ +Name[th]=เอาแผ่นออก +Name[tr]=Çıkart +Name[tt]=Çığar +Name[uk]=Виштовхнути +Name[uz]=Chiqarish +Name[uz@cyrillic]=Чиқариш +Name[ven]=Bvisa +Name[vi]=Đẩy đĩa ra +Name[wa]=Fé rexhe +Name[xh]=Khuphela ngaphandle +Name[zh_CN]=弹出 +Name[zh_TW]=退出 +Name[zu]=Khipha +Exec=tdeeject %v diff --git a/kdesktop/init/Templates/CMakeLists.txt b/kdesktop/init/Templates/CMakeLists.txt new file mode 100644 index 000000000..94a4ff5e0 --- /dev/null +++ b/kdesktop/init/Templates/CMakeLists.txt @@ -0,0 +1,27 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +install( FILES + linkProgram.desktop linkURL.desktop linkFloppy.desktop + linkHD.desktop linkCDROM.desktop Directory.desktop + TextFile.desktop HTMLFile.desktop linkZIP.desktop + linkDVDROM.desktop linkCAMERA.desktop linkNFS.desktop + linkCDWRITER.desktop linkMO.desktop + DESTINATION ${TEMPLATES_INSTALL_DIR} ) + +install( FILES + Program.desktop URL.desktop Floppy.desktop HD.desktop + CDROM-Device.desktop TextFile.txt HTMLFile.html + ZIP-Device.desktop DVDROM-Device.desktop CAMERA-Device.desktop + NFS.desktop CDWRITER-Device.desktop MO-Device.desktop + DESTINATION ${TEMPLATES_INSTALL_DIR}/.source ) + +tde_install_empty_directory( ${TEMPLATES_INSTALL_DIR}/.source/emptydir ) diff --git a/kdesktop/init/Templates/DVDROM-Device.desktop b/kdesktop/init/Templates/DVDROM-Device.desktop new file mode 100644 index 000000000..d4f272c43 --- /dev/null +++ b/kdesktop/init/Templates/DVDROM-Device.desktop @@ -0,0 +1,92 @@ +[Desktop Entry] +MountPoint= +Dev= +ReadOnly=false +Type=FSDevice +Icon=dvd_mount +UnmountIcon=dvd_unmount +Actions=Eject; +X-TDE-Priority=TopLevel +[Desktop Action Eject] +Name=Eject +Name[af]=Uitskiet +Name[ar]=أقذف +Name[az]=Çıxart +Name[be]=Вызваліць +Name[bg]=Изваждане +Name[bn]=ইজেক্ট +Name[br]=Stlepel +Name[bs]=Izbaci +Name[ca]=Expulsa +Name[cs]=Vysunout +Name[csb]=Wësënie +Name[cy]=Allfwrw +Name[da]=Skub ud +Name[de]=Auswerfen +Name[el]=Εξαγωγή +Name[eo]=Eligo +Name[es]=Expulsar +Name[et]=Väljastamine +Name[eu]=Egotzi +Name[fa]=پس زدن +Name[fi]=Poista +Name[fr]=Éjecter +Name[fy]=Utsmytknop +Name[ga]=Díchuir +Name[gl]=Expulsar +Name[he]=הוצא +Name[hi]=बाहर +Name[hr]=Izbaci +Name[hu]=Kidobás +Name[is]=Henda út +Name[it]=Espelli +Name[ja]=取り出し +Name[ka]=CD-ს ამოღება +Name[kk]=Алып-шығару +Name[km]=ច្រានចេញ +Name[ko]=꺼내기 +Name[lo]=ເອົາແຜ່ນອອກ +Name[lt]=Išmesti +Name[lv]=Izņemt +Name[mk]=Извади +Name[mn]=Гаргах +Name[ms]=Lenting +Name[mt]=Iftaħ +Name[nb]=Løs ut +Name[nds]=Rutsmieten +Name[ne]=निकाल्नुहोस् +Name[nl]=Uitwerpen +Name[nn]=Løys ut +Name[nso]=Ntsha +Name[oc]=Expulsa +Name[pa]=ਬਾਹਰ ਕੱਢੋ +Name[pl]=Wysuń +Name[pt]=Ejectar +Name[pt_BR]=Ejetar +Name[ro]=Ejectează +Name[ru]=Извлечь CD +Name[rw]=Gusohora +Name[se]=Bálkes olggos +Name[sk]=Vysunúť +Name[sl]=Izvrzi +Name[sr]=Избаци +Name[sr@Latn]=Izbaci +Name[ss]=Khafuna +Name[sv]=Mata ut +Name[ta]=வெளித்தள் +Name[te]=ఎజెక్ట్ +Name[tg]=Ихроҷ +Name[th]=เอาแผ่นออก +Name[tr]=Çıkart +Name[tt]=Çığar +Name[uk]=Виштовхнути +Name[uz]=Chiqarish +Name[uz@cyrillic]=Чиқариш +Name[ven]=Bvisa +Name[vi]=Đẩy đĩa ra +Name[wa]=Fé rexhe +Name[xh]=Khuphela ngaphandle +Name[zh_CN]=弹出 +Name[zh_TW]=退出 +Name[zu]=Khipha +Exec=tdeeject %v diff --git a/kdesktop/init/Templates/Directory.desktop b/kdesktop/init/Templates/Directory.desktop new file mode 100644 index 000000000..3ace5a6a4 --- /dev/null +++ b/kdesktop/init/Templates/Directory.desktop @@ -0,0 +1,146 @@ +[Desktop Entry] +Name=Folder... +Name[af]=Gids... +Name[ar]=المجلد... +Name[be]=Тэчка... +Name[bg]=Директория... +Name[bn]=ফোল্ডার... +Name[br]=Renkell ... +Name[bs]=Direktorij... +Name[ca]=Carpeta... +Name[cs]=Složka... +Name[csb]=Katalog... +Name[cy]=Plygell... +Name[da]=Mappe... +Name[de]=Ordner ... +Name[el]=Φάκελος... +Name[eo]=Dosierujo... +Name[es]=Carpeta... +Name[et]=Kataloog... +Name[eu]=Karpeta... +Name[fa]=پوشه... +Name[fi]=Kansio... +Name[fr]=Dossier... +Name[fy]=Map... +Name[ga]=Fillteán... +Name[gl]=Cartafol... +Name[he]=תיקייה... +Name[hi]=फ़ोल्डर... +Name[hr]=Mapa... +Name[hu]=Könyvtár... +Name[is]=Mappa... +Name[it]=Cartella... +Name[ja]=フォルダ... +Name[ka]=საქაღალდე... +Name[kk]=Қапшық... +Name[km]=ថត... +Name[ko]=폴더... +Name[lt]=Aplankas... +Name[lv]=Mape... +Name[mk]=Папка... +Name[mn]=Хавтас... +Name[mt]=Direttorju... +Name[nb]=Mappe … +Name[nds]=Orner... +Name[ne]=फोल्डर... +Name[nl]=Map... +Name[nn]=Mappe … +Name[pa]=ਫੋਲਡਰ... +Name[pl]=Katalog... +Name[pt]=Pasta... +Name[pt_BR]=Pasta... +Name[ru]=Папку... +Name[rw]=Ububiko... +Name[se]=Máhppa … +Name[sk]=Priečinok... +Name[sl]=Mapa ... +Name[sr]=Фасцикла... +Name[sr@Latn]=Fascikla... +Name[sv]=Katalog... +Name[ta]=அடைவு... +Name[tg]=Феҳрист... +Name[th]=โฟลเดอร์... +Name[tr]=Dizin... +Name[tt]=Törgäk... +Name[uk]=Тека... +Name[uz]=Jild +Name[uz@cyrillic]=Жилд +Name[vi]=Thư mục... +Name[wa]=Ridant... +Name[zh_CN]=文件夹... +Name[zh_TW]=資料夾... +Comment=Enter folder name: +Comment[af]=Voer gidsnaam in: +Comment[ar]=أدخل إسم المجلَد: +Comment[be]=Вызначце назву тэчкі: +Comment[bg]=Въведете името на директорията: +Comment[bn]=ফোল্ডারের নাম লিখুন: +Comment[br]=Roit un anv ar renkell : +Comment[bs]=Unesite naziv direktorija: +Comment[ca]=Entra el nom de la carpeta: +Comment[cs]=Zadejte název složky: +Comment[csb]=Wpiszë miono katalogù: +Comment[cy]=Mewnosodwch enw'r plygell: +Comment[da]=Indtast mappenavn: +Comment[de]=Ordnernamen eingeben: +Comment[el]=Δώστε το όνομα του φακέλου: +Comment[eo]=Enigu novan dosierujonomon: +Comment[es]=Introduzca el nombre de la carpeta: +Comment[et]=Sisesta kataloogi nimi: +Comment[eu]=Sartu karpetaren izena: +Comment[fa]=نام پوشه را وارد کنید: +Comment[fi]=Anna kansion nimi: +Comment[fr]=Donnez le nom du dossier : +Comment[fy]=Mapname ynfiere: +Comment[ga]=Iontráil ainm an fhillteáin: +Comment[gl]=Introduza o nome do cartafol: +Comment[he]=הזן שם תיקייה: +Comment[hi]=फ़ोल्डर नाम भरें: +Comment[hr]=Unesite naziv mape: +Comment[hu]=A könyvtár neve: +Comment[is]=Sláðu inn möppunafn: +Comment[it]=Immetti il nome della cartella: +Comment[ja]=フォルダ名を入力してください: +Comment[ka]=შეიყვანეთ საქაღალდის სახელი: +Comment[kk]=Қапшықты келтіріңіз: +Comment[km]=បញ្ចូលឈ្មោះថត ៖ +Comment[ko]=폴더 이름을 입력하십시오: +Comment[lt]=Įveskite aplanko vardą: +Comment[lv]=Ievadiet mapes nosaukumu: +Comment[mk]=Внесете го името на папката: +Comment[mn]=Лавлахын нэрийг өг: +Comment[ms]=Masukkan nama folder: +Comment[mt]=Daħħal isem id-direttorju: +Comment[nb]=Nytt mappenavn: +Comment[nds]=Ornernaam ingeven: +Comment[ne]=फोल्डर नाम प्रविष्ट गर्नुहोस्: +Comment[nl]=Mapnaam invoeren: +Comment[nn]=Nytt mappenamn: +Comment[pa]=ਫੋਲਡਰ ਨਾਂ ਦਿਓ: +Comment[pl]=Podaj nazwę katalogu: +Comment[pt]=Indique o nome da pasta: +Comment[pt_BR]=Digite o nome da pasta: +Comment[ro]=Introduceți numele folderului: +Comment[ru]=Введите имя папки: +Comment[rw]=Kwinjiza izina ry'ububiko: +Comment[se]=Bija máhppanama: +Comment[sk]=Zadajte meno priečinku: +Comment[sl]=Vnesite ime mape: +Comment[sr]=Унесите име фасцикле: +Comment[sr@Latn]=Unesite ime fascikle: +Comment[sv]=Ange katalognamn: +Comment[ta]=அடைவின் பெயரை உள்ளிடு: +Comment[tg]=Номи феҳристро ворид кунед: +Comment[th]=เติมชื่อโฟลเดอร์: +Comment[tr]=Dizin adını girin: +Comment[tt]=Törgäk adın kert: +Comment[uk]=Введіть назву теки: +Comment[uz]=Jildning nomini kiriting: +Comment[uz@cyrillic]=Жилднинг номини киритинг: +Comment[vi]=Điền tên thư mục: +Comment[wa]=Dinez l' no do ridant: +Comment[zh_CN]=输入文件夹名称: +Comment[zh_TW]=輸入目錄名稱: +Type=Link +URL=.source/emptydir +Icon=folder diff --git a/kdesktop/init/Templates/Floppy.desktop b/kdesktop/init/Templates/Floppy.desktop new file mode 100644 index 000000000..5d73d3648 --- /dev/null +++ b/kdesktop/init/Templates/Floppy.desktop @@ -0,0 +1,78 @@ +[Desktop Action Format] +Exec=kfloppy %v +Name=Format +Name[af]=Formaat +Name[ar]=الهيئة +Name[be]=Фармат +Name[bg]=Формат +Name[bn]=ফরম্যাট +Name[br]=Furmadiñ +Name[cs]=Formát +Name[csb]=Fòrmat +Name[cy]=Fformat +Name[de]=Formatieren +Name[el]=Μορφοποίηση +Name[eo]=Formato +Name[es]=Formato +Name[et]=Vorming +Name[eu]=Formatua +Name[fa]=قالب +Name[fi]=Formatoi +Name[fy]=Formattearje +Name[ga]=Formáid +Name[gl]=Formato +Name[he]=אתחל +Name[hi]=फार्मेट +Name[hr]=Oblik +Name[hu]=Formázás +Name[is]=Snið +Name[it]=Formatta +Name[ja]=フォーマット +Name[ka]=ფორმატი +Name[kk]=Пішін +Name[km]=ទ្រង់ទ្រាយ +Name[ko]=포맷 +Name[lo]=ສູດຄະນິດສານ - K +Name[lt]=Formatas +Name[lv]=Formatēt +Name[mk]=Формат +Name[mn]=Хэлбэр +Name[nds]=Formateren +Name[ne]=ढाँचा +Name[nl]=Formatteren +Name[nso]=Thlolego +Name[pa]=ਫਾਰਮਿਟ +Name[pt]=Formatar +Name[pt_BR]=Formato +Name[ru]=Формат +Name[rw]=Imiterere +Name[se]=Formáhtta +Name[sk]=Formát +Name[sl]=Oblika +Name[sr]=Формат +Name[ss]=Sakhiwo +Name[ta]=வடிவம் +Name[te]=ఫార్మెట్ +Name[tg]=Андоза +Name[th]=รูปแบบ +Name[tr]=Biçim +Name[uk]=Формат +Name[uz]=Format qilish +Name[uz@cyrillic]=Формат қилиш +Name[ven]=Tshivhumbeo +Name[vi]=Định dạng +Name[wa]=Abwesner +Name[xh]=Ifomati +Name[zh_CN]=格式 +Name[zh_TW]=格式化 +Name[zu]=Isakhiwo + +[Desktop Entry] +Actions=Format; +MountPoint= +Dev= +ReadOnly=false +Type=FSDevice +Icon=3floppy_mount +UnmountIcon=3floppy_unmount +X-TDE-Priority=TopLevel diff --git a/kdesktop/init/Templates/HD.desktop b/kdesktop/init/Templates/HD.desktop new file mode 100644 index 000000000..78ed614dc --- /dev/null +++ b/kdesktop/init/Templates/HD.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +MountPoint= +Dev= +ReadOnly=false +Type=FSDevice +Icon=hdd_mount +UnmountIcon=hdd_unmount diff --git a/kdesktop/init/Templates/HTMLFile.desktop b/kdesktop/init/Templates/HTMLFile.desktop new file mode 100644 index 000000000..d2ebe33b0 --- /dev/null +++ b/kdesktop/init/Templates/HTMLFile.desktop @@ -0,0 +1,148 @@ +[Desktop Entry] +Name=HTML File... +Name[af]=HTML Lêer... +Name[ar]=ملف لغة علامات النصّ الفائق... +Name[be]=Файл HTML... +Name[bg]=HTML файл... +Name[bn]=HTML ফাইল... +Name[br]=Restr HTML ... +Name[bs]=HTML datoteka... +Name[ca]=Fitxer HTML... +Name[cs]=HTML soubor... +Name[csb]=Lopk HTML... +Name[cy]=Ffeil HTML... +Name[da]=HTML-fil... +Name[de]=HTML-Datei ... +Name[el]=Αρχείο HTML... +Name[eo]=HTML-dosiero... +Name[es]=Archivo HTML... +Name[et]=HTML-fail... +Name[eu]=HTML fitxategia... +Name[fa]=پروندۀ زنگام... +Name[fi]=HTML-tiedosto... +Name[fr]=Fichier HTML... +Name[fy]=HTML-triem....... +Name[ga]=Comhad HTML... +Name[gl]=Ficheiro HTML... +Name[he]=קובץ HTML... +Name[hi]=एचटीएमएल फ़ाइल... +Name[hr]=HTML datoteka... +Name[hu]=HTML-fájl... +Name[is]=HTML skrá... +Name[it]=File HTML... +Name[ja]=HTML ファイル... +Name[ka]=HTML ფაილი... +Name[kk]=HTML файлы... +Name[km]=ឯកសារ HTML... +Name[ko]=HTML 파일 +Name[lt]=HTML byla... +Name[lv]=HTML Fails... +Name[mk]=HTML датотека... +Name[mn]=HTML-Файл... +Name[ms]=Fail HTML... +Name[mt]=Fajl HTML... +Name[nb]=HTML-fil … +Name[nds]=HTML-Datei... +Name[ne]=HTML फाइल... +Name[nl]=HTML-bestand... +Name[nn]=HTML-fil … +Name[pa]=HTML ਫਾਇਲ... +Name[pl]=Plik HTML... +Name[pt]=Ficheiro HTML... +Name[pt_BR]=Arquivo HTML... +Name[ro]=Fișier HTML... +Name[ru]=Страница HTML... +Name[rw]=Idosiye HTML... +Name[se]=HTML-fiila … +Name[sk]=Súbor HTML... +Name[sl]=Datoteka HTML ... +Name[sr]=HTML фајл... +Name[sr@Latn]=HTML fajl... +Name[sv]=HTML-fil... +Name[ta]=HTML கோப்பு... +Name[te]=హెచ్ టి ఎం ఎల్ దస్త్రం... +Name[tg]=Файли HTML... +Name[th]=แฟ้ม HTML... +Name[tr]=HTML Dosyası... +Name[tt]=HTML Birem... +Name[uk]=Файл HTML... +Name[uz]=HTML-fayli... +Name[uz@cyrillic]=HTML-файли... +Name[vi]=Tập tin HTML... +Name[wa]=Fitchî HTML... +Name[zh_CN]=HTML 文件... +Name[zh_TW]=HTML 檔案... +Comment=Enter HTML filename: +Comment[af]=Voer HTML lêernaam in: +Comment[ar]=أدخل إسم ملف لغة علامات النصّ الفائق: +Comment[be]=Вызначце назву файла HTML: +Comment[bg]=Въведете името на HTML файла: +Comment[bn]=HTML ফাইলের নাম: +Comment[br]=Roit un anv ar restr : +Comment[bs]=Unesite ime HTML datoteke: +Comment[ca]=Entra el nom del fitxer HTML: +Comment[cs]=Zadejte název HTML souboru: +Comment[csb]=Wpiszë miono lopkù HTML: +Comment[da]=Indtast HTML-filnavn: +Comment[de]=Name der HTML-Datei eingeben: +Comment[el]=Δώστε το όνομα του αρχείου HTML: +Comment[eo]=Enigu HTML-dosiernomon: +Comment[es]=Introduzca el nombre del archivo HTML: +Comment[et]=Sisesta HTML-faili nimi: +Comment[eu]=Sartu HTML fitxategiaren izena: +Comment[fa]=نام پروندۀ زنگام را وارد کنید: +Comment[fi]=Anna HTML-tiedostonimi: +Comment[fr]=Donnez le nom du fichier HTML : +Comment[fy]=Namme fan HTML-triem ynfiere: +Comment[ga]=Iontráil ainm an chomhaid HTML: +Comment[gl]=Introduza o nome do ficheiro HTML: +Comment[he]=הזן שם לקובץ ה־HTML: +Comment[hi]=एचटीएमएल फ़ाइल-नाम भरें: +Comment[hr]=Unesite naziv HTML datoteke: +Comment[hu]=A HTML-fájl neve: +Comment[is]=Sláðu inn HTML skráarnafn: +Comment[it]=Immetti nome file HTML: +Comment[ja]=HTML ファイル名を入力: +Comment[ka]=HTML ფაილის სახელი შეიყვანეთ: +Comment[kk]=HTML файлын келтіріңіз: +Comment[km]=បញ្ចូលឈ្មោះឯកសារ HTML ៖ +Comment[ko]=HTML 파일 이름을 입력하십시오: +Comment[lt]=Įveskite HTML bylos vardą: +Comment[lv]=Ievadiet HTML faila nosaukumu: +Comment[mk]=Внесете го името на HTML датотеката: +Comment[ms]=Masukkan nama fail HTML: +Comment[mt]=Ittajpja isem ta' fajl HTML: +Comment[nb]=Skriv inn HTML-filnavn: +Comment[nds]=Naam vun de HTML-Datei ingeven: +Comment[ne]=HTML फाइलनाम प्रविष्ट गर्नुहोस्: +Comment[nl]=Naam van HTML-bestand invoeren: +Comment[nn]=Oppgje HTML-filnamn: +Comment[pa]=HTML ਫਾਇਲ ਨਾਂ ਦਿਓ: +Comment[pl]=Podaj nazwę pliku HTML: +Comment[pt]=Indique o nome do ficheiro HTML: +Comment[pt_BR]=Insira nome do arquivo HTML: +Comment[ro]=Introduceți numele fișierului HTML: +Comment[ru]=Введите имя страницы HTML: +Comment[rw]=Kwinjiza izinadosiye HTML: +Comment[se]=Bija HTML-fiilanama: +Comment[sk]=Zadajte meno súboru HTML: +Comment[sl]=Vnesite ime datoteke HTML: +Comment[sr]=Унесите име HTML фајла: +Comment[sr@Latn]=Unesite ime HTML fajla: +Comment[sv]=Ange HTML-filnamn: +Comment[ta]=HTML கோப்பு பெயரை உள்ளிடு: +Comment[te]=హెచ్ టి ఎం ఎల్ దస్త్రం పేరును వ్రాయండి: +Comment[tg]=Номи файли HTML-ро ворид кунед: +Comment[th]=เติมชื่อแฟ้ม HTML: +Comment[tr]=HTML dosyasını girin: +Comment[tt]=HTML-birem adın kert: +Comment[uk]=Введіть назву файла HTML: +Comment[uz]=HTML-faylning nomini kiriting: +Comment[uz@cyrillic]=HTML-файлнинг номини киритинг: +Comment[vi]=Điền tên tập tin HTML: +Comment[wa]=Dinez l' no do fitchî HTML: +Comment[zh_CN]=输入 HTML 文件名: +Comment[zh_TW]=輸入 HTML 檔案名稱: +Type=Link +URL=.source/HTMLFile.html +Icon=html diff --git a/kdesktop/init/Templates/HTMLFile.html b/kdesktop/init/Templates/HTMLFile.html new file mode 100644 index 000000000..c217ab3fc --- /dev/null +++ b/kdesktop/init/Templates/HTMLFile.html @@ -0,0 +1,8 @@ +<html> + <head> + <title></title> + <meta content=""> + <style></style> + </head> + <body></body> +</html>
\ No newline at end of file diff --git a/kdesktop/init/Templates/MO-Device.desktop b/kdesktop/init/Templates/MO-Device.desktop new file mode 100644 index 000000000..7ad78fd18 --- /dev/null +++ b/kdesktop/init/Templates/MO-Device.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +MountPoint= +Dev= +ReadOnly=false +Type=FSDevice +Icon=mo_mount +UnmountIcon=mo_unmount diff --git a/kdesktop/init/Templates/Makefile.am b/kdesktop/init/Templates/Makefile.am new file mode 100644 index 000000000..b05dfcbd1 --- /dev/null +++ b/kdesktop/init/Templates/Makefile.am @@ -0,0 +1,21 @@ + +# The links (that contain translations) +templ_DATA = linkProgram.desktop \ + linkURL.desktop linkFloppy.desktop linkHD.desktop linkCDROM.desktop \ + Directory.desktop TextFile.desktop HTMLFile.desktop linkZIP.desktop \ + linkDVDROM.desktop linkCAMERA.desktop linkNFS.desktop linkCDWRITER.desktop \ + linkMO.desktop + +templdir = $(kde_templatesdir) + +# The source files (the actual templates) +sources_DATA = Program.desktop \ + URL.desktop Floppy.desktop HD.desktop CDROM-Device.desktop \ + TextFile.txt HTMLFile.html ZIP-Device.desktop DVDROM-Device.desktop \ + CAMERA-Device.desktop NFS.desktop CDWRITER-Device.desktop \ + MO-Device.desktop + +sourcesdir = $(kde_templatesdir)/.source + +install-data-hook: + $(mkinstalldirs) $(DESTDIR)$(sourcesdir)/emptydir diff --git a/kdesktop/init/Templates/NFS.desktop b/kdesktop/init/Templates/NFS.desktop new file mode 100644 index 000000000..dcfc043d4 --- /dev/null +++ b/kdesktop/init/Templates/NFS.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +MountPoint= +Dev= +ReadOnly=false +Type=FSDevice +Icon=nfs_mount +UnmountIcon=nfs_unmount diff --git a/kdesktop/init/Templates/Program.desktop b/kdesktop/init/Templates/Program.desktop new file mode 100644 index 000000000..263e1a155 --- /dev/null +++ b/kdesktop/init/Templates/Program.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Exec= +Icon=exec +Path= +Terminal=false +Type=Application diff --git a/kdesktop/init/Templates/TextFile.desktop b/kdesktop/init/Templates/TextFile.desktop new file mode 100644 index 000000000..3c371d42c --- /dev/null +++ b/kdesktop/init/Templates/TextFile.desktop @@ -0,0 +1,148 @@ +[Desktop Entry] +Name=Text File... +Name[af]=Teks Lêer... +Name[ar]=ملف نصي... +Name[be]=Тэкставы файл... +Name[bg]=Текстов файл... +Name[bn]=টেক্সট ফাইল... +Name[br]=Restr skrid ... +Name[bs]=Tekst datoteka... +Name[ca]=Fitxer de text... +Name[cs]=Textový soubor... +Name[csb]=Tekstowi lopk... +Name[cy]=Ffeil Testun... +Name[da]=Tekstfil... +Name[de]=Textdatei ... +Name[el]=Αρχείο κειμένου... +Name[eo]=Tekstdosiero... +Name[es]=Archivo de texto... +Name[et]=Tekstifail... +Name[eu]=Testu fitxategia... +Name[fa]=پروندۀ متنی... +Name[fi]=Tekstitiedosto... +Name[fr]=Fichier texte... +Name[fy]=Teksttriem...... +Name[ga]=Téacschomhad... +Name[gl]=Ficheiro de Texto... +Name[he]=קובץ טקסט... +Name[hi]=पाठ फ़ाइल... +Name[hr]=Tekstualna datoteka... +Name[hu]=Szöveges fájl... +Name[is]=Textaskrá... +Name[it]=File di testo... +Name[ja]=テキストファイル... +Name[ka]=ტექსტური ფაილი... +Name[kk]=Мәтін файлы... +Name[km]=ឯកសារអត្ថបទ... +Name[ko]=텍스트 파일... +Name[lt]=Teksto byla... +Name[lv]=Teksta Fails... +Name[mk]=Текстуална датотека... +Name[mn]=Текст файл... +Name[ms]=Fail Teks... +Name[mt]=Fajl ta' test... +Name[nb]=Tekstfil … +Name[nds]=Textdatei... +Name[ne]=पाठ फाइल... +Name[nl]=Tekstbestand... +Name[nn]=Tekstfil … +Name[pa]=ਪਾਠ ਫਾਇਲ... +Name[pl]=Plik tekstowy... +Name[pt]=Ficheiro de Texto... +Name[pt_BR]=Arquivo Texto... +Name[ro]=Fișier text... +Name[ru]=Текстовый файл... +Name[rw]= Idosiye Mwandiko... +Name[se]=Teakstafiila … +Name[sk]=Textový súbor... +Name[sl]=Besedilna datoteka ... +Name[sr]=Текстуални фајл... +Name[sr@Latn]=Tekstualni fajl... +Name[sv]=Textfil... +Name[ta]=உரைக் கோப்பு +Name[te]=వచన దస్త్రం... +Name[tg]=Файли матнӣ... +Name[th]=แฟ้มข้อความ... +Name[tr]=Metin Dosyası... +Name[tt]=Mäten Bireme... +Name[uk]=Текстовий файл... +Name[uz]=Matn fayli... +Name[uz@cyrillic]=Матн файли... +Name[vi]=Tập tin Văn bản... +Name[wa]=Fitchî tecse... +Name[zh_CN]=文本文件... +Name[zh_TW]=文字檔案... +Comment=Enter text filename: +Comment[af]=Voer teks lêernaam in: +Comment[ar]=أدخل اسم الملف النصي: +Comment[be]=Вызначце назву тэкставага файла: +Comment[bg]=Въведете име на текстовия файл: +Comment[bn]=টেক্সট ফাইলের নাম: +Comment[br]=Roit un anv ar restr skrid : +Comment[bs]=Unesite ime tekst datoteke: +Comment[ca]=Entra el nom del fitxer de text: +Comment[cs]=Zadejte název textového souboru: +Comment[csb]=Wpiszë miono tekstowégò lopkù: +Comment[da]=Indtast tekstfilnavn: +Comment[de]=Name der Textdatei eingeben: +Comment[el]=Δώστε το όνομα του αρχείου κειμένου: +Comment[eo]=Enigu la tekstodosieran nomon: +Comment[es]=Introduzca el nombre del archivo de texto: +Comment[et]=Sisesta tekstifaili nimi: +Comment[eu]=Sartu testu fitxategiaren izena +Comment[fa]=نام پروندۀ متنی را وارد کنید: +Comment[fi]=Anna tekstitiedoston nimi: +Comment[fr]=Donnez le nom du fichier de texte : +Comment[fy]=Namme fan teksttriem ynfiere: +Comment[ga]=Iontráil ainm an téacschomhaid: +Comment[gl]=Introduza o nome do ficheiro de texto: +Comment[he]=הזן שם לקובץ הטקסט: +Comment[hi]=पाठ फ़ाइल-नाम भरें: +Comment[hr]=Upišite naziv tekstualne datoteke: +Comment[hu]=A szöveges fájl neve: +Comment[is]=Sláðu inn nafn á textaskrá: +Comment[it]=Immetti nome file di testo: +Comment[ja]=テキストファイル名を入力: +Comment[ka]=შეიყვანეთ ტექსტური ფაილის სახელი: +Comment[kk]=Мәтін файлын келтіріңіз: +Comment[km]=បញ្ចូលឈ្មោះឯកសារអត្ថបទ ៖ +Comment[ko]=텍스트 파일 이름을 입력하십시오: +Comment[lt]=Įveskite teksto bylos vardą: +Comment[lv]=Ievadiet teksta faila nosaukumu: +Comment[mk]=Внесете го името на текстуалната датотека: +Comment[ms]=Masukkan nama fail teks: +Comment[mt]=Ittajpja isem ta' fajl b'test: +Comment[nb]=Skriv inn navnet på tekstfila: +Comment[nds]=Naam vun de Textdatei ingeven: +Comment[ne]=पाठ फाइलनाम प्रविष्ट गर्नुहोस्: +Comment[nl]=Naam van tekstbestand invoeren: +Comment[nn]=Oppgje tekstfilnamn: +Comment[pa]=ਪਾਠ ਫਾਇਲ ਨਾਂ ਦਿਓ: +Comment[pl]=Podaj nazwę pliku tekstowego: +Comment[pt]=Indique o nome do ficheiro de texto: +Comment[pt_BR]=Insira nome do arquivo de texto: +Comment[ro]=Introduceți numele fișierului text: +Comment[ru]=Введите имя тестового файла: +Comment[rw]=Kwinjiza izinadosiye mwandiko: +Comment[se]=Bija teakstafiilanama: +Comment[sk]=Zadajte meno textového súboru: +Comment[sl]=Vnesite ime besedilne datoteke: +Comment[sr]=Унесите име текстуалног фајла: +Comment[sr@Latn]=Unesite ime tekstualnog fajla: +Comment[sv]=Ange textfilnamn: +Comment[ta]=உரை கோப்பு பெயரை உள்ளிடு: +Comment[te]=వచన దస్త్రం పేరును వ్రాయండి: +Comment[tg]=Номи файли матнро ворид кунед: +Comment[th]=เติมชื่อแฟ้มข้อความ: +Comment[tr]=Metin dosya adını girin: +Comment[tt]=Mäten-birem adın kert: +Comment[uk]=Введіть назву текстового файла: +Comment[uz]=Matn faylining nomini kiriting: +Comment[uz@cyrillic]=Матн файлининг номини киритинг: +Comment[vi]=Điền tên tập tin văn bản: +Comment[wa]=Dinez l' no do fitchî tecse: +Comment[zh_CN]=输入文本文件名: +Comment[zh_TW]=輸入純文字檔案名稱: +Type=Link +URL=.source/TextFile.txt +Icon=txt diff --git a/kdesktop/init/Templates/TextFile.txt b/kdesktop/init/Templates/TextFile.txt new file mode 100644 index 000000000..8d1c8b69c --- /dev/null +++ b/kdesktop/init/Templates/TextFile.txt @@ -0,0 +1 @@ + diff --git a/kdesktop/init/Templates/URL.desktop b/kdesktop/init/Templates/URL.desktop new file mode 100644 index 000000000..968859c37 --- /dev/null +++ b/kdesktop/init/Templates/URL.desktop @@ -0,0 +1,3 @@ +[Desktop Entry] +URL= +Type=Link diff --git a/kdesktop/init/Templates/ZIP-Device.desktop b/kdesktop/init/Templates/ZIP-Device.desktop new file mode 100644 index 000000000..bec34fe73 --- /dev/null +++ b/kdesktop/init/Templates/ZIP-Device.desktop @@ -0,0 +1,92 @@ +[Desktop Entry] +MountPoint= +Dev= +ReadOnly=false +Type=FSDevice +Icon=zip_mount +UnmountIcon=zip_unmount +Actions=Eject; +X-TDE-Priority=TopLevel +[Desktop Action Eject] +Name=Eject +Name[af]=Uitskiet +Name[ar]=أقذف +Name[az]=Çıxart +Name[be]=Вызваліць +Name[bg]=Изваждане +Name[bn]=ইজেক্ট +Name[br]=Stlepel +Name[bs]=Izbaci +Name[ca]=Expulsa +Name[cs]=Vysunout +Name[csb]=Wësënie +Name[cy]=Allfwrw +Name[da]=Skub ud +Name[de]=Auswerfen +Name[el]=Εξαγωγή +Name[eo]=Eligo +Name[es]=Expulsar +Name[et]=Väljastamine +Name[eu]=Egotzi +Name[fa]=پس زدن +Name[fi]=Poista +Name[fr]=Éjecter +Name[fy]=Utsmytknop +Name[ga]=Díchuir +Name[gl]=Expulsar +Name[he]=הוצא +Name[hi]=बाहर +Name[hr]=Izbaci +Name[hu]=Kidobás +Name[is]=Henda út +Name[it]=Espelli +Name[ja]=取り出し +Name[ka]=CD-ს ამოღება +Name[kk]=Алып-шығару +Name[km]=ច្រានចេញ +Name[ko]=꺼내기 +Name[lo]=ເອົາແຜ່ນອອກ +Name[lt]=Išmesti +Name[lv]=Izņemt +Name[mk]=Извади +Name[mn]=Гаргах +Name[ms]=Lenting +Name[mt]=Iftaħ +Name[nb]=Løs ut +Name[nds]=Rutsmieten +Name[ne]=निकाल्नुहोस् +Name[nl]=Uitwerpen +Name[nn]=Løys ut +Name[nso]=Ntsha +Name[oc]=Expulsa +Name[pa]=ਬਾਹਰ ਕੱਢੋ +Name[pl]=Wysuń +Name[pt]=Ejectar +Name[pt_BR]=Ejetar +Name[ro]=Ejectează +Name[ru]=Извлечь CD +Name[rw]=Gusohora +Name[se]=Bálkes olggos +Name[sk]=Vysunúť +Name[sl]=Izvrzi +Name[sr]=Избаци +Name[sr@Latn]=Izbaci +Name[ss]=Khafuna +Name[sv]=Mata ut +Name[ta]=வெளித்தள் +Name[te]=ఎజెక్ట్ +Name[tg]=Ихроҷ +Name[th]=เอาแผ่นออก +Name[tr]=Çıkart +Name[tt]=Çığar +Name[uk]=Виштовхнути +Name[uz]=Chiqarish +Name[uz@cyrillic]=Чиқариш +Name[ven]=Bvisa +Name[vi]=Đẩy đĩa ra +Name[wa]=Fé rexhe +Name[xh]=Khuphela ngaphandle +Name[zh_CN]=弹出 +Name[zh_TW]=退出 +Name[zu]=Khipha +Exec=tdeeject %v diff --git a/kdesktop/init/Templates/linkCAMERA.desktop b/kdesktop/init/Templates/linkCAMERA.desktop new file mode 100644 index 000000000..5d9dc9be1 --- /dev/null +++ b/kdesktop/init/Templates/linkCAMERA.desktop @@ -0,0 +1,150 @@ +[Desktop Entry] +Name=Camera Device... +Name[af]=Kamera Toestel... +Name[ar]=جهاز الكاميرا... +Name[be]=Камера... +Name[bg]=Фотоапарат... +Name[bn]=ক্যমেরা ডিভাইস... +Name[br]=Trobarzhell ar gamera ... +Name[bs]=Kamera uređaj... +Name[ca]=Dispositiu de càmera... +Name[cs]=Kamera... +Name[csb]=Òdjimkòwô kaméra... +Name[cy]=Dyfais Camera... +Name[da]=Kamera-enhed... +Name[de]=Kamera ... +Name[el]=Συσκευή κάμερας... +Name[eo]=kamero-aparato... +Name[es]=Cámara... +Name[et]=Kaameraseade +Name[eu]=Kamera... +Name[fa]=دستگاه دوربین... +Name[fi]=Kamerat... +Name[fr]=Appareil photo +Name[fy]=Kamera... +Name[ga]=Gléas Ceamara... +Name[gl]=Dispositivo de Cámara... +Name[he]=התקן מצלמה... +Name[hi]=कैमरा उपकरण... +Name[hr]=Kamera... +Name[hu]=Fényképezőgép... +Name[is]=Myndavél... +Name[it]=Dispositivo macchina fotografica... +Name[ja]=カメラデバイス... +Name[ka]=კამერის მოწყობილობა +Name[kk]=Фотокамера құрылғысы... +Name[km]=ឧបករណ៍ម៉ាស៊ីនថត... +Name[ko]=카메라 장치... +Name[lt]=Kameros įrenginys... +Name[lv]=Kameras iekārta... +Name[mk]=Камера... +Name[mn]=Камерын Төхөөрөмж... +Name[ms]=Peranti Kamera... +Name[mt]=Kamera... +Name[nb]=Kameraenhet … +Name[nds]=Kamera... +Name[ne]=क्यामेरा यन्त्र... +Name[nl]=Camera... +Name[nn]=Kameraeining … +Name[pa]=ਕੈਮਰਾ ਜੰਤਰ... +Name[pl]=Aparat fotograficzny... +Name[pt]=Máquina Fotográfica... +Name[pt_BR]=Dispositivo de Câmera... +Name[ro]=Dispozitiv foto... +Name[ru]=Камера... +Name[rw]=Apareye Kamera... +Name[se]=Govvenapperáhttaovttadat … +Name[sk]=Zariadenie digitálneho fotoaparátu... +Name[sl]=Naprava kamere ... +Name[sr]=Камера... +Name[sr@Latn]=Kamera... +Name[sv]=Kameraenhet... +Name[ta]=புகைப்பட கருவி சாதனங்கள் +Name[te]=కెమెరా పరికరం... +Name[tg]=Дастгоҳи камера... +Name[th]=อุปกรณ์กล้อง... +Name[tr]=Kamera Aygıtı... +Name[tt]=kamera Cıhazı... +Name[uk]=Пристрій фотоапарата... +Name[uz]=Fotoaparat uskunasi... +Name[uz@cyrillic]=Фотоапарат ускунаси... +Name[vi]=Máy ảnh số... +Name[wa]=Éndjin camera... +Name[zh_CN]=相机设备... +Name[zh_TW]=照相機設備... +Comment=New camera +Comment[af]=Nuwe kamera +Comment[ar]=كاميرا جديدة +Comment[be]=Новая камера +Comment[bg]=Нов фотоапарат +Comment[bn]=নতুন ক্যামেরা +Comment[br]=Kamera nevez +Comment[bs]=Nova kamera +Comment[ca]=Càmera nova +Comment[cs]=Nová kamera +Comment[csb]=Nowô òdjimkòwô kaméra +Comment[cy]=Camera Newydd +Comment[da]=Nyt kamera +Comment[de]=Neue Kamera +Comment[el]=Νέα κάμερα +Comment[eo]=Nova kamero +Comment[es]=Nueva cámara +Comment[et]=Uus kaamera +Comment[eu]=Kamera berria +Comment[fa]=دوربین جدید +Comment[fi]=Uusi kamera +Comment[fr]=Nouvel appareil photo +Comment[fy]=Nije kamera +Comment[ga]=Ceamara nua +Comment[gl]=Nova cámara +Comment[he]=מצלמה חדשה +Comment[hi]=नया कैमरा +Comment[hr]=Nova kamera +Comment[hu]=Új fényképezőgép +Comment[is]=Ný myndavél +Comment[it]=Nuova macchina fotografica +Comment[ja]=新しいカメラ +Comment[ka]=ახალი კამერა +Comment[kk]=Жаңа фотокамера +Comment[km]=ម៉ាស៊ីនថតថ្មី +Comment[ko]=새 카메라 +Comment[lt]=Nauja kamera +Comment[lv]=Jauna kamera +Comment[mk]=Нова камера +Comment[mn]=Шинэ камер +Comment[ms]=Kamera baru +Comment[mt]=Kamera ġdida +Comment[nb]=Nytt kamera +Comment[nds]=Niege Kamera +Comment[ne]=नयाँ क्यामेरा +Comment[nl]=Nieuwe camera +Comment[nn]=Nytt kamera +Comment[pa]=ਨਵਾਂ ਕੈਮਰਾ +Comment[pl]=Nowy aparat fotograficzny +Comment[pt]=Nova máquina fotográfica +Comment[pt_BR]=Nova câmera +Comment[ro]=Aparat foto nou +Comment[ru]=Ссылка на устройство цифровой камеры +Comment[rw]=Kamera nshya +Comment[se]=Ođđa govvenapperáhtta +Comment[sk]=Nový digitálny fotoaparát +Comment[sl]=Nov fotoaparat +Comment[sr]=Нова камера +Comment[sr@Latn]=Nova kamera +Comment[sv]=Ny kamera +Comment[ta]=புதிய புகைப்பட கருவி +Comment[te]=కొత్త కెమెరా +Comment[tg]=Камераи нав +Comment[th]=เพิ่มกล้องใหม่ +Comment[tr]=Yeni kamera +Comment[tt]=Yaña kamera +Comment[uk]=Новий фотоапарат +Comment[uz]=Yangi fotoaparat +Comment[uz@cyrillic]=Янги фотоапарат +Comment[vi]=Tạo máy ảnh số mới +Comment[wa]=Novele camera +Comment[zh_CN]=新建相机 +Comment[zh_TW]=新增照相機 +Type=Link +URL=.source/CAMERA-Device.desktop +Icon=camera_unmount diff --git a/kdesktop/init/Templates/linkCDROM.desktop b/kdesktop/init/Templates/linkCDROM.desktop new file mode 100644 index 000000000..b895fe79b --- /dev/null +++ b/kdesktop/init/Templates/linkCDROM.desktop @@ -0,0 +1,150 @@ +[Desktop Entry] +Name=CD-ROM Device... +Name[af]=CD-ROM Toestel +Name[ar]=جهاز الأقراص المدمجة... +Name[be]=Прылада CD-ROM... +Name[bg]=CD-ROM... +Name[bn]=সিডি-রম ডিভাইস... +Name[br]=Trobarzhell CD-ROM ... +Name[bs]=CD-ROM uređaj... +Name[ca]=Dispositiu CD-ROM... +Name[cs]=Jednotka CD-ROM... +Name[csb]=Nëk CD-ROM... +Name[cy]=Dyfais CD-ROM... +Name[da]=Cd-rom-enhed... +Name[de]=CD-ROM-Laufwerk ... +Name[el]=Συσκευή CD-ROM... +Name[eo]=Lumdiskingo... +Name[es]=Unidad de CD-ROM... +Name[et]=CD-ROM seade... +Name[eu]=CD-ROM gailua... +Name[fa]=دستگاه CD-ROM... +Name[fi]=CD-ROM-laitteet... +Name[fr]=Lecteur de CD-ROM... +Name[fy]=kompaktskiifstasjon ... +Name[ga]=Gléas CD-ROM... +Name[gl]=Dispositivo de CD-ROM... +Name[he]=התקן תקליטור... +Name[hi]=सीडी-रोम उपकरण... +Name[hr]=CD/DVD-ROM uređaj... +Name[hu]=CD-meghajtó... +Name[is]=Geisladrif... +Name[it]=Dispositivo CD-ROM... +Name[ja]=CD-ROM デバイス... +Name[ka]=CD-ROM მოწყობილობა +Name[kk]=CD-ROM құрылғысы... +Name[km]=ឧបករណ៍ CD-ROM... +Name[ko]=CD-ROM 장치... +Name[lt]=CD-ROM įrenginys... +Name[lv]=CD-ROM Iekārta... +Name[mk]=CD-ROM Уред... +Name[mn]=КД-ROM төхөөрөмж... +Name[ms]=Peranti CD-ROM... +Name[mt]=CDROM... +Name[nb]=CD-ROM-enhet … +Name[nds]=CD-ROM-Reedschap... +Name[ne]=CD-ROM यन्त्र... +Name[nl]=CD-romspeler... +Name[nn]=CD-ROM-eining … +Name[pa]=CD-ROM ਜੰਤਰ... +Name[pl]=Urządzenie CD-ROM... +Name[pt]=Dispositivo de CD-ROM... +Name[pt_BR]=Dispositivo de CD-ROM... +Name[ro]=Dispozitiv CD-ROM... +Name[ru]=CD-ROM... +Name[rw]=Apareye CD-ROM... +Name[se]=CD-ROM-ovttadat … +Name[sk]=Zariadenie CD-ROM... +Name[sl]=Naprava CD-ROM ... +Name[sr]=CD/DVD-ROM уређај... +Name[sr@Latn]=CD/DVD-ROM uređaj... +Name[sv]=Cdrom-enhet... +Name[ta]=CD-ROM சாதனம்... +Name[te]=సీడి-రామ్ పరికరం... +Name[tg]=Дастгоҳи CD-ROM... +Name[th]=อุปกรณ์ซีดีรอม +Name[tr]=CD-ROM Aygıtı... +Name[tt]=CD-ROM Cıhazı... +Name[uk]=Пристрій CD-ROM... +Name[uz]=Kompakt-disk uskunasi... +Name[uz@cyrillic]=Компакт-диск ускунаси... +Name[vi]=Thiết bị đọc đĩa CD-ROM... +Name[wa]=Éndjin léjheu di plakes lazer... +Name[zh_CN]=CD-ROM 设备... +Name[zh_TW]=光碟機設備 +Comment=New CD-ROM Device +Comment[af]=Nuwe CD-ROM Toestel +Comment[ar]=جهاز أقراص مدمجة جديد +Comment[be]=Новая прылада CD-ROM +Comment[bg]=Ново устройство CD-ROM +Comment[bn]=নতুন সিডি-রম ডিভাইস +Comment[br]=Trobarzhell CD-ROM Nevez +Comment[bs]=Novi CD/DVD-ROM uređaj +Comment[ca]=Dispositiu CD-ROM nou +Comment[cs]=Nová jednotka CD-ROM +Comment[csb]=Nowi nëk CD +Comment[cy]=Dyfais CD-ROM Newydd +Comment[da]=Ny cd-rom-enhed +Comment[de]=Neues CD-ROM-Laufwerk +Comment[el]=Νέα συσκευή CD-ROM +Comment[eo]=Nova lumdiskingo... +Comment[es]=Nueva unidad de CD-ROM +Comment[et]=Uus CD-ROM seade +Comment[eu]=CD-ROM gailu berria +Comment[fa]=دستگاه CD-ROM جدید +Comment[fi]=Uusi CD/DVD-ROM -laite +Comment[fr]=Nouveau lecteur de CD-ROM +Comment[fy]=Nije kompaktskiifstasjon +Comment[ga]=Gléas nua CD-ROM +Comment[gl]=Novo Dispositivo de CD-ROM +Comment[he]=התקן תקליטור חדש +Comment[hi]=नया सीडी-रोम उपकरण +Comment[hr]=Novi CD/DVD-ROM uređaj +Comment[hu]=Új CD-meghajtó +Comment[is]=Nýtt geisladrif +Comment[it]=Nuovo dispositivo CD-ROM +Comment[ja]=新規 CD-ROM デバイス +Comment[ka]=ახალი CD-ROM მოწყობილობა +Comment[kk]=Жаңа CD-ROM құрылғысы +Comment[km]=ឧបករណ៍ CD-ROM ថ្មី +Comment[ko]=새 CD-ROM 장치 +Comment[lt]=Naujas CD-ROM įrenginys +Comment[lv]=Jauna CD-ROM Iekārta +Comment[mk]=Нов CD-ROM уред +Comment[mn]=Шинэ КД-ROM төхөөрөмж +Comment[ms]=Peranti CD-ROM Baru +Comment[mt]=CD-ROM ġdid +Comment[nb]=Ny CD-ROM-enhet +Comment[nds]=Niege CD-ROM-Reedschap +Comment[ne]=नयाँ CD-ROM यन्त्र +Comment[nl]=Nieuwe cd-romspeler +Comment[nn]=Ny CD-ROM-eining +Comment[pa]=ਨਵਾਂ CD-ROM ਜੰਤਰ +Comment[pl]=Nowe urządzenie CD-ROM +Comment[pt]=Novo Dispositivo de CD-ROM +Comment[pt_BR]=Novo dispositivo de CD-ROM +Comment[ro]=Dispozitiv CD-ROM nou +Comment[ru]=Ссылка на устройство CD-ROM +Comment[rw]=Apareye CD-ROM Nshya +Comment[se]=Ođđa CD-ROM-ovttadat +Comment[sk]=Nové zariadenie CD-ROM +Comment[sl]=Nova naprava CD-ROM +Comment[sr]=Нови CD/DVD-ROM уређај +Comment[sr@Latn]=Novi CD/DVD-ROM uređaj +Comment[sv]=Ny cdrom-enhet +Comment[ta]=புதிய CD-ROM சாதனம் +Comment[te]=కొత్త సీడి-రామ్ పరికరం +Comment[tg]=Дастгоҳи нави CD-ROM +Comment[th]=กำหนดอุปกรณ์ซีดีใหม่ +Comment[tr]=Yeni CD-ROM Aygıtı +Comment[tt]=Yaña CD-ROM Cıhazı +Comment[uk]=Новий пристрій CD-ROM +Comment[uz]=Yangi kompakt-disk uskunasi +Comment[uz@cyrillic]=Янги компакт-диск ускунаси +Comment[vi]=Tạo CD-ROM mới +Comment[wa]=Novea éndjin léjheu di plakes lazer +Comment[zh_CN]=新建 CD-ROM 设备 +Comment[zh_TW]=新光碟機設備 +Type=Link +URL=.source/CDROM-Device.desktop +Icon=cdrom_unmount diff --git a/kdesktop/init/Templates/linkCDWRITER.desktop b/kdesktop/init/Templates/linkCDWRITER.desktop new file mode 100644 index 000000000..8a080c55a --- /dev/null +++ b/kdesktop/init/Templates/linkCDWRITER.desktop @@ -0,0 +1,150 @@ +[Desktop Entry] +Name=CDWRITER Device... +Name[af]=CD Skrywer Toestel +Name[ar]=جهاز تسجيل الأقراص المدمجة... +Name[be]=Прылада CDWRITER... +Name[bg]=CDWRITER... +Name[bn]=সিডি-রাইটার ডিভাইস... +Name[br]=Trobarzhell an engraver CD ... +Name[bs]=CD pržilica... +Name[ca]=Dispositiu CDWRITER... +Name[cs]=Vypalovačka CD... +Name[csb]=Wëpôlôrz CD... +Name[cy]=Dyfais CDWRITER... +Name[da]=Cd-skriver enhed... +Name[de]=CD-Brenner ... +Name[el]=Συσκευή CDWRITER... +Name[eo]=Lumdiska skribilo... +Name[es]=Grabadora de CD... +Name[et]=CD-kirjutaja... +Name[eu]=CDWRITER gailua... +Name[fa]=دستگاه CDWRITER... +Name[fi]=CDWRITER-laite... +Name[fr]=Graveur de CD-ROM... +Name[fy]=kompaktskiifstasjon... +Name[ga]=Gléas CDWRITER... +Name[gl]=Dispositivo CDWRITER... +Name[he]=התקן צורב... +Name[hi]=सीडी-राइटर उपकरण... +Name[hr]=CD/DVD pržilica... +Name[hu]=CD-író... +Name[is]=Geisladiskaskrifari... +Name[it]=Masterizzatore... +Name[ja]=CD ライターデバイス... +Name[ka]=CDWRITER მოწყობილობა +Name[kk]=CDWRITER құрылғысы... +Name[km]=ឧបករណ៍ CDWRITER... +Name[ko]=CDWRITER 장치... +Name[lt]=CDWRITER įrenginys... +Name[lv]=CD rakstīšanas iekārta... +Name[mk]=CDWRITER Уред... +Name[mn]=КД бичигч төхөөрөмж +Name[ms]=Peranti CDWRITER... +Name[mt]=CDWRITER... +Name[nb]=CD-brenner-enhet +Name[nds]=CD-Brenner... +Name[ne]=CDWRITER यन्त्र... +Name[nl]=CD-writer... +Name[nn]=CD-brennareining … +Name[pa]=CDWRITER ਜੰਤਰ... +Name[pl]=Nagrywarka CD... +Name[pt]=Gravador de CDs... +Name[pt_BR]=Dispositivo de Gravação de CD... +Name[ro]=Dispozitiv CD-Writer... +Name[ru]=Пишущий CD-ROM... +Name[rw]=Apareye MWANDIKA-CD... +Name[se]=CDWRITER-ovttadat … +Name[sk]=Zariadenie CDWRITER... +Name[sl]=Naprava CDWRITER ... +Name[sr]=CD/DVD резач... +Name[sr@Latn]=CD/DVD rezač... +Name[sv]=Cd-brännarenhet... +Name[ta]=CDWRITER சாதனம் +Name[te]=సీడి వ్రైటర్ పరికరం... +Name[tg]=Дастгоҳи CDWRITER... +Name[th]=อุปกรณ์เขียนซีดี... +Name[tr]=CD Yazıcı Aygıtı... +Name[tt]=CD-Yazğıç Cıhazı... +Name[uk]=Пристрій CDWRITER... +Name[uz]=Kompakt-disk yozuvchi uskuna... +Name[uz@cyrillic]=Компакт-диск ёзувчи ускуна... +Name[vi]=Thiết bị ghi đĩa CD... +Name[wa]=Éndjin broûleu di plakes lazer... +Name[zh_CN]=刻录机设备... +Name[zh_TW]=光碟燒錄機設備 +Comment=New CDWRITER Device +Comment[af]=Nuwe CD Skrywer Toestel +Comment[ar]=جهاز تسجيل أقراص مدمجة جديد +Comment[be]=Новая прылада CDWRITER +Comment[bg]=Ново устройство CDWRITER +Comment[bn]=নতুন সিডি-রাইটার ডিভাইস +Comment[br]=Trobarzhell CDSKRIVER nevez +Comment[bs]=Nova CD pržilica +Comment[ca]=Dispositiu CDWRITER nou +Comment[cs]=Nová vypalovačka CD +Comment[csb]=Nowi wëpôlôrz CD +Comment[cy]=Dyfais CDWRITER Newydd +Comment[da]=Ny cd-skriver enhed +Comment[de]=Neuer CD-Brenner +Comment[el]=Νέα συσκευή CDWRITER +Comment[eo]=Nova lumdisk-skribilo +Comment[es]=Nueva grabadora de CD +Comment[et]=Uus CD-kirjutaja +Comment[eu]=CDWRITER gailu berria +Comment[fa]=دستگاه CDWRITER جدید +Comment[fi]=Uusi CDWRITER-laite +Comment[fr]=Nouveau graveur de CD-ROM +Comment[fy]=Nije kompaktskiifstasjon +Comment[ga]=Gléas CDWRITER Nua +Comment[gl]=Novo Dispositivo CDWRITER +Comment[he]=התקן צורב חדש +Comment[hi]=नया सीडी-राइटर उपकरण +Comment[hr]=Nova CD/DVD pržilica +Comment[hu]=Új CD-író +Comment[is]=Nýr geisladiskaskrifari +Comment[it]=Nuovo masterizzatore +Comment[ja]=新規 CD ライターデバイス +Comment[ka]=ახალი CDWRITER მოწყობილობა +Comment[kk]=Жаңа CDWRITER құрылғысы +Comment[km]=ឧបករណ៍ CDWRITER ថ្មី +Comment[ko]=새 CDWRITER 장치 +Comment[lt]=Naujas CDWRITER įrenginys +Comment[lv]=Jauna CD rakstīšanas iekārta +Comment[mk]=Нов CDWRITER уред +Comment[mn]=Шинэ КД бичигч төхөөрөмж +Comment[ms]=Peranti CDWRITER Baru +Comment[mt]=Apparat CDWRITER ġdid +Comment[nb]=Ny CD-brenner-enhet +Comment[nds]=Niegen CD-Brenner +Comment[ne]=नयाँ CDWRITER यन्त्र +Comment[nl]=Nieuwe CD-writer +Comment[nn]=Ny CD-brennareining +Comment[pa]=ਨਵਾਂ CDWRITER ਜੰਤਰ +Comment[pl]=Nowa nagrywarka CD +Comment[pt]=Novo Gravador de CDs +Comment[pt_BR]=Novo dispositivo de Gravação de CD +Comment[ro]=Dispozitiv CD-Writer nou +Comment[ru]=Ссылка на устройство пишущего CD-ROM +Comment[rw]=Apareye MWANDIKA-CD Nshya +Comment[se]=Ođđa CDWRITER-ovttadat +Comment[sk]=Nové zariadenie CDWRITER +Comment[sl]=Nova naprava CDWRITER +Comment[sr]=Нови CD/DVD резач +Comment[sr@Latn]=Novi CD/DVD rezač +Comment[sv]=Ny cd-brännarenhet +Comment[ta]=புது CDWRITER சாதனம் +Comment[te]=కొత్త సీడి వ్రైటర్ పరికరం +Comment[tg]=Дастгоҳ нави CDWRITER +Comment[th]=กำหนดอุปกรณ์เขียนซีดีใหม่ +Comment[tr]=Yeni CD Yazıcı Aygıtı +Comment[tt]=Yaña CD-Yazğıç Cıhazı +Comment[uk]=Новий пристрій CDWRITER +Comment[uz]=Yangi kompakt-disk yozuvchi uskuna +Comment[uz@cyrillic]=Янги компакт-диск ёзувчи ускуна +Comment[vi]=Tạo thiết bị ghi CD mới +Comment[wa]=Novea éndjin broûleu di plakes lazer +Comment[zh_CN]=新建刻录机设备 +Comment[zh_TW]=新光碟燒錄機設備 +Type=Link +URL=.source/CDWRITER-Device.desktop +Icon=cdwriter_unmount diff --git a/kdesktop/init/Templates/linkDVDROM.desktop b/kdesktop/init/Templates/linkDVDROM.desktop new file mode 100644 index 000000000..e65875b9d --- /dev/null +++ b/kdesktop/init/Templates/linkDVDROM.desktop @@ -0,0 +1,150 @@ +[Desktop Entry] +Name=DVD-ROM Device... +Name[af]=DVD-ROM Toestel +Name[ar]=جهاز قارئ أقراص رقمية مرئية... +Name[be]=Прылада DVD-ROM... +Name[bg]=DVD-ROM... +Name[bn]=ডিভিডি-রম ডিভাইস... +Name[br]=Trobarzhell DVD-ROM ... +Name[bs]=DVD-ROM uređaj... +Name[ca]=Dispositiu DVD-ROM... +Name[cs]=Jednotka DVD-ROM... +Name[csb]=Nëk DVD-ROM... +Name[cy]=Dyfais DVD-ROM... +Name[da]=Dvd-rom-enhed... +Name[de]=DVD-ROM-Laufwerk ... +Name[el]=Συσκευή DVD-ROM... +Name[eo]=DVDdiskingo... +Name[es]=Unidad de DVD-ROM... +Name[et]=DVD-ROM seade... +Name[eu]=DVD-ROM gailua... +Name[fa]=دستگاه DVD-ROM... +Name[fi]=DVD-ROM-laite +Name[fr]=Lecteur de DVD-ROM... +Name[fy]=Dûbelskiifstasjon +Name[ga]=Gléas DVD-ROM... +Name[gl]=Dispositivo DVD-ROM... +Name[he]=התקן DVD... +Name[hi]=डीवीडी-रोम उपकरण... +Name[hr]=CD/DVD-ROM uređaj... +Name[hu]=DVD-meghajtó... +Name[is]=DVD-ROM-drif... +Name[it]=Dispositivo DVD-ROM... +Name[ja]=DVD-ROM デバイス... +Name[ka]=DVD-ROM მოწყობილობა +Name[kk]=DVD-ROM құрылғысы... +Name[km]=ឧបករណ៍ DVD-ROM... +Name[ko]=DVD-ROM 장치... +Name[lt]=DVD-ROM įrenginys... +Name[lv]=DVD-ROM Iekārta... +Name[mk]=DVD-ROM Уред... +Name[mn]=DVD-ROM төхөөрөмж... +Name[ms]=Peranti DVD-ROM... +Name[mt]=DVD-ROM... +Name[nb]=DVD-ROM-enhet … +Name[nds]=DVD-ROM-Reedschap... +Name[ne]=DVD-ROM यन्त्र... +Name[nl]=DVD-romspeler... +Name[nn]=DVD-ROM-eining … +Name[pa]=DVD-ROM ਜੰਤਰ... +Name[pl]=Urządzenie DVD-ROM... +Name[pt]=Leitor de DVD-ROMs... +Name[pt_BR]=Dispositivo de DVD-ROM... +Name[ro]=Dispozitiv DVD-ROM... +Name[ru]=DVD-ROM... +Name[rw]=Apareye DVD-ROM Nshya... +Name[se]=DVD-ROM-ovttadat … +Name[sk]=Zariadenie DVD-ROM... +Name[sl]=Naprava DVD-ROM ... +Name[sr]=CD/DVD-ROM уређај... +Name[sr@Latn]=CD/DVD-ROM uređaj... +Name[sv]=Dvdrom-enhet... +Name[ta]=டிவிடிராம் சாதனம் +Name[te]=డివిడి-రామ్ పరికరం... +Name[tg]=Дастгоҳи DVD-ROM... +Name[th]=อุปกรณ์ดีวีดีรอม... +Name[tr]=CD/DVD-ROM Aygıtı... +Name[tt]=DVD-ROM Cıhazı... +Name[uk]=Пристрій DVD-ROM... +Name[uz]=DVD-ROM uskunasi... +Name[uz@cyrillic]=DVD-ROM ускунаси... +Name[vi]=Thiết bị đọc đĩa DVD-ROM... +Name[wa]=Éndjin léjheu di plakes lazer DVD... +Name[zh_CN]=DVD-ROM 设备... +Name[zh_TW]=DVD-ROM 設備... +Comment=New DVD-ROM Device +Comment[af]=Nuwe DVD-ROM Toestel +Comment[ar]=جهاز قارئ أقراص رقمية مرئية جديد +Comment[be]=Новая прылада DVD-ROM +Comment[bg]=Ново устройство DVD-ROM +Comment[bn]=নতুন ডিভিডি-রম ডিভাইস +Comment[br]=Trobarzhell DVD-ROM Nevez +Comment[bs]=Novi DVD-ROM uređaj +Comment[ca]=Dispositiu DVD-ROM nou +Comment[cs]=Nová jednotka DVD-ROM +Comment[csb]=Nowi nëk DVD-ROM +Comment[cy]=Dyfais DVD-ROM Newydd +Comment[da]=Ny dvd-rom enhed +Comment[de]=Neues DVD-ROM-Laufwerk +Comment[el]=Νέα συσκευή DVD-ROM +Comment[eo]=Nova DVDdiskingo... +Comment[es]=Nueva unidad de DVD-ROM +Comment[et]=Uus DVD-ROM seade +Comment[eu]=DVD-ROM gailu berria +Comment[fa]=دستگاه DVD-ROM جدید +Comment[fi]=Uusi DVD-ROM-laite +Comment[fr]=Nouveau lecteur de DVD-ROM +Comment[fy]=Nije dûbelskiifstasjon +Comment[ga]=Gléas nua DVD-ROM +Comment[gl]=Novo Dispositivo DVD-ROM +Comment[he]=התקן DVD חדש +Comment[hi]=नया डीवीडी-रोम उपकरण +Comment[hr]=Novi CD/DVD-ROM uređaj +Comment[hu]=Új DVD-meghajtó +Comment[is]=Nýtt DVD-ROM-drif +Comment[it]=Nuovo dispositivo DVD-ROM +Comment[ja]=新規 DVD-ROM デバイス +Comment[ka]=ახალი DVD-ROM მოწყობილობა +Comment[kk]=Жаңа DVD-ROM құрылғысы +Comment[km]=ឧបករណ៍ DVD-ROM ថ្មី +Comment[ko]=새 DVD-ROM 장치 +Comment[lt]=Naujas DVD-ROM įrenginys +Comment[lv]=Jauna DVD-ROM Iekārta +Comment[mk]=Нов DVD-ROM уред +Comment[mn]=Шинэ DVD-төхөөрөмж +Comment[ms]=Peranti DVD-ROM Baru +Comment[mt]=DVD-ROM ġdid +Comment[nb]=Ny DVD-ROM-enhet +Comment[nds]=Niege DVD-ROM-Reedschap +Comment[ne]=नयाँ DVD-ROM यन्त्र +Comment[nl]=Nieuwe DVD-romspeler +Comment[nn]=Ny DVD-ROM-eining +Comment[pa]=ਨਵਾਂ DVD-ROM ਜੰਤਰ +Comment[pl]=Nowe urządzenie DVD-ROM... +Comment[pt]=Novo leitor de DVD-ROMs +Comment[pt_BR]=Novo dispositivo de DVD-ROM +Comment[ro]=Dispozitiv DVD-ROM nou +Comment[ru]=Ссылка на устройство DVD-ROM +Comment[rw]=Apareye DVD-ROOM Nshya +Comment[se]=Ođđa DVD-ROM-ovttadat +Comment[sk]=Nové zariadenie DVD-ROM +Comment[sl]=Nova naprava DVD-ROM +Comment[sr]=Нови CD/DVD-ROM уређај +Comment[sr@Latn]=Novi CD/DVD-ROM uređaj +Comment[sv]=Ny dvdrom-enhet +Comment[ta]=புது DVD-ROM சாதனம் +Comment[te]=కొత్త డివిడి-రామ్ పరికరం +Comment[tg]=Дастгоҳи нави DVD-ROM +Comment[th]=กำหนดอุปกรณ์ซีดี/ดีวีดีรอมใหม่ +Comment[tr]=Yeni DVD-ROM Aygıtı +Comment[tt]=Yaña DVD-ROM Cıhazı +Comment[uk]=Новий пристрій DVD-ROM +Comment[uz]=Yangi DVD uskunasi +Comment[uz@cyrillic]=Янги DVD ускунаси +Comment[vi]=Tạo DVD-ROM mới +Comment[wa]=Novea éndjin léjheu di plakes lazer DVD +Comment[zh_CN]=新建 DVD-ROM 设备 +Comment[zh_TW]=新 DVD-ROM 設備 +Type=Link +URL=.source/DVDROM-Device.desktop +Icon=dvd_unmount diff --git a/kdesktop/init/Templates/linkFloppy.desktop b/kdesktop/init/Templates/linkFloppy.desktop new file mode 100644 index 000000000..2a86dd575 --- /dev/null +++ b/kdesktop/init/Templates/linkFloppy.desktop @@ -0,0 +1,158 @@ +[Desktop Entry] +Name=Floppy Device... +Name[af]=Sagteskyf Toestel... +Name[ar]=جهاز أقراص مرنة... +Name[be]=Дыскета... +Name[bg]=Флопи... +Name[bn]=ফ্লপি ডিভাইস... +Name[br]=Trobarzhell Pladennig ... +Name[bs]=Disketni uređaj... +Name[ca]=Dispositiu de disquet... +Name[cs]=Disketová jednotka... +Name[csb]=Nëk disczétków... +Name[cy]=Dyfais Disg Meddal... +Name[da]=Floppy-enhed... +Name[de]=Diskettenlaufwerk ... +Name[el]=Συσκευή δισκέτας... +Name[eo]=Disketingo... +Name[es]=Unidad de disquetes... +Name[et]=Flopiseade... +Name[eu]=Diskete gailua... +Name[fa]=دستگاه فلاپی... +Name[fi]=Levykeasema... +Name[fr]=Lecteur de disquettes... +Name[fy]=Slappe skiifstasjon... +Name[ga]=Gléas Diosca Flapach... +Name[gl]=Dispositivo de Disquete... +Name[he]=התקן תקליטון... +Name[hi]=फ़्लॉपी उपकरण... +Name[hr]=Disketni uređaj... +Name[hu]=Floppy-meghajtó... +Name[is]=Disklingadrif... +Name[it]=Dispositivo dischetti... +Name[ja]=フロッピーデバイス... +Name[ka]=დრეკადი დისკის წამყვანი +Name[kk]=Иілгіш диск... +Name[km]=ដ្រាយថាសទន់... +Name[ko]=플로피 장치... +Name[lt]=Diskelių įrenginys... +Name[lv]=Diskešu Iekārta... +Name[mk]=Дискетна единица... +Name[mn]=Уян диск... +Name[ms]=Peranti Liut... +Name[mt]=Floppy... +Name[nb]=Diskettenhet … +Name[nds]=Diskett-Reedschap... +Name[ne]=फ्लपी यन्त्र... +Name[nl]=Diskettestation... +Name[nn]=Disketteining … +Name[pa]=ਫਲਾਪੀ ਜੰਤਰ... +Name[pl]=Stacja dyskietek... +Name[pt]=Leitor de Disquetes... +Name[pt_BR]=Dispositivo de disquete... +Name[ro]=Dispozitiv Floppy... +Name[ru]=Дисковод... +Name[rw]=Apareye Disikete... +Name[se]=Dibmaskearroovttadat … +Name[sk]=Disketová mechanika... +Name[sl]=Disketna naprava ... +Name[sr]=Флопи уређај... +Name[sr@Latn]=Flopi uređaj... +Name[sv]=Diskettenhet... +Name[ta]=நெகிழ்வட்டு சாதனம்... +Name[te]=ఫ్లాపీ పరికరం... +Name[tg]=Дастгоҳи Floppy... +Name[th]=อุปกรณ์ฟลอปปี้... +Name[tr]=Disket Aygıtı... +Name[tt]=Floppy Cıhazı... +Name[uk]=Пристрій гнучкого диска... +Name[uz]=Disket uskunasi... +Name[uz@cyrillic]=Дискет ускунаси... +Name[vi]=Ổ mềm... +Name[wa]=Éndjin léjheu di plaketes... +Name[zh_CN]=软驱设备... +Name[zh_TW]=軟碟設備... +Comment=New Floppy Device +Comment[af]=Nuwe Sagteskyf Toestel +Comment[ar]=جهاز أقراص مرنة جديد +Comment[az]=Yeni Disket Avadanlığı +Comment[be]=Новая дыскета +Comment[bg]=Ново флопи-дисково устройство +Comment[bn]=নতুন ফ্লপি ডিভাইস +Comment[br]=Trobarzhell Bladennig Nevez +Comment[bs]=Novi disketni uređaj +Comment[ca]=Dispositiu de disquet nou +Comment[cs]=Nová disketová jednotka +Comment[csb]=Nowi nëk disczétków +Comment[cy]=Dyfais Disg Meddal Newydd +Comment[da]=Ny floppy-enhed +Comment[de]=Neues Diskettenlaufwerk +Comment[el]=Νέα συσκευή δισκέτας +Comment[eo]=Nova disketa ingo +Comment[es]=Nueva unidad de disquetes +Comment[et]=Uus flopiseade +Comment[eu]=Diskete gailu berria +Comment[fa]=دستگاه فلاپی جدید +Comment[fi]=Uusi levykeasema +Comment[fr]=Nouveau lecteur de disquettes +Comment[fy]=Nije slappe skiifstasjon +Comment[ga]=Gléas nua diosca flapach +Comment[gl]=Nova Disqueteira +Comment[he]=התקן תקליטון חדש +Comment[hi]=नया फ़्लॉपी उपकरण +Comment[hr]=Novi disketni uređaj +Comment[hu]=Új floppy-meghajtó +Comment[id]=Divais Floppy baru +Comment[is]=Nýtt disklingadrif +Comment[it]=Nuovo dispositivo dischetti +Comment[ja]=新規フロッピーディスク +Comment[ka]=ახალი დრეკადი დისკის წამყვანი +Comment[kk]=Жаңа иілгіш диск құрылғысы +Comment[km]=ឧបករណ៍ថាសទន់ថ្មី +Comment[ko]=새 플로피 장치 +Comment[lo]=ກຳນົດອັຸປະກອນຟອບປີ້ໃຫມ่ +Comment[lt]=Naujas diskelių įrenginys +Comment[lv]=Jauna Diskešu iekārta +Comment[mk]=Нова дискетна единица +Comment[mn]=Шинэ уян диск хөтлөгч +Comment[ms]=Peranti Liut Baru +Comment[mt]=Apparat floppy ġdid +Comment[nb]=Ny diskettenhet +Comment[nds]=Niege Diskettreedschap +Comment[ne]=नयाँ फ्लपी यन्त्र +Comment[nl]=Nieuw diskettestation +Comment[nn]=Ny disketteining +Comment[nso]=Leano le Leswa la Floopy +Comment[oc]=Dispositiu de disquet nou +Comment[pa]=ਨਵਾਂ ਫਲਾਪੀ ਜੰਤਰ +Comment[pl]=Nowa stacja dyskietek +Comment[pt]=Novo leitor de disquetes +Comment[pt_BR]=Novo dispositivo de disquete +Comment[ro]=Dispozitiv Floppy nou +Comment[ru]=Ссылка на устройство дисковода +Comment[rw]=Apareye Disikete Nshya +Comment[se]=Ođđa dibmaskearroovttadat +Comment[sk]=Nová disketová mechanika +Comment[sl]=Nova disketna naprava +Comment[sr]=Нови флопи уређај +Comment[sr@Latn]=Novi flopi uređaj +Comment[sv]=Ny diskettenhet +Comment[ta]=புது நெகிழ்வட்டு சாதனம் +Comment[te]=కొత్త ఫ్లాపీ పరికరం +Comment[tg]=Дастгоҳи нави Floppy +Comment[th]=กำหนดอุปกรณ์ฟล็อปปีใหม่ +Comment[tr]=Yeni Disket Aygıtı +Comment[tt]=Yaña Floppy Cıhazı +Comment[uk]=Новий пристрій гнучкого диска +Comment[uz]=Yangi disket uskunasi +Comment[uz@cyrillic]=Янги дискет ускунаси +Comment[ven]=Maano maswa a Floppy +Comment[vi]=Tạo ổ mềm mới +Comment[wa]=Novea éndjin léjheu di plaketes... +Comment[xh]=Icebo Elitsha le Floppy +Comment[zh_CN]=新建软驱设备 +Comment[zh_TW]=新軟碟設備 +Comment[zu]=Ithuluzi le-Floppy elisha +Type=Link +URL=.source/Floppy.desktop +Icon=3floppy_unmount diff --git a/kdesktop/init/Templates/linkHD.desktop b/kdesktop/init/Templates/linkHD.desktop new file mode 100644 index 000000000..43a5ba482 --- /dev/null +++ b/kdesktop/init/Templates/linkHD.desktop @@ -0,0 +1,157 @@ +[Desktop Entry] +Name=Hard Disc Device... +Name[af]=Hardeskyf Toestel... +Name[ar]=جهاز القرص الصلب... +Name[be]=Раздзел жорсткага дыска... +Name[bg]=Твърд диск... +Name[bn]=হার্ড ডিস্ক ডিভাইস... +Name[br]=Trobarzhell Bladenn ... +Name[bs]=Hard disk uređaj... +Name[ca]=Dispositius de disc dur... +Name[cs]=Pevný disk... +Name[csb]=Cwiardi disk... +Name[cy]=Dyfais Disg Caled... +Name[da]=Harddisk-enhed... +Name[de]=Festplatte ... +Name[el]=Συσκευή σκληρού δίσκου... +Name[eo]=Fiksdiskingo... +Name[es]=Disco duro... +Name[et]=Kõvaketas... +Name[eu]=Diska gogorra... +Name[fa]=دستگاه دیسک سخت... +Name[fi]=Kiintolevy... +Name[fr]=Disque dur... +Name[fy]=Fêste skiif... +Name[ga]=Gléas Diosca Crua... +Name[gl]=Dispositivo de Disco Duro... +Name[he]=התקן כונן קשיח... +Name[hi]=हार्ड डिस्क उपकरण... +Name[hr]=Tvrdi disk... +Name[hu]=Merevlemez-partíció... +Name[is]=Harður diskur... +Name[it]=Disco rigido... +Name[ja]=ハードディスクデバイス... +Name[ka]=ხისტი დისკი... +Name[kk]=Қатқыл диск... +Name[km]=ឧបករណ៍ថាសរឹង... +Name[ko]=하드 디스크 장치... +Name[lt]=Kietojo disko įrenginys... +Name[lv]=Cietais Disks... +Name[mk]=Тврд диск... +Name[mn]=Хатуу диск... +Name[ms]=Peranti Cakera Keras... +Name[mt]=Ħard disk... +Name[nb]=Harddisk … +Name[nds]=Fastplaat... +Name[ne]=हार्डडिस्क यन्त्र... +Name[nl]=Harde Schijf... +Name[nn]=Harddisk … +Name[pa]=ਹਾਰਡ-ਡਿਸਕ ਜੰਤਰ... +Name[pl]=Twardy dysk... +Name[pt]=Disco Rígido... +Name[pt_BR]=Disco rígido... +Name[ro]=Dispozitiv Hard Disc... +Name[ru]=Жёсткий диск... +Name[rw]=Ububiko Disiki... +Name[se]=Garraskearru-ovttadat … +Name[sk]=Pevný disk... +Name[sl]=Naprava trdega diska ... +Name[sr]=Хард диск... +Name[sr@Latn]=Hard disk... +Name[sv]=Hårddisk... +Name[ta]=வட்டு +Name[te]=హార్డ్ డిస్క్ పరికరం... +Name[tg]=Дастгоҳи Диски Сахти... +Name[th]=อุปกรณ์ฮาร์ดดิสก์... +Name[tr]=Sabit Disk Aygıtı... +Name[tt]=Eçke Disk Cıhazı... +Name[uk]=Пристрій жорсткого диска... +Name[uz]=Qattiq disk uskunasi... +Name[uz@cyrillic]=Қаттиқ диск ускунаси... +Name[vi]=Ổ cứng... +Name[wa]=Éndjin di deure plake... +Name[zh_CN]=硬盘设备... +Name[zh_TW]=硬碟設備... +Comment=New Hard Disc +Comment[af]=Nuwe Hardeskyf +Comment[ar]=قرص صلب جديد +Comment[az]=Yeni Sabit Disk +Comment[be]=Новы раздзел жорсткага дыска +Comment[bg]=Нов твърд диск +Comment[bn]=নতুন হার্ড ডিস্ক +Comment[br]=Trobarzhell Bladenn Nevez +Comment[bs]=Novi hard disk +Comment[ca]=Disc dur nou +Comment[cs]=Nový pevný disk +Comment[csb]=Nowi cwiardi disk +Comment[cy]=Disg Caled Newydd +Comment[da]=Ny harddisk +Comment[de]=Neue Festplatte +Comment[el]=Νέος σκληρός δίσκος +Comment[en_GB]=New Hard Disk +Comment[eo]=Nova fiksdisko +Comment[es]=Nuevo disco duro +Comment[et]=Uus kõvaketas +Comment[eu]=Disko gogor berria +Comment[fa]=دیسک سخت جدید +Comment[fi]=Uusi kiintolevy +Comment[fr]=Nouveau disque dur +Comment[fy]=Nije Fêste skiif +Comment[ga]=Diosca crua nua +Comment[gl]=Novo Disco Duro +Comment[he]=כונן קשיח חדש +Comment[hi]=नया हार्ड डिस्क +Comment[hr]=Novi tvrdi disk +Comment[hu]=Új merevlemez-partíció +Comment[is]=Nýr harður diskur +Comment[it]=Nuovo disco rigido +Comment[ja]=新規ハードディスク +Comment[ka]=ახალი ხისტი დისკი +Comment[kk]=Жаңа қатқыл дискі +Comment[km]=ថាសរឹងថ្មី +Comment[ko]=새 하드 디스크 +Comment[lo]=ກຳນົດອຸປະກອນຮາດດີສໃຫ່ມ +Comment[lt]=Naujas kietas diskas +Comment[lv]=Jauns Cietais Disks +Comment[mk]=Нов тврд диск +Comment[mn]=Шинэ хатуу диск +Comment[ms]=Cakera Keras Baru +Comment[mt]=Ħard disk ġdid +Comment[nb]=Ny harddisk +Comment[nds]=Niege Fastplaat +Comment[ne]=नयाँ हार्डडिस्क +Comment[nl]=Nieuwe harde schijf +Comment[nn]=Ny harddisk +Comment[nso]=Hard Disc ye Ntshwa +Comment[pa]=ਨਵੀਂ ਹਾਰਡ-ਡਿਸਕ +Comment[pl]=Nowy twardy dysk +Comment[pt]=Novo Disco Rígido +Comment[pt_BR]=Novo disco rígido +Comment[ro]=Hard Disc nou +Comment[ru]=Ссылка на устройство жёсткого диска +Comment[rw]=Ububiko Disiki Bushya +Comment[se]=Ođđa garraskearru +Comment[sk]=Nový pevný disk +Comment[sl]=Nov trdi disk +Comment[sr]=Нови хард диск +Comment[sr@Latn]=Novi hard disk +Comment[sv]=Ny hårddisk +Comment[ta]=புது வன் தகடு +Comment[te]=కొత్త హార్డ్ డిస్క్ +Comment[tg]=Диски Сахти нав +Comment[th]=กำหนดอุปกรณ์ฮาร์ดดิสก์ใหม่ +Comment[tr]=Yeni Sabit Disk +Comment[tt]=Yaña Qatı Disk +Comment[uk]=Новий жорсткий диск +Comment[uz]=Yangi qattiq disk uskunasi +Comment[uz@cyrillic]=Янги қаттиқ диск ускунаси +Comment[ven]=Disiki ntswa yo khwathaho +Comment[vi]=Tạo ổ cứng mới +Comment[wa]=Novea éndjin di deure plake +Comment[xh]=Hard Disc Entsha +Comment[zh_CN]=新建硬盘 +Comment[zh_TW]=新硬碟設備 +Comment[zu]=I-diski Elukhuni Entsha +Type=Link +URL=.source/HD.desktop +Icon=hdd_unmount diff --git a/kdesktop/init/Templates/linkMO.desktop b/kdesktop/init/Templates/linkMO.desktop new file mode 100644 index 000000000..44f801e5e --- /dev/null +++ b/kdesktop/init/Templates/linkMO.desktop @@ -0,0 +1,150 @@ +[Desktop Entry] +Name=MO Device... +Name[af]=MO Toestel... +Name[ar]=جهاز MO... +Name[be]=Прылада MO... +Name[bg]=MO... +Name[bn]=MO ডিভাইস... +Name[br]=Trobarzhell MO ... +Name[bs]=MO uređaj... +Name[ca]=Dispositiu MO... +Name[cs]=MO zařízení... +Name[csb]=Nëk MO... +Name[cy]=Dyfais MO... +Name[da]=MO-enhed... +Name[de]=MO-Laufwerk ... +Name[el]=Συσκευή MO... +Name[eo]=Magnetdiskingo... +Name[es]=Dispositivo de MO... +Name[et]=MO seade... +Name[eu]=MO gailua... +Name[fa]=دستگاه MO... +Name[fi]=MO-laite... +Name[fr]=Périphérique MO... +Name[fy]=Magnetyske skiif stasjon... +Name[ga]=Gléas MO... +Name[gl]=Dispositivo MO... +Name[he]=התקן MO... +Name[hi]=एमओ उपकरण... +Name[hr]=MO uređaj... +Name[hu]=Magnetooptikai eszköz... +Name[is]=MO tæki... +Name[it]=Dispositivo MO... +Name[ja]=MO デバイス... +Name[ka]=MO მოწყობილობა +Name[kk]=Магнитооптик құрылғысы... +Name[km]=ឧបករណ៍ MO... +Name[ko]=MO 장치... +Name[lt]=MO įrenginys... +Name[lv]=MO Iekārta... +Name[mk]=MO Уред... +Name[mn]=MO Төхөөрөмж... +Name[ms]=Peranti MO... +Name[mt]=Apparat MO... +Name[nb]=MO-enhet … +Name[nds]=MO-Reedschap... +Name[ne]=MO यन्त्र... +Name[nl]=MO-apparaat... +Name[nn]=MO-eining … +Name[pa]=MO ਜੰਤਰ... +Name[pl]=Napęd magnetooptyczny... +Name[pt]=Dispositivo MO... +Name[pt_BR]=Dispositivo MO... +Name[ro]=Dispozitiv MO... +Name[ru]=Магнитооптическое устройство... +Name[rw]=Apareye MO... +Name[se]=MO-ovttadat … +Name[sk]=Disk MO... +Name[sl]=MO naprava ... +Name[sr]=МО уређај... +Name[sr@Latn]=MO uređaj... +Name[sv]=Magneto-optisk enhet... +Name[ta]=MO சாதனம்... +Name[te]=ఎంఓ పరికరం... +Name[tg]=Дастгоҳи MO... +Name[th]=อุปกรณ์ MO +Name[tr]=MO Aygıtı... +Name[tt]=MO Cıhazı... +Name[uk]=Пристрій MO... +Name[uz]=MO uskunasi +Name[uz@cyrillic]=MO ускунаси +Name[vi]=Thiết bị MO... +Name[wa]=Éndjin MO... +Name[zh_CN]=MO 设备... +Name[zh_TW]=MO 設備... +Comment=New MO Device +Comment[af]=Nuwe MO Toestel +Comment[ar]=جهاز MO جديد +Comment[be]=Новая прылада MO +Comment[bg]=Ново устройство MO +Comment[bn]=নতুন MO ডিভাইস +Comment[br]=Trobarzhell MO nevez +Comment[bs]=Novi MO uređaj +Comment[ca]=Dispositiu MO nou +Comment[cs]=Nová MO mechanika +Comment[csb]=Nowi nëk MO +Comment[cy]=Dyfais MO Newydd +Comment[da]=Ny MO-enhed +Comment[de]=Neues MO-Laufwerk +Comment[el]=Νέα συσκευή MO +Comment[eo]=Nova magnetdiskingo +Comment[es]=Nuevo dispositivo de MO +Comment[et]=Uus MO seade +Comment[eu]=MO gailu berria +Comment[fa]=دستگاه MO جدید +Comment[fi]=Uusi MO-laite +Comment[fr]=Nouveau périphérique MO +Comment[fy]=Nije magnetyske skiif stasjon +Comment[ga]=Gléas MO Nua +Comment[gl]=Novo Dispositivo MO +Comment[he]=התקן MO חדש +Comment[hi]=नया एमओ उपकरण +Comment[hr]=Novi MO uređaj +Comment[hu]=Új magnetooptikai eszköz +Comment[is]=Nýtt MO tæki +Comment[it]=Nuovo dispositivo MO +Comment[ja]=新規 MO デバイス +Comment[ka]=ახალი MO მოწყობილობა +Comment[kk]=Жаңа магнитооптик құрылғысы +Comment[km]=ឧបករណ៍ MO ថ្មី +Comment[ko]=새 MO 장치 +Comment[lt]=Naujas MO įrenginys +Comment[lv]=Jauna MO iekārta +Comment[mk]=Нов MO уред +Comment[mn]=Шинэ MO төхөөрөмж +Comment[ms]=Peranti MO Baru +Comment[mt]=Apparat MO ġdid +Comment[nb]=Ny MO-enhet +Comment[nds]=Niege MO-Reedschap +Comment[ne]=नयाँ MO यन्त्र +Comment[nl]=Nieuw MO-aparaat +Comment[nn]=Ny MO-eining +Comment[pa]=ਨਵਾਂ MO ਜੰਤਰ +Comment[pl]=Nowy napęd magnetooptyczny +Comment[pt]=Novo Dispositivo MO +Comment[pt_BR]=Novo dispositivo MO +Comment[ro]=Dispozitiv MO nou +Comment[ru]=Ссылка на магнитооптическое устройство +Comment[rw]= Apareye MO Nshya +Comment[se]=Ođđa MO-ovttadat +Comment[sk]=Nové zariadenie MO +Comment[sl]=Nova MO naprava +Comment[sr]=Нови МО уређај +Comment[sr@Latn]=Novi MO uređaj +Comment[sv]=Ny magneto-optisk enhet +Comment[ta]=புது MO சாதனம் +Comment[te]=కొత్త ఎంఓ పరికరం +Comment[tg]=Дастгоҳи нави MO +Comment[th]=กำหนดอุปกรณ์ MO ใหม่ +Comment[tr]=Yeni MO Aygıtı +Comment[tt]=Yaña MO Cıhazı +Comment[uk]=Новий пристрій MO +Comment[uz]=Yangi MO uskunasi +Comment[uz@cyrillic]=Янги MO ускунаси +Comment[vi]=Tạo MO mới +Comment[wa]=Novea éndjin MO +Comment[zh_CN]=新建 MO 设备 +Comment[zh_TW]=新 MO 設備 +Type=Link +URL=.source/MO-Device.desktop +Icon=mo_unmount diff --git a/kdesktop/init/Templates/linkNFS.desktop b/kdesktop/init/Templates/linkNFS.desktop new file mode 100644 index 000000000..a7952c33f --- /dev/null +++ b/kdesktop/init/Templates/linkNFS.desktop @@ -0,0 +1,91 @@ +[Desktop Entry] +Name=NFS... +Name[ar]=نظام ملفات الشبكة (NFS)... +Name[bn]=এন-এফ-এস (NFS)... +Name[br]=NFS ... +Name[de]=NFS ... +Name[hi]=एनएफ़एस... +Name[hu]=NFS-megosztás... +Name[nb]=NFS … +Name[nn]=NFS … +Name[ru]=Диск NFS... +Name[se]=NFS … +Name[sl]=NFS ... +Name[te]=ఎన్ ఎఫ్ ఎస్... +Name[th]=การเชื่อมโยง NFS... +Comment=New NFS Link +Comment[af]=Nuwe NFS Skakel +Comment[ar]=رابط NFS جديد +Comment[be]=Новая спасылка на NFS +Comment[bg]=Нова връзка NFS +Comment[bn]=নতুন এন-এফ-এস লিঙ্ক +Comment[br]=Liamm NFS Nevez +Comment[bs]=Novi NFS link +Comment[ca]=Enllaç NFS nou +Comment[cs]=Nový NFS odkaz +Comment[csb]=Nowi lënk do NFS +Comment[cy]=Cyswllt NFS Newydd +Comment[da]=Nyt NFS-link +Comment[de]=Neue NFS-Verknüpfung +Comment[el]=Νέος δεσμός NFS +Comment[eo]=Nova NFS-ligo +Comment[es]=Nuevo enlace NFS +Comment[et]=Uus NFS viit +Comment[eu]=NFS esteka berria +Comment[fa]=پیوند NFS جدید +Comment[fi]=Uusi NFS-linkki +Comment[fr]=Nouveau lien NFS +Comment[fy]=Nije NFS-Keppeling +Comment[ga]=Nasc nua NFS +Comment[gl]=Nova Ligazón NFS +Comment[he]=קישור NFS חדש +Comment[hi]=नया एनएफ़एस लिंक +Comment[hr]=Nova NFS veza +Comment[hu]=Új NFS-link +Comment[is]=Ný NFS tenging +Comment[it]=Nuovo collegamento NFS +Comment[ja]=新規 NFS リンク +Comment[ka]=ახალი NFS ბმული +Comment[kk]=Жаңа NFS сілтемесі +Comment[km]=តំណ NFS ថ្មី +Comment[ko]=새 NFS 연결 +Comment[lt]=Nauja NFS nuoroda +Comment[lv]=Jauna NFS saite +Comment[mk]=Нова NFS врска +Comment[mn]=Шинэ NFS холбоос +Comment[ms]=Pautan NFS Baru +Comment[mt]=Link ġdid għal NFS +Comment[nb]=Ny NFS-lenke +Comment[nds]=Niegen NFS-Link +Comment[ne]=नयाँ NFS लिङ्क +Comment[nl]=Nieuwe NFS-koppeling +Comment[nn]=Ny NFS-lenkje +Comment[pa]=ਨਵਾਂ NFS ਸੰਬੰਧ +Comment[pl]=Nowy skrót do NFS... +Comment[pt]=Nova ligação NFS +Comment[pt_BR]=Novo Link NFS +Comment[ro]=Legătură NFS nouă +Comment[ru]=Ссылка на диск NFS +Comment[rw]= Ihuza NFS Rishya +Comment[se]=Ođđa NFS-liŋka +Comment[sk]=Nový odkaz NFS +Comment[sl]=Nova povezava NFS +Comment[sr]=Нова NFS веза +Comment[sr@Latn]=Nova NFS veza +Comment[sv]=Ny NFS-länk +Comment[ta]=புது NFS இணைப்பு +Comment[te]=కొత్త ఎన్ ఎఫ్ ఎస్ లింక్ +Comment[tg]=NFS-и пайванди нав +Comment[th]=สร้างการเชื่อมโยง NFS ใหม่ +Comment[tr]=Yeni NFS Bağlantısı +Comment[tt]=NFS öçen Yaña Bäy +Comment[uk]=Нове посилання NFS +Comment[uz]=NFS bilan yangi bogʻ +Comment[uz@cyrillic]=NFS билан янги боғ +Comment[vi]=Tạo liên kết NFS mới +Comment[wa]=Novea loyén NFS +Comment[zh_CN]=新建 NFS 链接 +Comment[zh_TW]=新 NFS 鏈結 +Type=Link +URL=.source/NFS.desktop +Icon=nfs_unmount diff --git a/kdesktop/init/Templates/linkProgram.desktop b/kdesktop/init/Templates/linkProgram.desktop new file mode 100644 index 000000000..867e9e380 --- /dev/null +++ b/kdesktop/init/Templates/linkProgram.desktop @@ -0,0 +1,153 @@ +[Desktop Entry] +Name=Link to Application... +Name[af]=Skakel na Program... +Name[ar]=رابط لتطبيق... +Name[be]=Спасылка на праграму... +Name[bg]=Връзка към програма... +Name[bn]=অ্যাপলিকেশন-এ লিঙ্ক... +Name[br]=Liamm ouzh un arload ... +Name[bs]=Veza do programa... +Name[ca]=Enllaç a aplicació... +Name[cs]=Odkaz na aplikaci... +Name[csb]=Lënk do programë... +Name[cy]=Cyswllt i Gymhwysiad... +Name[da]=Link til program... +Name[de]=Verknüpfung zu Programm ... +Name[el]=Δεσμός με εφαρμογή... +Name[eo]=Ligo al aplikaĵo... +Name[es]=Enlace a aplicación... +Name[et]=Viit rakendusele... +Name[eu]=Esteka aplikazioari... +Name[fa]=پیوند به کاربرد... +Name[fi]=Linkki sovellukseen... +Name[fr]=Lien vers une application... +Name[fy]=Keppeling nei tappasing... +Name[ga]=Nasc go Feidhmchlár... +Name[gl]=Ligazón a unha Aplicación... +Name[he]=קישור ליישום... +Name[hi]=अनुप्रयोग को लिंक... +Name[hr]=Veza s aplikacijom... +Name[hu]=Alkalmazásra mutató link... +Name[is]=Tengja við forrit... +Name[it]=Collegamento ad un'applicazione... +Name[ja]=アプリケーションへのリンク... +Name[ka]=პროგრამის ბმული... +Name[kk]=Қолданбаға сілтеме... +Name[km]=តំណទៅកម្មវិធី... +Name[ko]=프로그램으로 향한 연결... +Name[lt]=Programos nuoroda... +Name[lv]=Saite uz Aplikāciju... +Name[mk]=Врска до апликација... +Name[mn]=Програмтай холбох... +Name[ms]=Paut ke Aplikasi... +Name[mt]=Link għal programm... +Name[nb]=Lenke til program … +Name[nds]=Link na'n Programm... +Name[ne]=अनुप्रयोगमा लिङ्क गर्नुहोस्... +Name[nl]=Koppeling naar toepassing... +Name[nn]=Lenkje til program … +Name[pa]=ਕਾਰਜ ਨਾਲ ਸੰਬੰਧ... +Name[pl]=Skrót do programu... +Name[pt]=Atalho para Aplicação... +Name[pt_BR]=Link para Aplicativo... +Name[ro]=Legătură către aplicație... +Name[ru]=Ссылка на приложение... +Name[rw]=Ihuza kuri Porogaramu... +Name[se]=Liŋka prográmmii … +Name[sk]=Odkaz na aplikáciu... +Name[sl]=Povezava do programa ... +Name[sr]=Веза ка програму... +Name[sr@Latn]=Veza ka programu... +Name[sv]=Länk till program... +Name[ta]=விண்ணப்பத்துக்கு இணை... +Name[tg]=Пайванд ба барномаи... +Name[th]=เชื่อมโยงไปยังแอพพลิเคชัน... +Name[tr]=Uygulamaya Bağlantı... +Name[tt]=Yazılımğa Bäy... +Name[uk]=Посилання на програму... +Name[uz]=Dastur bilan bogʻ... +Name[uz@cyrillic]=Дастур билан боғ... +Name[vi]=Liên kết tới một Chương trình... +Name[wa]=Loyén viè on programe... +Name[zh_CN]=应用程序链接... +Name[zh_TW]=應用程式連結... +Comment=New Link to Application +Comment[af]=Nuwe Skakel na Aansoek +Comment[ar]=إرتباط جديد بتطبيق +Comment[be]=Новая спасылка на праграму +Comment[bg]=Нова връзка към програма +Comment[bn]=অ্যাপলিকেশন-এ নতুন লিঙ্ক +Comment[br]=Liamm nevez ouzh un arload ... +Comment[bs]=Nova veza do programa +Comment[ca]=Nou enllaç a l'aplicació +Comment[cs]=Nový odkaz na aplikaci +Comment[csb]=Nowi lënk do programë +Comment[cy]=Cyswllt Newydd i Gymhwysiad +Comment[da]=Nyt link til program +Comment[de]=Neue Verknüpfung mit Programm +Comment[el]=Νέος δεσμός με εφαρμογή +Comment[eo]=Nova ligo al aplikaĵo +Comment[es]=Nuevo enlace a aplicación +Comment[et]=Uus viit rakendusele +Comment[eu]=Aplikazioarekiko esteka berria +Comment[fa]=پیوند جدید به کاربرد +Comment[fi]=Uusi linkki sovellukseen +Comment[fr]=Nouveau lien vers une application +Comment[fy]=Nije keppeling naar toepassing +Comment[ga]=Nasc nua go feidhmchlár +Comment[gl]=Nova Ligazón a unha Aplicación +Comment[he]=קישור חדש ליישום +Comment[hi]=अनुप्रयोग को नई लिंक +Comment[hr]=Nova veza s aplikacijom +Comment[hu]=Alkalmazásra mutató új link +Comment[is]=Nýtt tengi við forrit +Comment[it]=Nuovo collegamento ad un'applicazione +Comment[ja]=新規アプリケーションリンク +Comment[ka]=პროგრამის ახალი ბმული +Comment[kk]=Қолданбаға жаңа сілтеме +Comment[km]=តំណថ្មីទៅកម្មវិធី +Comment[ko]=프로그램으로 향한 새 연결 +Comment[lo]=ສ້າງລິ້ງໄປຍັງແອບພີເຄຊັ້ນໃຫມ່ +Comment[lt]=Nauja programos nuoroda +Comment[lv]=Jauna Saite uz Aplikāciju +Comment[mk]=Нова врска до апликација +Comment[mn]=програмтай шинээр холбох +Comment[ms]=Pautan Baru ke Aplikasi +Comment[mt]=Link ġdid ġħal programm +Comment[nb]=Ny lenke til program +Comment[nds]=Niegen Link na'n Programm +Comment[ne]=अनुप्रयोगमा नयाँ लिङ्क गर्नुहोस् +Comment[nl]=Nieuwe koppeling naar toepassing +Comment[nn]=Ny lenkje til program +Comment[nso]=Kgokaganyo ye Ntshwa go Tshomiso +Comment[pa]=ਕਾਰਜ ਨਾਲ ਨਵਾਂ ਸੰਬੰਧ +Comment[pl]=Nowy skrót do programu +Comment[pt]=Novo Atalho para Aplicação +Comment[pt_BR]=Novo link para Aplicativo +Comment[ro]=Legătură nouă către aplicație +Comment[ru]=Новая ссылка на приложение +Comment[rw]=Ihuza Rishya kuri Porogaramu +Comment[se]=Ođđa liŋka prográmmii +Comment[sk]=Nový odkaz na aplikáciu +Comment[sl]=Nova povezava do programa +Comment[sr]=Нова веза ка програму +Comment[sr@Latn]=Nova veza ka programu +Comment[sv]=Ny länk till program +Comment[ta]=பயன்பாட்டுக்கான புதிய இணைப்பு +Comment[tg]=Пайванди нав ба барнома +Comment[th]=สร้างการเชื่อมโยงใหม่ไปยังแอพพลิเคชัน +Comment[tr]=Uygulamaya Yeni Bağlantı +Comment[tt]=Yazılım öçen Yaña Bäy +Comment[uk]=Нове посилання на програму +Comment[uz]=Dastur bilan yangi bogʻ +Comment[uz@cyrillic]=Дастур билан янги боғ +Comment[ven]=Thumanyo ntswa kha apulifikhesheni +Comment[vi]=Tạo liên kết mới tới một chương trình +Comment[wa]=Novea loyén viè on programe +Comment[xh]=Ikhonkco Elitsha Lwesicelo +Comment[zh_CN]=新建应用程序链接 +Comment[zh_TW]=新建應用程式連結 +Comment[zu]=Isixhumanisi esisha esiya kumyaleli +Icon=exec +Type=Link +URL=.source/Program.desktop diff --git a/kdesktop/init/Templates/linkURL.desktop b/kdesktop/init/Templates/linkURL.desktop new file mode 100644 index 000000000..1af2d73bb --- /dev/null +++ b/kdesktop/init/Templates/linkURL.desktop @@ -0,0 +1,153 @@ +[Desktop Entry] +Name=Link to Location (URL)... +Name[af]=Skakel na Ligging (URL)... +Name[ar]=رابط لموقع... +Name[be]=Спасылка на месцазнаходжанне (URL)... +Name[bg]=Връзка към адрес... +Name[bn]=ইউ-আর-এল অবস্থানে লিঙ্ক... +Name[br]=Liamm ouzh ul lec'hiadur (URL) ... +Name[bs]=Veza do lokacije (URL)... +Name[ca]=Enllaç al localitzador (URL)... +Name[cs]=Odkaz na umístění (URL)... +Name[csb]=Lënk do adresë (URL)... +Name[cy]=Cyswllt i Leoliad (URL)... +Name[da]=Internetlink (URL)... +Name[de]=Verknüpfung zu Adresse (URL) ... +Name[el]=Δεσμός με τοποθεσία (URL)... +Name[eo]=Ligo al situo (URL)... +Name[es]=Enlace a dirección (URL)... +Name[et]=Viit asukohale (URL)... +Name[eu]=Esteka kokapenari (URL)... +Name[fa]=پیوند به محل )نشانی وب(... +Name[fi]=Linkki sijaintiin (URL)... +Name[fr]=Lien vers une URL... +Name[fy]=Keppeling nei lokaasje (URL-adres)... +Name[ga]=Nasc le Suíomh (URL)... +Name[gl]=Ligazón a un Sítio (URL)... +Name[he]=קישור למיקום (URL)... +Name[hi]=स्थान (यूआरएल) को लिंक... +Name[hr]=Veza s lokacijom (URL)... +Name[hu]=Internet-cím (URL)... +Name[is]=Staðsetningartengill... +Name[it]=Collegamento ad un indirizzo (URL)... +Name[ja]=場所へのリンク (URL) +Name[ka]=ადგილმდებარეობის ბმული (URL)... +Name[kk]=URL-адреске сілтеме... +Name[km]=តំណទៅទីតាំង (URL)... +Name[ko]=위치로 향한 연결 (URL)... +Name[lt]=Adreso nuoroda (URL)... +Name[lv]=Saite uz Vietu (URL)... +Name[mk]=Врска до локација (URL)... +Name[mn]=Хаягтай (URL) холбох... +Name[ms]=Paut ke Aplikasi (URL)... +Name[mt]=Link għal lokazzjoni (URL)... +Name[nb]=Lenke til nettadresse (URL) … +Name[nds]=Link na'n Oort (URL)... +Name[ne]=स्थानमा लिङ्क गर्नुहोस् (यूआरएल)... +Name[nl]=Koppeling naar locatie (URL-adres)... +Name[nn]=Lenkje til nettadresse (URL) … +Name[pa]=ਸਥਿਤੀ (URL) ਨਾਲ ਸੰਬੰਧ... +Name[pl]=Skrót do adresu (URL)... +Name[pt]=Atalho para Localização (URL)... +Name[pt_BR]=Link para Localização (URL)... +Name[ro]=Legătură către locație (URL)... +Name[ru]=Адрес Интернета... +Name[rw]=Ihuza ku ndangahantu (URL)... +Name[se]=Liŋka fierpmádatčujuhussii (URL) … +Name[sk]=Odkaz na umiestnenie (URL)... +Name[sl]=Povezava do lokacije (URL) ... +Name[sr]=Веза ка локацији (URL)... +Name[sr@Latn]=Veza ka lokaciji (URL)... +Name[sv]=Länk till plats (URL)... +Name[ta]=இடத்திற்கு இணை (URL)... +Name[tg]=Пайванд ба макони (URL)... +Name[th]=เชื่อมโยงไปยังตำแหน่ง (URL)... +Name[tr]=Konuma (URL) Bağlantı... +Name[tt]=Urınlaşu öçen Bäy (URL)... +Name[uk]=Посилання до адреси (URL)... +Name[uz]=Mavzu bilan bogʻ (URL)... +Name[uz@cyrillic]=Мавзу билан боғ (URL)... +Name[vi]=Liên kết tới trang mạng (URL)... +Name[wa]=Loyén viè ene plaece (URL)... +Name[zh_CN]=到位置(URL)的链接... +Name[zh_TW]=到位置的連結(URL) +Comment=Enter link to location (URL): +Comment[af]=Invoer skakel na ligging (Url): +Comment[ar]=أدخل رابط لموقع: +Comment[be]=Вызначце спасылку на месцазнаходжанне (URL): +Comment[bg]=Въведете връзката към адреса: +Comment[bn]=লিঙ্কের অবস্থান: +Comment[br]=Roit al liamm ouzh ul lec'hiadur (URL) : +Comment[bs]=Unesite vezu do lokacije (URL): +Comment[ca]=Entreu un enllaç al localitzador (URL): +Comment[cs]=Zadejte odkaz na umístění (URL): +Comment[csb]=Nowi lënk do internetowi adresë (URL): +Comment[cy]=Mewnosodwch cyswllt i leoliad (URL): +Comment[da]=Indtast internetlink (URL): +Comment[de]=Verknüpfung mit Adresse (URL) eingeben: +Comment[el]=Δώστε δεσμό στην τοποθεσία (URL): +Comment[eo]=Enigu ligon al situo (URL): +Comment[es]=Introduzca el enlace a la dirección (URL): +Comment[et]=Sisesta viit asukohale (URL): +Comment[eu]=Sartu kokapenarekiko (URL) esteka: +Comment[fa]=پیوند به محل )نشانی وب( را وارد کنید: +Comment[fi]=Anna linkki sijaintiin (URL): +Comment[fr]=Nouveau lien vers une URL : +Comment[fy]=Keppeling nei lokaasje ynfiere (URL-adres): +Comment[ga]=Iontráil nasc le suíomh (URL): +Comment[gl]=Introduza a ligazón á localización (URL): +Comment[he]=הזן את הקישור למיקום (URL): +Comment[hi]=स्थान (यूआरएल) को लिंक भरें: +Comment[hr]=Nova veza s lokacijom (URL) +Comment[hu]=Adja meg az internet-címet (URL-t): +Comment[is]=Gefðu upp slóð að staðsetningu: +Comment[it]=Immetti collegamento all'indirizzo (URL): +Comment[ja]=新規の場所へのリンク(URL): +Comment[ka]=შეიყვანეთ პროგრამის ბმული ბმული (URL) +Comment[kk]=URL-адресін келтіріңіз: +Comment[km]=បញ្ចូលតំណទៅទីតាំង (URL) ៖ +Comment[ko]=연결할 위치(URL)를 입력하십시오: +Comment[lo]=ສ້າງລິໄປຍັງຕຳແຫນ່ງ (URL) ໃຫ່ມ +Comment[lt]=Nauja adreso nuoroda (URL) +Comment[lv]=Jauna Saite uz Vietu (URL): +Comment[mk]=Внесете врска до локацијата (URL): +Comment[mn]=Холбох хаяг (URL) өгөх: +Comment[ms]=Masukkan pautan ke lokasi (URL): +Comment[mt]=Link ġdid għal lokazzjoni (URL) +Comment[nb]=Ny lenke til en nettadresse: +Comment[nds]=Link na'n Oort (URL) ingeven: +Comment[ne]=स्थानमा प्रविष्टि लिङ्क गर्नुहोस् (यूआरएल): +Comment[nl]=Koppeling naar locatie invoeren (URL-adres): +Comment[nn]=Ny lenkje til Internettadresse: +Comment[nso]=Tsenya sekgokaganyi go tulo (URL): +Comment[pa]=ਸਥਿਤੀ (URL) ਨਾਲ ਸੰਬੰਧ ਦਿਓ: +Comment[pl]=Nowy skrót do adresu internetowego (URL): +Comment[pt]=Indique o atalho para a localização (URL): +Comment[pt_BR]=Digite o link para a localização (URL): +Comment[ro]=Introduceți legătura către locație (URL): +Comment[ru]=Адрес в Интернете: +Comment[rw]=Kwinjiza ihuza ku ndangahantu (URL): +Comment[se]=Bija liŋkka fierpmádatčujuhussii (URL): +Comment[sk]=Zadajte odkaz na umiestnenie (URL): +Comment[sl]=Vnesite povezavo do mesta (URL): +Comment[sr]=Унесите везу ка локацији (URL): +Comment[sr@Latn]=Unesite vezu ka lokaciji (URL): +Comment[sv]=Ange länk till plats (URL): +Comment[ta]=இடத்திற்கான இணைப்பை உள்ளிடு (URL): +Comment[tg]=Бадарғаро ба адреси (URL) ворид кунед: +Comment[th]=สร้างการเชื่อมโยงไปยังตำแหน่ง (URL) ใหม่ +Comment[tr]=Konuma bağlantıyı girin: +Comment[tt]=Urınlaşu bäyen kertü (URL): +Comment[uk]=Введіть посилання до адреси (URL): +Comment[uz]=Mavzuga bogʻni (URL) kiriting: +Comment[uz@cyrillic]=Мавзуга боғни (URL) киритинг: +Comment[ven]=Dzhenisani vhukwamani kha fhethu (URL): +Comment[vi]=Nhập liên kết tới trang mạng: +Comment[wa]=Novea loyén viè ene plaece (URL): +Comment[xh]=Ngenisa ikhonkco twindawo ekuyo (URL): +Comment[zh_CN]=输入到位置(URL)的链接: +Comment[zh_TW]=輸入到位置的連結(URL): +Comment[zu]=Ngenisa isixhumanisi esiya endaweni (URL): +URL=.source/URL.desktop +Type=Link +Icon=www diff --git a/kdesktop/init/Templates/linkZIP.desktop b/kdesktop/init/Templates/linkZIP.desktop new file mode 100644 index 000000000..9ef9eaee9 --- /dev/null +++ b/kdesktop/init/Templates/linkZIP.desktop @@ -0,0 +1,150 @@ +[Desktop Entry] +Name=ZIP Device... +Name[af]=ZIP Toestel... +Name[ar]=جهاز ZIP... +Name[be]=Прылада ZIP... +Name[bg]=ZIP... +Name[bn]=ZIP ডিভাইস... +Name[br]=Trobarzhell ZIP ... +Name[bs]=ZIP uređaj... +Name[ca]=Dispositiu ZIP... +Name[cs]=ZIP jednotka... +Name[csb]=Nëk ZIP... +Name[cy]=Dyfais ZIP... +Name[da]=ZIP-enhed... +Name[de]=ZIP-Laufwerk ... +Name[el]=Συσκευή ZIP... +Name[eo]=ZIP-ingo... +Name[es]=Unidad ZIP... +Name[et]=ZIP seade... +Name[eu]=ZIP gailua... +Name[fa]=دستگاه ZIP... +Name[fi]=ZIP-laite... +Name[fr]=Lecteur ZIP... +Name[fy]=ZIP-apparaat... +Name[ga]=Gléas Zip... +Name[gl]=Dispositivo Zip... +Name[he]=התקן ZIP... +Name[hi]=जिप उपकरण... +Name[hr]=ZIP uređaj... +Name[hu]=ZIP-meghajtó... +Name[is]=ZIP-drif... +Name[it]=Dispositivo ZIP... +Name[ja]=ZIP デバイス... +Name[ka]=ZIP მოწყობილობა... +Name[kk]=ZIP құрылғысы... +Name[km]=ឧបករណ៍ ZIP... +Name[ko]=ZIP 장치... +Name[lt]=ZIP įrenginys... +Name[lv]=ZIP Iekārta... +Name[mk]=ZIP Уред... +Name[mn]=ZIP Төхөөрөмж.. +Name[ms]=Peranti ZIP... +Name[mt]=Apparat ZIP +Name[nb]=ZIP-enhet … +Name[nds]=ZIP-Reedschap... +Name[ne]=ZIP यन्त्र... +Name[nl]=ZIP-apparaat... +Name[nn]=ZIP-eining … +Name[pa]=ZIP ਜੰਤਰ... +Name[pl]=Napęd ZIP... +Name[pt]=Dispositivo ZIP... +Name[pt_BR]=Dispositivo ZIP... +Name[ro]=Dispozitiv ZIP... +Name[ru]=ZIP... +Name[rw]=Apareye ZIPU... +Name[se]=ZIP-Ovttadat … +Name[sk]=Mechanika ZIP... +Name[sl]=Naprava ZIP ... +Name[sr]=ZIP Уређај... +Name[sr@Latn]=ZIP Uređaj... +Name[sv]=Zip-enhet... +Name[ta]=ZIP சாதனங்கள் +Name[te]=జిప్ పరికరం... +Name[tg]=Дастгоҳи ZIP... +Name[th]=อุปกรณ์ ZIP... +Name[tr]=ZIP Aygıtı... +Name[tt]=ZIP Cıhazı... +Name[uk]=Пристрій ZIP... +Name[uz]=ZIP uskunasi... +Name[uz@cyrillic]=ZIP ускунаси... +Name[vi]=Ổ ZIP... +Name[wa]=Éndjin léjheu di plaketes ZIP... +Name[zh_CN]=ZIP 设备... +Name[zh_TW]=ZIP 設備... +Comment=New ZIP Device +Comment[af]=Nuwe ZIP Toestel... +Comment[ar]=جهاز ZIP جديد +Comment[be]=Новая прылада ZIP +Comment[bg]=Ново устройство ZIP +Comment[bn]=নতুন ZIP ডিভাইস +Comment[br]=Trobarzhell ZIP Nevez +Comment[bs]=Novi ZIP uređaj +Comment[ca]=Dispositiu ZIP nou +Comment[cs]=Nová ZIP jednotka +Comment[csb]=Nowi nëk ZIP +Comment[cy]=Dyfais ZIP Newydd +Comment[da]=Ny ZIP-enhed +Comment[de]=Neues ZIP-Laufwerk +Comment[el]=Νέα συσκευή ZIP +Comment[eo]=Nova ZIP-ingo +Comment[es]=Nueva unidad ZIP +Comment[et]=Uus ZIP seade +Comment[eu]=ZIP gailu berria +Comment[fa]=دستگاه ZIP جدید +Comment[fi]=Uusi ZIP-laite +Comment[fr]=Nouveau lecteur ZIP +Comment[fy]=Nije ZIP-apparaat +Comment[ga]=Gléas Nua Zip +Comment[gl]=Novo Dispositivo Zip +Comment[he]=התקן ZIP חדש +Comment[hi]=नया जिप उपकरण +Comment[hr]=Novi ZIP uređaj +Comment[hu]=Új ZIP-lemezes meghajtó +Comment[is]=Nýtt ZIP-drif +Comment[it]=Nuovo dispositivo ZIP +Comment[ja]=新規 ZIP デバイス +Comment[ka]=ახალი ZIP მოწყობილობა +Comment[kk]=Жаңа ZIP құрылғысы +Comment[km]=ឧបករណ៍ ZIP ថ្មី +Comment[ko]=새 ZIP 장치 +Comment[lt]=Naujas ZIP įrenginys +Comment[lv]=Jauna ZIP iekārta +Comment[mk]=Нов ZIP уред +Comment[mn]=Шинэ ZIP Төхөөрөмж.. +Comment[ms]=Peranti ZIP Baru +Comment[mt]=Apparat ZIP ġdid +Comment[nb]=Ny ZIP-enhet +Comment[nds]=Niege ZIP-Reedschap +Comment[ne]=नयाँ ZIP यन्त्र +Comment[nl]=Nieuw ZIP-apparaat +Comment[nn]=Ny ZIP-eining +Comment[pa]=ਨਵਾਂ ZIP ਜੰਤਰ +Comment[pl]=Nowy napęd ZIP +Comment[pt]=Novo Dispositivo ZIP +Comment[pt_BR]=Novo Dispositivo ZIP +Comment[ro]=Dispozitiv ZIP nou +Comment[ru]=Ссылка на устройство ZIP +Comment[rw]=Apareye ZIP Nshya +Comment[se]=Ođđa ZIP-ovttadat … +Comment[sk]=Nové zariadenie ZIP +Comment[sl]=Nova naprava ZIP +Comment[sr]=Нови ZIP уређај +Comment[sr@Latn]=Novi ZIP uređaj +Comment[sv]=Ny Zip-enhet +Comment[ta]=புதிய ZIP சாதனம் +Comment[te]=కొత్త జిప్ పరికరం +Comment[tg]=Дастгоҳи нави ZIP +Comment[th]=กำหนดอุปกรณ์ ZIP ตัวใหม่ +Comment[tr]=Yeni ZIP Aygıtı +Comment[tt]=Yaña ZIP Cıhazı +Comment[uk]=Новий пристрій ZIP +Comment[uz]=Yangi ZIP uskunasi +Comment[uz@cyrillic]=Янги ZIP ускунаси +Comment[vi]=Tạo ổ ZIP mới +Comment[wa]=Novea éndjin léjheu di plaketes ZIP +Comment[zh_CN]=新建 ZIP 设备 +Comment[zh_TW]=新 ZIP 設備 +Type=Link +URL=.source/ZIP-Device.desktop +Icon=zip_unmount diff --git a/kdesktop/init/Trash b/kdesktop/init/Trash new file mode 100644 index 000000000..064d0ab28 --- /dev/null +++ b/kdesktop/init/Trash @@ -0,0 +1,88 @@ +[Desktop Entry] +Type=Link +URL=trash:/ +Encoding=UTF-8 +Icon=trashcan_full +EmptyIcon=trashcan_empty +Name=Trash +Name[af]=Gemors +Name[ar]=سلة النفايات +Name[az]=Zibil +Name[be]=Сметніца +Name[bg]=Кошче +Name[bn]=আবর্জনা +Name[br]=Pod-lastez +Name[bs]=Smeće +Name[ca]=Paperera +Name[cs]=Koš +Name[csb]=Kòsz +Name[cy]=Sbwriel +Name[da]=Affald +Name[de]=Mülleimer +Name[el]=Κάδος απορριμμάτων +Name[en_GB]=Wastebin +Name[en_US]=Trash +Name[eo]=Rubujo +Name[es]=Papelera +Name[et]=Prügikast +Name[eu]=Zaborra +Name[fa]=زباله +Name[fi]=Roskakori +Name[fr]=Corbeille +Name[fy]=Jiskefet +Name[ga]=Bruscar +Name[gl]=Lixo +Name[he]=אשפה +Name[hi]=रद्दी +Name[hr]=Otpad +Name[hsb]=Papjernik +Name[hu]=Szemétkosár +Name[is]=Rusl +Name[it]=Cestino +Name[ja]=ごみ箱 +Name[ka]=ურნა +Name[kk]=Өшірілгендер +Name[km]=ធុងសំរាម +Name[lo]=ຖັງຂີ້ເຫຍື່ອ +Name[lt]=Šiukšliadėžė +Name[lv]=Miskaste +Name[mk]=Корпа +Name[mn]=Хогийн сав +Name[ms]=Sampah +Name[mt]=Skart +Name[nb]=Papirkurv +Name[nds]=Affalltünn +Name[ne]=रद्दीटोकरी +Name[nl]=Prullenbak +Name[nn]=Papirkorg +Name[nso]=Seswaraditlakala +Name[pa]=ਰੱਦੀ +Name[pl]=Kosz +Name[pt]=Lixo +Name[pt_BR]=Lixo +Name[ro]=Gunoi +Name[ru]=Корзина +Name[se]=Ruskalihtti +Name[sk]=Kôš +Name[sl]=Smeti +Name[sr]=Смеће +Name[sr@Latn]=Smeće +Name[sv]=Skräp +Name[ta]=குப்பை +Name[te]=చెత్త బుట్ట +Name[tg]=Ахлотдон +Name[th]=ถังขยะ +Name[tr]=Çöp +Name[tt]=Çüplek +Name[uk]=Смітник +Name[uz]=Chiqindilar qutisi +Name[uz@cyrillic]=Чиқиндилар қутиси +Name[ven]=Tshikha +Name[vi]=Thùng rác +Name[wa]=Batch +Name[xh]=Inkukumo +Name[zh_CN]=回收站 +Name[zh_TW]=資源回收桶 +Name[zu]=Izibi +Comment=Contains removed files +X-Trinity-BuiltIn=true
\ No newline at end of file diff --git a/kdesktop/init/Web_Browser b/kdesktop/init/Web_Browser new file mode 100644 index 000000000..9a13b38c0 --- /dev/null +++ b/kdesktop/init/Web_Browser @@ -0,0 +1,40 @@ +[Desktop Entry] +Comment=Browse the World Wide Web +Comment[en_US]=Browse the World Wide Web +Exec=kfmclient openBrowser %u +GenericName=Web Browser +GenericName[en_US]=Web Browser +Icon=konqueror +MimeType=application/vnd.mozilla.xul+xml;application/xhtml+xml;application/xml;image/gif;image/jpeg;image/png;text/html;text/xml +Name=Web Browser +Name[ca]=Navegador web +Name[cs]=Webový prohlížeč +Name[de]=Web-Browser +Name[en_US]=Web Browser +Name[es]=Navegador web +Name[fa]=مرورگر اینترنتی +Name[fi]=-selain +Name[fr]=Navigateur Web +Name[hu]=webböngésző +Name[it]=Browser Web +Name[ja]=ウェブ・ブラウザ +Name[ko]=웹 브라우저 +Name[nb]=Nettleser +Name[nl]=webbrowser +Name[nn]=Nettlesar +Name[no]=Nettleser +Name[pl]=Przeglądarka WWW +Name[pt]=Navegador Web +Name[pt_BR]=Navegador Web +Name[sk]=Internetový prehliadač +Name[sv]=Webbläsaren +Path= +StartupNotify=true +Terminal=false +TerminalOptions= +Type=Application +X-DCOP-ServiceType= +X-TDE-SubstituteUID=false +X-TDE-Username= +X-Trinity-BuiltIn=true +OnlyShowIn=TDE; diff --git a/kdesktop/init/directory.autostart b/kdesktop/init/directory.autostart new file mode 100644 index 000000000..d63845aed --- /dev/null +++ b/kdesktop/init/directory.autostart @@ -0,0 +1,68 @@ +[Desktop Entry] +Type=Directory +Name=Autostart +Name[af]=Outomatiese begin +Name[ar]=بدء تشغيل تلقائي +Name[az]=Öz-Özünə Başlama +Name[be]=Аўтазапуск +Name[bg]=Автоматично стартиране +Name[bn]=অটো-স্টার্ট +Name[br]=Emloc'h +Name[ca]=Autoengega +Name[csb]=Aùtosztart +Name[cy]=Hunan-gychwyn +Name[el]=Αυτόματη Έναρξη +Name[eo]=Aŭtolanĉo +Name[es]=Inicio automático +Name[eu]=Autoabiatu +Name[fa]=خودآغاز +Name[fi]=Käynnistä +Name[fr]=Démarrage automatique +Name[fy]=Automatysk Begjinne +Name[ga]=Tús uathoibríoch +Name[gl]=Autoinício +Name[he]=הפעלה אוטומטית +Name[hi]=स्वतःप्रारंभ +Name[hr]=Automatsko pokretanje +Name[hu]=Automatikus indítás +Name[is]=Sjálfræsing +Name[it]=Avvio automatico +Name[ja]=自動起動 +Name[ka]=ავტოგაშვება +Name[kk]=Автобастау +Name[km]=ចាប់ផ្ដើមស្វ័យប្រវត្តិ +Name[lo]=ເລິ່ມອັດໂນມັດ +Name[lt]=Autostartas +Name[lv]=Autostarts +Name[mk]=Автостарт +Name[mn]=Автомат эхлэгч +Name[ms]=Automula +Name[mt]=Awto-bidu +Name[ne]=स्वत: सुरु +Name[nso]=Thomo yago Itirisa +Name[pa]=ਸਵੈ-ਚਾਲਤ +Name[pt]=Arranque +Name[pt_BR]=Inicialização Automática +Name[ru]=Автозапуск +Name[se]=Autoálggaheapmi +Name[sk]=Autoštart +Name[sl]=Samodejni zagon +Name[sr]=Аутоматско покретање +Name[sr@Latn]=Automatsko pokretanje +Name[ta]=தானாகதுவக்கு +Name[te]=స్వయంచాలన +Name[tg]=Сар кунии автоматикӣ +Name[th]=เริ่มอัตโนมัติ +Name[tr]=Otomatik Başlat +Name[tt]=Üze Cibäreläse +Name[uk]=Автостарт +Name[uz]=Avto-boshlash +Name[uz@cyrillic]=Авто-бошлаш +Name[ven]=Thoma +Name[vi]=Tự khởi động +Name[wa]=Enonde tot seu +Name[xh]=Isiqalo esizenzekelayo +Name[zh_CN]=自动启动 +Name[zh_TW]=自動啟動 +Name[zu]=Ukuqala ngokuzenzekela + diff --git a/kdesktop/init/directory.desktop b/kdesktop/init/directory.desktop new file mode 100644 index 000000000..2269e69dd --- /dev/null +++ b/kdesktop/init/directory.desktop @@ -0,0 +1,81 @@ +[Desktop Entry] +Type=Directory +BgImage= +Icon=desktop +Name=Desktop +Name[af]=Werkskerm +Name[ar]=سطح المكتب +Name[az]=Masa Üstü +Name[be]=Працоўны стол +Name[bg]=Работен плот +Name[bn]=ডেস্কটপ +Name[br]=Gorretaol +Name[bs]=Radna površina +Name[ca]=Escriptori +Name[cs]=Pracovní plocha +Name[csb]=Pùlt +Name[cy]=Penbwrdd +Name[de]=Arbeitsfläche +Name[el]=Επιφάνεια εργασίας +Name[eo]=Tabulo +Name[es]=Escritorio +Name[et]=Töölaud +Name[eu]=Mahaigaina +Name[fa]=رومیزی +Name[fi]=Työpöytä +Name[fo]=Skriviborð +Name[fr]=Bureau +Name[fy]=Buroblêd +Name[ga]=Deasc +Name[gl]=Escritorio +Name[he]=שולחן עבודה +Name[hi]=डेस्कटॉप +Name[hr]=Radna površina +Name[hsb]=Dźěłowy powjerch +Name[hu]=Munkaasztal +Name[is]=Skjáborð +Name[ja]=デスクトップ +Name[ka]=სამუშაო დაფა +Name[kk]=Жұмыс үстелі +Name[km]=ផ្ទៃតុ +Name[ko]=데스크톱 +Name[lo]=ພື້ນທີ່ເຮັດວງກ +Name[lt]=Darbastalis +Name[lv]=Darbvirsma +Name[mk]=Работна површина +Name[mn]=Ажлын тавцан +Name[ms]=Ruang Kerja +Name[nb]=Skrivebord +Name[nds]=Schriefdisch +Name[ne]=डेस्कटप +Name[nl]=Bureaublad +Name[nn]=Skrivebord +Name[oc]=BurèU +Name[pa]=ਵੇਹੜਾ +Name[pl]=Pulpit +Name[pt]=Ambiente de Trabalho +Name[pt_BR]=Área de Trabalho +Name[ru]=Рабочий стол +Name[rw]=Ibiro +Name[se]=Čállinbeavdi +Name[sk]=Plocha +Name[sl]=Namizje +Name[sr]=Радна површина +Name[sr@Latn]=Radna površina +Name[ss]=Desktop +Name[sv]=Skrivbord +Name[ta]=மேல்மேசை +Name[te]=రంగస్ఠలం +Name[tg]=Мизи корӣ +Name[th]=พื้นที่ทำงาน +Name[tr]=Masaüstü +Name[tt]=Östäl +Name[uk]=Стільниця +Name[uz]=Ish stoli +Name[uz@cyrillic]=Иш столи +Name[ven]=Desikithopo +Name[vi]=Màn hình nền +Name[wa]=Sicribanne +Name[zh_CN]=桌面 +Name[zh_TW]=桌面 + diff --git a/kdesktop/init/directory.templates b/kdesktop/init/directory.templates new file mode 100644 index 000000000..d77fa5cb6 --- /dev/null +++ b/kdesktop/init/directory.templates @@ -0,0 +1,78 @@ +[Desktop Entry] +Type=Directory +Name=Templates +Name[af]=Voorbeelde +Name[ar]=القوالب +Name[az]=Nümunələr +Name[be]=Шаблоны +Name[bg]=Шаблони +Name[bn]=টেমপ্লেট +Name[br]=Patromoù +Name[bs]=Šabloni +Name[ca]=Plantilles +Name[cs]=Šablony +Name[csb]=Mùstrë +Name[cy]=Patrymluniau +Name[da]=Skabeloner +Name[de]=Vorlagen +Name[el]=Πρότυπα +Name[eo]=Ŝablonoj +Name[es]=Plantillas +Name[et]=Mallid +Name[eu]=Txantiloiak +Name[fa]=الگوها +Name[fi]=Pohjat +Name[fr]=Modèles +Name[fy]=Sjabloanen +Name[ga]=Teimpléid +Name[gl]=Modelos +Name[he]=תבניות +Name[hi]=टैम्प्लेट्स +Name[hr]=Predlošci +Name[hu]=Sablonok +Name[is]=Snið +Name[it]=Modelli +Name[ja]=テンプレート +Name[ka]=ნიმუშები +Name[kk]=Үлгілер +Name[km]=ពុម្ព +Name[lo]=ຕົ້ນແບບ +Name[lt]=Šablonai +Name[lv]=Šabloni +Name[mk]=Шаблони +Name[mn]=Шаблом +Name[ms]=Templat +Name[mt]=Mudelli +Name[nb]=Maler +Name[nds]=Vörlagen +Name[ne]=टेम्प्लेट +Name[nl]=Sjablonen +Name[nn]=Malar +Name[nso]=Dipapiso +Name[pa]=ਨਮੂਨਾ +Name[pl]=Wzorce +Name[pt]=Modelos +Name[pt_BR]=Modelos +Name[ro]=Modele +Name[ru]=Шаблоны +Name[se]=Mállet +Name[sk]=Šablóny +Name[sl]=Predloge +Name[sr]=Шаблони +Name[sr@Latn]=Šabloni +Name[sv]=Mallar +Name[ta]=வார்ப்புருக்கள் +Name[te]=టెంప్లెటులు +Name[tg]=Намунаҳо +Name[th]=ต้นแบบ +Name[tr]=Şablonlar +Name[tt]=Ürçetmä +Name[uk]=Шаблони +Name[uz]=Namunalar +Name[uz@cyrillic]=Намуналар +Name[vi]=Tiêu bản +Name[wa]=Modeles +Name[zh_CN]=模板 +Name[zh_TW]=範本 +Name[zu]=Ama-Templates + diff --git a/kdesktop/kcheckrunning.cpp b/kdesktop/kcheckrunning.cpp new file mode 100644 index 000000000..eaf8b9ebb --- /dev/null +++ b/kdesktop/kcheckrunning.cpp @@ -0,0 +1,29 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Lubos Lunak <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <X11/Xlib.h> + +int main() + { + Display* dpy = XOpenDisplay( NULL ); + if( dpy == NULL ) + return 1; + Atom atom = XInternAtom( dpy, "_KDE_RUNNING", False ); + return XGetSelectionOwner( dpy, atom ) != None ? 0 : 1; + } diff --git a/kdesktop/kcustommenu.cc b/kdesktop/kcustommenu.cc new file mode 100644 index 000000000..2e825c0d9 --- /dev/null +++ b/kdesktop/kcustommenu.cc @@ -0,0 +1,111 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Waldo Bastian <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <tqimage.h> +#include <tqregexp.h> + +#include <tdeconfig.h> +#include <kiconloader.h> +#include <tdeapplication.h> + +#include "kcustommenu.h" + +class KCustomMenu::KCustomMenuPrivate +{ +public: + TQMap<int,KService::Ptr> entryMap; +}; + +KCustomMenu::KCustomMenu(const TQString &configfile, TQWidget *parent) + : TQPopupMenu(parent, "kcustom_menu") +{ + d = new KCustomMenuPrivate; + + TDEConfig cfg(configfile, true, false); + int count = cfg.readNumEntry("NrOfItems"); + for(int i = 0; i < count; i++) + { + TQString entry = cfg.readEntry(TQString("Item%1").arg(i+1)); + if (entry.isEmpty()) + continue; + + // Try KSycoca first. + KService::Ptr menuItem = KService::serviceByDesktopPath( entry ); + if (!menuItem) + menuItem = KService::serviceByDesktopName( entry ); + if (!menuItem) + menuItem = new KService( entry ); + + if (!menuItem->isValid()) + continue; + + insertMenuItem( menuItem, -1 ); + } + connect(this, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotActivated(int))); +} + +KCustomMenu::~KCustomMenu() +{ + delete d; +} + +void +KCustomMenu::slotActivated(int id) +{ + KService::Ptr s = d->entryMap[id]; + if (!s) + return; + kapp->startServiceByDesktopPath(s->desktopEntryPath()); +} + +// The following is copied from kicker's PanelServiceMenu +void +KCustomMenu::insertMenuItem(KService::Ptr & s, int nId, int nIndex/*= -1*/) +{ + TQString serviceName = s->name(); + + // item names may contain ampersands. To avoid them being converted + // to accelators, replace them with two ampersands. + serviceName.replace("&", "&&"); + + TQPixmap normal = TDEGlobal::instance()->iconLoader()->loadIcon(s->icon(), TDEIcon::Small, + 0, TDEIcon::DefaultState, 0L, true); + TQPixmap active = TDEGlobal::instance()->iconLoader()->loadIcon(s->icon(), TDEIcon::Small, + 0, TDEIcon::ActiveState, 0L, true); + // make sure they are not larger than 16x16 + if (normal.width() > 16 || normal.height() > 16) { + TQImage tmp = normal.convertToImage(); + tmp = tmp.smoothScale(16, 16); + normal.convertFromImage(tmp); + } + if (active.width() > 16 || active.height() > 16) { + TQImage tmp = active.convertToImage(); + tmp = tmp.smoothScale(16, 16); + active.convertFromImage(tmp); + } + + TQIconSet iconset; + iconset.setPixmap(normal, TQIconSet::Small, TQIconSet::Normal); + iconset.setPixmap(active, TQIconSet::Small, TQIconSet::Active); + + int newId = insertItem(iconset, serviceName, nId, nIndex); + d->entryMap.insert(newId, s); +} + +#include "kcustommenu.moc" diff --git a/kdesktop/kcustommenu.h b/kdesktop/kcustommenu.h new file mode 100644 index 000000000..93b8d671f --- /dev/null +++ b/kdesktop/kcustommenu.h @@ -0,0 +1,56 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Waldo Bastian <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __kcustommenu_h__ +#define __kcustommenu_h__ + +#include <tqpopupmenu.h> +#include <kservice.h> + +/* + * This class provides a Popup Menu with programs that can be executed and + * that reads its configuration from a config file. + */ +class KCustomMenu : public TQPopupMenu +{ + Q_OBJECT +public: + /** + * Create a custome menu described by @p configfile. + */ + KCustomMenu(const TQString &configfile, TQWidget *parent=0); + + /** + * Destructor + */ + ~KCustomMenu(); + +protected slots: + void slotActivated(int id); + +protected: + void insertMenuItem(KService::Ptr &s, int nId, int nIndex = -1); + +private: + class KCustomMenuPrivate; + KCustomMenuPrivate *d; +}; + + +#endif diff --git a/kdesktop/kdesktop.desktop.cmake b/kdesktop/kdesktop.desktop.cmake new file mode 100644 index 000000000..03d65ced5 --- /dev/null +++ b/kdesktop/kdesktop.desktop.cmake @@ -0,0 +1,85 @@ +[Desktop Entry] +Exec=@TDE_BIN_DIR@/kdesktop +X-DCOP-ServiceType=wait +Name=TDE Desktop +Name[af]=TDE Werkskerm +Name[ar]=سطح المكتب TDE +Name[az]=TDE Masa üstü +Name[be]=Працоўны стол TDE +Name[bn]=কে.ডি.ই. ডেস্কটপ +Name[br]=Burev TDE +Name[bs]=TDE radna površina +Name[ca]=Escriptori TDE +Name[cs]=Pracovní plocha TDE +Name[csb]=Pùlt TDE +Name[cy]=Penbwrdd TDE +Name[da]=TDE-desktop +Name[de]=TDE-Arbeitsfläche +Name[el]=Επιφάνεια εργασίας του TDE +Name[eo]=TDE Labortablo +Name[es]=Escritorio de TDE +Name[et]=TDE töölaud +Name[eu]=TDE mahaigaina +Name[fa]=رومیزی TDE +Name[fi]=TDE-työpöytä +Name[fr]=Bureau de TDE +Name[fy]=TDE Buroblêd +Name[ga]=Deasc TDE +Name[gl]=Escritório de TDE +Name[he]=שולחן העבודה של TDE +Name[hi]=केडीई डेस्कटॉप +Name[hr]=TDE radna površina +Name[hu]=Munkaasztal +Name[id]=Desktop TDE +Name[is]=TDE skjáborð +Name[it]=Desktop TDE +Name[ja]=TDE デスクトップ +Name[ka]=TDE სამუშაო დაფა +Name[kk]=TDE үстелі +Name[km]=ផ្ទៃតុ TDE +Name[ko]=데스크톱 +Name[lo]=ພື້ນທີ່ທຳງານ TDE +Name[lt]=TDE Darbastalis +Name[lv]=TDE Darbvirsma +Name[mk]=TDE Десктоп +Name[mn]=TДЭ-Ажлын тавцан +Name[ms]=Desktop TDE +Name[mt]=Desktop TDE +Name[nb]=TDE Skrivebord +Name[nds]=TDE-Schriefdisch +Name[ne]=TDE डेस्कटप +Name[nl]=TDE Bureaublad +Name[nn]=TDE-skrivebord +Name[nso]=Desktop ya TDE +Name[pa]=TDE ਵੇਹੜਾ +Name[pl]=Pulpit TDE +Name[pt]=Ecrã do TDE +Name[pt_BR]=Área de Trabalho TDE +Name[ro]=Ecran TDE +Name[ru]=Рабочий стол TDE +Name[rw]=TDE Ibiro +Name[se]=TDE-čallinbeavdi +Name[sk]=Pracovná plocha +Name[sl]=Namizje TDE +Name[sr]=TDE радна површина +Name[sr@Latn]=TDE radna površina +Name[sv]=TDE-skrivbord +Name[ta]=TDE மேல்மேசை +Name[te]=కెడిఈ రంగస్థలం +Name[tg]=Мизи Кории TDE +Name[th]=พื้นที่ทำงาน TDE +Name[tr]=TDE Masaüstü +Name[tt]=TDE Östäl +Name[uk]=Стільниця TDE +Name[uz]=TDE ish stoli +Name[uz@cyrillic]=TDE иш столи +Name[ven]=Desikithopo ya TDE +Name[vi]=Môi trường TDE +Name[wa]=Sicribanne TDE +Name[zh_CN]=TDE 桌面 +Name[zh_TW]=TDE 桌面 +Name[zu]=I-Desktop ye-TDE +Type=Service +X-TDE-StartupNotify=false +OnlyShowIn=TDE; +X-TDE-autostart-phase=0 diff --git a/kdesktop/kdesktop.kcfg b/kdesktop/kdesktop.kcfg new file mode 100644 index 000000000..2298e16c5 --- /dev/null +++ b/kdesktop/kdesktop.kcfg @@ -0,0 +1,443 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <kcfgfile arg="true" /> + + <group name="Background Common"> + <entry key="CommonDesktop" type="Bool"> + <default>true</default> + <label>Common settings for all desktops</label> + <whatsthis>If you want the same background settings to be applied to all desktops enable this option.</whatsthis> + </entry> + <entry key="CommonScreen" type="Bool"> + <default>true</default> + <label>Common settings for all screens</label> + <whatsthis>If you want the same background settings to be applied to all screens enable this option.</whatsthis> + </entry> + <entry key="DrawBackgroundPerScreen" type="Bool"> + <default>false</default> + <label>Draw backgrounds per screen</label> + <whatsthis>If you want to draw to each screen separately in xinerama mode enable this option.</whatsthis> + </entry> + <entry key="LimitCache" type="Bool"> + <default>false</default> + <label>Limit background cache</label> + <whatsthis>Enable this option if you want to limit the cache size for the background.</whatsthis> + </entry> + <entry key="CacheSize" type="Int"> + <default>2048</default> + <label>Background cache size</label> + <whatsthis>Here you can enter how much memory TDE should use for caching the background(s). If you have different backgrounds for the different desktops caching can make switching desktops smoother at the expense of higher memory use.</whatsthis> + </entry> + <entry key="BackgroundOpacity" type="Int"> + <default>100</default> + <label>Background Opacity</label> + <whatsthis>Here you can the opacity of the background (0-100). A composite manager can then render something behind it.</whatsthis> + </entry> + </group> + <group name="General"> + <entry name="DesktopEnabled" key="Enabled" type="Bool"> + <default>true</default> + <label>Show icons on desktop</label> + <whatsthis>Uncheck this option if you do not want to have icons on the desktop. Without icons the desktop will be somewhat faster but you will no longer be able to drag files to the desktop.</whatsthis> + </entry> + <entry key="SetVRoot" type="Bool"> + <default>false</default> + <label>Allow programs in desktop window</label> + <whatsthis>Check this option if you want to run X11 programs that draw into the desktop such as xsnow, xpenguin or xmountain. If you have problems with applications like netscape that check the root window for running instances, disable this option.</whatsthis> + </entry> + <entry key="CopyDesktopLinks" type="Bool"> + <default>true</default> + <label></label> + <whatsthis></whatsthis> + <!-- init.cc:138 --> + <!-- if (!config->readBoolEntry("CopyDesktopLinks", true)) --> + </entry> + <entry key="AutoLineUpIcons" type="Bool"> + <default>true</default> + <label>Automatically line up icons</label> + <whatsthis>Check this option if you want to see your icons automatically aligned to the grid when you move them.</whatsthis> + </entry> + <entry key="SortDirectoriesFirst" type="Bool"> + <default>false</default> + <label>Sort directories first</label> + <whatsthis></whatsthis> + <!-- krootwm.cc:251 --> + <!-- aSortDirsFirst->setChecked( tdeconfig->readBoolEntry("SortDirectoriesFirst", true)); --> + <!-- krootwm.cc:496 --> + <!-- config->writeEntry( "SortDirectoriesFirst", b ); --> + </entry> + </group> + <group name="Mouse Buttons"> + <entry key="WheelSwitchesWorkspace" type="Bool"> + <default>false</default> + <label>Mouse wheel over desktop background switches desktop</label> + <whatsthis>You can switch between the virtual desktops by using the mouse wheel over the desktop background.</whatsthis> + </entry> + <entry key="WheelDirection" type="String"> + <default>Forward</default> + <label></label> + <whatsthis></whatsthis> + <!-- desktop.cc:397 --> + <!-- (config->readEntry("WheelDirection", default_dir_string) == forward_string) ? Forward : Reverse; --> + </entry> + <entry key="TerminalApplication" type="Path"> + <default>konsole</default> + <label>Terminal application</label> + <whatsthis>Defines which terminal application is used.</whatsthis> + </entry> + <entry key="Left" type="String"> + <default></default> + <label>Left Mouse Button Action</label> + <whatsthis>You can choose what happens when you click the left button of your pointing device on the desktop.</whatsthis> + </entry> + <entry key="Middle" type="String"> + <default>WindowListMenu</default> + <label>Middle Mouse Button Action</label> + <whatsthis>You can choose what happens when you click the middle button of your pointing device on the desktop.</whatsthis> + </entry> + <entry key="Right" type="String"> + <default>DesktopMenu</default> + <label>Right Mouse Button Action</label> + <whatsthis>You can choose what happens when you click the right button of your pointing device on the desktop.</whatsthis> + </entry> + </group> + <group name="Version"> + <entry key="KDEVersionMajor" type="Int"> + <default>0</default> + <label>KDE major version number</label> + <whatsthis></whatsthis> + </entry> + <entry key="KDEVersionMinor" type="Int"> + <default>0</default> + <label>KDE minor version number</label> + <whatsthis></whatsthis> + </entry> + <entry key="KDEVersionRelease" type="Int"> + <default>0</default> + <label>KDE release version number</label> + <whatsthis></whatsthis> + </entry> + </group> + <group name="FMSettings"> + <entry key="NormalTextColor" type="Color"> <!--SHARED--> + <default>Qt::white</default> + <label>Normal text color used for icon labels</label> + <whatsthis></whatsthis> + </entry> + <entry key="ItemTextBackground" type="Color"> <!--SHARED--> + <label>Background color used for icon labels</label> + <whatsthis></whatsthis> + </entry> + <entry key="ShadowEnabled" type="Bool"> + <default>true</default> + <label>Enable text shadow</label> + <whatsthis>Check here to enable a shadow outline around the desktop font. This also improves the readability of the desktop text against backgrounds of a similar color.</whatsthis> + </entry> + <entry key="ShadowParameters" type="String"> + <default>0,0,4.0,120.0,2,1,1,0,0,0</default> + <label></label> + <whatsthis></whatsthis> + <!-- kdesktopshadowsettings.cpp:84 --> + <!-- fromString(config->readEntry(SHADOW_CONFIG_ENTRY)); --> + </entry> + </group> + <group name="Desktop Icons"> + <entry key="ShowHidden" type="Bool"> + <default>false</default> + <label>Show hidden files</label> + <whatsthis><p>If you check this option, any files in your desktop directory that begin with a period (.) will be shown. Usually, such files contain configuration information, and remain hidden from view.</p>\n<p>For example, files which are named \".directory\" are plain text files which contain information for Konqueror, such as the icon to use in displaying a directory, the order in which files should be sorted, etc. You should not change or delete these files unless you know what you are doing.</p></whatsthis> + </entry> + <entry key="VertAlign" type="Bool"> + <default>true</default> + <label>Align direction</label> + <whatsthis>If this is enabled, icons are aligned vertically, otherwise horizontally.</whatsthis> + </entry> + <entry key="Preview" type="StringList"> + <default></default> + <label>Show Icon Previews For</label> + <whatsthis>Select for which types of files you want to enable preview images.</whatsthis> + </entry> + <entry key="SortCriterion" type="Int"> +<!-- + <entry key="SortCriterion" type="Enum"> + <choices> + <choice name="NameCaseSensitive" /> + <choice name="NameCaseInsensitive" /> + <choice name="Size" /> + <choice name="Type" /> + <choice name="Date" /> + </choices> +--> + <default>0</default> + <label>Sort criterion</label> + <whatsthis>Sets the sort criterion. Possible choices are NameCaseSensitive = 0, NameCaseInsensitive = 1, Size = 2, Type = 3, Date = 4.</whatsthis> + </entry> + <entry key="DirectoriesFirst" type="Bool"> + <default>true</default> + <label>Sort directories first</label> + <whatsthis>Enable this to place directories in front of the sorted list, otherwise they are amongst the files.</whatsthis> + </entry> + <entry key="LockIcons" type="Bool"> + <default>false</default> + <label>Lock in Place</label> + <whatsthis>Check this option if you want to keep your icons from moving.</whatsthis> + </entry> + + <entry key="AlwaysFirstItems" type="StringList"> + <default></default> + <label></label> + <whatsthis></whatsthis> + <!-- kdiconview.cc:254 --> + <!-- m_itemsAlwaysFirst = config->readListEntry("AlwaysFirstItems"); // Distributor plug-in --> + </entry> + </group> + <group name="Media"> + <entry name="MediaEnabled" key="enabled" type="Bool"> + <default>true</default> + <label></label> + <whatsthis></whatsthis> + <!-- kdiconview.cc:258 --> + <!-- m_enableMedia=config->readBoolEntry("enabled",false); --> + </entry> + <entry key="exclude" type="String"> + <default>media/nfs_mounted,media/nfs_unmounted,media/hdd_mounted,media/hdd_unmounted,media/floppy_unmounted,media/cdrom_unmounted,media/floppy5_unmounted</default> + <label>Device Types to exclude</label> + <whatsthis>The device types which you do not want to see on the desktop.</whatsthis> + <!-- kdiconview.cc:261 --> + <!-- TQString tmpList=config->readEntry("exclude","media/hdd_mounted,media/hdd_unmounted,media/floppy_unmounted,media/cdrom_unmounted,media/floppy5_unmounted"); --> + </entry> + <entry name="MediaFreeSpaceDisplayEnabled" key="FreeSpaceDisplayEnabled" type="Bool"> + <default>true</default> + <label></label> + <whatsthis></whatsthis> + </entry> + </group> + <group name="KDE"> + <entry key="macStyle" type="Bool"> + <default>false</default> + <label>Current application's menu bar (Mac OS-style)</label> + <whatsthis>If this option is selected, applications will not have their menu bar attached to their own window anymore. Instead, there is one menu bar at the top of the screen which shows the menus of the currently active application. You might recognize this behavior from Mac OS.</whatsthis> + </entry> + </group> + <group name="Menubar"> + <entry key="ShowMenubar" type="Bool"> + <default>false</default> + <label>Desktop menu bar</label> + <whatsthis>If this option is selected, there is one menu bar at the top of the screen which shows the desktop menus.</whatsthis> + </entry> + </group> + <group name="ScreenSaver"> + <entry name="ScreenSaverEnabled" key="Enabled" type="Bool"> + <default>false</default> + <label>Enable screen saver</label> + <whatsthis>Enables the screen saver.</whatsthis> + </entry> + <entry key="Timeout" type="Int"> + <default>300</default> + <label>Screen saver timeout</label> + <whatsthis>Sets the seconds after which the screen saver is started.</whatsthis> + </entry> + <entry name="DpmsDependent" key="DPMS-dependent" type="Bool"> + <default>true</default> + <label>Suspend screen saver when DPMS kicks in</label> + <whatsthis>Usually the screen saver is suspended when display power saving kicks in, + as nothing can be seen on the screen anyway, obviously. However, some screen savers + actually perform useful computations, so it is not desirable to suspend them.</whatsthis> + </entry> + <entry key="ActionTopLeft" type="Int"> + <default>0</default> + <label></label> + <whatsthis></whatsthis> + </entry> + <entry key="ActionTopRight" type="Int"> + <default>0</default> + <label></label> + <whatsthis></whatsthis> + </entry> + <entry key="ActionBottomLeft" type="Int"> + <default>0</default> + <label></label> + <whatsthis></whatsthis> + </entry> + <entry key="ActionBottomRight" type="Int"> + <default>0</default> + <label></label> + <whatsthis></whatsthis> + </entry> + <entry key="Lock" type="Bool"> + <default>false</default> + <label></label> + <whatsthis></whatsthis> + <!-- /home/paco/cvsroot/tdebase/kdesktop/lock/lockprocess.cc:308 --> + <!-- if(config.readBoolEntry("Lock", false)) --> + </entry> + <entry key="LockGrace" type="Int"> + <default>5000</default> + <label></label> + <whatsthis></whatsthis> + <!-- /home/paco/cvsroot/tdebase/kdesktop/lock/lockprocess.cc:310 --> + <!-- mLockGrace = config.readNumEntry("LockGrace", LOCK_GRACE_DEFAULT); --> + </entry> + <entry key="AutoLogout" type="Bool"> + <default>false</default> + <label></label> + <whatsthis></whatsthis> + <!-- /home/paco/cvsroot/tdebase/kdesktop/lock/lockprocess.cc:319 --> + <!-- if (config.readBoolEntry("AutoLogout", false)) --> + </entry> + <entry key="AutoLogoutTimeout" type="Int"> + <default>600</default> + <label></label> + <whatsthis></whatsthis> + <!-- /home/paco/cvsroot/tdebase/kdesktop/lock/lockprocess.cc:322 --> + <!-- mAutoLogoutTimeout = config.readNumEntry("AutoLogoutTimeout", AUTOLOGOUT_DEFAULT); --> + </entry> + <entry key="Priority" type="Int"> + <default>19</default> + <label></label> + <whatsthis></whatsthis> + <!-- /home/paco/cvsroot/tdebase/kdesktop/lock/lockprocess.cc:332 --> + <!-- mPriority = config.readNumEntry("Priority", 19); --> + </entry> + <entry key="Saver" type="String"> + <default></default> + <label></label> + <whatsthis></whatsthis> + <!-- /home/paco/cvsroot/tdebase/kdesktop/lock/lockprocess.cc:336 --> + <!-- mSaver = config.readEntry("Saver"); --> + </entry> + <entry key="UseUnmanagedLockWindows" type="Bool"> + <default>false</default> + <label></label> + <whatsthis>When enabled this restores the old style unmanaged window behavior of desktop locking.</whatsthis> + <!-- /home/paco/cvsroot/tdebase/kdesktop/lock/lockprocess.cc:336 --> + <!-- mSaver = config.readEntry("UseUnmanagedLockWindows"); --> + </entry> + <entry key="ShowLockDateTime" type="Bool"> + <default>true</default> + <label></label> + <whatsthis>When enabled the date and time when the desktop was locked is displayed as an additional intrusion detection measure.</whatsthis> + <!-- /home/paco/cvsroot/tdebase/kdesktop/lock/lockprocess.cc:336 --> + <!-- mSaver = config.readEntry("ShowLockDateTime"); --> + </entry> + <entry key="DelaySaverStart" type="Bool"> + <default>true</default> + <label></label> + <whatsthis>When disabled the screensaver starts immediately when locking the desktop.</whatsthis> + <!-- /home/paco/cvsroot/tdebase/kdesktop/lock/lockprocess.cc:336 --> + <!-- mSaver = config.readEntry("DelaySaverStart"); --> + </entry> + <entry key="HideActiveWindowsFromSaver" type="Bool"> + <default>true</default> + <label></label> + <whatsthis>When enabled all active windows are hidden from the screensaver, showing only the desktop background as a result.</whatsthis> + <!-- /home/paco/cvsroot/tdebase/kdesktop/lock/lockprocess.cc:336 --> + <!-- mSaver = config.readEntry("HideActiveWindowsFromSaver"); --> + </entry> + <entry key="UseTDESAK" type="Bool"> + <default>true</default> + <label></label> + <whatsthis>When enabled, the Trinity Secure Attention Key (TSAK) system will be used to secure the screen locker. This requires system wide TSAK support to be enabled prior to use.</whatsthis> + <!-- /home/paco/cvsroot/tdebase/kdesktop/lock/lockprocess.cc:336 --> + <!-- mSaver = config.readEntry("UseTDESAK"); --> + </entry> + <entry key="PluginsUnlock" type="StringList"> + <default></default> + <label></label> + <whatsthis></whatsthis> + <!-- /home/paco/cvsroot/tdebase/kdesktop/lock/lockprocess.cc:342 --> + <!-- mPlugins = config.readListEntry("PluginsUnlock"); --> + </entry> + <entry key="PluginOptions" type="StringList"> + <default></default> + <label></label> + <whatsthis></whatsthis> + <!-- /home/paco/cvsroot/tdebase/kdesktop/lock/lockprocess.cc:345 --> + <!-- mPluginOptions = config.readListEntry("PluginOptions"); --> + </entry> + </group> + <group name="MiniCli"> + <entry key="History" type="PathList"> + <default></default> + <label></label> + <whatsthis></whatsthis> + <!-- minicli.cpp:191 --> + <!-- TQStringList histList = config->readPathListEntry("History"); --> + <!-- minicli.cpp:242 --> + <!-- config->writePathEntry( "History", m_dlg->cbCommand->historyItems() ); --> + </entry> + <entry key="HistoryLength" type="Int"> + <default>50</default> + <label></label> + <whatsthis></whatsthis> + <!-- minicli.cpp:192 --> + <!-- int maxHistory = config->readNumEntry("HistoryLength", 50); --> + </entry> + <entry key="MiniCLIAutocompletionLength" type="Int"> + <default>10</default> + <label></label> + <whatsthis></whatsthis> + <!-- minicli.cpp:651 --> + <!-- int maxAutocompletion = KDesktopSettings::MiniCLIAutocompletionLength(); --> + </entry> + <entry key="MiniCLIFilesystemAutoComplete" type="Bool"> + <default>false</default> + <label></label> + <whatsthis></whatsthis> + <!-- minicli.cpp:216 --> + <!-- m_dlg->cbAutocomplete->setChecked( KDesktopSettings::miniCLIFilesystemAutoComplete() ); --> + </entry> + <entry key="MiniCLISystempathAutoComplete" type="Bool"> + <default>false</default> + <label></label> + <whatsthis></whatsthis> + <!-- minicli.cpp:216 --> + <!-- m_dlg->cbAutocomplete->setChecked( KDesktopSettings::miniCLISystempathAutoComplete() ); --> + </entry> + <entry key="MiniCLIHistoryAndFilesystemAutoComplete" type="Bool"> + <default>false</default> + <label></label> + <whatsthis></whatsthis> + <!-- minicli.cpp:217 --> + <!-- m_dlg->cbAutohistory->setChecked( KDesktopSettings::miniCLIHistoryAndFilesystemAutoComplete() ); --> + </entry> + <entry key="TerminalApps" type="PathList"> + <default></default> + <label></label> + <whatsthis></whatsthis> + <!-- minicli.cpp:193 --> + <!-- m_terminalAppList = config->readPathListEntry("TerminalApps"); --> + <!-- minicli.cpp:243 --> + <!-- config->writePathEntry( "TerminalApps", m_terminalAppList ); --> + </entry> + <entry key="CompletionItems" type="PathList"> + <default></default> + <label></label> + <whatsthis></whatsthis> + <!-- minicli.cpp:204 --> + <!-- TQStringList compList = config->readPathListEntry("CompletionItems"); --> + <!-- minicli.cpp:244 --> + <!-- config->writePathEntry( "CompletionItems", m_dlg->cbCommand->completionObject()->items() ); --> + </entry> + <entry key="CompletionMode" type="Int"> + <default code="true">TDEGlobalSettings::completionMode()</default> + <label></label> + <whatsthis></whatsthis> + <!-- minicli.cpp:210 --> + <!-- int mode = config->readNumEntry( "CompletionMode", TDEGlobalSettings::completionMode() ); --> + <!-- minicli.cpp:252 --> + <!-- config->writeEntry( "CompletionMode", m_dlg->cbCommand->completionMode() ); --> + </entry> + <entry key="MaxUsernameCompletions" type="Int"> + <default>30</default> + <label></label> + <whatsthis></whatsthis> + <!-- minicli.cpp:220 --> + <!-- int maxEntries = config->readNumEntry("MaxUsernameCompletions", 30); --> + </entry> + </group> + +</kcfg> diff --git a/kdesktop/kdesktopSetAsBackground.desktop b/kdesktop/kdesktopSetAsBackground.desktop new file mode 100644 index 000000000..79c879b20 --- /dev/null +++ b/kdesktop/kdesktopSetAsBackground.desktop @@ -0,0 +1,210 @@ +[Desktop Entry] +ServiceTypes=image/* +Actions=setAsBackground;tileAsBackground; +X-TDE-Submenu=Set as Background +X-TDE-Submenu[af]=Stel as agtergrond +X-TDE-Submenu[be]=Зрабіць фонавым малюнкам +X-TDE-Submenu[bg]=Установяване като фон +X-TDE-Submenu[bn]=পশ্চাদ্পট হিসাবে বেছে নাও +X-TDE-Submenu[bs]=Postavi kao pozadinu +X-TDE-Submenu[ca]=Estableix com a fons +X-TDE-Submenu[cs]=Nastavit jako pozadí +X-TDE-Submenu[csb]=Ùstôwi jakno spòdlé +X-TDE-Submenu[da]=Sæt som baggrund +X-TDE-Submenu[de]=Als Hintergrund setzen +X-TDE-Submenu[el]=Ορισμός ως ταπετσαρία +X-TDE-Submenu[eo]=Agordu kiel fono +X-TDE-Submenu[es]=Establecer como fondo +X-TDE-Submenu[et]=Sea taustapildiks +X-TDE-Submenu[eu]=Ezarri atzeko plano gisa +X-TDE-Submenu[fa]=تنظیم به عنوان زمینه +X-TDE-Submenu[fi]=Aseta taustakuvaksi +X-TDE-Submenu[fr]=Définir comme arrière-plan +X-TDE-Submenu[fy]=As eftergrûn brûke +X-TDE-Submenu[gl]=Pór como Fondo de Escritório +X-TDE-Submenu[he]=קבע כרקע +X-TDE-Submenu[hr]=Postavi kao pozadinu +X-TDE-Submenu[hu]=Beállítás háttérképnek +X-TDE-Submenu[is]=Setja sem bakgrunn +X-TDE-Submenu[it]=Imposta come sfondo +X-TDE-Submenu[ja]=背景としてセット +X-TDE-Submenu[kk]=Ая ретінде орнату +X-TDE-Submenu[km]=កំណត់ជាផ្ទៃខាងក្រោយ +X-TDE-Submenu[lt]=Nustatyti fonu +X-TDE-Submenu[mk]=Постави како подлога +X-TDE-Submenu[nb]=Sett som bakgrunn +X-TDE-Submenu[nds]=As Achtergrund fastleggen +X-TDE-Submenu[ne]=पृष्ठभूमिको रुपमा सेट गर्छ +X-TDE-Submenu[nl]=Als achtergrond gebruiken +X-TDE-Submenu[nn]=Bruk som bakgrunn +X-TDE-Submenu[pa]=ਪਿੱਠਭੂਮੀ ਬਣਾਓ +X-TDE-Submenu[pl]=Ustaw jako tło +X-TDE-Submenu[pt]=Colocar como Fundo +X-TDE-Submenu[pt_BR]=Configurar como Plano de fundo +X-TDE-Submenu[ro]=Setează ca fundal +X-TDE-Submenu[ru]=Сделать фоновым рисунком +X-TDE-Submenu[se]=Geavat duogášgovvan +X-TDE-Submenu[sk]=Nastaviť ako pozadie +X-TDE-Submenu[sl]=Nastavi kot ozadje +X-TDE-Submenu[sr]=Постави као позадину +X-TDE-Submenu[sr@Latn]=Postavi kao pozadinu +X-TDE-Submenu[sv]=Använd som bakgrund +X-TDE-Submenu[th]=ตั้งให้เป็นพื้นหลัง +X-TDE-Submenu[tr]=Masaüstü Arkaplanı Yap +X-TDE-Submenu[uk]=Встановити як тло +X-TDE-Submenu[uz]=Ish stoliga qoʻyish +X-TDE-Submenu[uz@cyrillic]=Иш столига қўйиш +X-TDE-Submenu[vi]=Đặt làm Hình nền +X-TDE-Submenu[wa]=Mete come fond d' waitroûle +X-TDE-Submenu[zh_CN]=设为背景 +X-TDE-Submenu[zh_TW]=設為背景 + +[Desktop Action setAsBackground] +Name=Centered +Name[af]=Gesentreer +Name[ar]=مركز +Name[be]=Пасярэдзіне +Name[bg]=Центрирано +Name[bn]=মাঝামাঝি +Name[br]=Kreizennet +Name[bs]=Centrirano +Name[ca]=Centrat +Name[cs]=Na střed +Name[csb]=Na westrzódkù +Name[cy]=Canoledig +Name[da]=Centreret +Name[de]=Zentriert +Name[el]=Κεντράρισμα +Name[en_GB]=Centred +Name[eo]=Meza +Name[es]=Centrado +Name[et]=Tsentreeritud +Name[eu]=Erdiratua +Name[fa]=مرکزی +Name[fi]=Keskitetty +Name[fr]=Centré +Name[fy]=sintraal setten +Name[ga]=Láraithe +Name[gl]=Centrado +Name[he]=ממורכז +Name[hi]=बीचों-बीच +Name[hr]=Sredinom +Name[hu]=Középre igazítva +Name[is]=Miðjað +Name[it]=Centrato +Name[ja]=中央 +Name[ka]=ცენტრზე +Name[kk]=Ортаға +Name[km]=កណ្ដាល +Name[lt]=Centruota +Name[lv]=Centrēts +Name[mk]=Центриран +Name[ms]=Tengah +Name[mt]=Iċċentrat +Name[nb]=Sentrert +Name[nds]=In de Merrn +Name[ne]=केन्द्रित +Name[nl]=Gecentreerd +Name[nn]=Sentrert +Name[pa]=ਕੇਂਦਰੀ +Name[pl]=Wyśrodkowane +Name[pt]=Centrado +Name[pt_BR]=Centralizado +Name[ro]=Centrat +Name[ru]=По центру +Name[rw]=Biri hagati +Name[se]=Guovdut +Name[sk]=V strede +Name[sl]=Usrediščeno +Name[sr]=Центрирано +Name[sr@Latn]=Centrirano +Name[sv]=Centrerad +Name[ta]=மைய +Name[te]=మద్యన +Name[tg]=Марказӣ +Name[th]=จัดกลาง +Name[tr]=Uzat +Name[tt]=Üzäkläşep +Name[uk]=По центру +Name[uz]=Markazda +Name[uz@cyrillic]=Марказда +Name[vi]=Giữa +Name[wa]=Å mitan +Name[zh_CN]=居中 +Name[zh_TW]=置中 +Icon=background +Exec=dcop kdesktop KBackgroundIface setWallpaper %u 6 + +[Desktop Action tileAsBackground] +Name=Tiled +Name[af]=Geteël +Name[ar]=مبلّط +Name[be]=Расцягнутае +Name[bg]=Каскадно +Name[bn]=টাইল করা +Name[br]=Teolet +Name[bs]=Popločano +Name[ca]=Repetit +Name[cs]=Dlaždice +Name[csb]=Kachelkòwóné +Name[cy]=Teiledig +Name[da]=Fliselagt +Name[de]=Gekachelt +Name[el]=Σε παράθεση +Name[eo]=kahela +Name[es]=Mosaico +Name[et]=Paanidena +Name[eu]=Mosaikoa +Name[fa]=کاشیشده +Name[fi]=Vierekkäin +Name[fr]=Mosaïque +Name[fy]=Tegele +Name[ga]=Tilithe +Name[gl]=Mosaico +Name[he]=פרוש +Name[hi]=चटाई-दार +Name[hr]=Popločeno +Name[hu]=Mozaikszerűen +Name[is]=Flísað +Name[it]=Ripetuto +Name[ja]=タイル状 +Name[ka]=მოზაიკა +Name[kk]=Қатарлап +Name[km]=ក្បឿង +Name[lt]=Iškloti +Name[mk]=Поплочен +Name[ms]=Berjubin +Name[mt]=Madum +Name[nb]=Flislagt +Name[nds]=Kachelt +Name[ne]=टायल गरिएको +Name[nl]=Tegels +Name[nn]=Jamsides +Name[pa]=ਤਣਿਆ +Name[pl]=Kafelkowane +Name[pt]=Mosaico +Name[pt_BR]=Ladrilhado +Name[ro]=Mozaic +Name[ru]=Черепицей +Name[rw]=Byudukaro +Name[se]=Bálddalaga +Name[sk]=Dlaždice +Name[sl]=Razdeljeno +Name[sr]=Поређано +Name[sr@Latn]=Poređano +Name[sv]=Sida vid sida +Name[ta]=பிண்ணனி +Name[te]=పలకలుగా +Name[tg]=Тахтасангӣ +Name[th]=ปูทั้งหน้าจอ +Name[tr]=Sırala +Name[tt]=Bülengän +Name[uk]=Плиткою +Name[uz]=Kafel +Name[uz@cyrillic]=Кафель +Name[vi]=Xếp ngói +Name[wa]=A schaeyes +Name[zh_CN]=平铺 +Name[zh_TW]=拼貼 +Icon=background +Exec=dcop kdesktop KBackgroundIface setWallpaper %u 2 diff --git a/kdesktop/kdesktop_custom_menu1 b/kdesktop/kdesktop_custom_menu1 new file mode 100644 index 000000000..f0466b886 --- /dev/null +++ b/kdesktop/kdesktop_custom_menu1 @@ -0,0 +1,2 @@ +NrOfItems=1 +Item1=konsole diff --git a/kdesktop/kdesktop_custom_menu2 b/kdesktop/kdesktop_custom_menu2 new file mode 100644 index 000000000..2073a0d77 --- /dev/null +++ b/kdesktop/kdesktop_custom_menu2 @@ -0,0 +1,2 @@ +NrOfItems=1 +Item1=xterm diff --git a/kdesktop/kdesktopapp.cpp b/kdesktop/kdesktopapp.cpp new file mode 100644 index 000000000..ba05dc655 --- /dev/null +++ b/kdesktop/kdesktopapp.cpp @@ -0,0 +1,95 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Dennis Kasprzyk <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <kdesktopapp.h> + +KDesktopApp::KDesktopApp(): +KUniqueApplication() +{ +#ifdef COMPOSITE + initCmBackground(); +#endif +} + +KDesktopApp::KDesktopApp(Display * dpy, Qt::HANDLE visual, Qt::HANDLE colormap): +KUniqueApplication(dpy, visual, colormap) +{ +#ifdef COMPOSITE + initCmBackground(); +#endif +} + +#ifdef COMPOSITE +void KDesktopApp::initCmBackground() +{ + Atom type; + int format; + unsigned long num, rest; + unsigned char *data; + + m_bgSupported = false; + m_cmBackground = + XInternAtom (tqt_xdisplay(), "_COMPIZ_WALLPAPER_SUPPORTED", false); + + XSelectInput (tqt_xdisplay(), tqt_xrootwin(), PropertyChangeMask); + + if (XGetWindowProperty (tqt_xdisplay(), tqt_xrootwin(), m_cmBackground, + 0, 1, FALSE, XA_CARDINAL, &type, &format, &num, + &rest, &data) == Success && num) + { + if (type == XA_CARDINAL) + m_bgSupported = (*data == 1); + XFree (data); + } +} + +bool KDesktopApp::x11EventFilter (XEvent * xevent) +{ + if (xevent->type == PropertyNotify && + xevent->xproperty.window == tqt_xrootwin() && + xevent->xproperty.atom == m_cmBackground) + { + Atom type; + int format; + unsigned long num, rest; + unsigned char *data; + + Bool supported = false; + + if (XGetWindowProperty (tqt_xdisplay(), tqt_xrootwin(), m_cmBackground, + 0, 1, FALSE, XA_CARDINAL, &type, &format, &num, + &rest, &data) == Success && num) + { + if (type == XA_CARDINAL) + supported = (*data == 1); + XFree (data); + } + + if (m_bgSupported != supported) + { + m_bgSupported = supported; + emit cmBackgroundChanged(supported); + } + } + return KUniqueApplication::x11EventFilter (xevent); +} + +#endif + +#include "kdesktopapp.moc" diff --git a/kdesktop/kdesktopapp.h b/kdesktop/kdesktopapp.h new file mode 100644 index 000000000..94cdd1d33 --- /dev/null +++ b/kdesktop/kdesktopapp.h @@ -0,0 +1,67 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Dennis Kasprzyk <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __kdesktopapp_h__ +#define __kdesktopapp_h__ + +#include <config.h> +#include <kuniqueapplication.h> + +#if defined(Q_WS_X11) && defined(HAVE_XRENDER) && TQT_VERSION >= 0x030300 +#define COMPOSITE +#endif + +#ifdef COMPOSITE +# include <X11/Xlib.h> +# include <X11/Xatom.h> +# include <fixx11h.h> +#endif + +class KDesktopApp : public KUniqueApplication +{ + Q_OBJECT + public: + KDesktopApp(); + KDesktopApp(Display * dpy, Qt::HANDLE visual = 0, + Qt::HANDLE colormap = 0); + +#ifdef COMPOSITE + bool x11EventFilter (XEvent *); + + bool cmBackground () + { + return m_bgSupported; + } +#endif + + signals: + void cmBackgroundChanged(bool supported); + +#ifdef COMPOSITE + private: + void initCmBackground(); + + private: + + Atom m_cmBackground; + Bool m_bgSupported; +#endif +}; + +#endif diff --git a/kdesktop/kdesktopbindings.cpp b/kdesktop/kdesktopbindings.cpp new file mode 100644 index 000000000..91bddb5b3 --- /dev/null +++ b/kdesktop/kdesktopbindings.cpp @@ -0,0 +1,54 @@ +#ifndef NOSLOTS +# define DEF( name, key3, key4, fnSlot ) \ + keys->insert( name, i18n(name), TQString(), key3, key4, TQT_TQOBJECT(this), TQT_SLOT(fnSlot) ) +# define DEF2( name, key3, key4, receiver, slot ) \ + keys->insert( name, i18n(name), TQString(), key3, key4, receiver, slot ); +#else +# define DEF( name, key3, key4, fnSlot ) \ + keys->insert( name, i18n(name), TQString(), key3, key4 ) +# define DEF2( name, key3, key4, receiver, slot ) \ + keys->insert( name, i18n(name), TQString(), key3, key4 ) +#endif +#define WIN KKey::QtWIN + + keys->insert( "Program:kdesktop", i18n("Desktop") ); + +#ifndef NOSLOTS + if (kapp->authorize("run_command")) + { +#endif + DEF( I18N_NOOP("Run Command"), ALT+Qt::Key_F2, WIN+Qt::Key_Return, slotExecuteCommand() ); +#ifndef NOSLOTS + } +#endif + DEF( I18N_NOOP("Show Taskmanager"), CTRL+Qt::Key_Escape, WIN+CTRL+Qt::Key_Pause, slotShowTaskManager() ); + DEF( I18N_NOOP("Show Window List"), ALT+Qt::Key_F5, WIN+Qt::Key_0, slotShowWindowList() ); + DEF( I18N_NOOP("Switch User"), ALT+CTRL+Qt::Key_Insert, WIN+Qt::Key_Insert, slotSwitchUser() ); +#ifndef NOSLOTS + if (kapp->authorize("lock_screen")) + { +#endif + DEF2( I18N_NOOP("Lock Session"), ALT+CTRL+Qt::Key_L, WIN+Qt::Key_ScrollLock, KRootWm::self(), TQT_SLOT(slotLock()) ); + DEF2( I18N_NOOP("Lock Session (Hotkey)"), TDEShortcut(TQString("XF86ScreenSaver")), TDEShortcut(TQString("XF86ScreenSaver")), KRootWm::self(), TQT_SLOT(slotLock()) ); +#ifndef NOSLOTS + } + if (kapp->authorize("start_screensaver")) + { +#endif + DEF2( I18N_NOOP("Start Screen Saver"), ALT+CTRL+Qt::Key_S, WIN+Qt::Key_S, KRootWm::self(), TQT_SLOT(slotSave()) ); +#ifndef NOSLOTS + } + if (kapp->authorize("logout")) + { +#endif + DEF( I18N_NOOP("Log Out"), ALT+CTRL+Qt::Key_Delete, WIN+Qt::Key_Escape, slotLogout() ); + DEF( I18N_NOOP("Log Out Without Confirmation"), ALT+CTRL+SHIFT+Qt::Key_Delete, WIN+SHIFT+Qt::Key_Escape, slotLogoutNoCnf() ); + DEF( I18N_NOOP("Halt without Confirmation"), ALT+CTRL+SHIFT+Qt::Key_PageDown, WIN+CTRL+SHIFT+Qt::Key_PageDown, slotHaltNoCnf() ); + DEF( I18N_NOOP("Reboot without Confirmation"), ALT+CTRL+SHIFT+Qt::Key_PageUp, WIN+CTRL+SHIFT+Qt::Key_PageUp, slotRebootNoCnf() ); +#ifndef NOSLOTS + } +#endif + +#undef DEF +#undef DEF2 +#undef WIN diff --git a/kdesktop/kdesktopsettings.kcfgc b/kdesktop/kdesktopsettings.kcfgc new file mode 100644 index 000000000..f3577d133 --- /dev/null +++ b/kdesktop/kdesktopsettings.kcfgc @@ -0,0 +1,4 @@ +File=kdesktop.kcfg +ClassName=KDesktopSettings +Singleton=true +Mutators=true diff --git a/kdesktop/kdesktopshadowsettings.cpp b/kdesktop/kdesktopshadowsettings.cpp new file mode 100644 index 000000000..2d483840c --- /dev/null +++ b/kdesktop/kdesktopshadowsettings.cpp @@ -0,0 +1,93 @@ +/* This file is proposed to be part of the KDE base. + * Copyright (C) 2003 Laur Ivan <[email protected]> + * + * Many thanks to: + * - Bernardo Hung <[email protected]> for the enhanced shadow + * algorithm (currently used) + * - Tim Jansen <[email protected]> for the API updates and fixes. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <tqcolor.h> +#include <kdebug.h> +#include "kdesktopshadowsettings.h" + + +//#define DEBUG + +KDesktopShadowSettings::KDesktopShadowSettings(TDEConfig *cfg) : + KShadowSettings(), + m_textColor(TQColor("#FFFFFF")), + _UID(0L) +{ + setConfig(cfg); +} + +KDesktopShadowSettings::~KDesktopShadowSettings() +{ +} + +/** + * + */ +void KDesktopShadowSettings::setUID(unsigned long val) +{ + if (val == 0L || val == _UID) + _UID++; + else + _UID = val; +} + +unsigned long KDesktopShadowSettings::UID() +{ + return _UID; +} + +/** + * Loads a new configuration + */ +void KDesktopShadowSettings::setConfig(TDEConfig *val) +{ + config = val; + + if (val == NULL) + return; + + // increment the UID so the items will rebuild their + // pixmaps + setUID(); + + config->setGroup("FMSettings"); + TQColor textWhiteColor("#FFFFFF"); + m_textColor = config->readColorEntry("NormalTextColor", &textWhiteColor); + m_bgColor = config->readColorEntry("ItemTextBackground"); + m_isEnabled = config->readBoolEntry("ShadowEnabled", true); + +#ifdef DEBUG + // debug + kdDebug(1204) << "setConfig()" << endl; +#endif + + if (config->hasKey(SHADOW_CONFIG_ENTRY)) + fromString(config->readEntry(SHADOW_CONFIG_ENTRY)); + +#ifdef DEBUG + // debug + kdDebug(1204) << " \t" << SHADOW_TEXT_COLOR << "=" << m_textColor << endl; + kdDebug(1204) << " \t" << SHADOW_TEXT_BACKGROUND << "=" << m_bgColor << endl; + kdDebug(1204) << " \t" << toString() << endl; +#endif +} diff --git a/kdesktop/kdesktopshadowsettings.h b/kdesktop/kdesktopshadowsettings.h new file mode 100644 index 000000000..c7e73db71 --- /dev/null +++ b/kdesktop/kdesktopshadowsettings.h @@ -0,0 +1,117 @@ +/* This file is proposed to be part of the KDE base. + * Copyright (C) 2003 Laur Ivan <[email protected]> + * + * Many thanks to: + * - Bernardo Hung <[email protected]> for the enhanced shadow + * algorithm (currently used) + * - Tim Jansen <[email protected]> for the API updates and fixes. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef __FX_DATA_DESKTOP +#define __FX_DATA_DESKTOP + +#include <tqcolor.h> +#include <kstandarddirs.h> +#include <tdeconfig.h> + +#include <kshadowsettings.h> + +#define FX_GROUP "FX" + +#define ALGO_KEY "Shadow.Algorithm" +#define MULT_KEY "Shadow.MultiplicationFactor" +#define OPAC_KEY "Shadow.MaxOpacity" +#define OFSX_KEY "Shadow.OffsetX" +#define OFSY_KEY "Shadow.OffsetY" +#define THIK_KEY "Shadow.Thickness" +#define SELT_KEY "Shadow.SelectionType" + +/** + * This implementation of FxData will read a the default configuration + * file. The values used for shadow are frouped under "FX". + * + * The values are: + * Shadow.Algorithm: the algorithm used for making the sahdow + * Shadow.Scale the normailsation factor for veraging the sum + * Shadow.MaxOpacity the maximum allowable opacity (255 = 100%opaque) + * Shadow.OffsetX the X-coordinate offset (0 centered) + * Shadow.OffsetY the Y-coordinate offset (0 centered) + * Shadow.Thickness the shadow thickness (usually 3-5 px) + * Shadow.SelectionType the selection type - inverse video or use + * the selection colours. + * + * 06-Feb-03: Added simple UID algorithm + * + */ +class KDesktopShadowSettings : public KShadowSettings +{ + public: + /** + * Constructor + * @param cfg the configuration file + */ + KDesktopShadowSettings(TDEConfig *cfg = NULL); + + virtual ~KDesktopShadowSettings(); + + /** + * Sets a specific configuration file after the object's creation + * @param config new configuration object + */ + void setConfig(TDEConfig *); + + /** + * Returns the text color as definied in the configuraiton + * @return the text color as definied in the configuraiton + */ + TQColor &textColor(){ return m_textColor; }; + + /** + * Returns the shadow color as definied in the configuraiton + * @return the shadow color as definied in the configuraiton + */ + TQColor &bgColor() { return m_bgColor; }; + + /** + * Returns true if the shadow engine is enabled. + * @return true if the shadow engine is enabled. + */ + bool isEnabled() { return m_isEnabled; }; + + /** + * Returns an UID for shadow rebuilding purposes + * @return an UID for shadow rebuilding purposes + */ + unsigned long UID(); + + /** + * (Re)sets an UID for shadow rebuilding purposes + * @param the new UID (if 0/default, increments the stored UID) + */ + void setUID(unsigned long val = 0L); + + private: + TDEConfig *config; + TQColor m_textColor; + TQColor m_bgColor; + bool m_isEnabled; + + // uid of the object. Use this to determine the oportunity of a new + // rebuild. + unsigned long _UID; +}; + +#endif diff --git a/kdesktop/kdiconview.cc b/kdesktop/kdiconview.cc new file mode 100644 index 000000000..948ea511c --- /dev/null +++ b/kdesktop/kdiconview.cc @@ -0,0 +1,2092 @@ +/* This file is part of the TDE project + Copyright (C) 1998, 1999 Torben Weis <[email protected]> + Copyright (C) 2000, 2001 David Faure <[email protected]> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License version 2 as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kdiconview.h" +#include "krootwm.h" +#include "desktop.h" +#include "kdesktopsettings.h" + +#include <tdeio/paste.h> +#include <tdeaccel.h> +#include <tdeapplication.h> +#include <kcolordrag.h> +#include <kdebug.h> +#include <kdesktopfile.h> +#include <kdirlister.h> +#include <tdeglobalsettings.h> +#include <kpropertiesdialog.h> +#include <tdelocale.h> +#include <konqbookmarkmanager.h> +#include <konq_defaults.h> +#include <konq_drag.h> +#include <konq_operations.h> +#include <konq_popupmenu.h> +#include <konq_settings.h> +#include <konq_undo.h> +#include <kivfreespaceoverlay.h> +#include <kprotocolinfo.h> +#include <kstdaction.h> +#include <kstandarddirs.h> +#include <kurldrag.h> +#include <twin.h> +#include <twinmodule.h> + +#include <fixx11h.h> + +#include <tqclipboard.h> +#include <tqdir.h> +#include <tqevent.h> +#include <tqregexp.h> + +#include <unistd.h> + +#include "kshadowengine.h" +#include "kdesktopshadowsettings.h" +#include "tdefileividesktop.h" + +// for multihead +extern int kdesktop_screen_number; + +// ----------------------------------------------------------------------------- + +TQRect KDIconView::desktopRect() +{ + return ( kdesktop_screen_number == 0 ) + ? TQApplication::desktop()->geometry() // simple case, or xinerama + : TQApplication::desktop()->screenGeometry( kdesktop_screen_number ); // multi-head +} + +// ----------------------------------------------------------------------------- + +void KDIconView::saveIconPosition(KSimpleConfig *config, int x, int y) +{ + // save the icon position in absolute coordinates + config->writeEntry("Xabs", x); + config->writeEntry("Yabs", y); + + // save also mentioning desktop size + TQRect desk = desktopRect(); + TQString sizeStr = TQString( "_%1x%2" ).arg(desk.width()).arg(desk.height()); + + config->writeEntry("Xabs" + sizeStr, x); + config->writeEntry("Yabs" + sizeStr, y); +} + +// ----------------------------------------------------------------------------- + +void KDIconView::readIconPosition(KSimpleConfig *config, int &x, int &y) +{ + // check if we have the position for the current desktop size + TQRect desk = desktopRect(); + TQString sizeStr = TQString( "_%1x%2" ).arg(desk.width()).arg(desk.height()); + + x = config->readNumEntry("Xabs" + sizeStr, -99999); + + if ( x != -99999 ) + y = config->readNumEntry("Yabs" + sizeStr); + else + { + // not found; use the resolution independent position + x = config->readNumEntry("Xabs", -99999); + + if ( x != -99999 ) + y = config->readNumEntry("Yabs"); + else // for compatibility, read the old iconArea-relative-position + { + // problem here: when reading a position before we know the correct + // desktopIconsArea, the relative position do not make sense + // workaround: use desktopRect() as the allowed size + + TQRect desk = desktopRect(); + TQString X_w = TQString("X %1").arg(desk.width() ); + TQString Y_h = TQString("Y %1").arg(desk.height()); + + x = config->readNumEntry(X_w, -99999); + if ( x != -99999 ) x = config->readNumEntry("X"); + if ( x < 0 ) x += desk.width(); + + y = config->readNumEntry(Y_h, -99999); + if ( y != -99999 ) y = config->readNumEntry("Y"); + if ( y < 0 ) y += desk.height(); + } + } +} + +// ----------------------------------------------------------------------------- + +KDIconView::KDIconView( TQWidget *parent, const char* name ) + : KonqIconViewWidget( parent, name, (WFlags)WResizeNoErase, true ), + m_actionCollection( this, "KDIconView::m_actionCollection" ), + m_accel( 0L ), + m_bNeedRepaint( false ), + m_bNeedSave( false ), + m_autoAlign( false ), + m_hasExistingPos( false ), + m_bEditableDesktopIcons( kapp->authorize("editable_desktop_icons") ), + m_bShowDot( false ), + m_bVertAlign( true ), + m_dirLister( 0L ), + m_mergeDirs(), + m_dotDirectory( 0L ), + m_lastDeletedIconPos(), + m_eSortCriterion( NameCaseInsensitive ), + m_bSortDirectoriesFirst( true ), + m_itemsAlwaysFirst(), + m_enableMedia(false), + m_gotIconsArea(false), + m_needDesktopAlign(true), + m_paOutstandingFreeSpaceOverlaysTimer( 0L ) +{ + setResizeMode( Fixed ); + setIconArea( desktopRect() ); // the default is the whole desktop + + // Initialise the shadow data objects... + m_shadowEngine = new KShadowEngine(new KDesktopShadowSettings(TDEGlobal::config())); + + // Initialize media handler + mMediaListView = new TQListView(); + + connect( TQApplication::clipboard(), TQT_SIGNAL(dataChanged()), this, TQT_SLOT(slotClipboardDataChanged()) ); + + setURL( desktopURL() ); // sets m_url + + m_desktopDirs = TDEGlobal::dirs()->findDirs( "appdata", "Desktop" ); + initDotDirectories(); + + connect( this, TQT_SIGNAL( executed( TQIconViewItem * ) ), + TQT_SLOT( slotExecuted( TQIconViewItem * ) ) ); + connect( this, TQT_SIGNAL( returnPressed( TQIconViewItem * ) ), + TQT_SLOT( slotReturnPressed( TQIconViewItem * ) ) ); + connect( this, TQT_SIGNAL( mouseButtonPressed(int, TQIconViewItem*, const TQPoint&)), + TQT_SLOT( slotMouseButtonPressed(int, TQIconViewItem*, const TQPoint&)) ); + connect( this, TQT_SIGNAL( mouseButtonClicked(int, TQIconViewItem*, const TQPoint&)), + TQT_SLOT( slotMouseButtonClickedKDesktop(int, TQIconViewItem*, const TQPoint&)) ); + connect( this, TQT_SIGNAL( contextMenuRequested(TQIconViewItem*, const TQPoint&)), + TQT_SLOT( slotContextMenuRequested(TQIconViewItem*, const TQPoint&)) ); + + connect( this, TQT_SIGNAL( enableAction( const char * , bool ) ), + TQT_SLOT( slotEnableAction( const char * , bool ) ) ); + + // Hack: KonqIconViewWidget::slotItemRenamed is not virtual :-( + disconnect( this, TQT_SIGNAL(itemRenamed(TQIconViewItem *, const TQString &)), + this, TQT_SLOT(slotItemRenamed(TQIconViewItem *, const TQString &)) ); + connect( this, TQT_SIGNAL(itemRenamed(TQIconViewItem *, const TQString &)), + this, TQT_SLOT(slotItemRenamed(TQIconViewItem *, const TQString &)) ); + + if (!m_bEditableDesktopIcons) + { + setItemsMovable(false); + setAcceptDrops(false); + viewport()->setAcceptDrops(false); + } +} + +KDIconView::~KDIconView() +{ + if (m_dotDirectory && !m_bEditableDesktopIcons) { + m_dotDirectory->rollback(false); // Don't save positions + } + + delete m_dotDirectory; + delete m_dirLister; + delete m_shadowEngine; +} + +void KDIconView::initDotDirectories() +{ + TQStringList dirs = m_desktopDirs; + KURL u = desktopURL(); + if (u.isLocalFile()) { + dirs.prepend(u.path()); + } + + TQString prefix = iconPositionGroupPrefix(); + TQString dotFileName = locateLocal("appdata", "IconPositions"); + if (kdesktop_screen_number != 0) { + dotFileName += "_Desktop" + TQString::number(kdesktop_screen_number); + } + + if (m_dotDirectory && !m_bEditableDesktopIcons) { + m_dotDirectory->rollback(false); // Don't save positions + } + + delete m_dotDirectory; + + m_dotDirectory = new KSimpleConfig( dotFileName ); + // If we don't allow editable desktop icons, empty m_dotDirectory + if (!m_bEditableDesktopIcons) + { + TQStringList groups = m_dotDirectory->groupList(); + TQStringList::ConstIterator gIt = groups.begin(); + TQStringList::ConstIterator gEnd = groups.end(); + for (; gIt != gEnd; ++gIt ) + { + m_dotDirectory->deleteGroup(*gIt, true); + } + } + TQRect desk = desktopRect(); + TQString X_w = TQString( "X %1" ).arg( desk.width() ); + TQString Y_h = TQString( "Y %1" ).arg( desk.height() ); + for ( TQStringList::ConstIterator it = dirs.begin() ; it != dirs.end() ; ++it ) + { + kdDebug(1204) << "KDIconView::initDotDirectories found dir " << *it << endl; + TQString localDotFileName = *it + "/.directory"; + + if (TQFile::exists(localDotFileName)) + { + KSimpleConfig dotDir(localDotFileName, true); // Read only + + TQStringList groups = dotDir.groupList(); + TQStringList::ConstIterator gIt = groups.begin(); + TQStringList::ConstIterator gEnd = groups.end(); + for (; gIt != gEnd; ++gIt ) + { + if ( (*gIt).startsWith(prefix) ) + { + dotDir.setGroup( *gIt ); + m_dotDirectory->setGroup( *gIt ); + + if (!m_dotDirectory->hasKey( X_w )) + { + int x,y; + readIconPosition(&dotDir, x, y); + m_dotDirectory->writeEntry( X_w, x ); + m_dotDirectory->writeEntry( Y_h, y ); // Not persistent! + } + } + } + } + } +} + +void KDIconView::initConfig( bool init ) +{ + //kdDebug() << "initConfig " << init << endl; + + if ( !init ) { + KonqFMSettings::reparseConfiguration(); + KDesktopSettings::self()->readConfig(); + } + + TDEConfig * config = TDEGlobal::config(); + + if ( !init ) { + KDesktopShadowSettings *shadowSettings = static_cast<KDesktopShadowSettings *>(m_shadowEngine->shadowSettings()); + shadowSettings->setConfig(config); + } + + setMaySetWallpaper(!config->isImmutable() && !TDEGlobal::dirs()->isRestrictedResource("wallpaper")); + m_bShowDot = KDesktopSettings::showHidden(); + m_bVertAlign = KDesktopSettings::vertAlign(); + TQStringList oldPreview = previewSettings(); + setPreviewSettings( KDesktopSettings::preview() ); + + // read arrange configuration + m_eSortCriterion = (SortCriterion)KDesktopSettings::sortCriterion(); + m_bSortDirectoriesFirst = KDesktopSettings::directoriesFirst(); + m_itemsAlwaysFirst = KDesktopSettings::alwaysFirstItems(); // Distributor plug-in + + if (KProtocolInfo::isKnownProtocol(TQString::fromLatin1("media"))) { + m_enableMedia=KDesktopSettings::mediaEnabled(); + } + else { + m_enableMedia=false; + } + TQString tmpList=KDesktopSettings::exclude(); + kdDebug(1204)<<"m_excludeList"<<tmpList<<endl; + m_excludedMedia=TQStringList::split(",",tmpList,false); + kdDebug(1204)<<" m_excludeList / item count:" <<m_excludedMedia.count()<<endl; + if ( m_dirLister ) // only when called while running - not on first startup + { + configureMedia(); + m_dirLister->setShowingDotFiles( m_bShowDot ); + m_dirLister->emitChanges(); + } + slotFreeSpaceOverlaySettingChanged(); + + setArrangement(m_bVertAlign ? TopToBottom : LeftToRight); + + if ( KonqIconViewWidget::initConfig( init ) ) + lineupIcons(); // called if the font changed. + + setAutoArrange( false ); + + if ( previewSettings().count() ) + { + for ( TQStringList::ConstIterator it = oldPreview.begin(); it != oldPreview.end(); ++it) + if ( !previewSettings().contains( *it ) ){ + kdDebug(1204) << "Disabling preview for " << *it << endl; + if ( *it == "audio/" ) + disableSoundPreviews(); + else + { + KService::Ptr serv = KService::serviceByDesktopName( *it ); + Q_ASSERT( serv != 0L ); + if ( serv ) + { + setIcons( iconSize( ), serv->property("MimeTypes").toStringList() /* revert no-longer wanted previews to icons */ ); + } + } + } + startImagePreview( TQStringList(), true ); + } + else + { + stopImagePreview(); + setIcons( iconSize(), "*" /* stopImagePreview */ ); + } + + if ( !init ) + updateContents(); +} + +void KDIconView::start() +{ + // We can only start once + Q_ASSERT(!m_dirLister); + if (m_dirLister) { + return; + } + + kdDebug(1204) << "KDIconView::start" << endl; + + // Create the directory lister + m_dirLister = new KDirLister(); + + m_bNeedSave = false; + + connect( m_dirLister, TQT_SIGNAL( clear() ), this, TQT_SLOT( slotClear() ) ); + connect( m_dirLister, TQT_SIGNAL( started(const KURL&) ), this, TQT_SLOT( slotStarted(const KURL&) ) ); + connect( m_dirLister, TQT_SIGNAL( completed() ), this, TQT_SLOT( slotCompleted() ) ); + connect( m_dirLister, TQT_SIGNAL( newItems( const KFileItemList & ) ), this, TQT_SLOT( slotNewItems( const KFileItemList & ) ) ); + connect( m_dirLister, TQT_SIGNAL( deleteItem( KFileItem * ) ), this, TQT_SLOT( slotDeleteItem( KFileItem * ) ) ); + connect( m_dirLister, TQT_SIGNAL( refreshItems( const KFileItemList & ) ), this, TQT_SLOT( slotRefreshItems( const KFileItemList & ) ) ); + + // Start the directory lister ! + m_dirLister->setShowingDotFiles( m_bShowDot ); + kapp->allowURLAction("list", KURL(), url()); + startDirLister(); + createActions(); +} + +void KDIconView::configureMedia() +{ + kdDebug(1204) << "***********KDIconView::configureMedia() " <<endl; + m_dirLister->setMimeExcludeFilter(m_excludedMedia); + m_dirLister->emitChanges(); + updateContents(); + if (m_enableMedia) { + for (KURL::List::Iterator it1=m_mergeDirs.begin();it1!=m_mergeDirs.end();++it1) { + if ((*it1).url()=="media:/") { + return; + } + } + m_mergeDirs.append(KURL("media:/")); + m_dirLister->openURL(KURL("media:/"), true); + } + else { + for (KURL::List::Iterator it2=m_mergeDirs.begin();it2!=m_mergeDirs.end();++it2) { + if ((*it2).url()=="media:/") { + delete m_dirLister; + m_dirLister=0; + start(); + if (m_mergeDirs.contains(*it2)) { + m_mergeDirs.remove(*it2); + m_dirLister->stop("media"); + } + return; + } + } + return; + } +} + +void KDIconView::createActions() +{ + if (m_bEditableDesktopIcons) + { + TDEAction *undo = KStdAction::undo( KonqUndoManager::self(), TQT_SLOT( undo() ), &m_actionCollection, "undo" ); + connect( KonqUndoManager::self(), TQT_SIGNAL( undoAvailable( bool ) ), + undo, TQT_SLOT( setEnabled( bool ) ) ); + connect( KonqUndoManager::self(), TQT_SIGNAL( undoTextChanged( const TQString & ) ), + undo, TQT_SLOT( setText( const TQString & ) ) ); + undo->setEnabled( KonqUndoManager::self()->undoAvailable() ); + + TDEAction* paCut = KStdAction::cut( TQT_TQOBJECT(this), TQT_SLOT( slotCut() ), &m_actionCollection, "cut" ); + TDEShortcut cutShortCut = paCut->shortcut(); + cutShortCut.remove( KKey( SHIFT + Key_Delete ) ); // used for deleting files + paCut->setShortcut( cutShortCut ); + + KStdAction::copy( TQT_TQOBJECT(this), TQT_SLOT( slotCopy() ), &m_actionCollection, "copy" ); + KStdAction::paste( TQT_TQOBJECT(this), TQT_SLOT( slotPaste() ), &m_actionCollection, "paste" ); + TDEAction *pasteTo = KStdAction::paste( TQT_TQOBJECT(this), TQT_SLOT( slotPopupPasteTo() ), &m_actionCollection, "pasteto" ); + pasteTo->setEnabled( false ); // only enabled during popupMenu() + + TDEShortcut reloadShortcut = TDEStdAccel::shortcut(TDEStdAccel::Reload); + new TDEAction( i18n( "&Reload" ), "reload", reloadShortcut, TQT_TQOBJECT(this), TQT_SLOT( refreshIcons() ), &m_actionCollection, "reload" ); + + (void) new TDEAction( i18n( "&Rename" ), /*"editrename",*/ Key_F2, TQT_TQOBJECT(this), TQT_SLOT( renameSelectedItem() ), &m_actionCollection, "rename" ); + (void) new TDEAction( i18n( "&Properties" ), ALT+Key_Return, TQT_TQOBJECT(this), TQT_SLOT( slotProperties() ), &m_actionCollection, "properties" ); + TDEAction* trash = new TDEAction( i18n( "&Move to Trash" ), "edittrash", Key_Delete, &m_actionCollection, "trash" ); + connect( trash, TQT_SIGNAL( activated( TDEAction::ActivationReason, TQt::ButtonState ) ), + this, TQT_SLOT( slotTrashActivated( TDEAction::ActivationReason, TQt::ButtonState ) ) ); + + TDEConfig config("kdeglobals", true, false); + config.setGroup( "KDE" ); + (void) new TDEAction( i18n( "&Delete" ), "editdelete", SHIFT+Key_Delete, TQT_TQOBJECT(this), TQT_SLOT( slotDelete() ), &m_actionCollection, "del" ); + + // Initial state of the actions (cut/copy/paste/...) + slotSelectionChanged(); + //init paste action + slotClipboardDataChanged(); + } +} + +void KDIconView::rearrangeIcons( SortCriterion sc, bool bSortDirectoriesFirst ) +{ + m_eSortCriterion = sc; + m_bSortDirectoriesFirst = bSortDirectoriesFirst; + rearrangeIcons(); +} + +void KDIconView::rearrangeIcons() +{ + setupSortKeys(); + sort(); // calls arrangeItemsInGrid() which does not honor iconArea() + + if ( m_autoAlign ) + lineupIcons( m_bVertAlign ? TQIconView::TopToBottom : TQIconView::LeftToRight ); // also saves position + else + { + KonqIconViewWidget::lineupIcons(m_bVertAlign ? TQIconView::TopToBottom : TQIconView::LeftToRight); + saveIconPositions(); + } +} + +void KDIconView::lineupIcons() +{ + if ( !m_gotIconsArea ) return; + KonqIconViewWidget::lineupIcons(); + saveIconPositions(); +} + +void KDIconView::setAutoAlign( bool b ) +{ + m_autoAlign = b; + + // Auto line-up icons + if ( b ) { + // set maxItemWidth to ensure sane initial icon layout before the auto align code is fully activated + int sz = iconSize() ? iconSize() : TDEGlobal::iconLoader()->currentSize( TDEIcon::Desktop ); + setMaxItemWidth( TQMAX( TQMAX( sz, previewIconSize( iconSize() ) ), KonqFMSettings::settings()->iconTextWidth() ) ); + setFont( font() ); // Force calcRect() + + if (!KRootWm::self()->startup) { + lineupIcons(); + } + else { + KRootWm::self()->startup = false; + } + connect( this, TQT_SIGNAL( iconMoved() ), + this, TQT_SLOT( lineupIcons() ) ); + } + else { + // change maxItemWidth, because when grid-align was active, it changed this for the grid + int sz = iconSize() ? iconSize() : TDEGlobal::iconLoader()->currentSize( TDEIcon::Desktop ); + setMaxItemWidth( TQMAX( TQMAX( sz, previewIconSize( iconSize() ) ), KonqFMSettings::settings()->iconTextWidth() ) ); + setFont( font() ); // Force calcRect() + + disconnect( this, TQT_SIGNAL( iconMoved() ), + this, TQT_SLOT( lineupIcons() ) ); + } +} + +void KDIconView::startDirLister() +{ + // if desktop is resized before start() is called (XRandr) + if (!m_dirLister) return; + + m_dirLister->openURL( url() ); + + // Gather the list of directories to merge into the desktop + // (the main URL is desktopURL(), no need for it in the m_mergeDirs list) + m_mergeDirs.clear(); + for ( TQStringList::ConstIterator it = m_desktopDirs.begin() ; it != m_desktopDirs.end() ; ++it ) + { + kdDebug(1204) << "KDIconView::desktopResized found merge dir " << *it << endl; + KURL u; + u.setPath( *it ); + m_mergeDirs.append( u ); + // And start listing this dir right now + kapp->allowURLAction("list", KURL(), u); + m_dirLister->openURL( u, true ); + } + configureMedia(); +} + +void KDIconView::lineupIcons(TQIconView::Arrangement align) +{ + m_bVertAlign = ( align == TQIconView::TopToBottom ); + setArrangement( m_bVertAlign ? TopToBottom : LeftToRight ); + + if ( m_autoAlign ) + { + KonqIconViewWidget::lineupIcons( align ); + saveIconPositions(); + } + else + rearrangeIcons(); // also saves the position + + KDesktopSettings::setVertAlign( m_bVertAlign ); + KDesktopSettings::writeConfig(); +} + +// Only used for DCOP +TQStringList KDIconView::selectedURLs() +{ + TQStringList seq; + + TQIconViewItem *it = firstItem(); + for (; it; it = it->nextItem() ) + if ( it->isSelected() ) { + KFileItem *fItem = ((KFileIVI *)it)->item(); + seq.append( fItem->url().url() ); // copy the URL + } + + return seq; +} + +void KDIconView::recheckDesktopURL() +{ + // Did someone change the path to the desktop ? + kdDebug(1204) << desktopURL().url() << endl; + kdDebug(1204) << url().url() << endl; + if ( desktopURL() != url() ) + { + kdDebug(1204) << "Desktop path changed from " << url().url() << + " to " << desktopURL().url() << endl; + setURL( desktopURL() ); // sets m_url + initDotDirectories(); + m_dirLister->openURL( url() ); + } +} + +KURL KDIconView::desktopURL() +{ + // Support both paths and URLs + TQString desktopPath = TDEGlobalSettings::desktopPath(); + if (kdesktop_screen_number != 0) { + TQString dn = "Desktop"; + dn += TQString::number(kdesktop_screen_number); + desktopPath.replace("Desktop", dn); + } + + KURL desktopURL; + if (desktopPath[0] == '/') + desktopURL.setPath(desktopPath); + else + desktopURL = desktopPath; + + Q_ASSERT( desktopURL.isValid() ); + if ( !desktopURL.isValid() ) { // should never happen + KURL u; + u.setPath( TQDir::homeDirPath() + "/" + "Desktop" + "/" ); + return u; + } + + return desktopURL; +} + +void KDIconView::contentsMousePressEvent( TQMouseEvent *e ) +{ + if (!m_dirLister) return; + //kdDebug(1204) << "KDIconView::contentsMousePressEvent" << endl; + // TQIconView, as of Qt 2.2, doesn't emit mouseButtonPressed for LMB on background + if ( e->button() == Qt::LeftButton && KRootWm::self()->hasLeftButtonMenu() ) + { + TQIconViewItem *item = findItem( e->pos() ); + if ( !item ) + { + // Left click menu + KRootWm::self()->mousePressed( e->globalPos(), e->button() ); + return; + } + } + KonqIconViewWidget::contentsMousePressEvent( e ); +} + +void KDIconView::mousePressEvent( TQMouseEvent *e ) +{ + KRootWm::self()->mousePressed( e->globalPos(), e->button() ); +} + +void KDIconView::wheelEvent( TQWheelEvent* e ) +{ + if (!m_dirLister) return; + //kdDebug(1204) << "KDIconView::wheelEvent" << endl; + + TQIconViewItem *item = findItem( e->pos() ); + if ( !item ) + { + emit wheelRolled( e->delta() ); + return; + } + + KonqIconViewWidget::wheelEvent( e ); +} + +void KDIconView::slotProperties() +{ + KFileItemList selectedFiles = selectedFileItems(); + + if( selectedFiles.isEmpty() ) + return; + + (void) new KPropertiesDialog( selectedFiles ); +} + +void KDIconView::slotContextMenuRequested(TQIconViewItem *_item, const TQPoint& _global) +{ + if (_item) + { + ((KFileIVI*)_item)->setSelected( true ); + popupMenu( _global, selectedFileItems() ); + } +} + +void KDIconView::slotMouseButtonPressed(int _button, TQIconViewItem* _item, const TQPoint& _global) +{ + //kdDebug(1204) << "KDIconView::slotMouseButtonPressed" << endl; + if (!m_dirLister) return; + m_lastDeletedIconPos = TQPoint(); // user action -> not renaming an icon + if(!_item) { + KRootWm::self()->mousePressed( _global, _button ); + } +} + +void KDIconView::slotMouseButtonClickedKDesktop(int _button, TQIconViewItem* _item, const TQPoint&) +{ + if (!m_dirLister) return; + //kdDebug(1204) << "KDIconView::slotMouseButtonClickedKDesktop" << endl; + if ( _item && _button == Qt::MidButton ) { + slotExecuted(_item); + } +} + +// ----------------------------------------------------------------------------- + +void KDIconView::slotReturnPressed( TQIconViewItem *item ) +{ + if (item && item->isSelected()) { + slotExecuted(item); + } +} + +// ----------------------------------------------------------------------------- + +void KDIconView::slotExecuted( TQIconViewItem *item ) +{ + kapp->propagateSessionManager(); + m_lastDeletedIconPos = TQPoint(); // user action -> not renaming an icon + if (item) { + visualActivate(item); + ((KFileIVI*)item)->returnPressed(); + } +} + +// ----------------------------------------------------------------------------- + +void KDIconView::slotCut() +{ + cutSelection(); +} + +// ----------------------------------------------------------------------------- + +void KDIconView::slotCopy() +{ + copySelection(); +} + +// ----------------------------------------------------------------------------- + +void KDIconView::slotPaste() +{ + KonqOperations::doPaste(this, url(), KRootWm::self()->desktopMenuPosition()); +} + +void KDIconView::slotPopupPasteTo() +{ + Q_ASSERT( !m_popupURL.isEmpty() ); + if ( !m_popupURL.isEmpty() ) + paste( m_popupURL ); +} + +// These two functions and the following class are all lifted from desktopbehavior_impl.cpp to handle the media icons +class DesktopBehaviorMediaItem : public TQCheckListItem +{ +public: + DesktopBehaviorMediaItem(TQListView *parent, const TQString name, const TQString mimetype, bool on) + : TQCheckListItem(parent, name, CheckBox), + m_mimeType(mimetype){setOn(on);} + + const TQString &mimeType() const { return m_mimeType; } + +private: + TQString m_mimeType; +}; + +void KDIconView::fillMediaListView() +{ + g_pConfig = new TDEConfig("kdesktoprc"); + mMediaListView->hide(); + mMediaListView->clear(); + KMimeType::List mimetypes = KMimeType::allMimeTypes(); + TQValueListIterator<KMimeType::Ptr> it2(mimetypes.begin()); + g_pConfig->setGroup( "Media" ); + TQString excludedMedia=g_pConfig->readEntry("exclude","media/hdd_mounted,media/hdd_unmounted,media/floppy_unmounted,media/cdrom_unmounted,media/floppy5_unmounted"); + for (; it2 != mimetypes.end(); ++it2) { + if ( ((*it2)->name().startsWith("media/")) ) + { + bool ok=excludedMedia.contains((*it2)->name())==0; + new DesktopBehaviorMediaItem (mMediaListView, (*it2)->comment(), (*it2)->name(),ok); + } + } + delete g_pConfig; +} + +void KDIconView::saveMediaListView() +{ + g_pConfig = new TDEConfig("kdesktoprc"); + g_pConfig->setGroup( "Media" ); + TQStringList exclude; + for (DesktopBehaviorMediaItem *it=static_cast<DesktopBehaviorMediaItem *>(mMediaListView->firstChild()); + it; it=static_cast<DesktopBehaviorMediaItem *>(it->nextSibling())) + { + if (!it->isOn()) exclude << it->mimeType(); + } + g_pConfig->writeEntry("exclude",exclude); + g_pConfig->sync(); + + // Reload kdesktop configuration to apply changes + TQByteArray data; + int konq_screen_number = TDEApplication::desktop()->primaryScreen(); + TQCString appname; + if (konq_screen_number == 0) + appname = "kdesktop"; + else + appname.sprintf("kdesktop-screen-%d", konq_screen_number); + kapp->dcopClient()->send( appname, "KDesktopIface", "configure()", data ); + delete g_pConfig; +} + +void KDIconView::removeBuiltinIcon(TQString iconName) +{ + DesktopBehaviorMediaItem *changeItem; + fillMediaListView(); + changeItem = static_cast<DesktopBehaviorMediaItem *>(mMediaListView->findItem(iconName, 0)); + if (changeItem != 0) { + changeItem->setOn(false); + } + saveMediaListView(); + KMessageBox::information(0, i18n("You have chosen to remove a system icon") + TQString(".\n") + i18n("You can restore this icon in the future through the") + TQString(" \"") + ("Device Icons") + TQString("\" ") + i18n("tab in the") + TQString(" \"") + i18n("Behavior") + TQString("\" ") + i18n("pane of the Desktop Settings control module."), "System Icon Removed", "sysiconremovedwarning"); +} + +/** + * The files on the desktop come from a variety of sources. + * If an attempt is made to delete a .desktop file that does + * not originate from the users own Desktop directory then + * a .desktop file with "Hidden=true" is written to the users + * own Desktop directory to hide the file. + * + * Returns true if all selected items have been deleted. + * Returns false if there are selected items remaining that + * still need to be deleted in a regular fashion. + */ +bool KDIconView::deleteGlobalDesktopFiles() +{ + KURL desktop_URL = desktopURL(); + if (!desktop_URL.isLocalFile()) + return false; // Dunno how to do this. + + TQString desktopPath = desktop_URL.path(); + + bool itemsLeft = false; + TQIconViewItem *it = 0; + TQIconViewItem *nextIt = firstItem(); + for (; (it = nextIt); ) + { + nextIt = it->nextItem(); + if ( !it->isSelected() ) + continue; + + KFileItem *fItem = ((KFileIVI *)it)->item(); + if (fItem->url().path().startsWith(desktopPath)) + { + itemsLeft = true; + continue; // File is in users own Desktop directory + } + + if (!isDesktopFile(fItem)) + { + itemsLeft = true; + continue; // Not a .desktop file + } + + // Ignore these special files + // Name URL Type OnlyShowIn + // My Documents kxdglauncher --xdgname DOCUMENTS Application TDE; + // My Computer media:/ Link TDE; + // My Network Places remote:/ Link TDE; + // Printers [exec] kjobviewer --all --show %i %m Application TDE; + // Trash trash:/ Link TDE; + // Web Browser kfmclient openBrowser %u Application TDE; + + if ( isDesktopFile(fItem) ) { + KSimpleConfig cfg( fItem->url().path(), true ); + cfg.setDesktopGroup(); + if ( cfg.readEntry( "X-Trinity-BuiltIn" ) == "true" ) { + removeBuiltinIcon(cfg.readEntry( "Name" )); + continue; + } + } + + KDesktopFile df(desktopPath + fItem->url().fileName()); + df.writeEntry("Hidden", true); + df.sync(); + + delete it; + } + return !itemsLeft; +} + +void KDIconView::slotTrashActivated( TDEAction::ActivationReason reason, TQt::ButtonState state ) +{ + if (deleteGlobalDesktopFiles()) + return; // All items deleted + + if ( reason == TDEAction::PopupMenuActivation && ( state & TQt::ShiftButton ) ) + KonqOperations::del(this, KonqOperations::DEL, selectedUrls()); + else + KonqOperations::del(this, KonqOperations::TRASH, selectedUrls()); +} + +void KDIconView::slotDelete() +{ + if (deleteGlobalDesktopFiles()) + return; // All items deleted + KonqOperations::del(this, KonqOperations::DEL, selectedUrls()); +} + +// ----------------------------------------------------------------------------- + +// This method is called when right-clicking over one or more items +// Not to be confused with the global popup-menu, KRootWm, when doing RMB on the desktop +void KDIconView::popupMenu( const TQPoint &_global, const KFileItemList& _items ) +{ + if (!kapp->authorize("action/kdesktop_rmb")) return; + if (!m_dirLister) return; + if ( _items.count() == 1 ) + m_popupURL = _items.getFirst()->url(); + + TDEAction* pasteTo = m_actionCollection.action( "pasteto" ); + if (pasteTo) + pasteTo->setEnabled( m_actionCollection.action( "paste" )->isEnabled() ); + + bool hasMediaFiles = false; + KFileItemListIterator it(_items); + for (; it.current() && !hasMediaFiles; ++it) { + hasMediaFiles = it.current()->url().protocol() == "media"; + } + + KParts::BrowserExtension::PopupFlags itemFlags = KParts::BrowserExtension::DefaultPopupItems; + if ( hasMediaFiles ) + itemFlags |= KParts::BrowserExtension::NoDeletion; + KonqPopupMenu * popupMenu = new KonqPopupMenu( KonqBookmarkManager::self(), _items, + url(), + m_actionCollection, + KRootWm::self()->newMenu(), + this, + KonqPopupMenu::ShowProperties | KonqPopupMenu::ShowNewWindow, + itemFlags ); + + popupMenu->exec( _global ); + delete popupMenu; + m_popupURL = KURL(); + if (pasteTo) + pasteTo->setEnabled( false ); +} + +void KDIconView::slotNewMenuActivated() +{ + //kdDebug(1204) << "KDIconView::slotNewMenuActivated" << endl; + // New / <template> was chosen, a new file is going to appear soon, + // make it appear at the position of the popupmenu. + m_nextItemPos = KRootWm::self()->desktopMenuPosition(); +} + +// ----------------------------------------------------------------------------- + +void KDIconView::slotEnableAction( const char * name, bool enabled ) +{ + //kdDebug(1204) << "slotEnableAction " << name << " enabled=" << enabled << endl; + TQCString sName( name ); + // No such actions here... konqpopupmenu provides them. + if ( sName == "properties" || sName == "editMimeType" ) + return; + + TDEAction * act = m_actionCollection.action( sName.data() ); + if (act) + act->setEnabled( enabled ); +} + +// ----------------------------------------------------------------------------- + +// Straight from kpropsdlg :) +bool KDIconView::isDesktopFile( KFileItem * _item ) const +{ + // only local files + if ( !_item->isLocalFile() ) + return false; + + // only regular files + if ( !S_ISREG( _item->mode() ) ) + return false; + + TQString t( _item->url().path() ); + + // only if readable + if ( access( TQFile::encodeName(t), R_OK ) != 0 ) + return false; + + // return true if desktop file + return ( (_item->mimetype() == TQString::fromLatin1("application/x-desktop")) + || (_item->mimetype() == TQString::fromLatin1("media/builtin-mydocuments")) + || (_item->mimetype() == TQString::fromLatin1("media/builtin-mycomputer")) + || (_item->mimetype() == TQString::fromLatin1("media/builtin-mynetworkplaces")) + || (_item->mimetype() == TQString::fromLatin1("media/builtin-printers")) + || (_item->mimetype() == TQString::fromLatin1("media/builtin-trash")) + || (_item->mimetype() == TQString::fromLatin1("media/builtin-webbrowser")) ); +} + +TQString KDIconView::stripDesktopExtension( const TQString & text ) +{ + if (text.right(7) == TQString::fromLatin1(".kdelnk")) + return text.left(text.length() - 7); + else if (text.right(8) == TQString::fromLatin1(".desktop")) + return text.left(text.length() - 8); + return text; +} + +bool KDIconView::makeFriendlyText( KFileIVI *fileIVI ) +{ + KFileItem *item = fileIVI->item(); + TQString desktopFile; + if ( item->isDir() && item->isLocalFile() ) + { + KURL u( item->url() ); + u.addPath( ".directory" ); + // using TDEStandardDirs as this one checks for path being + // a file instead of a directory + if ( TDEStandardDirs::exists( u.path() ) ) { + desktopFile = u.path(); + } + } + else if ( isDesktopFile( item ) ) + { + desktopFile = item->url().path(); + } + + if ( !desktopFile.isEmpty() ) + { + KSimpleConfig cfg( desktopFile, true ); + cfg.setDesktopGroup(); + if (cfg.readBoolEntry("Hidden")) { + return false; + } + + if (cfg.readBoolEntry( "NoDisplay", false )) { + return false; + } + + TQStringList tmpList; + if (cfg.hasKey("OnlyShowIn")) + { + if (!cfg.readListEntry("OnlyShowIn", ';').contains("TDE")) { + return false; + } + } + if (cfg.hasKey("NotShowIn")) + { + if (cfg.readListEntry("NotShowIn", ';').contains("TDE")) { + return false; + } + } + if (cfg.hasKey("TryExec")) + { + if (TDEStandardDirs::findExe( cfg.readEntry( "TryExec" ) ).isEmpty()) { + return false; + } + } + + TQString name = cfg.readEntry("Name"); + if ( !name.isEmpty() ) { + fileIVI->setText( name ); + } + else { + // For compatibility + fileIVI->setText( stripDesktopExtension( fileIVI->text() ) ); + } + } + + return true; +} + +// ----------------------------------------------------------------------------- + +void KDIconView::slotClear() +{ + clear(); +} + +// ----------------------------------------------------------------------------- + +void KDIconView::slotNewItems( const KFileItemList & entries ) +{ + bool firstRun = (count() == 0); // no icons yet, this seems to be the initial loading + + // delay updates until all new items have been created + setUpdatesEnabled( false ); + TQRect area = iconArea(); + setIconArea( TQRect( 0, 0, -1, -1 ) ); + + TQString desktopPath; + KURL desktop_URL = desktopURL(); + if (desktop_URL.isLocalFile()) { + desktopPath = desktop_URL.path(); + } + // We have new items, so we'll need to repaint in slotCompleted + m_bNeedRepaint = true; + kdDebug(1214) << "KDIconView::slotNewItems count=" << entries.count() << endl; + KFileItemListIterator it(entries); + KFileIVI* fileIVI = 0L; + + typedef TQValueList<KFileIVI*> KFileIVIList; + KFileIVIList newItemsList; + + // Ensure that the saved positions had a chance to be loaded + if (!m_dotDirectory) { + initDotDirectories(); + } + + if (m_nextItemPos.isNull() && !m_dotDirectory) { + // Not found, we'll need to save the new pos + kdDebug(1214)<<"Neither a drop position stored nor m_dotDirectory set"<<endl; + m_dotDirectory = new KSimpleConfig( dotDirectoryPath(), true ); + // recursion + slotNewItems( entries ); + delete m_dotDirectory; + m_dotDirectory = 0; + return; + } + + for (; it.current(); ++it) + { + KURL url = it.current()->url(); + if (!desktopPath.isEmpty() && url.isLocalFile() && !url.path().startsWith(desktopPath)) + { + TQString fileName = url.fileName(); + if (TQFile::exists(desktopPath + fileName)) { + continue; // Don't duplicate entry + } + + TQString mostLocal = locate("appdata", "Desktop/"+fileName); + if (!mostLocal.isEmpty() && (mostLocal != url.path())) { + continue; // Don't duplicate entry + } + } + + // No delayed mimetype determination on the desktop + it.current()->determineMimeType(); + fileIVI = new KFileIVIDesktop( this, it.current(), iconSize(), m_shadowEngine ); + if (!makeFriendlyText( fileIVI )) + { + delete fileIVI; + continue; + } + + kdDebug(1214) << " slotNewItems: " << url.url() << " text: " << fileIVI->text() << endl; + fileIVI->setRenameEnabled( false ); + + if ( !m_nextItemPos.isNull() ) // position remembered from e.g. RMB-popupmenu position, when doing New/... + { + kdDebug(1214) << "slotNewItems : using popupmenu position " << m_nextItemPos.x() << "," << m_nextItemPos.y() << endl; + fileIVI->move( m_nextItemPos.x(), m_nextItemPos.y() ); + m_nextItemPos = TQPoint(); + } + else + { + kdDebug(1214) << "slotNewItems : trying to read position from .directory file"<<endl; + TQString group = iconPositionGroupPrefix(); + TQString filename = url.fileName(); + if ( filename.endsWith(".part") && !m_dotDirectory->hasGroup( group + filename ) ) + filename = filename.left( filename.length() - 5 ); + group.append( filename ); + kdDebug(1214) << "slotNewItems : looking for group " << group << endl; + if ( m_dotDirectory->hasGroup( group ) ) + { + m_dotDirectory->setGroup( group ); + m_hasExistingPos = true; + int x,y; + readIconPosition(m_dotDirectory, x, y); + + kdDebug(1214)<<"slotNewItems() x: "<<x<<" y: "<<y<<endl; + + TQRect oldPos = fileIVI->rect(); + fileIVI->move( x, y ); + if ( (!firstRun) && (!isFreePosition( fileIVI, area )) && (!m_needDesktopAlign) ) // if we can't put it there, then let TQIconView decide + { + if (!isFreePosition( fileIVI, area )) + { + // Find the offending icon and move it out of the way; saved positions have precedence! + TQRect r = fileIVI->rect(); + TQIconViewItem *it = firstItem(); + for (; it; it = it->nextItem() ) + { + if ( !it->rect().isValid() || it == fileIVI ) + { + continue; + } + + if ( it->intersects( r ) ) + { + moveToFreePosition(it, area); + } + } + } + else { + kdDebug(1214)<<"slotNewItems() pos was not free :-("<<endl; + fileIVI->move( oldPos.x(), oldPos.y() ); + m_dotDirectory->deleteGroup( group ); + m_bNeedSave = true; + } + } + else + { + if (!isFreePosition( fileIVI, area )) + { + kdDebug(1214)<<"slotNewItems() pos was not free :-("<<endl; + // Find the offending icon and move it out of the way; saved positions have precedence! + TQRect r = fileIVI->rect(); + TQIconViewItem *it = firstItem(); + for (; it; it = it->nextItem() ) + { + if ( !it->rect().isValid() || it == fileIVI ) + { + continue; + } + + if ( it->intersects( r ) ) + { + moveToFreePosition(it, area); + } + } + } + else + { + kdDebug(1214)<<"Using saved position"<<endl; + } + } + } + else + { + // Not found, we'll need to save the new pos + kdDebug(1214)<<"slotNewItems(): New item without position information, try to find a sane location"<<endl; + newItemsList.append(fileIVI); + } + } + + KFileItem* fileItem = fileIVI->item(); + if ( fileItem->mimetype().startsWith("media/") && KDesktopSettings::mediaFreeSpaceDisplayEnabled() ) { + if (fileItem->mimetype().contains("_mounted")) { + showFreeSpaceOverlay(fileIVI); + } + else { + // If not mounted, hide free space overlay + fileIVI->setShowFreeSpaceOverlay(false); + } + } + } + + KFileIVIList::iterator newitemit; + for ( newitemit = newItemsList.begin(); newitemit != newItemsList.end(); ++newitemit ) + { + fileIVI = (*newitemit); + moveToFreePosition(fileIVI, area); + m_bNeedSave = true; + } + + setIconArea( area ); + + // align on grid + if ( m_autoAlign ) + { + lineupIcons(); + } + + setUpdatesEnabled( true ); +} + +// ----------------------------------------------------------------------------- + +// see also KonqKfmIconView::slotRefreshItems +void KDIconView::slotRefreshItems( const KFileItemList & entries ) +{ + kdDebug(1204) << "KDIconView::slotRefreshItems" << endl; + bool bNeedPreviewJob = false; + KFileItemListIterator rit(entries); + for (; rit.current(); ++rit) + { + bool found = false; + TQIconViewItem *it = firstItem(); + for ( ; it ; it = it->nextItem() ) + { + KFileIVI * fileIVI = static_cast<KFileIVI *>(it); + if ( fileIVI->item() == rit.current() ) // compare the pointers + { + kdDebug(1204) << "KDIconView::slotRefreshItems refreshing icon " << fileIVI->item()->url().url() << endl; + found = true; + fileIVI->setText( rit.current()->text() ); + if (!makeFriendlyText( fileIVI )) + { + delete fileIVI; + break; + } + if ( fileIVI->isThumbnail() ) { + bNeedPreviewJob = true; + fileIVI->invalidateThumbnail(); + } + else + fileIVI->refreshIcon( true ); + if ( rit.current()->isMimeTypeKnown() ) { + fileIVI->setMouseOverAnimation( rit.current()->iconName() ); + } + if ( rit.current()->mimetype().startsWith("media/") && KDesktopSettings::mediaFreeSpaceDisplayEnabled() ) { + if (rit.current()->mimetype().contains("_mounted")) { + showFreeSpaceOverlay(fileIVI); + } + else { + // If not mounted, hide free space overlay + fileIVI->setShowFreeSpaceOverlay(false); + } + } + break; + } + } + if ( !found ) + kdDebug(1204) << "Item not found: " << rit.current()->url().url() << endl; + } + if ( bNeedPreviewJob && previewSettings().count() ) + { + startImagePreview( TQStringList(), false ); + } + else + { + // In case we replace a big icon with a small one, need to repaint. + updateContents(); + // Can't do that with m_bNeedRepaint since slotCompleted isn't called + m_bNeedRepaint = false; + } +} + + +void KDIconView::refreshIcons() +{ + TQIconViewItem *it = firstItem(); + for ( ; it ; it = it->nextItem() ) + { + KFileIVI * fileIVI = static_cast<KFileIVI *>(it); + if (!(fileIVI->item()->mimetype().startsWith("media/"))) { + fileIVI->item()->refresh(); + } + fileIVI->refreshIcon( true ); + makeFriendlyText( fileIVI ); + } + if (m_enableMedia) { + m_dirLister->updateDirectory(KURL("media:/")); + } +} + + +void KDIconView::FilesAdded( const KURL & directory ) +{ + if ( directory.path().length() <= 1 && directory.protocol() == "trash" ) { + refreshTrashIcon(); + } +} + +void KDIconView::FilesRemoved( const KURL::List & fileList ) +{ + if ( !fileList.isEmpty() ) { + const KURL url = fileList.first(); + if ( url.protocol() == "trash" ) { + refreshTrashIcon(); + } + } +} + +void KDIconView::refreshTrashIcon() +{ + TQIconViewItem *it = firstItem(); + for ( ; it ; it = it->nextItem() ) + { + KFileIVI * fileIVI = static_cast<KFileIVI *>(it); + KFileItem* item = fileIVI->item(); + if ( isDesktopFile( item ) ) { + KSimpleConfig cfg( item->url().path(), true ); + cfg.setDesktopGroup(); + if ( cfg.readEntry( "Type" ) == "Link" && + cfg.readEntry( "URL" ) == "trash:/" ) { + fileIVI->refreshIcon( true ); + } + } + } +} + +void KDIconView::slotFreeSpaceOverlaySettingChanged() +{ + bool show = KDesktopSettings::mediaFreeSpaceDisplayEnabled(); + + for ( TQIconViewItem *item = firstItem(); item; item = item->nextItem() ) + { + KFileIVI* kItem = static_cast<KFileIVI*>(item); + if ( !kItem->item()->isDir() ) continue; + + if (show) { + showFreeSpaceOverlay(kItem); + } else { + kItem -> setShowFreeSpaceOverlay(false); + } + } + + updateContents(); +} + +void KDIconView::showFreeSpaceOverlay(KFileIVI* item) +{ + KFileItem* fileItem = item->item(); + + if ( TDEGlobalSettings::showFilePreview( fileItem->url() ) ) { + m_paOutstandingFreeSpaceOverlays.append(item); + if (m_paOutstandingFreeSpaceOverlays.count() == 1) + { + if (!m_paOutstandingFreeSpaceOverlaysTimer) + { + m_paOutstandingFreeSpaceOverlaysTimer = new TQTimer(this); + connect(m_paOutstandingFreeSpaceOverlaysTimer, TQT_SIGNAL(timeout()), TQT_SLOT(slotFreeSpaceOverlayStart())); + } + m_paOutstandingFreeSpaceOverlaysTimer->start(20, true); + } + } +} + +void KDIconView::slotFreeSpaceOverlayStart() +{ + do + { + KFileIVI* item = m_paOutstandingFreeSpaceOverlays.first(); + if (!item) { + return; // Nothing to do + } + + KIVFreeSpaceOverlay* overlay = item->setShowFreeSpaceOverlay( true ); + + if (overlay) + { + connect( overlay, TQT_SIGNAL( finished() ), this, TQT_SLOT( slotFreeSpaceOverlayFinished() ) ); + overlay->start(); // Watch out, may emit finished() immediately!! + return; // Let it run.... + } + m_paOutstandingFreeSpaceOverlays.removeFirst(); + } while (true); +} + +void KDIconView::slotFreeSpaceOverlayFinished() +{ + m_paOutstandingFreeSpaceOverlays.removeFirst(); + + if (m_paOutstandingFreeSpaceOverlays.count() > 0) { + m_paOutstandingFreeSpaceOverlaysTimer->start(0, true); // Don't call directly to prevent deep recursion. + } +} + +// ----------------------------------------------------------------------------- + +void KDIconView::slotDeleteItem( KFileItem * _fileitem ) +{ + kdDebug(1204) << "KDIconView::slotDeleteItems" << endl; + // we need to find out the KFileIVI containing the fileitem + TQIconViewItem *it = firstItem(); + while ( it ) { + KFileIVI * fileIVI = static_cast<KFileIVI *>(it); + if ( fileIVI->item() == _fileitem ) { // compare the pointers + // Delete this item. + //kdDebug(1204) << fileIVI->text() << endl; + + TQString group = iconPositionGroupPrefix(); + group.append( fileIVI->item()->url().fileName() ); + if ( m_dotDirectory->hasGroup( group ) ) { + m_dotDirectory->deleteGroup( group ); + } + + m_lastDeletedIconPos = fileIVI->pos(); + delete fileIVI; + break; + } + it = it->nextItem(); + } + m_bNeedRepaint = true; +} + +// ----------------------------------------------------------------------------- + +void KDIconView::slotStarted( const KURL& _url ) +{ + kdDebug(1204) << "KDIconView::slotStarted url: " << _url.url() << " url().url(): "<<url().url()<<endl; +} + +void KDIconView::slotCompleted() +{ + // Root item ? Store in konqiconviewwidget (used for drops onto the background, for instance) + if ( m_dirLister->rootItem() ) + setRootItem( m_dirLister->rootItem() ); + + if ( previewSettings().count() ) + startImagePreview( TQStringList(), true ); + else + { + stopImagePreview(); + setIcons( iconSize(), "*" /* stopImagePreview */ ); + } + + // during first run need to rearrange all icons so default config settings will be used + kdDebug(1204)<<"slotCompleted() m_hasExistingPos: "<<(m_hasExistingPos?(int)1:(int)0)<<endl; + if (!m_hasExistingPos) + rearrangeIcons(); + +// kdDebug(1204) << "KDIconView::slotCompleted save:" << m_bNeedSave << " repaint:" << m_bNeedRepaint << endl; + if ( m_bNeedSave ) + { + // Done here because we want to align icons only once initially, and each time new icons appear. + // This MUST precede the call to saveIconPositions(). + emit iconMoved(); + saveIconPositions(); + m_hasExistingPos = true; // if we didn't have positions, we have now. + m_bNeedSave = false; + } + if ( m_bNeedRepaint ) + { + viewport()->repaint(); + m_bNeedRepaint = false; + } +} + +void KDIconView::slotClipboardDataChanged() +{ + // This is very related to KonqDirPart::slotClipboardDataChanged + + KURL::List lst; + TQMimeSource *data = TQApplication::clipboard()->data(); + if ( data->provides( "application/x-tde-cutselection" ) && data->provides( "text/uri-list" ) ) + if ( KonqDrag::decodeIsCutSelection( data ) ) + (void) KURLDrag::decode( data, lst ); + + disableIcons( lst ); + + TQString actionText = TDEIO::pasteActionText(); + bool paste = !actionText.isEmpty(); + if ( paste ) { + TDEAction* pasteAction = m_actionCollection.action( "paste" ); + if ( pasteAction ) + pasteAction->setText( actionText ); + } + slotEnableAction( "paste", paste ); +} + +void KDIconView::renameDesktopFile(const TQString &path, const TQString &name) +{ + KDesktopFile cfg( path, false ); + + // if we don't have the desktop entry group, then we assume that + // it's not a config file (and we don't nuke it!) + if ( !cfg.hasGroup( "Desktop Entry" ) ) + return; + + if ( cfg.readName() == name ) + return; + + cfg.writeEntry( "Name", name, true, false, false ); + cfg.writeEntry( "Name", name, true, false, true ); + cfg.sync(); +} + +void KDIconView::slotItemRenamed(TQIconViewItem* _item, const TQString &name) +{ + kdDebug(1204) << "KDIconView::slotItemRenamed(item, \"" << name << "\" )" << endl; + TQString newName(name); + if ( _item) + { + KFileIVI *fileItem = static_cast< KFileIVI* >( _item ); + //save position of item renamed + m_lastDeletedIconPos = fileItem->pos(); + if ( fileItem->item() && !fileItem->item()->isLink() ) + { + TQString desktopFile( fileItem->item()->url().path() ); + if (!desktopFile.isEmpty()) + { + // first and foremost, we make sure that this is a .desktop file + // before we write anything to it + KMimeType::Ptr type = KMimeType::findByURL( fileItem->item()->url() ); + bool bDesktopFile = false; + + if ( (type->name() == "application/x-desktop") + || (type->name() == "media/builtin-mydocuments") + || (type->name() == "media/builtin-mycomputer") + || (type->name() == "media/builtin-mynetworkplaces") + || (type->name() == "media/builtin-printers") + || (type->name() == "media/builtin-trash") + || (type->name() == "media/builtin-webbrowser") ) + { + bDesktopFile = true; + if (!newName.endsWith(".desktop")) { + newName += ".desktop"; + } + } + else if(type->name() == "inode/directory") { + desktopFile += "/.directory"; + bDesktopFile = true; + } + + if (TQFile(desktopFile).exists() && bDesktopFile) + { + renameDesktopFile(desktopFile, name); + return; + } + } + } + } + KonqIconViewWidget::slotItemRenamed(_item, newName); +} + +void KDIconView::slotAboutToCreate(const TQPoint &pos, const TQValueList<TDEIO::CopyInfo> &files) +{ + if (pos.isNull()) + return; + + if (m_dropPos != pos) + { + m_dropPos = pos; + m_lastDropPos = pos; + } + + TQString dir = url().path(-1); // Strip trailing / + + TQValueList<TDEIO::CopyInfo>::ConstIterator it = files.begin(); + int gridX = gridXValue(); + int gridY = 120; // 120 pixels should be enough for everyone (tm) + + for ( ; it!= files.end() ; ++it ) + { + kdDebug(1214) << "KDIconView::saveFuturePosition x=" << m_lastDropPos.x() << " y=" << m_lastDropPos.y() << " filename=" << (*it).uDest.prettyURL() << endl; + if ((*it).uDest.isLocalFile() && ((*it).uDest.directory() == dir)) + { + m_dotDirectory->setGroup( iconPositionGroupPrefix() + (*it).uDest.fileName() ); + saveIconPosition(m_dotDirectory, m_lastDropPos.x(), m_lastDropPos.y()); + int dX = m_lastDropPos.x() - m_dropPos.x(); + int dY = m_lastDropPos.y() - m_dropPos.y(); + if ((QABS(dX) > QABS(dY)) || (m_lastDropPos.x() + 2*gridX > width())) + m_lastDropPos = TQPoint(m_dropPos.x(), m_lastDropPos.y() + gridY); + else + m_lastDropPos = TQPoint(m_lastDropPos.x() + gridX, m_lastDropPos.y()); + } + } + m_dotDirectory->sync(); +} + +// ----------------------------------------------------------------------------- + +void KDIconView::showEvent( TQShowEvent *e ) +{ + //HACK to avoid TQIconView calling arrangeItemsInGrid (Simon) + //EVEN MORE HACK: unfortunately, TQScrollView has no concept of + //TopToBottom, therefore, it always adds LeftToRight. So, if any of + //the icons have a setting, we'll use TQScrollView.. but otherwise, + //we use the iconview + //kdDebug(1204)<<"showEvent() m_hasExistingPos: "<<(m_hasExistingPos?(int)1:(int)0)<<endl; + if (m_hasExistingPos) + TQScrollView::showEvent( e ); + else + TDEIconView::showEvent( e ); +} + +void KDIconView::contentsDropEvent( TQDropEvent * e ) +{ + kdDebug(1204)<<"void KDIconView::contentsDropEvent( TQDropEvent * e )\n"; + // mind: if it's a filedrag which itself is an image, libkonq is called. There's a popup for drops as well + // that contains the same line "Set as Wallpaper" in void KonqOperations::asyncDrop + bool isColorDrag = KColorDrag::canDecode(e); + bool isImageDrag = TQImageDrag::canDecode(e); + bool isUrlDrag = KURLDrag::canDecode(e); + + bool isImmutable = TDEGlobal::config()->isImmutable(); + + if ( (isColorDrag || isImageDrag) && !isUrlDrag ) { + // Hack to clear the drag shape + bool bMovable = itemsMovable(); + bool bSignals = signalsBlocked(); + setItemsMovable(false); + blockSignals(true); + TDEIconView::contentsDropEvent( e ); + blockSignals(bSignals); + setItemsMovable(bMovable); + // End hack + + if ( !isImmutable ) // just ignore event in kiosk-mode + { + if ( isColorDrag) + emit colorDropEvent( e ); + else if (isImageDrag) + emit imageDropEvent( e ); + } + } else { + setLastIconPosition( e->pos() ); + KonqIconViewWidget::contentsDropEvent( e ); + } + + // Check if any items have been moved outside the desktop area. + // If we find any, move them right back in there. (#40418) + TQRect desk = desktopRect(); + bool adjustedAnyItems = false; + for( TQIconViewItem *item = firstItem(); item; item = item->nextItem() ) + { + if( !desk.contains( item->rect(), true )) + { + TQRect r = item->rect(); + + if( r.top() < 0 ) + r.moveTop( 0 ); + if( r.bottom() > rect().bottom() ) + r.moveBottom( rect().bottom() ); + if( r.left() < 0 ) + r.moveLeft( 0 ); + if( r.right() > rect().right() ) + r.moveRight( rect().right() ); + + item->move( r.x(), r.y() ); + adjustedAnyItems = true; + } + } + if( adjustedAnyItems ) + { + // Make sure the viewport isn't unnecessarily resized by now, + // then schedule a repaint to remove any garbage pixels. + resizeContents( width(), height() ); + viewport()->update(); + } + + if (TQIconDrag::canDecode(e)) { + emit iconMoved(); + if ( !m_autoAlign ) // if autoAlign, positions were saved in lineupIcons + saveIconPositions(); + } +} + +// don't scroll when someone uses his nifty mouse wheel +void KDIconView::viewportWheelEvent( TQWheelEvent * e ) +{ + e->accept(); +} + +void KDIconView::updateWorkArea( const TQRect &wr ) +{ + m_gotIconsArea = true; // now we have it! + + if (( iconArea() == wr ) && (m_needDesktopAlign == false)) { + // nothing changed; avoid repaint/saveIconPosition ... + return; + } + + TQRect oldArea = iconArea(); + setIconArea( wr ); + + kdDebug(1204) << "KDIconView::updateWorkArea wr: " << wr.x() << "," << wr.y() << " " << wr.width() << "x" << wr.height() << endl; + kdDebug(1204) << " oldArea: " << oldArea.x() << "," << oldArea.y() << " " << oldArea.width() << "x" << oldArea.height() << endl; + + bool needRepaint = false; + TQIconViewItem* item; + int dx, dy; + + dx = wr.left() - oldArea.left(); + dy = wr.top() - oldArea.top(); + + if ( dx != 0 || dy != 0 ) { + if ( (dx > 0) || (dy > 0) ) { + // the iconArea was shifted right/down; less space now + for ( item = firstItem(); item; item = item->nextItem() ) { + // check if there is any item inside the now unavailable area + // If so, we have to move _all_ items + // If not, we don't have to move any item (avoids bug:117868) + if ( (item->x() < wr.x()) || (item->y() < wr.y()) ) { + needRepaint = true; + break; + } + } + } + else { + // the iconArea was shifted left/up; more space now - use it + needRepaint = true; + } + + if ( needRepaint ) { + for ( item = firstItem(); item; item = item->nextItem() ) { + item->moveBy( dx, dy ); + } + } + } + + for ( item = firstItem(); item; item = item->nextItem() ) { + TQRect r( item->rect() ); + int dx = 0, dy = 0; + if ( r.bottom() > wr.bottom() ) { + dy = wr.bottom() - r.bottom() - 1; + } + if ( r.right() > wr.right() ) { + dx = wr.right() - r.right() - 1; + } + if ( dx != 0 || dy != 0 ) { + needRepaint = true; + item->moveBy( dx, dy ); + } + } + if ( needRepaint ) { + viewport()->repaint( FALSE ); + repaint( FALSE ); + saveIconPositions(); + } + + m_needDesktopAlign = false; + lineupIcons(); +} + +void KDIconView::setupSortKeys() +{ + // can't use sorting in KFileIVI::setKey() + setProperty("sortDirectoriesFirst", TQVariant(false, 0)); + + for (TQIconViewItem *it = firstItem(); it; it = it->nextItem()) + { + TQString strKey; + + if (!m_itemsAlwaysFirst.isEmpty()) + { + TQString strFileName = static_cast<KFileIVI *>( it )->item()->url().fileName(); + int nFind = m_itemsAlwaysFirst.findIndex(strFileName); + if (nFind >= 0) + strKey = "0" + TQString::number(nFind); + } + + if (strKey.isEmpty()) + { + switch (m_eSortCriterion) + { + case NameCaseSensitive: + strKey = it->text(); + break; + case NameCaseInsensitive: + strKey = it->text().lower(); + break; + case Size: + strKey = TDEIO::number(static_cast<KFileIVI *>( it )->item()->size()).rightJustify(20, '0'); + break; + case Type: + // Sort by Type + Name (#17014) + strKey = static_cast<KFileIVI *>( it )->item()->mimetype() + '~' + it->text().lower(); + break; + case Date: + TQDateTime dayt; + dayt.setTime_t( static_cast<KFileIVI *>( it )-> + item()->time( TDEIO::UDS_MODIFICATION_TIME ) ); + strKey = dayt.toString( "yyyyMMddhhmmss" ); + break; + } + + if (m_bSortDirectoriesFirst) + { + if (S_ISDIR(static_cast<KFileIVI *>( it )->item()->mode())) + strKey.prepend(sortDirection() ? '1' : '2'); + else + strKey.prepend(sortDirection() ? '2' : '1' ); + } + else + strKey.prepend('1'); + } + + it->setKey(strKey); + } +} + +bool KDIconView::isFreePosition( const TQIconViewItem *item, const TQRect ¤tIconArea ) const +{ + TQRect r = item->rect(); + TQRect area = currentIconArea; + if (area.isNull()) area = iconArea(); + + // If the proposed item rect is not contained by the desktop, by definition the item position is not free! + if (!area.contains(r, FALSE)) { + return false; + } + + TQIconViewItem *it = firstItem(); + for (; it; it = it->nextItem() ) { + if ( !it->rect().isValid() || it == item ) { + continue; + } + + if ( it->intersects( r ) ) { + return false; + } + } + + return true; +} + +bool KDIconView::isFreePosition( const TQIconViewItem *item, const TQRect& rect, const TQRect& currentIconArea) const +{ + TQRect area = currentIconArea; + if (area.isNull()) area = iconArea(); + + // If the proposed item rect is not contained by the desktop, by definition the item position is not free! + if (!area.contains(rect, FALSE)) { + return false; + } + + TQIconViewItem *it = firstItem(); + for (; it; it = it->nextItem() ) { + if ( !rect.isValid() || it == item ) { + continue; + } + + if ( it->intersects( rect ) ) { + return false; + } + } + + return true; +} + +void KDIconView::setLastIconPosition( const TQPoint &_pos ) +{ + m_lastDeletedIconPos = _pos; +} + +void KDIconView::moveToFreePosition(TQIconViewItem *item, const TQRect ¤tIconArea) +{ + bool success = false; + // It may be that a file has been renamed. In this case, + // m_lastDeletedIconPos is the position to use for this "apparently new" item. + // (We rely on deleteItem being now emitted before newItems). + if ( !m_lastDeletedIconPos.isNull() ) { + // Problem is: I'd like to compare those two file's attributes + // (size, creation time, modification time... etc.) but since renaming + // is done by kpropsdlg, all of those can have changed (and creation time + // is different since the new file is a copy!) + kdDebug(1214) << "Moving " << item->text() << " to position of last deleted icon." << endl; + item->move( m_lastDeletedIconPos ); + m_lastDeletedIconPos = TQPoint(); + return; + } + + //try to find a free place to put the item, honouring the m_bVertAlign property + TQRect rect=item->rect(); + if (m_bVertAlign) { + kdDebug(1214)<<"moveToFreePosition for vertical alignment"<<endl; + + rect.moveTopLeft(TQPoint(currentIconArea.x()+spacing(),currentIconArea.y()+spacing())); + do { + success=false; + while (rect.bottom()<(currentIconArea.y()+currentIconArea.height())) { + if (!isFreePosition(item,rect,currentIconArea)) { + rect.moveBy(0,rect.height()+spacing()); + } + else { + success=true; + break; + } + } + + if (!success) { + rect.moveTopLeft(TQPoint(rect.right()+spacing(),spacing())); + } + else { + break; + } + } while (item->rect().right()<(currentIconArea.x()+currentIconArea.width())); + + if (success) { + item->move(rect.x(),rect.y()); + } + else { + item->move(width()-spacing()-item->rect().width(),height()-spacing()-item->rect().height()); + } + } +} + + +TQPoint KDIconView::findPlaceForIconCol( int column, int dx, int dy, const TQRect ¤tIconArea ) +{ + if (column < 0) + return TQPoint(); + + TQRect rect; + rect.moveTopLeft( TQPoint(column * dx, 0) ); + rect.setWidth(dx); + rect.setHeight(dy); + + if (rect.right() > viewport()->width()) + return TQPoint(); + + while ( rect.bottom() < viewport()->height() - spacing() ) + { + if ( !isFreePosition(0,rect,currentIconArea) ) { + rect.moveBy(0, rect.height()); + } + else { + return rect.topLeft(); + } + } + + return TQPoint(); +} + +TQPoint KDIconView::findPlaceForIconRow( int row, int dx, int dy, const TQRect ¤tIconArea ) +{ + if (row < 0) + return TQPoint(); + + TQRect rect; + rect.moveTopLeft(TQPoint(0, row * dy)); + rect.setWidth(dx); + rect.setHeight(dy); + + if (rect.bottom() > viewport()->height()) + return TQPoint(); + + while (rect.right() < viewport()->width() - spacing()) + { + if (!isFreePosition(0,rect,currentIconArea)) + rect.moveBy(rect.width()+spacing(), 0); + else + return rect.topLeft(); + } + + return TQPoint(); +} + +TQPoint KDIconView::findPlaceForIcon( int column, int row, const TQRect ¤tIconArea ) +{ + int dx = gridXValue(), dy = 0; + TQIconViewItem *item = firstItem(); + for ( ; item; item = item->nextItem() ) { + dx = TQMAX( dx, item->width() ); + dy = TQMAX( dy, item->height() ); + } + + dx += spacing(); + dy += spacing(); + + if (row == -1) { + int max_cols = viewport()->width() / dx; + int delta = 0; + TQPoint res; + do { + delta++; + res = findPlaceForIconCol(column + (delta / 2) * (-2 * (delta % 2) + 1), + dx, dy, currentIconArea); + if (delta / 2 > TQMAX(max_cols - column, column)) + return res; + } while (res.isNull()); + return res; + } + + if (column == -1) { + int max_rows = viewport()->height() / dy; + int delta = 0; + TQPoint res; + do { + delta++; + res = findPlaceForIconRow(row + (delta / 2) * (-2 * (delta % 2) + 1), + dx, dy, currentIconArea); + if (delta / 2 > TQMAX(max_rows - row, row)) + return res; + } while (res.isNull()); + return res; + } + + // very unlikely - if I may add that + return TQPoint(0, 0); +} + +void KDIconView::saveIconPositions() +{ + kdDebug(1214) << "KDIconView::saveIconPositions" << endl; + + if (!m_bEditableDesktopIcons) { + return; // Don't save position + } + + TQString prefix = iconPositionGroupPrefix(); + TQIconViewItem *it = firstItem(); + if ( !it ) { + return; // No more icons. Maybe we're closing and they've been removed already + } + + while ( it ) + { + KFileIVI *ivi = static_cast<KFileIVI *>( it ); + KFileItem *item = ivi->item(); + + m_dotDirectory->setGroup( prefix + item->url().fileName() ); + kdDebug(1214) << "KDIconView::saveIconPositions " << item->url().fileName() << " " << it->x() << " " << it->y() << endl; + saveIconPosition(m_dotDirectory, it->x(), it->y()); + + it = it->nextItem(); + } + + m_dotDirectory->sync(); +} + +void KDIconView::update( const TQString &_url ) +{ + if (m_dirLister) { + m_dirLister->updateDirectory( _url ); + } +} + + +#include "kdiconview.moc" diff --git a/kdesktop/kdiconview.h b/kdesktop/kdiconview.h new file mode 100644 index 000000000..7b20e1817 --- /dev/null +++ b/kdesktop/kdiconview.h @@ -0,0 +1,287 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 Torben Weis <[email protected]> + Copyright (C) 2000, 2001 David Faure <[email protected]> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License version 2 as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef kdiconview_h +#define kdiconview_h + +#include <tqtimer.h> +#include <tqlistview.h> + +#include <konq_iconviewwidget.h> +#include <tdeaction.h> +#include <tdefileitem.h> +#include <kdirnotify.h> +#include <tdemessagebox.h> + +#include <dcopclient.h> + +class KDirLister; +class KonqSettings; +class KSimpleConfig; +class TDEAccel; +class KShadowEngine; +class KDesktopShadowSettings; + +/** + * This class is KDesktop's icon view. + * The icon view is a child widget of the KDesktop widget. + * + * Added shadow capability by Laur Ivan (C) 2003 + * The shadow is supported by the new KFileIVIDesktop objects + * which replace KFileIVI objects. + */ +class KDIconView : public KonqIconViewWidget, public KDirNotify +{ + Q_OBJECT + +public: + KDIconView( TQWidget *parent, const char* name = 0L ); + ~KDIconView(); + + virtual void initConfig( bool init ); + void configureMedia(); + /** + * Start listing + */ + void start(); + + TDEActionCollection *actionCollection() { return &m_actionCollection; } + + enum SortCriterion { + NameCaseSensitive = 0, NameCaseInsensitive, Size, Type, Date }; + + void rearrangeIcons( SortCriterion sc, bool bSortDirectoriesFirst); + + /** + * Re-arrange the desktop icons without confirmation. + */ + void rearrangeIcons(); + + void lineupIcons(TQIconView::Arrangement); + + void setAutoAlign( bool b ); + + TQStringList selectedURLs(); + + void update( const TQString &url ); + + /** + * Save the icon positions + */ + void saveIconPositions(); + + /** + * Check if the URL to the desktop has changed + */ + void recheckDesktopURL(); + + /** + * Called when the desktop icons area has changed + */ + void updateWorkArea( const TQRect &wr ); + + /** + * Reimplemented from KonqIconViewWidget (for image drops) + */ + virtual void setWallpaper(const KURL &url) { emit newWallpaper( url ); } + void setLastIconPosition( const TQPoint & ); + + static KURL desktopURL(); + + /// KDirNotify interface, for trash:/ + virtual void FilesAdded( const KURL & directory ); + virtual void FilesRemoved( const KURL::List & fileList ); + virtual void FilesChanged( const KURL::List & ) {} + + void startDirLister(); + + TQPoint findPlaceForIconCol( int column, int dx, int dy, const TQRect ¤tIconArea ); + TQPoint findPlaceForIconRow( int row, int dx, int dy, const TQRect ¤tIconArea ); + TQPoint findPlaceForIcon( int column, int row, const TQRect ¤tIconArea = TQRect() ); + +protected slots: + + // slots connected to the icon view + void slotReturnPressed( TQIconViewItem *item ); + void slotExecuted( TQIconViewItem *item ); + void slotMouseButtonPressed(int _button, TQIconViewItem* _item, const TQPoint& _global); + void slotMouseButtonClickedKDesktop(int _button, TQIconViewItem* _item, const TQPoint& _global); + void slotContextMenuRequested(TQIconViewItem* _item, const TQPoint& _global); + void slotEnableAction( const char * name, bool enabled ); +public slots: + void slotAboutToCreate(const TQPoint &pos, const TQValueList<TDEIO::CopyInfo> &files); +protected slots: + void slotItemRenamed(TQIconViewItem*, const TQString &name); + + // slots connected to the directory lister + void slotStarted( const KURL& url ); + void slotCompleted(); + void slotNewItems( const KFileItemList& ); + void slotDeleteItem( KFileItem * ); + void slotRefreshItems( const KFileItemList& ); + + // slots connected to the popupmenu (actions) + void slotCut(); + void slotCopy(); + void slotTrashActivated( TDEAction::ActivationReason reason, TQt::ButtonState state ); + void slotDelete(); + void slotPopupPasteTo(); + void slotProperties(); + + void slotClipboardDataChanged(); + + void slotNewMenuActivated(); + + // For communication with KDesktop +signals: + void colorDropEvent( TQDropEvent *e ); + void imageDropEvent( TQDropEvent *e ); + void newWallpaper( const KURL & ); + void iconMoved(); + void wheelRolled( int delta ); + +public slots: + /** + * Lineup the desktop icons. + */ + void lineupIcons(); + void slotPaste(); // for krootwm + void slotClear(); + void refreshIcons(); + +protected slots: + void slotFreeSpaceOverlayStart(); + void slotFreeSpaceOverlayFinished(); + void slotFreeSpaceOverlaySettingChanged(); + +protected: + void createActions(); + void setupSortKeys(); + void initDotDirectories(); + + bool makeFriendlyText( KFileIVI *fileIVI ); + static TQString stripDesktopExtension( const TQString & text ); + bool isDesktopFile( KFileItem * _item ) const; + bool isFreePosition( const TQIconViewItem *item, const TQRect ¤tIconArea ) const; + bool isFreePosition( const TQIconViewItem *item, const TQRect& rect, const TQRect ¤tIconArea ) const; + void moveToFreePosition(TQIconViewItem *item, const TQRect ¤tIconArea ); + + bool deleteGlobalDesktopFiles(); + void removeBuiltinIcon(TQString iconName); + void fillMediaListView(); + void saveMediaListView(); + + static void renameDesktopFile(const TQString &path, const TQString &name); + + void popupMenu( const TQPoint &_global, const KFileItemList& _items ); + virtual void showEvent( TQShowEvent *e ); + virtual void contentsDropEvent( TQDropEvent *e ); + virtual void viewportWheelEvent( TQWheelEvent * ); + virtual void contentsMousePressEvent( TQMouseEvent *e ); + virtual void mousePressEvent( TQMouseEvent *e ); + virtual void wheelEvent( TQWheelEvent* e ); + +private: + void refreshTrashIcon(); + + static TQRect desktopRect(); + static void saveIconPosition(KSimpleConfig *config, int x, int y); + static void readIconPosition(KSimpleConfig *config, int &x, int &y); + + void showFreeSpaceOverlay(KFileIVI* item); + + /** Our action collection, parent of all our actions */ + TDEActionCollection m_actionCollection; + + /** TDEAccel object, to make the actions shortcuts work */ + TDEAccel *m_accel; + + bool m_bNeedRepaint; + bool m_bNeedSave; + bool m_autoAlign; + + /** true if even one icon has an icon-position entry in the .directory */ + bool m_hasExistingPos; + + /** whether the user may move/edit/remove desktop icons */ + bool m_bEditableDesktopIcons; + + /** Show dot files ? */ + bool m_bShowDot; + + /** Vertical or Horizontal align of icons on desktop */ + bool m_bVertAlign; + + /** The directory lister - created only in start() */ + KDirLister* m_dirLister; + + /** The list of urls to be merged into the desktop, in addition to desktopURL */ + KURL::List m_mergeDirs; + + /** The list of dirs to be merged into the desktop, in addition to desktopURL **/ + TQStringList m_desktopDirs; + + /** The desktop's .directory, used for storing icon positions */ + KSimpleConfig *m_dotDirectory; + + /** Position of last deleted icon - used when renaming a file */ + TQPoint m_lastDeletedIconPos; + + /** Sorting */ + SortCriterion m_eSortCriterion; + bool m_bSortDirectoriesFirst; + TQStringList m_itemsAlwaysFirst; + + /** + * The shadow object + */ + KShadowEngine *m_shadowEngine; + + /** Position where to move the next item. + * It is set to the KRootWm position when "new file" is chosen. */ + TQPoint m_nextItemPos; + + /** Position where the last drop occurred */ + TQPoint m_dropPos; + + /** Position for the last dropped item */ + TQPoint m_lastDropPos; + + /** URL of the items which is being RMB'ed - when only one */ + KURL m_popupURL; + + /** media list management */ + bool m_enableMedia; + TQStringList m_excludedMedia; + + // did we already get the correct desktopIconsArea (from kicker) + // needed when we want to line up icons on a grid + bool m_gotIconsArea; + + bool m_needDesktopAlign; + + TQListView *mMediaListView; + + TQPtrList<KFileIVI> m_paOutstandingFreeSpaceOverlays; + TQTimer *m_paOutstandingFreeSpaceOverlaysTimer; + + TDEConfig *g_pConfig; +}; + +#endif diff --git a/kdesktop/krootwm.cc b/kdesktop/krootwm.cc new file mode 100644 index 000000000..02f073136 --- /dev/null +++ b/kdesktop/krootwm.cc @@ -0,0 +1,916 @@ +/* + * krootwm.cc Part of the KDE project. + * + * Copyright (C) 1997 Matthias Ettrich + * (C) 1997 Torben Weis, [email protected] + * (C) 1998 S.u.S.E. [email protected] + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License version 2 as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +#include <stdlib.h> +#include <signal.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <unistd.h> +#include <sys/types.h> +#include <dirent.h> +#include <errno.h> + +#include <kprocess.h> +#include <kstandarddirs.h> +#include <tdepopupmenu.h> +#include <tdeapplication.h> +#include <tdeconfig.h> +#include <kcmultidialog.h> +#include <kbookmarkmenu.h> +#include <konqbookmarkmanager.h> +#include <tdelocale.h> +#include <knewmenu.h> +#include <dcopclient.h> +#include <dcopref.h> +#include <khelpmenu.h> +#include <kdebug.h> +#include <twindowlistmenu.h> +#include <twin.h> +#include <tdemenubar.h> +#include <tdemessagebox.h> +#include <kuser.h> +#include <tqfile.h> + +#include "krootwm.h" +#include "kdiconview.h" +#include "desktop.h" +#include "kcustommenu.h" +#include "kdesktopsettings.h" + +#include <netwm.h> +#include <X11/X.h> +#include <X11/Xlib.h> + +#include <dmctl.h> + +KRootWm * KRootWm::s_rootWm = 0; + +extern TQCString kdesktop_name, kicker_name, twin_name; + +KRootWm::KRootWm(KDesktop* _desktop) : TQObject(_desktop), startup(FALSE) +{ + s_rootWm = this; + m_actionCollection = new TDEActionCollection(_desktop, this, "KRootWm::m_actionCollection"); + m_pDesktop = _desktop; + m_bDesktopEnabled = (m_pDesktop->iconView() != 0); + customMenu1 = 0; + customMenu2 = 0; + m_configDialog = 0; + + + // Creates the new menu + menuBar = 0; // no menubar yet + menuNew = 0; + if (m_bDesktopEnabled && kapp->authorize("editable_desktop_icons")) + { + menuNew = new KNewMenu( m_actionCollection, "new_menu" ); + connect(menuNew->popupMenu(), TQT_SIGNAL( aboutToShow() ), + this, TQT_SLOT( slotFileNewAboutToShow() ) ); + connect( menuNew, TQT_SIGNAL( activated() ), + m_pDesktop->iconView(), TQT_SLOT( slotNewMenuActivated() ) ); + } + + if (kapp->authorizeTDEAction("bookmarks")) + { + bookmarks = new TDEActionMenu( i18n("Bookmarks"), "bookmark", m_actionCollection, "bookmarks" ); + // The KBookmarkMenu is needed to fill the Bookmarks menu in the desktop menubar. + bookmarkMenu = new KBookmarkMenu( KonqBookmarkManager::self(), new KBookmarkOwner(), + bookmarks->popupMenu(), + m_actionCollection, + true, false ); + } + else + { + bookmarks = 0; + bookmarkMenu = 0; + } + + // The windowList and desktop menus can be part of a menubar (Mac style) + // so we create them here + desktopMenu = new TQPopupMenu; + windowListMenu = new KWindowListMenu; + connect( windowListMenu, TQT_SIGNAL( aboutToShow() ), + this, TQT_SLOT( slotWindowListAboutToShow() ) ); + + // Create the actions +#if 0 + if (m_bDesktopEnabled) + { + // Don't do that! One action in two parent collections means some invalid write + // during the second ~TDEActionCollection. + TDEAction *action = m_pDesktop->actionCollection()->action( "paste" ); + if (action) + m_actionCollection->insert( action ); + action = m_pDesktop->actionCollection()->action( "undo" ); + if (action) + m_actionCollection->insert( action ); + } +#endif + + if (kapp->authorize("run_command")) + { + new TDEAction(i18n("Run Command..."), "run", 0, TQT_TQOBJECT(m_pDesktop), TQT_SLOT( slotExecuteCommand() ), m_actionCollection, "exec" ); + new TDEAction(i18n("Open Terminal Here..." ), "terminal", CTRL+Key_T, this, TQT_SLOT( slotOpenTerminal() ), + m_actionCollection, "open_terminal" ); + } + + if (!TDEGlobal::config()->isImmutable()) + { + new TDEAction(i18n("Configure Desktop..."), "configure", 0, this, TQT_SLOT( slotConfigureDesktop() ), + m_actionCollection, "configdesktop" ); + new TDEAction(i18n("Disable Desktop Menu"), 0, this, TQT_SLOT( slotToggleDesktopMenu() ), + m_actionCollection, "togglemenubar" ); + } + + new TDEAction(i18n("Unclutter Windows"), 0, this, TQT_SLOT( slotUnclutterWindows() ), + m_actionCollection, "unclutter" ); + new TDEAction(i18n("Cascade Windows"), 0, this, TQT_SLOT( slotCascadeWindows() ), + m_actionCollection, "cascade" ); + + // arrange menu actions + if (m_bDesktopEnabled && kapp->authorize("editable_desktop_icons")) + { + new TDEAction(i18n("By Name (Case Sensitive)"), 0, this, TQT_SLOT( slotArrangeByNameCS() ), + m_actionCollection, "sort_ncs"); + new TDEAction(i18n("By Name (Case Insensitive)"), 0, this, TQT_SLOT( slotArrangeByNameCI() ), + m_actionCollection, "sort_nci"); + new TDEAction(i18n("By Size"), 0, this, TQT_SLOT( slotArrangeBySize() ), + m_actionCollection, "sort_size"); + new TDEAction(i18n("By Type"), 0, this, TQT_SLOT( slotArrangeByType() ), + m_actionCollection, "sort_type"); + new TDEAction(i18n("By Date"), 0, this, TQT_SLOT( slotArrangeByDate() ), + m_actionCollection, "sort_date"); + + TDEToggleAction *aSortDirsFirst = new TDEToggleAction( i18n("Directories First"), 0, m_actionCollection, "sort_directoriesfirst" ); + connect( aSortDirsFirst, TQT_SIGNAL( toggled( bool ) ), + this, TQT_SLOT( slotToggleDirFirst( bool ) ) ); + new TDEAction(i18n("Line Up Horizontally"), 0, + this, TQT_SLOT( slotLineupIconsHoriz() ), + m_actionCollection, "lineupHoriz" ); + new TDEAction(i18n("Line Up Vertically"), 0, + this, TQT_SLOT( slotLineupIconsVert() ), + m_actionCollection, "lineupVert" ); + TDEToggleAction *aAutoAlign = new TDEToggleAction(i18n("Align to Grid"), 0, + m_actionCollection, "realign" ); + connect( aAutoAlign, TQT_SIGNAL( toggled( bool ) ), + this, TQT_SLOT( slotToggleAutoAlign( bool ) ) ); + TDEToggleAction *aLockIcons = new TDEToggleAction(i18n("Lock in Place"), 0, m_actionCollection, "lock_icons"); + connect( aLockIcons, TQT_SIGNAL( toggled( bool ) ), + this, TQT_SLOT( slotToggleLockIcons( bool ) ) ); + } + if (m_bDesktopEnabled) + { + new TDEAction(i18n("Refresh Desktop"), "desktop", 0, this, TQT_SLOT( slotRefreshDesktop() ), + m_actionCollection, "refresh" ); + } + // Icons in sync with kicker + if (kapp->authorize("lock_screen")) + { + new TDEAction(i18n("Lock Session"), "lock", 0, this, TQT_SLOT( slotLock() ), + m_actionCollection, "lock" ); + } + if (kapp->authorize("logout")) + { + new TDEAction(i18n("Log Out \"%1\"...").arg(KUser().loginName()), "exit", 0, + this, TQT_SLOT( slotLogout() ), m_actionCollection, "logout" ); + } + + if (kapp->authorize("start_new_session") && DM().isSwitchable()) + { + new TDEAction(i18n("Start New Session"), "fork", 0, this, + TQT_SLOT( slotNewSession() ), m_actionCollection, "newsession" ); + if (kapp->authorize("lock_screen")) + { + new TDEAction(i18n("Lock Current && Start New Session"), "lock", 0, this, + TQT_SLOT( slotLockNNewSession() ), m_actionCollection, "lockNnewsession" ); + } + } + + initConfig(); +} + +KRootWm::~KRootWm() +{ + delete m_actionCollection; + delete desktopMenu; + delete windowListMenu; +} + +void KRootWm::initConfig() +{ +// kdDebug() << "KRootWm::initConfig" << endl; + + // parse the configuration + m_bGlobalMenuBar = KDesktopSettings::macStyle(); + m_bShowMenuBar = m_bGlobalMenuBar || KDesktopSettings::showMenubar(); + + static const int choiceCount = 7; + // read configuration for clicks on root window + static const char * const s_choices[choiceCount] = { "", "WindowListMenu", "DesktopMenu", "AppMenu", "CustomMenu1", "CustomMenu2", "BookmarksMenu" }; + leftButtonChoice = middleButtonChoice = rightButtonChoice = NOTHING; + TQString s = KDesktopSettings::left(); + for ( int c = 0 ; c < choiceCount ; c ++ ) + if (s == s_choices[c]) + { leftButtonChoice = (menuChoice) c; break; } + s = KDesktopSettings::middle(); + for ( int c = 0 ; c < choiceCount ; c ++ ) + if (s == s_choices[c]) + { middleButtonChoice = (menuChoice) c; break; } + s = KDesktopSettings::right(); + for ( int c = 0 ; c < choiceCount ; c ++ ) + if (s == s_choices[c]) + { rightButtonChoice = (menuChoice) c; break; } + + // Read configuration for icons alignment + if ( m_bDesktopEnabled ) { + m_pDesktop->iconView()->setAutoAlign( KDesktopSettings::autoLineUpIcons() ); + if ( kapp->authorize( "editable_desktop_icons" ) ) { + m_pDesktop->iconView()->setItemsMovable( !KDesktopSettings::lockIcons() ); + TDEToggleAction *aLockIcons = static_cast<TDEToggleAction*>(m_actionCollection->action("lock_icons")); + if (aLockIcons) + aLockIcons->setChecked( KDesktopSettings::lockIcons() ); + } + TDEToggleAction *aAutoAlign = static_cast<TDEToggleAction*>(m_actionCollection->action("realign")); + if (aAutoAlign) + aAutoAlign->setChecked( KDesktopSettings::autoLineUpIcons() ); + TDEToggleAction *aSortDirsFirst = static_cast<TDEToggleAction*>(m_actionCollection->action("sort_directoriesfirst")); + if (aSortDirsFirst) + aSortDirsFirst->setChecked( KDesktopSettings::sortDirectoriesFirst() ); + } + + buildMenus(); +} + +void KRootWm::buildMenus() +{ +// kdDebug() << "KRootWm::buildMenus" << endl; + + delete menuBar; + menuBar = 0; + + delete customMenu1; + customMenu1 = 0; + delete customMenu2; + customMenu2 = 0; + + if (m_bShowMenuBar) + { +// kdDebug() << "showMenuBar" << endl; + menuBar = new KMenuBar; + menuBar->setCaption("TDE Desktop"); + } + + // create Arrange menu + TQPopupMenu *pArrangeMenu = 0; + TQPopupMenu *pLineupMenu = 0; + TDEAction *action; + help = new KHelpMenu(0, 0, false); + help->menu()->removeItem( KHelpMenu::menuAboutApp ); + + if (m_bDesktopEnabled && m_actionCollection->action("realign")) + { + pArrangeMenu = new TQPopupMenu; + m_actionCollection->action("sort_ncs")->plug( pArrangeMenu ); + m_actionCollection->action("sort_nci")->plug( pArrangeMenu ); + m_actionCollection->action("sort_size")->plug( pArrangeMenu ); + m_actionCollection->action("sort_type")->plug( pArrangeMenu ); + m_actionCollection->action("sort_date" )->plug( pArrangeMenu ); + pArrangeMenu->insertSeparator(); + m_actionCollection->action("sort_directoriesfirst")->plug( pArrangeMenu ); + + pLineupMenu = new TQPopupMenu; + m_actionCollection->action( "lineupHoriz" )->plug( pLineupMenu ); + m_actionCollection->action( "lineupVert" )->plug( pLineupMenu ); + pLineupMenu->insertSeparator(); + m_actionCollection->action( "realign" )->plug( pLineupMenu ); + } + + sessionsMenu = 0; + if (m_actionCollection->action("newsession")) + { + sessionsMenu = new TQPopupMenu; + connect( sessionsMenu, TQT_SIGNAL(aboutToShow()), TQT_SLOT(slotPopulateSessions()) ); + connect( sessionsMenu, TQT_SIGNAL(activated(int)), TQT_SLOT(slotSessionActivated(int)) ); + } + + if (menuBar) { + bool needSeparator = false; + file = new TQPopupMenu; + + action = m_actionCollection->action("exec"); + if (action) + { + action->plug( file ); + file->insertSeparator(); + } + + action = m_actionCollection->action("open_terminal"); + if (action) + { + action->plug( file ); + } + + action = m_actionCollection->action("lock"); + if (action) + action->plug( file ); + + action = m_actionCollection->action("logout"); + if (action) + action->plug( file ); + + desk = new TQPopupMenu; + + if (m_bDesktopEnabled) + { + m_actionCollection->action("unclutter")->plug( desk ); + m_actionCollection->action("cascade")->plug( desk ); + desk->insertSeparator(); + + if (pArrangeMenu) + desk->insertItem(i18n("Sort Icons"), pArrangeMenu); + if (pLineupMenu) + desk->insertItem(i18n("Line Up Icons"), pLineupMenu ); + + m_actionCollection->action("refresh")->plug( desk ); + needSeparator = true; + } + action = m_actionCollection->action("configdesktop"); + if (action) + { + if (needSeparator) + desk->insertSeparator(); + action->plug( desk ); + needSeparator = true; + } + + action = m_actionCollection->action("togglemenubar"); + if (action) + { + if (needSeparator) + desk->insertSeparator(); + action->plug( desk ); + action->setText(i18n("Disable Desktop Menu")); + } + } + else + { + action = m_actionCollection->action("togglemenubar"); + if (action) + action->setText(i18n("Enable Desktop Menu")); + } + + desktopMenu->clear(); + desktopMenu->disconnect( this ); + bool needSeparator = false; + + if (menuNew) + { + menuNew->plug( desktopMenu ); + needSeparator = true; + } + +#if 0 + if (bookmarks) + { + bookmarks->plug( desktopMenu ); + needSeparator = true; + } +#endif + + action = m_actionCollection->action("exec"); + if (action) + { + action->plug( desktopMenu ); + needSeparator = true; + } + + action = m_actionCollection->action("open_terminal"); + if (action) + action->plug( desktopMenu ); + + if (needSeparator) + { + desktopMenu->insertSeparator(); + needSeparator = false; + } + + if (m_bDesktopEnabled) + { + action = m_pDesktop->actionCollection()->action( "undo" ); + if (action) + action->plug( desktopMenu ); + action = m_pDesktop->actionCollection()->action( "paste" ); + if (action) + action->plug( desktopMenu ); + desktopMenu->insertSeparator(); + } + + if (m_bDesktopEnabled && m_actionCollection->action("realign")) + { + TQPopupMenu* pIconOperationsMenu = new TQPopupMenu; + + pIconOperationsMenu->insertItem(i18n("Sort Icons"), pArrangeMenu); + pIconOperationsMenu->insertSeparator(); + m_actionCollection->action( "lineupHoriz" )->plug( pIconOperationsMenu ); + m_actionCollection->action( "lineupVert" )->plug( pIconOperationsMenu ); + pIconOperationsMenu->insertSeparator(); + m_actionCollection->action( "realign" )->plug( pIconOperationsMenu ); + TDEAction *aLockIcons = m_actionCollection->action( "lock_icons" ); + if ( aLockIcons ) + aLockIcons->plug( pIconOperationsMenu ); + + desktopMenu->insertItem(SmallIconSet("icons"), i18n("Icons"), pIconOperationsMenu); + } + + TQPopupMenu* pWindowOperationsMenu = new TQPopupMenu; + m_actionCollection->action("cascade")->plug( pWindowOperationsMenu ); + m_actionCollection->action("unclutter")->plug( pWindowOperationsMenu ); + desktopMenu->insertItem(SmallIconSet("window_list"), i18n("Windows"), pWindowOperationsMenu); + + if (m_bDesktopEnabled) + { + m_actionCollection->action("refresh")->plug( desktopMenu ); + } + + action = m_actionCollection->action("configdesktop"); + if (action) + { + action->plug( desktopMenu ); + } + int lastSep = desktopMenu->insertSeparator(); + + if (sessionsMenu && kapp->authorize("switch_user")) + { + desktopMenu->insertItem(SmallIconSet("switchuser" ), i18n("Switch User"), sessionsMenu); + needSeparator = true; + } + + action = m_actionCollection->action("lock"); + if (action) + { + action->plug( desktopMenu ); + needSeparator = true; + } + + action = m_actionCollection->action("logout"); + if (action) + { + action->plug( desktopMenu ); + needSeparator = true; + } + + if (!needSeparator) + { + desktopMenu->removeItem(lastSep); + } + + connect( desktopMenu, TQT_SIGNAL( aboutToShow() ), this, TQT_SLOT( slotFileNewAboutToShow() ) ); + + if (menuBar) { + menuBar->insertItem(i18n("File"), file); + if (sessionsMenu) + { + menuBar->insertItem(i18n("Sessions"), sessionsMenu); + } + if (menuNew) + { + menuBar->insertItem(i18n("New"), menuNew->popupMenu()); + } + if (bookmarks) + { + menuBar->insertItem(i18n("Bookmarks"), bookmarks->popupMenu()); + } + menuBar->insertItem(i18n("Desktop"), desk); + menuBar->insertItem(i18n("Windows"), windowListMenu); + menuBar->insertItem(i18n("Help"), help->menu()); + + menuBar->setTopLevelMenu( true ); + menuBar->show(); // we need to call show() as we delayed the creation with the timer + } +} + +void KRootWm::slotToggleDirFirst( bool b ) +{ + KDesktopSettings::setSortDirectoriesFirst( b ); + KDesktopSettings::writeConfig(); +} + +void KRootWm::slotToggleAutoAlign( bool b ) +{ + KDesktopSettings::setAutoLineUpIcons( b ); + KDesktopSettings::writeConfig(); + + // Also save it globally... + int desktop = TDEApplication::desktop()->primaryScreen(); + TQCString cfilename; + if (desktop == 0) + cfilename = "kdesktoprc"; + else + cfilename.sprintf("kdesktop-screen-%drc", desktop); + + TDEConfig *kdg_config = new TDEConfig(cfilename, false, false); + kdg_config->setGroup( "General" ); + kdg_config->writeEntry( "AutoLineUpIcons", b ); + kdg_config->sync(); + delete kdg_config; + + // Auto line-up icons + m_pDesktop->iconView()->setAutoAlign( b ); +} + +void KRootWm::slotFileNewAboutToShow() +{ + if (menuNew) + { +// kdDebug() << " KRootWm:: (" << this << ") slotFileNewAboutToShow() menuNew=" << menuNew << endl; + // As requested by KNewMenu : + menuNew->slotCheckUpToDate(); + // And set the files that the menu apply on : + menuNew->setPopupFiles( m_pDesktop->url() ); + } +} + +void KRootWm::slotWindowListAboutToShow() +{ + windowListMenu->init(); +} + +void KRootWm::activateMenu( menuChoice choice, const TQPoint& global ) +{ + switch ( choice ) + { + case SESSIONSMENU: + if (sessionsMenu) + sessionsMenu->popup(global); + break; + case WINDOWLISTMENU: + windowListMenu->popup(global); + break; + case DESKTOPMENU: + m_desktopMenuPosition = global; // for KDIconView::slotPaste + desktopMenu->popup(global); + break; + case BOOKMARKSMENU: + if (bookmarks) + bookmarks->popup(global); + break; + case APPMENU: + { + // This allows the menu to disappear when clicking on the background another time + XUngrabPointer(tqt_xdisplay(), CurrentTime); + XSync(tqt_xdisplay(), False); + + // Ask kicker to showup the menu + DCOPRef( kicker_name, kicker_name ).send( "popupKMenu", global ); + break; + } + case CUSTOMMENU1: + if (!customMenu1) + customMenu1 = new KCustomMenu("kdesktop_custom_menu1"); + customMenu1->popup(global); + break; + case CUSTOMMENU2: + if (!customMenu2) + customMenu2 = new KCustomMenu("kdesktop_custom_menu2"); + customMenu2->popup(global); + break; + case NOTHING: + default: + break; + } +} + +void KRootWm::mousePressed( const TQPoint& _global, int _button ) +{ + if (!desktopMenu) return; // initialisation not yet done + switch ( _button ) { + case Qt::LeftButton: + if ( m_bShowMenuBar && menuBar ) + menuBar->raise(); + activateMenu( leftButtonChoice, _global ); + break; + case Qt::MidButton: + activateMenu( middleButtonChoice, _global ); + break; + case Qt::RightButton: + if (!kapp->authorize("action/kdesktop_rmb")) return; + activateMenu( rightButtonChoice, _global ); + break; + default: + // nothing + break; + } +} + +void KRootWm::slotWindowList() { +// kdDebug() << "KRootWm::slotWindowList" << endl; +// Popup at the center of the screen, this is from keyboard shortcut. + TQDesktopWidget* desktop = TDEApplication::desktop(); + TQRect r; + if (desktop->numScreens() < 2) + r = desktop->geometry(); + else + r = desktop->screenGeometry( desktop->screenNumber(TQCursor::pos())); + windowListMenu->init(); + disconnect( windowListMenu, TQT_SIGNAL( aboutToShow() ), + this, TQT_SLOT( slotWindowListAboutToShow() ) ); // avoid calling init() twice + // windowListMenu->rect() is not valid before showing, use sizeHint() + windowListMenu->popup(r.center() - TQRect( TQPoint( 0, 0 ), windowListMenu->sizeHint()).center()); + windowListMenu->selectActiveWindow(); // make the popup more useful + connect( windowListMenu, TQT_SIGNAL( aboutToShow() ), + this, TQT_SLOT( slotWindowListAboutToShow() ) ); +} + +void KRootWm::slotSwitchUser() { +// kdDebug() << "KRootWm::slotSwitchUser" << endl; + if (!sessionsMenu) + return; + TQDesktopWidget* desktop = TDEApplication::desktop(); + TQRect r; + if (desktop->numScreens() < 2) + r = desktop->geometry(); + else + r = desktop->screenGeometry( desktop->screenNumber(TQCursor::pos())); + slotPopulateSessions(); + disconnect( sessionsMenu, TQT_SIGNAL( aboutToShow() ), + this, TQT_SLOT( slotPopulateSessions() ) ); // avoid calling init() twice + sessionsMenu->popup(r.center() - TQRect( TQPoint( 0, 0 ), sessionsMenu->sizeHint()).center()); + connect( sessionsMenu, TQT_SIGNAL( aboutToShow() ), + TQT_SLOT( slotPopulateSessions() ) ); +} + +void KRootWm::slotArrangeByNameCS() +{ + if (m_bDesktopEnabled) + { + bool b = static_cast<TDEToggleAction *>(m_actionCollection->action("sort_directoriesfirst"))->isChecked(); + m_pDesktop->iconView()->rearrangeIcons( KDIconView::NameCaseSensitive, b); + } +} + +void KRootWm::slotArrangeByNameCI() +{ + if (m_bDesktopEnabled) + { + bool b = static_cast<TDEToggleAction *>(m_actionCollection->action("sort_directoriesfirst"))->isChecked(); + m_pDesktop->iconView()->rearrangeIcons( KDIconView::NameCaseInsensitive, b); + } +} + +void KRootWm::slotArrangeBySize() +{ + if (m_bDesktopEnabled) + { + bool b = static_cast<TDEToggleAction *>(m_actionCollection->action("sort_directoriesfirst"))->isChecked(); + m_pDesktop->iconView()->rearrangeIcons( KDIconView::Size, b); + } +} + +void KRootWm::slotArrangeByDate() +{ + if (m_bDesktopEnabled) + { + bool b = static_cast<TDEToggleAction *>( m_actionCollection->action( "sort_directoriesfirst" ) )->isChecked(); + m_pDesktop->iconView()->rearrangeIcons( KDIconView::Date, b ); + } +} + +void KRootWm::slotArrangeByType() +{ + if (m_bDesktopEnabled) + { + bool b = static_cast<TDEToggleAction *>(m_actionCollection->action("sort_directoriesfirst"))->isChecked(); + m_pDesktop->iconView()->rearrangeIcons( KDIconView::Type, b); + } +} + +void KRootWm::slotLineupIconsHoriz() { + if (m_bDesktopEnabled) + { + m_pDesktop->iconView()->lineupIcons(TQIconView::LeftToRight); + } +} + +void KRootWm::slotLineupIconsVert() { + if (m_bDesktopEnabled) + { + m_pDesktop->iconView()->lineupIcons(TQIconView::TopToBottom); + } +} + +void KRootWm::slotLineupIcons() { + if (m_bDesktopEnabled) + { + m_pDesktop->iconView()->lineupIcons(); + } +} + +void KRootWm::slotToggleLockIcons( bool lock ) +{ + if (m_bDesktopEnabled) + { + m_pDesktop->iconView()->setItemsMovable( !lock ); + KDesktopSettings::setLockIcons( lock ); + KDesktopSettings::writeConfig(); + } +} + +void KRootWm::slotRefreshDesktop() { + if (m_bDesktopEnabled) + { + m_pDesktop->refresh(); + } +} + +TQStringList KRootWm::configModules() { + TQStringList args; + args << "tde-background.desktop" << "tde-desktopbehavior.desktop" << "tde-desktop.desktop" + << "tde-screensaver.desktop" << "tde-display.desktop"; + return args; +} + +void KRootWm::slotOpenTerminal() +{ + // kdDebug() << "KRootWm::slotOpenTerminal" << endl; + TDEProcess* p = new TDEProcess; + TQ_CHECK_PTR(p); + + TDEConfigGroupSaver gs(TDEGlobal::config(), "General"); + TQString terminal = TDEGlobal::config()->readPathEntry("TerminalApplication", "konsole"); + + *p << terminal << "--workdir=" + TDEGlobalSettings::desktopPath() + "/"; + + p->start(TDEProcess::DontCare); + + delete p; +} + +void KRootWm::slotConfigureDesktop() { + if (!m_configDialog) + { + m_configDialog = new KCMultiDialog( (TQWidget*)0, "configureDialog" ); + connect(m_configDialog, TQT_SIGNAL(finished()), this, TQT_SLOT(slotConfigClosed())); + + TQStringList modules = configModules(); + for (TQStringList::const_iterator it = modules.constBegin(); it != modules.constEnd(); ++it) + { + if (kapp->authorizeControlModule(*it)) + { + m_configDialog->addModule(*it); + } + } + } + + KWin::setOnDesktop(m_configDialog->winId(), KWin::currentDesktop()); + m_configDialog->show(); + m_configDialog->raise(); +} + +void KRootWm::slotConfigClosed() +{ + m_configDialog->delayedDestruct(); + m_configDialog = 0; +} + +void KRootWm::slotToggleDesktopMenu() +{ + KDesktopSettings::setShowMenubar( !(m_bShowMenuBar && menuBar) ); + KDesktopSettings::writeConfig(); + + TQByteArray data; + kapp->dcopClient()->send( kdesktop_name, "KDesktopIface", "configure()", data); + // for the standalone menubar setting + kapp->dcopClient()->send( "menuapplet*", "menuapplet", "configure()", data ); + kapp->dcopClient()->send( kicker_name, kicker_name, "configureMenubar()", data ); + kapp->dcopClient()->send( "twin*", "", "reconfigure()", data ); +} + + +void KRootWm::slotUnclutterWindows() +{ + kapp->dcopClient()->send(twin_name, "KWinInterface", "unclutterDesktop()", TQString("")); +} + + +void KRootWm::slotCascadeWindows() { + kapp->dcopClient()->send(twin_name, "KWinInterface", "cascadeDesktop()", TQString("")); +} + + +void KRootWm::slotLock() { + kapp->dcopClient()->send(kdesktop_name, "KScreensaverIface", "lock()", TQString("")); +} + + +void KRootWm::slotSave() { + kapp->dcopClient()->send(kdesktop_name, "KScreensaverIface", "save()", TQString("")); +} + + +void KRootWm::slotLogout() { + m_pDesktop->logout(TDEApplication::ShutdownConfirmDefault, TDEApplication::ShutdownTypeDefault); +} + +void KRootWm::slotPopulateSessions() +{ + TDEAction *action; + int p; + DM dm; + + sessionsMenu->clear(); + action = m_actionCollection->action("newsession"); + if (action && (p = dm.numReserve()) >= 0) + { + action->plug( sessionsMenu ); + action->setEnabled( p ); + action = m_actionCollection->action("lockNnewsession"); + if (action) + { + action->plug( sessionsMenu ); + action->setEnabled( p ); + } + sessionsMenu->insertSeparator(); + } + SessList sess; + if (dm.localSessions( sess )) + for (SessList::ConstIterator it = sess.begin(); it != sess.end(); ++it) { + int id = sessionsMenu->insertItem( DM::sess2Str( *it ), (*it).vt ); + if (!(*it).vt) + sessionsMenu->setItemEnabled( id, false ); + if ((*it).self) + sessionsMenu->setItemChecked( id, true ); + } +} + +void KRootWm::slotSessionActivated( int ent ) +{ + if (ent > 0 && !sessionsMenu->isItemChecked( ent )) + DM().lockSwitchVT( ent ); +} + +void KRootWm::slotNewSession() +{ + doNewSession( false ); +} + +void KRootWm::slotLockNNewSession() +{ + doNewSession( true ); +} + +void KRootWm::doNewSession( bool lock ) +{ + int result = KMessageBox::warningContinueCancel( + m_pDesktop, + i18n("<p>You have chosen to open another desktop session.<br>" + "The current session will be hidden " + "and a new login screen will be displayed.<br>" + "An F-key is assigned to each session; " + "F%1 is usually assigned to the first session, " + "F%2 to the second session and so on. " + "You can switch between sessions by pressing " + "Ctrl, Alt and the appropriate F-key at the same time. " + "Additionally, the TDE Panel and Desktop menus have " + "actions for switching between sessions.</p>") + .arg(7).arg(8), + i18n("Warning - New Session"), + KGuiItem(i18n("&Start New Session"), "fork"), + ":confirmNewSession", + KMessageBox::PlainCaption | KMessageBox::Notify); + + if (result==KMessageBox::Cancel) + return; + + if (lock) + slotLock(); + + DM().startReserve(); +} + +void KRootWm::slotMenuItemActivated(int /* item */ ) +{ +} + +#include "krootwm.moc" diff --git a/kdesktop/krootwm.h b/kdesktop/krootwm.h new file mode 100644 index 000000000..dabe5ac23 --- /dev/null +++ b/kdesktop/krootwm.h @@ -0,0 +1,178 @@ +/* + * krootwm.h Part of the KDE project. + * + * Copyright (C) 1997 Matthias Ettrich + * (C) 1997 Torben Weis, [email protected] + * (C) 1998 S.u.S.E, [email protected] + * + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License version 2 as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef __krootwm_h__ +#define __krootwm_h__ + +#include <tqpixmap.h> +#include <tqobject.h> + +// we need Window but do not want to include X.h since it +// #defines way too many constants +typedef unsigned long XID; +typedef XID Window; + +class KMenuBar; +class KDesktop; +class TQPopupMenu; +class KCMultiDialog; +class KNewMenu; +class KWinModule; +class KBookmarkMenu; +class KHelpMenu; +class TDEActionCollection; +class TDEActionMenu; +class KWindowListMenu; + +enum { + ITEM_HELP=100, + ITEM_PASTE, + ITEM_EXECUTE, + ITEM_CONFIGURE_BACKGROUND, + ITEM_CONFIGURE_ICONS, + ITEM_UNCLUTTER_WINDOWS, + ITEM_CASCADE_WINDOWS, + ITEM_ARRANGE_ICONS, + ITEM_LOCK_SCREEN, + ITEM_LOGOUT +}; + +/** + * This class is the handler for the menus (root popup menu and desktop menubar) + */ +class KRootWm: public TQObject { + Q_OBJECT + +public: + KRootWm(KDesktop*); + ~KRootWm(); + + bool startup; + void mousePressed( const TQPoint& _global, int _button ); + bool hasLeftButtonMenu() { return leftButtonChoice != NOTHING; } + + /** + * Return the unique KRootWm instance + */ + static KRootWm * self() { return s_rootWm; } + + /** + * share this with desktop.cc + */ + KNewMenu * newMenu() const { return menuNew; } + + /** + * The position of the (usually RMB) click that opened the 'desktop' menu + */ + TQPoint desktopMenuPosition() const { return m_desktopMenuPosition; } + + /** + * Read and apply configuration + */ + void initConfig(); + + /** + * List of config modules used by Configure Desktop + */ + static TQStringList configModules(); + +public slots: + void slotArrangeByNameCS(); + void slotArrangeByNameCI(); + void slotArrangeBySize(); + void slotArrangeByType(); + void slotArrangeByDate(); + void slotLineupIconsHoriz(); + void slotLineupIconsVert(); + void slotLineupIcons(); + void slotRefreshDesktop(); + void slotConfigureDesktop(); + void slotToggleDirFirst( bool ); + void slotToggleAutoAlign( bool ); + void slotToggleLockIcons( bool ); + void slotToggleDesktopMenu(); + void slotUnclutterWindows(); + void slotCascadeWindows(); + void slotWindowList(); + void slotLock(); + void slotLogout(); + void slotSave(); + void slotSwitchUser(); + void slotPopulateSessions(); + void slotSessionActivated( int ); + void slotNewSession(); + void slotOpenTerminal(); + void slotLockNNewSession(); + +private: + KDesktop* m_pDesktop; + + // The five root menus : + KWindowListMenu* windowListMenu; + TQPopupMenu* desktopMenu; + // the appMenu is (will be) provided by kicker + TQPopupMenu* customMenu1; + TQPopupMenu* customMenu2; + KCMultiDialog* m_configDialog; + + // Configuration for the root menus : + typedef enum { NOTHING = 0, WINDOWLISTMENU, DESKTOPMENU, APPMENU, CUSTOMMENU1, CUSTOMMENU2, BOOKMARKSMENU, SESSIONSMENU } menuChoice; + menuChoice leftButtonChoice; + menuChoice middleButtonChoice; + menuChoice rightButtonChoice; + + KNewMenu* menuNew; + TDEActionMenu* bookmarks; + KBookmarkMenu* bookmarkMenu; + TDEActionCollection * m_actionCollection; + TQPoint m_desktopMenuPosition; + + void activateMenu( menuChoice choice, const TQPoint& global ); + void buildMenus(); + + bool m_bShowMenuBar; + bool m_bGlobalMenuBar; + bool m_bInit; + bool m_bDesktopEnabled; + KMenuBar *menuBar; + + TQPopupMenu *file; + TQPopupMenu *desk; + KHelpMenu *help; + + TQPixmap defaultPixmap; + + void doNewSession( bool lock ); + TQPopupMenu *sessionsMenu; + + static KRootWm * s_rootWm; + + +private slots: + + void slotMenuItemActivated(int); + void slotFileNewAboutToShow(); + void slotWindowListAboutToShow(); + void slotConfigClosed(); +}; + +#endif diff --git a/kdesktop/kshadowengine.cpp b/kdesktop/kshadowengine.cpp new file mode 100644 index 000000000..9b6529360 --- /dev/null +++ b/kdesktop/kshadowengine.cpp @@ -0,0 +1,195 @@ +/* This file is proposed to be part of the KDE libraries. + * Copyright (C) 2003 Laur Ivan <[email protected]> + * + * Many thanks to: + * - Bernardo Hung <[email protected]> for the enhanced shadow + * algorithm (currently used) + * - Tim Jansen <[email protected]> for the API updates and fixes. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "kshadowengine.h" +#include <tqcolor.h> +#include "kshadowsettings.h" + +KShadowEngine::KShadowEngine() : + m_shadowSettings( new KShadowSettings ) +{ +} + +KShadowEngine::~KShadowEngine() +{ + delete m_shadowSettings; +} + +KShadowEngine::KShadowEngine(KShadowSettings *fx) : + m_shadowSettings(0L) +{ + setShadowSettings(fx); +} + + +void KShadowEngine::setShadowSettings(KShadowSettings *fx) +{ + delete m_shadowSettings; + + m_shadowSettings = fx; +} + +KShadowSettings *KShadowEngine::shadowSettings() +{ + return m_shadowSettings; +} + +TQImage KShadowEngine::makeShadow(const TQPixmap& textPixmap, const TQColor &bgColor) +{ + TQImage result; + + // create a new image for for the shaddow + int w = textPixmap.width(); + int h = textPixmap.height(); + + // avoid calling these methods for every pixel + int bgRed = bgColor.red(); + int bgGreen = bgColor.green(); + int bgBlue = bgColor.blue(); + + int thick = m_shadowSettings->thickness() >> 1; + + double alphaShadow; + + /* + * This is the source pixmap + */ + TQImage img = textPixmap.convertToImage().convertDepth(32); + + /* + * Resize the image if necessary + */ + if ((result.width() != w) || (result.height() != h)) + { + result.create(w, h, 32); + } + + result.fill(0); // alpha to zero (Qt3 needs this) + result.setAlphaBuffer(true); + result.fill(0); // rest to all black (Qt4 needs this) + + for (int i = thick; i < w - thick; i++) + { + for (int j = thick; j < h - thick; j++) + { + switch (m_shadowSettings->algorithm()) + { + case KShadowSettings::DoubleLinearDecay: + alphaShadow = doubleLinearDecay(img, i, j); + break; + case KShadowSettings::RadialDecay: + alphaShadow = radialDecay(img, i, j); + break; + case KShadowSettings::NoDecay: + alphaShadow = noDecay(img, i, j); + break; + case KShadowSettings::DefaultDecay: + default: + alphaShadow = defaultDecay(img, i, j); + } + + alphaShadow = (alphaShadow > m_shadowSettings->maxOpacity()) ? m_shadowSettings->maxOpacity() : alphaShadow; + + // update the shadow's i,j pixel. + result.setPixel(i,j, tqRgba(bgRed, bgGreen , bgBlue, (int) alphaShadow)); + } + } + return result; +} + +// Multiplication factor for pixels directly above, under, or next to the text +#define AXIS_FACTOR 2.0 +// Multiplication factor for pixels diagonal to the text +#define DIAGONAL_FACTOR 1.0 + +double KShadowEngine::defaultDecay(TQImage& source, int i, int j) +{ + if ((i < 1) || (j < 1) || (i > source.width() - 2) || (j > source.height() - 2)) + return 0; + + double alphaShadow; + alphaShadow =(tqGray(source.pixel(i-1,j-1)) * DIAGONAL_FACTOR + + tqGray(source.pixel(i-1,j )) * AXIS_FACTOR + + tqGray(source.pixel(i-1,j+1)) * DIAGONAL_FACTOR + + tqGray(source.pixel(i ,j-1)) * AXIS_FACTOR + + 0 + + tqGray(source.pixel(i ,j+1)) * AXIS_FACTOR + + tqGray(source.pixel(i+1,j-1)) * DIAGONAL_FACTOR + + tqGray(source.pixel(i+1,j )) * AXIS_FACTOR + + tqGray(source.pixel(i+1,j+1)) * DIAGONAL_FACTOR) / m_shadowSettings->multiplicationFactor(); + + return alphaShadow; +} + +double KShadowEngine::doubleLinearDecay(TQImage& source, int i, int j) +{ + //printf("img: %p, %d %d\n", (char *) &source, i, j); + return defaultDecay( source, i, j ); // for now +} + +double KShadowEngine::radialDecay(TQImage& source, int i, int j) +{ + //printf("img: %p, %d %d\n", (char *) &source, i, j); + return defaultDecay( source, i, j ); // for now +} + +double KShadowEngine::noDecay(TQImage& source, int i, int j) +{ + // create a new image for for the shaddow + int w = source.width(); + int h = source.height(); + int sx, sy; + //int thick = m_shadowSettings->thickness() >> 1; + + double alphaShadow = 0; + double opacity = 0; + for (int k = 1; k <= m_shadowSettings->thickness(); k++) { + /* Generate a shadow THICKNESS pixels thicker + * on either side than the text image. Ensure + * that i +/- k and j +/- k are within the + * bounds of the text pixmap. + */ + opacity = 0; + for (int l = -k; l <= k; l++) { + if (i < k) + sx = 0; + else if (i >= w - k) + sx = w - 1; + else + sx = i + l; + + for (int m = -k; m <= k; m++) { + if (j < k) + sy = 0; + else if (j >= h - k) + sy = h - 1; + else + sy = j + m; + + opacity += tqGray(source.pixel(sx, sy)); + } + } + alphaShadow += opacity / m_shadowSettings->multiplicationFactor(); + } + return alphaShadow; +} diff --git a/kdesktop/kshadowengine.h b/kdesktop/kshadowengine.h new file mode 100644 index 000000000..3443eda40 --- /dev/null +++ b/kdesktop/kshadowengine.h @@ -0,0 +1,113 @@ +/* This file is proposed to be part of the KDE libraries. + * Copyright (C) 2003 Laur Ivan <[email protected]> + * + * Many thanks to: + * - Bernardo Hung <[email protected]> for the enhanced shadow + * algorithm (currently used) + * - Tim Jansen <[email protected]> for the API updates and fixes. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __FX_SHADOW +#define __FX_SHADOW + +#include <tqpixmap.h> +#include <tqimage.h> +#include <tqcolor.h> + +class KShadowSettings; + +/** + * This class implements the shadow algorithm(s). It uses a FxData + * object for its parameters. Note that the shadow algorithm is using the + * luminosity of the original pixmap for the shadow one. + * @see KShadowSettings + * @author [email protected] + * @since 3.2 + */ +class KShadowEngine +{ + public: + /// Creates a new shadow engine. + KShadowEngine(); + + ~KShadowEngine(); + + /** + * Creates a new shadow engine. + * @param fx the shadow settings object with the configuration. The Shadow + * Engine will own this object and also delete it. Must + * be heap-allocated + */ + KShadowEngine(KShadowSettings *fx); + + /** + * Set the KShadowSettings object. + * @param fx the shadow settings object with the configuration. The Shadow + * Engine will own this object and also delete it. Must + * be heap-allocated. + */ + void setShadowSettings(KShadowSettings *fx); + + /** + * Get the current KShadowSettings. + * @param the current shadow settings + */ + KShadowSettings *shadowSettings(); + + /** + * Make shadow! + * + * textPixmap is the original pixmap where a (white) text is drawn. + * bgColor is the color used for the shadow. + * @param textPixmap the pixmap of the text + * @param bgColor the background color + * @return the resulting image + */ + TQImage makeShadow(const TQPixmap& textPixmap, const TQColor &bgColor); + + private: + // No static objects in libs, and no static deleters in tdefx... + //static KShadowSettings s_defaultShadowSettings; + + KShadowSettings *m_shadowSettings; + + /* + * a simple algorithm with 3 pixels thickness + */ + double defaultDecay(TQImage& source, int x, int y); + + /* + * a slower algorithm where the influence of a pixel + * is tqGray(px)/(abs(dx) + abs(dy) +1). + */ + double doubleLinearDecay(TQImage& source, int x, int y); + + /* + * a very slow algorithm where the influence of a pixel + * is tqGray(px)/(sqrt(sqr(dx) + sqr(dy)) +1). + */ + double radialDecay(TQImage& source, int x, int y); + + /* + * a nice/fast algorithm proposed by Bernardo Hung + */ + double noDecay(TQImage& source, int x, int y); + + void *d; +}; + +#endif diff --git a/kdesktop/kshadowsettings.cpp b/kdesktop/kshadowsettings.cpp new file mode 100644 index 000000000..4d6bce5c3 --- /dev/null +++ b/kdesktop/kshadowsettings.cpp @@ -0,0 +1,182 @@ +/* This file is proposed to be part of the KDE libraries. + * Copyright (C) 2003 Laur Ivan <[email protected]> + * + * Many thanks to: + * - Tim Jansen <[email protected]> for the API updates and fixes. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <tqstring.h> +#include <tqstringlist.h> +#include "kshadowsettings.h" + +KShadowSettings::KShadowSettings() +{ + // init the components with some default values + setDefaults(); +} + +// load/save methods +void KShadowSettings::fromString(const TQString &val) +{ + setOffsetX(val.section(',', OFFSET_X, OFFSET_X).toInt()); + setOffsetY(val.section(',', OFFSET_Y, OFFSET_Y).toInt()); + setMultiplicationFactor(val.section(',', MULTIPLICATION_FACTOR, MULTIPLICATION_FACTOR).toDouble()); + setMaxOpacity(val.section(',', MAX_OPACITY, MAX_OPACITY).toDouble()); + setThickness(val.section(',', THICKNESS, THICKNESS).toInt()); + setAlgorithm((Algorithm) val.section(',', ALGORITHM, ALGORITHM).toInt()); + setSelectionType((SelectionType)val.section(',', SELECTION_TYPE, SELECTION_TYPE).toInt()); +} + +TQString KShadowSettings::toString() const +{ + TQString result; + result.sprintf("%d,%d,%f,%f,%d,%d,%d", + offsetX(), + offsetY(), + multiplicationFactor(), + maxOpacity(), + thickness(), + (int)algorithm(), + (int)selectionType()); + return result; +} + +//*********************************** +// get methods +//*********************************** + +/** + * Returns the decay algorithm to be used (see the alg. enumeration in the .h) + */ +KShadowSettings::Algorithm KShadowSettings::algorithm() const +{ + return _algorithm; +} + +/** + * Returns a multiplication facor used to average the resulted data + */ +double KShadowSettings::multiplicationFactor() const +{ + return _multiplicationFactor; +} + +/** + * Returns the max opacity allowed (0 = transparent, 255 = opaque) + */ +double KShadowSettings::maxOpacity() const +{ + return _maxOpacity; +} + +/** + * Returns the Y offset (0 is centered on text) + */ +int KShadowSettings::offsetX() const +{ + return _offsetX; +} + +/** + * Returns the Y offset (0 is centered on text) + */ +int KShadowSettings::offsetY() const +{ + return _offsetY; +} + +/** + * Returns the thickness. Used by the KShadow algorithm + */ +int KShadowSettings::thickness() const +{ + return _thickness; +} + +/** + * Returns the selection type + */ +KShadowSettings::SelectionType KShadowSettings::selectionType() const +{ + return _selectionType; +} + +// set methods +/** + * set the default parameters + */ +void KShadowSettings::setDefaults() +{ + fromString(DEFAULT_SHADOW_CONFIGURATION); +} + + +/** + * Set the algorithm + */ +void KShadowSettings::setAlgorithm(Algorithm val) +{ + _algorithm = val; +} + +/** + * Set the multiplication factor + */ +void KShadowSettings::setMultiplicationFactor(double val) +{ + _multiplicationFactor = val; +} + +/** + * Set the max. opacity + */ +void KShadowSettings::setMaxOpacity(double val) +{ + _maxOpacity = val; +} + +/** + * Set the X offset of the shadow + */ +void KShadowSettings::setOffsetX(int val) +{ + _offsetX = val; +} + +/** + * Set the Y offset of the shadow + */ +void KShadowSettings::setOffsetY(int val) +{ + _offsetY = val; +} + +/** + * Set the shadow thickness + */ +void KShadowSettings::setThickness(int val) +{ + _thickness = val; +} + +/** + * Set the selection type + */ +void KShadowSettings::setSelectionType(SelectionType val) +{ + _selectionType = val; +} diff --git a/kdesktop/kshadowsettings.h b/kdesktop/kshadowsettings.h new file mode 100644 index 000000000..1af544898 --- /dev/null +++ b/kdesktop/kshadowsettings.h @@ -0,0 +1,234 @@ +/* This file is proposed to be part of the KDE libraries. + * Copyright (C) 2003 Laur Ivan <[email protected]> + * + * Many thanks to: + * - Tim Jansen <[email protected]> for the API updates and fixes. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __FX_DATA +#define __FX_DATA + +#define SHADOW_CONFIG_ENTRY TQString("ShadowParameters") +#define SHADOW_TEXT_COLOR TQString("ShadowTextColor") +#define SHADOW_TEXT_BACKGROUND TQString("ShadowTextBackground") + +// fallback configuration string +#define DEFAULT_SHADOW_CONFIGURATION TQString("0,0,4.0,120.0,2,1,1,0,0,0") + +/** + * This class is the implementation of a structure for the + * various parameters required by the shadow class. + * + * One may afford this implementation since the shadow class is + * designed to be used as singleton for an application. + * @see KShadowEngine + * @author [email protected] + * @since 3.2 + */ +class KShadowSettings +{ + public: + /** + * Specifies the order of the options. + * @see fromString + */ + enum ConfigurationOrder + { + OFFSET_X = 0, + OFFSET_Y = OFFSET_X + 1, + MULTIPLICATION_FACTOR = OFFSET_Y + 1, + MAX_OPACITY = MULTIPLICATION_FACTOR + 1, + THICKNESS = MAX_OPACITY + 1, + ALGORITHM = THICKNESS + 1, + SELECTION_TYPE = ALGORITHM + 1 + }; + + public: + /** + * The algorithm used. + */ + enum Algorithm + { + DefaultDecay = 1, ///< the default AXIS/DIAGONAL_FACTOR based alg + DoubleLinearDecay, ///< decay factor is 1/dx+dy + RadialDecay, ///< decay factor is 1/sqrt(dx*dx + dy*dy) + NoDecay ///< decay factor is 1 always + }; + + /** + * The selected method used. + */ + enum SelectionType + { + InverseVideoOnSelection = 0, ///< when selected, the halo is on I/Video + SelectionColorsOnSelection ///< the halo is made w/ selected colors + }; + + /** + * The default constructor. + * Creates an object with default settings for all the variabless. + */ + KShadowSettings(); + + // load/save methods + /** + * Loads the configuration from a string. + * @param the string to load from (comma-separated values) + * @see ConfigurationOrder + */ + virtual void fromString(const TQString &s); + /** + * Saves the configuration to a string. + * @return the configuration (comma-separated values) + * @see ConfigurationOrder + */ + virtual TQString toString() const; + + // get methods + /** + * Returns the x offset of the shadow. + * @return the x offset + */ + int offsetX() const; + + /** + * Returns the y offset of the shadow. + * @return the y offset + */ + int offsetY() const; + + /** + * Returns the multiplication factor. + * @return the multiplication factor + */ + double multiplicationFactor() const; + + /** + * Returns the maximum opacity of the shadow. + * @return the maximum opacity + */ + double maxOpacity() const; + + /** + * Returns the thickness. + * @return the thickness + */ + int thickness() const; + + /** + * Returns the used algorithm. + * @return the algorithm used + */ + Algorithm algorithm() const; + + /** + * Returns the selection type used. + * @return the selection type + */ + SelectionType selectionType() const; + + // set methods + /** + * Sets default values. + */ + virtual void setDefaults(); + + /** + * Sets the used algorithm. + * @param a the algorithm used + */ + virtual void setAlgorithm(Algorithm a); + + /** + * Sets the multiplication factor. + * @param mf the multiplication factor + */ + virtual void setMultiplicationFactor(double mf); + + /** + * Sets the maximum opacity of the shadow. + * @param mo the maximum opacity + */ + virtual void setMaxOpacity(double mo); + + /** + * Sets the x offset of the shadow. + * @param x the x offset + */ + virtual void setOffsetX(int x); + + /** + * Sets the y offset of the shadow. + * @param y the y offset + */ + virtual void setOffsetY(int y); + + /** + * Sets the thickness. + * @param t the thickness + */ + virtual void setThickness(int t); + + /** + * Sets the selection type used. + * @param s the selection type + */ + virtual void setSelectionType(SelectionType s); + + private: + + /* + * The employed algorithm (see fxshadow.h) + */ + Algorithm _algorithm; + + /** + * This is the multiplication factor for the resulted shadow + */ + double _multiplicationFactor; + + /** + * The maximum permitted opacity for the shadow + */ + double _maxOpacity; + + /* + * offsetX and offsetY are the x/y offsets of the shadow with + * the mention that 0,0 is a centered shadow. + */ + int _offsetX; + int _offsetY; + + /* + * The shadow thickness: + * shadow is this many pixels thicker than the text. + */ + int _thickness; + + /* + * If the value is InverseVideoOnSelection, then the fg/bg + * colours are swapped when the element is selected. + * Otherwise, the selected fg/bg colors are used for text + * as well + */ + SelectionType _selectionType; + + void *d; +}; + + +#endif diff --git a/kdesktop/kwebdesktop/CMakeLists.txt b/kdesktop/kwebdesktop/CMakeLists.txt new file mode 100644 index 000000000..741b8df34 --- /dev/null +++ b/kdesktop/kwebdesktop/CMakeLists.txt @@ -0,0 +1,42 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES kwebdesktop.desktop DESTINATION ${DATA_INSTALL_DIR}/kdesktop/programs ) +install( FILES kwebdesktop.kcfg DESTINATION ${KCFG_INSTALL_DIR} ) + + +##### kwebdesktop (executable) ################## + +set( target kwebdesktop ) + +set( ${target}_SRCS + kwebdesktop.cpp kwebdesktopsettings.kcfgc +) + +tde_add_executable( ${target} AUTOMOC + SOURCES ${${target}_SRCS} + LINK tdehtml-shared + DESTINATION ${BIN_INSTALL_DIR} +) diff --git a/kdesktop/kwebdesktop/Makefile.am b/kdesktop/kwebdesktop/Makefile.am new file mode 100644 index 000000000..0d627675f --- /dev/null +++ b/kdesktop/kwebdesktop/Makefile.am @@ -0,0 +1,15 @@ + +INCLUDES= $(all_includes) +LDADD = $(LIB_TDEHTML) + +bin_PROGRAMS = kwebdesktop + +METASOURCES = AUTO + +kwebdesktop_SOURCES = kwebdesktop.cpp kwebdesktopsettings.kcfgc +kwebdesktop_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor + +kdesktop_kwebdesktop_data_DATA = kwebdesktop.desktop +kdesktop_kwebdesktop_datadir = $(kde_datadir)/kdesktop/programs + +kde_kcfg_DATA = kwebdesktop.kcfg diff --git a/kdesktop/kwebdesktop/kwebdesktop.cpp b/kdesktop/kwebdesktop/kwebdesktop.cpp new file mode 100644 index 000000000..1e2499ea2 --- /dev/null +++ b/kdesktop/kwebdesktop/kwebdesktop.cpp @@ -0,0 +1,193 @@ +/* This file is part of the KDE project + Copyright (C) 2000 David Faure <[email protected]> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// Idea by Gael Duval +// Implementation by David Faure + +#include <config.h> + +#include <tdeapplication.h> +#include <tdeconfig.h> +#include <kdebug.h> +#include <tdelocale.h> +#include <tdecmdlineargs.h> +#include <tdeaboutdata.h> +#include <kurifilter.h> +#include <tdeio/job.h> + +#include <tqscrollview.h> +#include "kwebdesktop.h" +#include <kmimetype.h> +#include <tdeparts/componentfactory.h> +#include "kwebdesktopsettings.h" + +#include "kwebdesktop.moc" + +static TDECmdLineOptions options[] = +{ + { "+width", I18N_NOOP("Width of the image to create"), 0 }, + { "+height", I18N_NOOP("Height of the image to create"), 0 }, + { "+file", I18N_NOOP("File sname where to dump the output in png format"), 0 }, + { "+[URL]", I18N_NOOP("URL to open (if not specified, it is read from kwebdesktoprc)"), 0 }, + TDECmdLineLastOption +}; + +KWebDesktopRun::KWebDesktopRun( KWebDesktop* webDesktop, const KURL & url ) + : m_webDesktop(webDesktop), m_url(url) +{ + kdDebug() << "KWebDesktopRun::KWebDesktopRun starting get" << endl; + TDEIO::Job * job = TDEIO::get(m_url, false, false); + connect( job, TQT_SIGNAL( result( TDEIO::Job *)), + this, TQT_SLOT( slotFinished(TDEIO::Job *))); + connect( job, TQT_SIGNAL( mimetype( TDEIO::Job *, const TQString &)), + this, TQT_SLOT( slotMimetype(TDEIO::Job *, const TQString &))); +} + +void KWebDesktopRun::slotMimetype( TDEIO::Job *job, const TQString &_type ) +{ + TDEIO::SimpleJob *sjob = static_cast<TDEIO::SimpleJob *>(job); + // Update our URL in case of a redirection + m_url = sjob->url(); + TQString type = _type; // necessary copy if we plan to use it + sjob->putOnHold(); + kdDebug() << "slotMimetype : " << type << endl; + + KParts::ReadOnlyPart* part = m_webDesktop->createPart( type ); + // Now open the URL in the part + if ( part ) + part->openURL( m_url ); +} + +void KWebDesktopRun::slotFinished( TDEIO::Job * job ) +{ + // The whole point of all this is to abort silently on error + if (job->error()) + { + kdDebug() << job->errorString() << endl; + kapp->exit(1); + } +} + + +int main( int argc, char **argv ) +{ + TDEAboutData data( "kwebdesktop", I18N_NOOP("TDE Web Desktop"), + VERSION, + I18N_NOOP("Displays an HTML page as the background of the desktop"), + TDEAboutData::License_GPL, + "(c) 2000, David Faure <[email protected]>" ); + data.addAuthor( "David Faure", I18N_NOOP("developer and maintainer"), "[email protected]" ); + + TDECmdLineArgs::init( argc, argv, &data ); + + TDECmdLineArgs::addCmdLineOptions( options ); // Add our own options. + + TDEApplication app; + + TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); + if ( args->count() != 3 && args->count() != 4 ) + { + args->usage(); + return 1; + } + const int width = TQCString(args->arg(0)).toInt(); + const int height = TQCString(args->arg(1)).toInt(); + TQCString imageFile = args->arg(2); + TQString url; + if (args->count() == 4) + url = TQString::fromLocal8Bit(args->arg(3)); + + KWebDesktop *webDesktop = new KWebDesktop( 0, imageFile, width, height ); + + if (url.isEmpty()) + url = KWebDesktopSettings::uRL(); + // Apply uri filter + KURIFilterData uridata = url; + KURIFilter::self()->filterURI( uridata ); + KURL u = uridata.uri(); + + // Now start getting, to ensure mimetype and possible connection + KWebDesktopRun * run = new KWebDesktopRun( webDesktop, u ); + + int ret = app.exec(); + + TDEIO::SimpleJob::removeOnHold(); // Kill any slave that was put on hold. + delete webDesktop; + delete run; + //tdehtml::Cache::clear(); + + return ret; +} + +void KWebDesktop::slotCompleted() +{ + kdDebug() << "KWebDesktop::slotCompleted" << endl; + // Dump image to m_imageFile + TQPixmap snapshot = TQPixmap::grabWidget( m_part->widget() ); + snapshot.save( m_imageFile, "PNG" ); + // And terminate the app. + kapp->quit(); +} + +KParts::ReadOnlyPart* KWebDesktop::createPart( const TQString& mimeType ) +{ + delete m_part; + m_part = 0; + + KMimeType::Ptr mime = KMimeType::mimeType( mimeType ); + if ( !mime || mime == KMimeType::defaultMimeTypePtr() ) + return 0; + if ( mime->is( "text/html" ) || mime->is( "text/xml" ) || mime->is( "application/xhtml+xml" ) ) + { + TDEHTMLPart* htmlPart = new TDEHTMLPart; + htmlPart->widget()->resize(m_width,m_height); + + htmlPart->setMetaRefreshEnabled(false); + htmlPart->setJScriptEnabled(false); + htmlPart->setJavaEnabled(false); + htmlPart->setPluginsEnabled(false); + + ((TQScrollView *)htmlPart->widget())->setFrameStyle( TQFrame::NoFrame ); + ((TQScrollView *)htmlPart->widget())->setHScrollBarMode( TQScrollView::AlwaysOff ); + ((TQScrollView *)htmlPart->widget())->setVScrollBarMode( TQScrollView::AlwaysOff ); + + connect( htmlPart, TQT_SIGNAL( completed() ), this, TQT_SLOT( slotCompleted() ) ); + m_part = htmlPart; + } else { + // Try to find an appropriate viewer component + m_part = KParts::ComponentFactory::createPartInstanceFromQuery<KParts::ReadOnlyPart> + ( mimeType, TQString(), 0, 0, this, 0 ); + if ( !m_part ) + kdWarning() << "No handler found for " << mimeType << endl; + else { + kdDebug() << "Loaded " << m_part->className() << endl; + connect( m_part, TQT_SIGNAL( completed() ), + this, TQT_SLOT( slotCompleted() ) ); + } + } + if ( m_part ) { + connect( m_part, TQT_SIGNAL( canceled(const TQString &) ), + this, TQT_SLOT( slotCompleted() ) ); + } + return m_part; +} + +KWebDesktop::~KWebDesktop() +{ + delete m_part; +} diff --git a/kdesktop/kwebdesktop/kwebdesktop.desktop b/kdesktop/kwebdesktop/kwebdesktop.desktop new file mode 100644 index 000000000..a60c009d0 --- /dev/null +++ b/kdesktop/kwebdesktop/kwebdesktop.desktop @@ -0,0 +1,80 @@ +[TDE Desktop Program] +Comment=TDE Web Desktop +Comment[af]=TDE Web Werkskerm +Comment[ar]=سطح المكتب TDE للشبكة +Comment[az]=TDE Veb Masa üstü +Comment[be]=Працоўны стол Web +Comment[bn]=কে.ডি.ই. ওয়েব ডেস্কটপ +Comment[br]=Burev gwiad TDE +Comment[bs]=TDE Web radna površina +Comment[ca]=Escriptori Web TDE +Comment[cs]=Aktivní plocha TDE +Comment[csb]=Pùlt w sztélu sécë WWW +Comment[cy]=Penbwrdd Gwe TDE +Comment[da]=TDE-net-desktop +Comment[de]=TDE-Web-Arbeitsfläche +Comment[el]=Επιφάνεια εργασίας Ιστού του TDE +Comment[eo]=TDEa TTT-tabulo +Comment[es]=Escritorio Web para TDE +Comment[et]=TDE veebitöölaud +Comment[eu]=TDE web mahaigaina +Comment[fa]=رومیزی وب TDE +Comment[fi]=TDE:n web-työpöytä +Comment[fr]=Bureau web de TDE +Comment[fy]=TDE Web Buroblêd +Comment[gl]=Escritório Web de TDE +Comment[he]=שולחן העבודה האינטרנטי של TDE +Comment[hi]=केडीई वेब डेस्कटॉप +Comment[hr]=TDE web radna površina +Comment[hu]=TDE internetes munkaasztal +Comment[id]=Desktop Web TDE +Comment[is]=TDE vefskjáborð +Comment[it]=Desktop Web di TDE +Comment[ja]=TDE ウェブデスクトップ +Comment[ka]=TDE ვებ სამუშაო დაფა +Comment[km]=ផ្ទៃតុបណ្ដាញ TDE +Comment[lo]=ພື້ນທີ່ທຳງານບົນເວ໊ບ TDE +Comment[lt]=TDE žiniatinklio darbastalis +Comment[lv]=TDE Web Darbvirsma +Comment[mk]=TDE веб-површина +Comment[mn]=КДЭ-Вэб-Ажлын тавцан +Comment[ms]=Desktop Web TDE +Comment[mt]=Desktop Web TDE +Comment[nb]=TDE nettskrivebord +Comment[nds]=TDE-Nettschriefdisch +Comment[ne]=TDE वेब डेस्कटप +Comment[nl]=TDE Web Bureaublad +Comment[nn]=TDE Vevskrivebord +Comment[nso]=Desktop ya Web ya TDE +Comment[oc]=BurèU Web TDE +Comment[pa]=TDE ਵੈੱਬ ਵੇਹੜਾ +Comment[pl]=Pulpit w stylu sieci WWW +Comment[pt]=Ecrã Web do TDE +Comment[pt_BR]=Área de Trabalho Web do TDE +Comment[ro]=Ecran web pentru TDE +Comment[rw]=TDE Ibiro Rubugamakuru +Comment[se]=TDE Web-čállinbeavdi +Comment[sk]=TDE Web pracovná plocha +Comment[sl]=Spletno namizje TDE +Comment[sr]=TDE веб радна површина +Comment[sr@Latn]=TDE veb radna površina +Comment[sv]=TDE-webbskrivbord +Comment[ta]=TDE வலை மேல்மேசை +Comment[te]=కెడిఈ వెబ్ రంగస్థలం +Comment[tg]=Мизи кории TDE Вэб +Comment[th]=พื้นที่ทำงาน TDE แบบเว็บ +Comment[tr]=TDE Web Masaüstü +Comment[tt]=TDE Web Östäl +Comment[uk]=Стільниця "а ля Web" для TDE +Comment[uz]=TDE veb-ish stoli +Comment[uz@cyrillic]=TDE веб-иш столи +Comment[ven]=Webe ya desikithopo ya TDE +Comment[vi]=màn hình nền kiểu trang mạng của TDE +Comment[wa]=Sicribanne waibe TDE +Comment[zh_CN]=TDE Web 桌面 +Comment[zh_TW]=TDE 網頁桌面 +Comment[zu]=I-Desktop ye-Web ye-TDE +Executable=kwebdesktop +Command=kwebdesktop %x %y %f http://www.kde.org/ +PreviewCommand=kwebdesktop %x %y %f http://www.kde.org/ +Refresh=10 diff --git a/kdesktop/kwebdesktop/kwebdesktop.h b/kdesktop/kwebdesktop/kwebdesktop.h new file mode 100644 index 000000000..2641378cf --- /dev/null +++ b/kdesktop/kwebdesktop/kwebdesktop.h @@ -0,0 +1,70 @@ +/* This file is part of the KDE project + Copyright (C) 2000 David Faure <[email protected]> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KWEBDESKTOP_H +#define KWEBDESKTOP_H + +#include <tqobject.h> +#include <tqcstring.h> +#include <tdeparts/browserextension.h> +#include <tdehtml_part.h> + +namespace TDEIO { class Job; } + +class KWebDesktop : public TQObject +{ + Q_OBJECT +public: + KWebDesktop( TQObject* parent, const TQCString & imageFile, int width, int height ) + : TQObject( parent ), + m_part( 0 ), + m_imageFile( imageFile ), + m_width( width ), + m_height( height ) {} + ~KWebDesktop(); + + KParts::ReadOnlyPart* createPart( const TQString& mimeType ); + +private slots: + void slotCompleted(); + +private: + KParts::ReadOnlyPart* m_part; + TQCString m_imageFile; + int m_width; + int m_height; +}; + + +class KWebDesktopRun : public QObject +{ + Q_OBJECT +public: + KWebDesktopRun( KWebDesktop* webDesktop, const KURL & url ); + ~KWebDesktopRun() {} + +protected slots: + void slotMimetype( TDEIO::Job *job, const TQString &_type ); + void slotFinished( TDEIO::Job * job ); + +private: + KWebDesktop* m_webDesktop; + KURL m_url; +}; + +#endif diff --git a/kdesktop/kwebdesktop/kwebdesktop.kcfg b/kdesktop/kwebdesktop/kwebdesktop.kcfg new file mode 100644 index 000000000..b0920f410 --- /dev/null +++ b/kdesktop/kwebdesktop/kwebdesktop.kcfg @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <kcfgfile name="kwebdesktoprc" /> + <!-- generated by TDEConfig XTraKtor --> + + <group name="Settings"> + <entry key="URL" type="String"> + <default>http://www.kde.org/</default> + <label></label> + <whatsthis></whatsthis> + <!-- kdiconview.cc:1103 --> + <!-- cfg.readEntry( "URL" ) == "trash:/" ) { --> + </entry> + </group> + +</kcfg> diff --git a/kdesktop/kwebdesktop/kwebdesktopsettings.kcfgc b/kdesktop/kwebdesktop/kwebdesktopsettings.kcfgc new file mode 100644 index 000000000..6989a0071 --- /dev/null +++ b/kdesktop/kwebdesktop/kwebdesktopsettings.kcfgc @@ -0,0 +1,4 @@ +File=kwebdesktop.kcfg +ClassName=KWebDesktopSettings +Singleton=true +Mutators=true diff --git a/kdesktop/kxdglauncher.cpp b/kdesktop/kxdglauncher.cpp new file mode 100644 index 000000000..9d689d95f --- /dev/null +++ b/kdesktop/kxdglauncher.cpp @@ -0,0 +1,188 @@ +/* This file is part of the KDE project + Copyright (C) 2010 Timothy Pearson <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <tqfile.h> +#include <tqdir.h> +#include <tqtimer.h> +#include <tqstring.h> +#include <tqtextcodec.h> + +#include <krun.h> +#include <tdefile.h> +#include <tdelocale.h> +#include <tdeapplication.h> +#include <tdecmdlineargs.h> +#include <tdeglobalsettings.h> +#include <kinputdialog.h> +#include <tdemessagebox.h> +#include <tdeconfig.h> +#include <kurlrequester.h> +#include <kurlrequesterdlg.h> + +#include <stdlib.h> + +#include "kxdglauncher.h" + +// helper function for reading xdg user dirs: it is required for obvious reasons +void readXdgUserDirs(TQString *desktop, TQString *documents) +{ + TQFile f( TQDir::homeDirPath() + "/.config/user-dirs.dirs" ); + + if (!f.open(IO_ReadOnly)) + return; + + // set the codec for the current locale + TQTextStream s(&f); + s.setCodec( TQTextCodec::codecForLocale() ); + + TQString line = s.readLine(); + while (!line.isNull()) + { + if (line.startsWith("XDG_DESKTOP_DIR=")) { + *desktop = TQString(line.remove("XDG_DESKTOP_DIR=").remove("\"")).replace("$HOME", TQDir::homeDirPath()); + } + else if (line.startsWith("XDG_DOCUMENTS_DIR=")) { + *documents = TQString(line.remove("XDG_DOCUMENTS_DIR=").remove("\"")).replace("$HOME", TQDir::homeDirPath()); + } + + line = s.readLine(); + } +} + +TQString getDocumentPath() +{ + TQString s_desktopPath; + TQString s_documentPath; + + readXdgUserDirs(&s_desktopPath, &s_documentPath); + + if (s_documentPath.isEmpty() == true) { +#ifdef Q_WS_WIN + s_documentPath = getWin32ShellFoldersPath("Personal"); +#else + s_documentPath = TQDir::homeDirPath() + "/Documents/"; +#endif + } + s_documentPath = TQDir::cleanDirPath( s_documentPath ); + if ( !s_documentPath.endsWith("/")) + s_documentPath.append('/'); + + return s_documentPath; +} + +static TDECmdLineOptions options[] = +{ + { "xdgname <argument>", I18N_NOOP("XDG variable name to open"), 0 }, + { "getpath", I18N_NOOP("Do not launch Konqueror; instead print path to directory if it exists)"), 0 }, + TDECmdLineLastOption +}; + +int main( int argc, char **argv) +{ + TDECmdLineArgs::init( argc, argv, "kxdglauncher", I18N_NOOP("TDE XDG File Browser Launcher and Prompter"), I18N_NOOP("Prompts if directory does not exist, otherwise launches"), "1.0" ); + TDECmdLineArgs::addCmdLineOptions( options ); + TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); + + TDEApplication app; + app.disableSessionManagement(); + + if (args->isSet( "xdgname" ) == true) { + TQString desiredFolder = args->getOption("xdgname"); + if (desiredFolder == "DOCUMENTS") { + TQDir myqdir; + if (myqdir.exists(getDocumentPath(), TRUE) == true) { + if (args->isSet( "getpath" ) == true) { + printf("%s\n", (const char *)getDocumentPath().local8Bit()); + return 0; + } + else { + KRun * run = new KRun( KURL(getDocumentPath()), 0, false, false ); + TQObject::connect( run, TQT_SIGNAL( finished() ), &app, TQT_SLOT( quit() )); + TQObject::connect( run, TQT_SIGNAL( error() ), &app, TQT_SLOT( quit() )); + app.exec(); + return 0; + } + } + else { + KURLRequesterDlg newDirectoryRequester(getDocumentPath(), i18n("Please confirm your Documents directory location<br>Upon confimation a new directory will be created"), 0, NULL, true); + newDirectoryRequester.setCaption(i18n("Create Documents directory")); + newDirectoryRequester.urlRequester()->setMode(KFile::Directory); + if (newDirectoryRequester.exec() != TQDialog::Accepted) { + return 1; + } + else { + TQString newDirectory = newDirectoryRequester.urlRequester()->url(); + if (newDirectory == TQString::null) { + return 1; + } + else { + if (newDirectory.length() < 4096) { + bool directoryOk = false; + if (myqdir.exists(newDirectory, TRUE) == false) { + if (myqdir.mkdir(newDirectory, TRUE) == true) { + directoryOk = TRUE; + } + } + else { + directoryOk = TRUE; + } + if (directoryOk == true) { + TQString xdgModifiedDirectory = newDirectory; + xdgModifiedDirectory = xdgModifiedDirectory.replace(TQDir::homeDirPath(), "$HOME"); + while (xdgModifiedDirectory.endsWith("/")) { + xdgModifiedDirectory.truncate(xdgModifiedDirectory.length()-1); + } + TDEConfig config(TQDir::homeDirPath() + "/.config/user-dirs.dirs", false, false); + config.writeEntry("XDG_DOCUMENTS_DIR", TQString("\"") + xdgModifiedDirectory + TQString("\""), true); + config.sync(); + if (args->isSet( "getpath" ) == true) { + printf("%s\n", (const char *)getDocumentPath().local8Bit()); + return 0; + } + else { + KRun * run = new KRun( getDocumentPath(), 0, false, false ); + TQObject::connect( run, TQT_SIGNAL( finished() ), &app, TQT_SLOT( quit() )); + TQObject::connect( run, TQT_SIGNAL( error() ), &app, TQT_SLOT( quit() )); + app.exec(); + } + return 0; + } + else { + KMessageBox::error(0, i18n("Unable to create directory ") + TQString("\"") + newDirectory + TQString("\"\n") + i18n("Please check folder permissions and try again"), i18n("Unable to create directory")); + return 1; + } + } + else { + KMessageBox::error(0, i18n("Unable to create the directory ") + newDirectory + TQString("\n") + i18n("Directory path cannot be longer than 4096 characters"), i18n("Unable to create directory")); + return 1; + } + } + } + } + } + else { + printf("[kxdglauncher] XDG variable not recognized\n"); + return 1; + } + } + else { + printf("[kxdglauncher] Please specify the desired XDG variable name with --xdgname\n"); + return 1; + } +} diff --git a/kdesktop/kxdglauncher.h b/kdesktop/kxdglauncher.h new file mode 100644 index 000000000..8f487e88e --- /dev/null +++ b/kdesktop/kxdglauncher.h @@ -0,0 +1,25 @@ +/* This file is part of the KDE project + Copyright (c) 2003 Oswald Buddenhagen <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _MAIN_H +#define _MAIN_H + +#include <tdeapplication.h> + +#endif diff --git a/kdesktop/lock/CMakeLists.txt b/kdesktop/lock/CMakeLists.txt new file mode 100644 index 000000000..256c6a498 --- /dev/null +++ b/kdesktop/lock/CMakeLists.txt @@ -0,0 +1,43 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# (C) 2012 Timothy Pearson +# kb9vqf (AT) pearsoncomputing.net +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR}/kdesktop + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/tdmlib + ${CMAKE_SOURCE_DIR}/kcheckpass + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### kdesktop_lock (executable) ################ + +set( target kdesktop_lock ) + +set( ${target}_SRCS + lockprocess.cc lockdlg.cc infodlg.cc querydlg.cc sakdlg.cc + securedlg.cc autologout.cc main.cc +) + +tde_add_executable( ${target} AUTOMOC + SOURCES ${${target}_SRCS} + LINK kdesktopsettings-static dmctl-static tdeio-shared Xext + ${GL_LIBRARIES} "${LINKER_IMMEDIATE_BINDING_FLAGS}" + DESTINATION ${BIN_INSTALL_DIR} +) diff --git a/kdesktop/lock/Makefile.am b/kdesktop/lock/Makefile.am new file mode 100644 index 000000000..7713707e9 --- /dev/null +++ b/kdesktop/lock/Makefile.am @@ -0,0 +1,24 @@ +## Makefile.am of tdebase/kdesktop/lock + +INCLUDES = -I.. -I$(top_srcdir)/kcheckpass -I$(top_srcdir)/tdmlib $(GLINC) $(all_includes) +kdesktop_lock_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor +kdesktop_lock_LDADD = ../libkdesktopsettings.la ../../tdmlib/libdmctl.la $(LIB_TDEIO) $(LIB_XF86MISC) $(GLLIB) + +####### Files + +bin_PROGRAMS = kdesktop_lock + +kdesktop_lock_SOURCES = lockprocess.cc lockdlg.cc infodlg.cc querydlg.cc autologout.cc main.cc + +noinst_HEADERS = lockprocess.h lockdlg.h infodlg.h querydlg.h autologout.h main.h + +METASOURCES = AUTO + +lockprocess.o: ../kdesktopsettings.h + +####### Build rules + +PAM = @TDESCREENSAVER_PAM_SERVICE@ + +install-data-local: + -@test -n "$(DESTDIR)" || test -z "$(PAM)" || $(top_srcdir)/mkpamserv $(PAM) diff --git a/kdesktop/lock/autologout.cc b/kdesktop/lock/autologout.cc new file mode 100644 index 000000000..0861eaef0 --- /dev/null +++ b/kdesktop/lock/autologout.cc @@ -0,0 +1,132 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 2004 Chris Howells <[email protected]> + +#include "lockprocess.h" +#include "autologout.h" + +#include <tdeapplication.h> +#include <tdelocale.h> +#include <tdeglobalsettings.h> +#include <tdeconfig.h> +#include <kiconloader.h> +#include <kdebug.h> +#include <dcopref.h> +#include <tdemessagebox.h> +#include <kdialog.h> + +#include <tqlayout.h> +#include <tqmessagebox.h> +#include <tqlabel.h> +#include <tqstyle.h> +#include <tqapplication.h> +#include <tqdialog.h> +#include <tqprogressbar.h> + +#include <X11/Xatom.h> + +#define COUNTDOWN 30 + +extern bool trinity_desktop_lock_use_system_modal_dialogs; + +AutoLogout::AutoLogout(LockProcess *parent) : TQDialog(parent, "password dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))) +{ + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + setCaption(i18n("Automatic Logout Notification")); + + frame = new TQFrame(this); + if (trinity_desktop_lock_use_system_modal_dialogs) + frame->setFrameStyle( TQFrame::NoFrame ); + else + frame->setFrameStyle(TQFrame::Panel | TQFrame::Raised); + frame->setLineWidth(2); + + TQLabel *pixLabel = new TQLabel( frame, "pixlabel" ); + pixLabel->setPixmap(DesktopIcon("exit")); + + TQLabel *greetLabel = new TQLabel(i18n("<nobr><qt><b>Automatic Log Out</b></qt><nobr>"), frame); + TQLabel *infoLabel = new TQLabel(i18n("<qt>To prevent being logged out, resume using this session by moving the mouse or pressing a key.</qt>"), frame); + + mStatusLabel = new TQLabel("<b> </b>", frame); + mStatusLabel->setAlignment(TQLabel::AlignCenter); + + TQLabel *mProgressLabel = new TQLabel("Time Remaining:", frame); + mProgressRemaining = new TQProgressBar(frame); + mProgressRemaining->setPercentageVisible(false); + + TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); + unlockDialogLayout->addWidget( frame ); + + frameLayout = new TQGridLayout(frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint()); + frameLayout->addMultiCellWidget(pixLabel, 0, 2, 0, 0, Qt::AlignCenter | Qt::AlignTop); + frameLayout->addWidget(greetLabel, 0, 1); + frameLayout->addWidget(mStatusLabel, 1, 1); + frameLayout->addWidget(infoLabel, 2, 1); + frameLayout->addWidget(mProgressLabel, 3, 1); + frameLayout->addWidget(mProgressRemaining, 4, 1); + + // get the time remaining in seconds for the status label + mRemaining = COUNTDOWN * 25; + + mProgressRemaining->setTotalSteps(COUNTDOWN * 25); + + updateInfo(mRemaining); + + mCountdownTimerId = startTimer(1000/25); + + connect(tqApp, TQT_SIGNAL(activity()), TQT_SLOT(slotActivity())); + + setFixedSize( sizeHint() ); +} + +AutoLogout::~AutoLogout() +{ + hide(); +} + +void AutoLogout::updateInfo(int timeout) +{ + mStatusLabel->setText(i18n("<nobr><qt>You will be automatically logged out in 1 second</qt></nobr>", + "<nobr><qt>You will be automatically logged out in %n seconds</qt></nobr>", + timeout / 25) ); + mProgressRemaining->setProgress(timeout); +} + +void AutoLogout::timerEvent(TQTimerEvent *ev) +{ + if (ev->timerId() == mCountdownTimerId) + { + updateInfo(mRemaining); + --mRemaining; + if (mRemaining < 0) + { + logout(); + } + } +} + +void AutoLogout::slotActivity() +{ + accept(); +} + +void AutoLogout::logout() +{ + TQT_TQOBJECT(this)->killTimers(); + DCOPRef("ksmserver","ksmserver").send("logout", 0, 0, 0); +} + +void AutoLogout::show() +{ + TQDialog::show(); + TQApplication::flushX(); +} + +#include "autologout.moc" diff --git a/kdesktop/lock/autologout.h b/kdesktop/lock/autologout.h new file mode 100644 index 000000000..c15a47f07 --- /dev/null +++ b/kdesktop/lock/autologout.h @@ -0,0 +1,51 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 1999 Martin R. Jones <[email protected]> +// Copyright (c) 2003 Oswald Buddenhagen <[email protected]> +// Coypright (c) 2004 Chris Howells <[email protected]> + +#ifndef __TIMEOUT_H__ +#define __TIMEOUT_H__ + +#include <tqstringlist.h> + +#include <tqlayout.h> + +class LockProcess; +class TQFrame; +class TQGridLayout; +class TQLabel; +class TQDialog; +class TQProgressBar; + +class AutoLogout : public TQDialog +{ + Q_OBJECT + +public: + AutoLogout(LockProcess *parent); + ~AutoLogout(); + virtual void show(); + +protected: + virtual void timerEvent(TQTimerEvent *); + +private slots: + void slotActivity(); + +private: + void updateInfo(int); + TQFrame *frame; + TQGridLayout *frameLayout; + TQLabel *mStatusLabel; + int mCountdownTimerId; + int mRemaining; + TQTimer countDownTimer; + TQProgressBar *mProgressRemaining; + void logout(); +}; + +#endif + diff --git a/kdesktop/lock/configure.in.in b/kdesktop/lock/configure.in.in new file mode 100644 index 000000000..d5d61a5f9 --- /dev/null +++ b/kdesktop/lock/configure.in.in @@ -0,0 +1,37 @@ +xss_save_ldflags="$LDFLAGS" +LDFLAGS="$X_LDFLAGS" + +LIB_XF86MISC= + +KDE_CHECK_HEADER(X11/extensions/xf86misc.h, + [ + AC_CHECK_LIB(Xxf86misc,XF86MiscQueryVersion, + [ + AC_DEFINE(HAVE_XF86MISC, 1, [Define if you have the xf86misc extension]) + LIB_XF86MISC="-lXxf86misc" + ], + [], [ $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS ]) + ],[], + [ + #include <X11/Xlib.h> + ]) +AC_SUBST(LIB_XF86MISC) + +if test -n "$LIB_XF86MISC"; then + AC_CHECK_LIB(Xxf86misc,XF86MiscSetGrabKeysState, + [ + AC_DEFINE(HAVE_XF86MISCSETGRABKEYSSTATE, 1, [Define if you have XF86MiscSetGrabKeysState()]) + ], + [], [ $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS ]) +fi + +LDFLAGS="$xss_save_ldflags" + +AC_HAVE_GL( + [ + AC_CHECK_LIB(GL,glXChooseVisual, + [ + AC_DEFINE(HAVE_GLXCHOOSEVISUAL, 1, [Define if you have glXChooseVisual()]) + ]) + ],[] + ) diff --git a/kdesktop/lock/infodlg.cc b/kdesktop/lock/infodlg.cc new file mode 100644 index 000000000..d248d7bd0 --- /dev/null +++ b/kdesktop/lock/infodlg.cc @@ -0,0 +1,147 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 2010 Timothy Pearson <[email protected]> + +#include <config.h> + +#include "infodlg.h" + +#include <dmctl.h> + +#include <tdeapplication.h> +#include <tdelocale.h> +#include <kpushbutton.h> +#include <kseparator.h> +#include <kstandarddirs.h> +#include <tdeglobalsettings.h> +#include <tdeconfig.h> +#include <kiconloader.h> +#include <tdesu/defaults.h> +#include <kpassdlg.h> +#include <kdebug.h> +#include <kuser.h> +#include <dcopref.h> +#include <tdemessagebox.h> + +#include <tqlayout.h> +#include <tqpushbutton.h> +#include <tqmessagebox.h> +#include <tqsimplerichtext.h> +#include <tqlabel.h> +#include <tqstringlist.h> +#include <tqfontmetrics.h> +#include <tqstyle.h> +#include <tqapplication.h> +#include <tqlistview.h> +#include <tqheader.h> +#include <tqcheckbox.h> + +#include <ctype.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +#include <pwd.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> +#include <fixx11h.h> + +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif + +extern bool trinity_desktop_lock_use_system_modal_dialogs; + +//=========================================================================== +// +// Simple dialog for displaying an unlock status or recurring error message +// +InfoDlg::InfoDlg(LockProcess *parent) + : TQDialog(parent, "information dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), + mUnlockingFailed(false) +{ + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + setCaption(i18n("Information")); + + frame = new TQFrame( this ); + if (trinity_desktop_lock_use_system_modal_dialogs) + frame->setFrameStyle( TQFrame::NoFrame ); + else + frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); + frame->setLineWidth( 2 ); + + mpixLabel = new TQLabel( frame, "pixlabel" ); + mpixLabel->setPixmap(DesktopIcon("unlock")); + + KUser user; + + mStatusLabel = new TQLabel( "<b> </b>", frame ); + mStatusLabel->setAlignment( TQLabel::AlignCenter ); + + TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); + unlockDialogLayout->addWidget( frame ); + + TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + layStatus->addWidget( mStatusLabel ); + + frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); + frameLayout->addMultiCellWidget( mpixLabel, 0, 2, 0, 0, Qt::AlignTop ); + frameLayout->addLayout( layStatus, 1, 1 ); + + installEventFilter(this); + setFixedSize( sizeHint() ); +} + +InfoDlg::~InfoDlg() +{ + hide(); +} + +void InfoDlg::updateLabel(TQString &txt) +{ + mStatusLabel->setPaletteForegroundColor(Qt::black); + mStatusLabel->setText("<b>" + txt + "</b>"); +} + +void InfoDlg::setUnlockIcon() +{ + mpixLabel->setPixmap(DesktopIcon("unlock")); +} + +void InfoDlg::setKDEIcon() +{ + mpixLabel->setPixmap(DesktopIcon("about_kde")); +} + +void InfoDlg::setInfoIcon() +{ + mpixLabel->setPixmap(DesktopIcon("messagebox_info")); +} + +void InfoDlg::setWarningIcon() +{ + mpixLabel->setPixmap(DesktopIcon("messagebox_warning")); +} + +void InfoDlg::setErrorIcon() +{ + mpixLabel->setPixmap(DesktopIcon("messagebox_critical")); +} + +void InfoDlg::show() +{ + TQDialog::show(); + TQApplication::flushX(); +} + +#include "infodlg.moc" diff --git a/kdesktop/lock/infodlg.h b/kdesktop/lock/infodlg.h new file mode 100644 index 000000000..bb974282f --- /dev/null +++ b/kdesktop/lock/infodlg.h @@ -0,0 +1,56 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 2010 Timothy Pearson <[email protected]> +// + +#ifndef __INFODLG_H__ +#define __INFODLG_H__ + +#include <tqdialog.h> +#include <tqstringlist.h> + +#include "lockprocess.h" + +class TQFrame; +class TQGridLayout; +class TQLabel; +class KPushButton; +class TQListView; + +//=========================================================================== +// +// Simple dialog for displaying an info message. +// It does not handle password validation. +// +class InfoDlg : public TQDialog +{ + Q_OBJECT + +public: + InfoDlg(LockProcess *parent); + ~InfoDlg(); + virtual void show(); + + void updateLabel( TQString &txt ); + void setUnlockIcon(); + void setKDEIcon(); + void setInfoIcon(); + void setWarningIcon(); + void setErrorIcon(); + +private: + TQFrame *frame; + TQGridLayout *frameLayout; + TQLabel *mStatusLabel; + TQLabel *mpixLabel; + int mCapsLocked; + bool mUnlockingFailed; + TQStringList layoutsList; + TQStringList::iterator currLayout; + int sPid, sFd; +}; + +#endif + diff --git a/kdesktop/lock/lockdlg.cc b/kdesktop/lock/lockdlg.cc new file mode 100644 index 000000000..163a03e43 --- /dev/null +++ b/kdesktop/lock/lockdlg.cc @@ -0,0 +1,876 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 1999 Martin R. Jones <[email protected]> +// Copyright (c) 2003 Chris Howells <[email protected]> +// Copyright (c) 2003 Oswald Buddenhagen <[email protected]> + +#include <config.h> + +#include "lockprocess.h" +#include "lockdlg.h" +#include "kdesktopsettings.h" + +#include <kcheckpass.h> +#include <dmctl.h> + +#include <tdeapplication.h> +#include <tdelocale.h> +#include <kpushbutton.h> +#include <kseparator.h> +#include <kstandarddirs.h> +#include <tdeglobalsettings.h> +#include <tdeconfig.h> +#include <kiconloader.h> +#include <tdesu/defaults.h> +#include <kpassdlg.h> +#include <kdebug.h> +#include <kuser.h> +#include <dcopref.h> +#include <tdemessagebox.h> + +#include <tqlayout.h> +#include <tqpushbutton.h> +#include <tqmessagebox.h> +#include <tqsimplerichtext.h> +#include <tqlabel.h> +#include <tqstringlist.h> +#include <tqfontmetrics.h> +#include <tqstyle.h> +#include <tqapplication.h> +#include <tqlistview.h> +#include <tqheader.h> +#include <tqcheckbox.h> + +#include <ctype.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +#include <pwd.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> +#include <fixx11h.h> + +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif + +#define PASSDLG_HIDE_TIMEOUT dialogHideTimeout + +extern bool trinity_desktop_lock_autohide_lockdlg; +extern bool trinity_desktop_lock_delay_screensaver_start; +extern bool trinity_desktop_lock_use_system_modal_dialogs; +extern bool trinity_desktop_lock_use_sak; + +int dialogHideTimeout = 10*1000; + +//=========================================================================== +// +// Simple dialog for entering a password. +// +PasswordDlg::PasswordDlg(LockProcess *parent, GreeterPluginHandle *plugin) + : TQDialog(parent, "password dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), + mPlugin( plugin ), + mCapsLocked(-1), + mUnlockingFailed(false) +{ + init(plugin); +} + +// +// Simple dialog for entering a password. +// This version includes support for displaying the date and time the lock process was started +// +PasswordDlg::PasswordDlg(LockProcess *parent, GreeterPluginHandle *plugin, TQDateTime lockStartDateTime) + : TQDialog(parent, "password dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), + mPlugin( plugin ), + mCapsLocked(-1), + mUnlockingFailed(false) +{ + m_lockStartDT = lockStartDateTime; + init(plugin); +} + +void PasswordDlg::init(GreeterPluginHandle *plugin) +{ + dialogHideTimeout = trinity_desktop_lock_delay_screensaver_start?KDesktopSettings::timeout()*1000:10*1000; + + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + setCaption(i18n("Desktop Session Locked")); + + frame = new TQFrame( this ); + if (trinity_desktop_lock_use_system_modal_dialogs) + frame->setFrameStyle( TQFrame::NoFrame ); + else + frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); + frame->setLineWidth( 2 ); + + TQLabel *pixLabel = NULL; + if (!trinity_desktop_lock_use_system_modal_dialogs) { + pixLabel = new TQLabel( frame, "pixlabel" ); + pixLabel->setPixmap(DesktopIcon("lock")); + } + + KUser user; + TQLabel *greetLabel; + if (trinity_desktop_lock_use_system_modal_dialogs) { + greetLabel = new TQLabel( user.fullName().isEmpty() ? + "<b>" + i18n("This computer is in use and has been locked.") + "</b>" : + "<b>" + i18n("This computer is in use and has been locked.") + "</b><br><nobr>" + i18n("Only '%1' may unlock this session.").arg( user.fullName() ), frame ); + } + else { + greetLabel = new TQLabel( user.fullName().isEmpty() ? + i18n("<nobr><b>The session is locked</b><br>") : + i18n("<nobr><b>The session was locked by %1</b><br>").arg( user.fullName() ), frame ); + } + + TQLabel *lockDTLabel = NULL; + if ((trinity_desktop_lock_use_system_modal_dialogs) && (!m_lockStartDT.isNull())) { + lockDTLabel = new TQLabel(i18n("This session has been locked since %1").arg(m_lockStartDT.toString()), frame); + } + + mStatusLabel = new TQLabel( "<b> </b>", frame ); + mStatusLabel->setAlignment( TQLabel::AlignCenter ); + + mLayoutButton = new TQPushButton( frame ); + mLayoutButton->setFlat( true ); + + KSeparator *sep = new KSeparator( KSeparator::HLine, frame ); + + mNewSessButton = new KPushButton( KGuiItem(i18n("Sw&itch User..."), "fork"), frame ); + ok = new KPushButton( i18n("Unl&ock"), frame ); + cancel = new KPushButton( KStdGuiItem::cancel(), frame ); + if (!trinity_desktop_lock_autohide_lockdlg && !trinity_desktop_lock_use_sak) cancel->setEnabled(false); + + greet = plugin->info->create( this, 0, this, mLayoutButton, TQString::null, + KGreeterPlugin::Authenticate, KGreeterPlugin::ExUnlock ); + + + TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); + unlockDialogLayout->addWidget( frame ); + + TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + layStatus->addWidget( mStatusLabel ); + layStatus->addWidget( mLayoutButton ); + + TQHBoxLayout *layButtons = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + layButtons->addWidget( mNewSessButton ); + layButtons->addStretch(); + layButtons->addWidget( ok ); + layButtons->addWidget( cancel ); + + if (trinity_desktop_lock_use_system_modal_dialogs) { + KSMModalDialogHeader* theader = new KSMModalDialogHeader( frame ); + + if (!m_lockStartDT.isNull()) { + frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); + frameLayout->addMultiCellWidget( theader, 0, 0, 0, 2, Qt::AlignTop ); + frameLayout->addWidget( greetLabel, 1, 1 ); + frameLayout->addWidget( lockDTLabel, 2, 1 ); + frameLayout->addItem( greet->getLayoutItem(), 3, 1 ); + frameLayout->addLayout( layStatus, 4, 1 ); + frameLayout->addMultiCellWidget( sep, 5, 5, 0, 1 ); + frameLayout->addMultiCellLayout( layButtons, 6, 6, 0, 1 ); + } + else { + frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); + frameLayout->addMultiCellWidget( theader, 0, 0, 0, 2, Qt::AlignTop ); + frameLayout->addWidget( greetLabel, 1, 1 ); + frameLayout->addItem( greet->getLayoutItem(), 2, 1 ); + frameLayout->addLayout( layStatus, 3, 1 ); + frameLayout->addMultiCellWidget( sep, 4, 4, 0, 1 ); + frameLayout->addMultiCellLayout( layButtons, 5, 5, 0, 1 ); + } + } + else { + frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); + frameLayout->addMultiCellWidget( pixLabel, 0, 2, 0, 0, Qt::AlignTop ); + frameLayout->addWidget( greetLabel, 0, 1 ); + frameLayout->addItem( greet->getLayoutItem(), 1, 1 ); + frameLayout->addLayout( layStatus, 2, 1 ); + frameLayout->addMultiCellWidget( sep, 3, 3, 0, 1 ); + frameLayout->addMultiCellLayout( layButtons, 4, 4, 0, 1 ); + } + + setTabOrder( ok, cancel ); + setTabOrder( cancel, mNewSessButton ); + setTabOrder( mNewSessButton, mLayoutButton ); + + connect(mLayoutButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(layoutClicked())); + connect(cancel, TQT_SIGNAL(clicked()), TQT_SLOT(reject())); + connect(ok, TQT_SIGNAL(clicked()), TQT_SLOT(slotOK())); + connect(mNewSessButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotSwitchUser())); + + if (!DM().isSwitchable() || !kapp->authorize("switch_user")) + mNewSessButton->hide(); + + installEventFilter(this); + setFixedSize( sizeHint() ); + + mFailedTimerId = 0; + mTimeoutTimerId = startTimer(PASSDLG_HIDE_TIMEOUT); + connect(tqApp, TQT_SIGNAL(activity()), TQT_SLOT(slotActivity()) ); + + greet->start(); + + DCOPRef kxkb("kxkb", "kxkb"); + if( !kxkb.isNull() ) { + DCOPReply reply = kxkb.call("getLayoutsList"); + if (reply.isValid()) { + layoutsList = reply; + } + reply = kxkb.call("getCurrentLayout"); + TQString currentLayout; + if (reply.isValid()) { + reply.get(currentLayout); + } + if( !currentLayout.isEmpty() && layoutsList.count() > 1 ) { + currLayout = layoutsList.find(currentLayout); + if (currLayout == layoutsList.end()) + setLayoutText("err"); + else + setLayoutText(*currLayout); + } else + mLayoutButton->hide(); + } else { + mLayoutButton->hide(); // no kxkb running + } + capsLocked(); +} + +PasswordDlg::~PasswordDlg() +{ + hide(); + frameLayout->removeItem( greet->getLayoutItem() ); + delete greet; +} + +void PasswordDlg::reject() +{ + if (trinity_desktop_lock_autohide_lockdlg || trinity_desktop_lock_use_sak) + TQDialog::reject(); +} + +void PasswordDlg::layoutClicked() +{ + + if( ++currLayout == layoutsList.end() ) + currLayout = layoutsList.begin(); + + DCOPRef kxkb("kxkb", "kxkb"); + setLayoutText( kxkb.call("setLayout", *currLayout) ? *currLayout : "err" ); + +} + +void PasswordDlg::setLayoutText( const TQString &txt ) +{ + mLayoutButton->setText( txt ); + TQSize sz = mLayoutButton->fontMetrics().size( 0, txt ); + int mrg = mLayoutButton->style().pixelMetric( TQStyle::PM_ButtonMargin ) * 2; + mLayoutButton->setFixedSize( sz.width() + mrg, sz.height() + mrg ); +} + +void PasswordDlg::updateLabel() +{ + if (mUnlockingFailed) + { + mStatusLabel->setPaletteForegroundColor(Qt::black); + mStatusLabel->setText(i18n("<b>Unlocking failed</b>")); +// mStatusLabel->show(); + } + else + if (mCapsLocked) + { + mStatusLabel->setPaletteForegroundColor(Qt::red); + mStatusLabel->setText(i18n("<b>Warning: Caps Lock on</b>")); +// mStatusLabel->show(); + } + else + { + mStatusLabel->setText("<b> </b>"); +// mStatusLabel->hide(); + } +} + +//--------------------------------------------------------------------------- +// +// Handle timer events. +// +void PasswordDlg::timerEvent(TQTimerEvent *ev) +{ + if (ev->timerId() == mTimeoutTimerId) + { + if (trinity_desktop_lock_autohide_lockdlg) { + reject(); + } + else { + slotActivity(); + } + } + else if (ev->timerId() == mFailedTimerId) + { + killTimer(mFailedTimerId); + mFailedTimerId = 0; + // Show the normal password prompt. + mUnlockingFailed = false; + updateLabel(); + ok->setEnabled(true); + if (trinity_desktop_lock_autohide_lockdlg || trinity_desktop_lock_use_sak) cancel->setEnabled(true); + mNewSessButton->setEnabled( true ); + greet->revive(); + greet->start(); + } +} + +bool PasswordDlg::eventFilter(TQObject *, TQEvent *ev) +{ + if (ev->type() == TQEvent::KeyPress || ev->type() == TQEvent::KeyRelease) + capsLocked(); + return false; +} + +void PasswordDlg::slotActivity() +{ + if (mTimeoutTimerId) { + killTimer(mTimeoutTimerId); + mTimeoutTimerId = startTimer(PASSDLG_HIDE_TIMEOUT); + } +} + +////// kckeckpass interface code + +int PasswordDlg::Reader (void *buf, int count) +{ + int ret, rlen; + + for (rlen = 0; rlen < count; ) { + dord: + ret = ::read (sFd, (void *)((char *)buf + rlen), count - rlen); + if (ret < 0) { + if (errno == EINTR) + goto dord; + if (errno == EAGAIN) + break; + return -1; + } + if (!ret) + break; + rlen += ret; + } + return rlen; +} + +bool PasswordDlg::GRead (void *buf, int count) +{ + return Reader (buf, count) == count; +} + +bool PasswordDlg::GWrite (const void *buf, int count) +{ + return ::write (sFd, buf, count) == count; +} + +bool PasswordDlg::GSendInt (int val) +{ + return GWrite (&val, sizeof(val)); +} + +bool PasswordDlg::GSendStr (const char *buf) +{ + int len = buf ? ::strlen (buf) + 1 : 0; + return GWrite (&len, sizeof(len)) && GWrite (buf, len); +} + +bool PasswordDlg::GSendArr (int len, const char *buf) +{ + return GWrite (&len, sizeof(len)) && GWrite (buf, len); +} + +bool PasswordDlg::GRecvInt (int *val) +{ + return GRead (val, sizeof(*val)); +} + +bool PasswordDlg::GRecvArr (char **ret) +{ + int len; + char *buf; + + if (!GRecvInt(&len)) + return false; + if (!len) { + *ret = 0; + return true; + } + if (!(buf = (char *)::malloc (len))) + return false; + *ret = buf; + return GRead (buf, len); +} + +void PasswordDlg::reapVerify() +{ + ::close( sFd ); + int status; + pid_t retpid = ::waitpid( sPid, &status, 0 ); + if (retpid < 0) { + // FIXME + // ERROR + } + else { + if (WIFEXITED(status)) { + switch (WEXITSTATUS(status)) { + case AuthOk: + greet->succeeded(); + accept(); + return; + case AuthBad: + greet->failed(); + mUnlockingFailed = true; + updateLabel(); + mFailedTimerId = startTimer(1500); + ok->setEnabled(false); + cancel->setEnabled(false); + mNewSessButton->setEnabled( false ); + return; + case AuthAbort: + return; + } + } + else if (WIFSIGNALED(status)) { + // FIXME + // ERROR + } + } + cantCheck(); +} + +void PasswordDlg::handleVerify() +{ + int ret; + char *arr; + + while (GRecvInt( &ret )) { + switch (ret) { + case ConvGetBinary: + if (!GRecvArr( &arr )) + break; + greet->binaryPrompt( arr, false ); + if (arr) + ::free( arr ); + return; + case ConvGetNormal: + if (!GRecvArr( &arr )) + break; + greet->textPrompt( arr, true, false ); + if (arr) + ::free( arr ); + return; + case ConvGetHidden: + if (!GRecvArr( &arr )) + break; + greet->textPrompt( arr, false, false ); + if (arr) + ::free( arr ); + return; + case ConvPutInfo: + if (!GRecvArr( &arr )) + break; + if (!greet->textMessage( arr, false )) + static_cast< LockProcess* >(parent())->msgBox( TQMessageBox::Information, TQString::fromLocal8Bit( arr ) ); + ::free( arr ); + continue; + case ConvPutError: + if (!GRecvArr( &arr )) + break; + if (!greet->textMessage( arr, true )) + static_cast< LockProcess* >(parent())->msgBox( TQMessageBox::Warning, TQString::fromLocal8Bit( arr ) ); + ::free( arr ); + continue; + } + break; + } + reapVerify(); +} + +////// greeter plugin callbacks + +void PasswordDlg::gplugReturnText( const char *text, int tag ) +{ + GSendStr( text ); + if (text) + GSendInt( tag ); + handleVerify(); +} + +void PasswordDlg::gplugReturnBinary( const char *data ) +{ + if (data) { + unsigned const char *up = (unsigned const char *)data; + int len = up[3] | (up[2] << 8) | (up[1] << 16) | (up[0] << 24); + if (!len) + GSendArr( 4, data ); + else + GSendArr( len, data ); + } else + GSendArr( 0, 0 ); + handleVerify(); +} + +void PasswordDlg::gplugSetUser( const TQString & ) +{ + // ignore ... +} + +void PasswordDlg::cantCheck() +{ + greet->failed(); + static_cast< LockProcess* >(parent())->msgBox( TQMessageBox::Critical, + i18n("Cannot unlock the session because the authentication system failed to work;\n" + "you must kill kdesktop_lock (pid %1) manually.").arg(getpid()) ); + greet->revive(); +} + +//--------------------------------------------------------------------------- +// +// Starts the kcheckpass process to check the user's password. +// +void PasswordDlg::gplugStart() +{ + int sfd[2]; + char fdbuf[16]; + + if (::socketpair(AF_LOCAL, SOCK_STREAM, 0, sfd)) { + cantCheck(); + return; + } + if ((sPid = ::fork()) < 0) { + ::close(sfd[0]); + ::close(sfd[1]); + cantCheck(); + return; + } + if (!sPid) { + ::close(sfd[0]); + sprintf(fdbuf, "%d", sfd[1]); + execlp("kcheckpass", "kcheckpass", +#ifdef HAVE_PAM + "-c", TDESCREENSAVER_PAM_SERVICE, +#endif + "-m", mPlugin->info->method, + "-S", fdbuf, + (char *)0); + exit(20); + } + ::close(sfd[1]); + sFd = sfd[0]; + handleVerify(); +} + +void PasswordDlg::gplugActivity() +{ + slotActivity(); +} + +void PasswordDlg::gplugMsgBox( TQMessageBox::Icon type, const TQString &text ) +{ + TQDialog dialog( this, 0, true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM)) ); + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), dialog.winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + dialog.setCaption(i18n("Authentication Subsystem Notice")); + TQFrame *winFrame = new TQFrame( &dialog ); + if (trinity_desktop_lock_use_system_modal_dialogs) + winFrame->setFrameStyle( TQFrame::NoFrame ); + else + winFrame->setFrameStyle( TQFrame::WinPanel | TQFrame::Raised ); + winFrame->setLineWidth( 2 ); + TQVBoxLayout *vbox = new TQVBoxLayout( &dialog ); + vbox->addWidget( winFrame ); + + TQLabel *label1 = new TQLabel( winFrame ); + label1->setPixmap( TQMessageBox::standardIcon( type ) ); + TQLabel *label2 = new TQLabel( text, winFrame ); + KPushButton *button = new KPushButton( KStdGuiItem::ok(), winFrame ); + button->setDefault( true ); + button->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Preferred ) ); + connect( button, TQT_SIGNAL( clicked() ), TQT_SLOT( accept() ) ); + + TQGridLayout *grid = new TQGridLayout( winFrame, 2, 2, 10 ); + grid->addWidget( label1, 0, 0, Qt::AlignCenter ); + grid->addWidget( label2, 0, 1, Qt::AlignCenter ); + grid->addMultiCellWidget( button, 1,1, 0,1, Qt::AlignCenter ); + + static_cast< LockProcess* >(parent())->execDialog( &dialog ); +} + +void PasswordDlg::slotOK() +{ + greet->next(); +} + + +void PasswordDlg::show() +{ + TQDialog::show(); + TQApplication::flushX(); + setFixedSize( sizeHint() ); +} + +void PasswordDlg::slotStartNewSession() +{ + if (!KMessageBox::shouldBeShownContinue( ":confirmNewSession" )) { + DM().startReserve(); + return; + } + + killTimer(mTimeoutTimerId); + mTimeoutTimerId = 0; + + TQDialog *dialog = new TQDialog( this, "warnbox", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))); + + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), dialog->winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + dialog->setCaption(i18n("New Session")); + + TQFrame *winFrame = new TQFrame( dialog ); + if (trinity_desktop_lock_use_system_modal_dialogs) + winFrame->setFrameStyle( TQFrame::NoFrame ); + else + winFrame->setFrameStyle( TQFrame::WinPanel | TQFrame::Raised ); + winFrame->setLineWidth( 2 ); + TQVBoxLayout *vbox = new TQVBoxLayout( dialog ); + vbox->addWidget( winFrame ); + + TQLabel *label1 = new TQLabel( winFrame ); + label1->setPixmap( TQMessageBox::standardIcon( TQMessageBox::Warning ) ); + TQString qt_text = + i18n("You have chosen to open another desktop session " + "instead of resuming the current one.<br>" + "The current session will be hidden " + "and a new login screen will be displayed.<br>" + "An F-key is assigned to each session; " + "F%1 is usually assigned to the first session, " + "F%2 to the second session and so on. " + "You can switch between sessions by pressing " + "Ctrl, Alt and the appropriate F-key at the same time. " + "Additionally, the TDE Panel and Desktop menus have " + "actions for switching between sessions.") + .arg(7).arg(8); + TQLabel *label2 = new TQLabel( qt_text, winFrame ); + KPushButton *okbutton = new KPushButton( KGuiItem(i18n("&Start New Session"), "fork"), winFrame ); + okbutton->setDefault( true ); + connect( okbutton, TQT_SIGNAL( clicked() ), dialog, TQT_SLOT( accept() ) ); + KPushButton *cbutton = new KPushButton( KStdGuiItem::cancel(), winFrame ); + connect( cbutton, TQT_SIGNAL( clicked() ), dialog, TQT_SLOT( reject() ) ); + + TQBoxLayout *mbox = new TQVBoxLayout( winFrame, KDialog::marginHint(), KDialog::spacingHint() ); + + TQGridLayout *grid = new TQGridLayout( mbox, 2, 2, 2 * KDialog::spacingHint() ); + grid->setMargin( KDialog::marginHint() ); + grid->addWidget( label1, 0, 0, Qt::AlignCenter ); + grid->addWidget( label2, 0, 1, Qt::AlignCenter ); + TQCheckBox *cb = new TQCheckBox( i18n("&Do not ask again"), winFrame ); + grid->addMultiCellWidget( cb, 1,1, 0,1 ); + + TQBoxLayout *hbox = new TQHBoxLayout( mbox, KDialog::spacingHint() ); + hbox->addStretch( 1 ); + hbox->addWidget( okbutton ); + hbox->addStretch( 1 ); + hbox->addWidget( cbutton ); + hbox->addStretch( 1 ); + + // stolen from kmessagebox + int pref_width = 0; + int pref_height = 0; + // Calculate a proper size for the text. + { + TQSimpleRichText rt(qt_text, dialog->font()); + TQRect rect = TDEGlobalSettings::desktopGeometry(dialog); + + pref_width = rect.width() / 3; + rt.setWidth(pref_width); + int used_width = rt.widthUsed(); + pref_height = rt.height(); + if (used_width <= pref_width) + { + while(true) + { + int new_width = (used_width * 9) / 10; + rt.setWidth(new_width); + int new_height = rt.height(); + if (new_height > pref_height) + break; + used_width = rt.widthUsed(); + if (used_width > new_width) + break; + } + pref_width = used_width; + } + else + { + if (used_width > (pref_width *2)) + pref_width = pref_width *2; + else + pref_width = used_width; + } + } + label2->setFixedSize(TQSize(pref_width+10, pref_height)); + + int ret = static_cast< LockProcess* >( parent())->execDialog( dialog ); + + delete dialog; + + if (ret == TQDialog::Accepted) { + if (cb->isChecked()) + KMessageBox::saveDontShowAgainContinue( ":confirmNewSession" ); + DM().startReserve(); + } + + mTimeoutTimerId = startTimer(PASSDLG_HIDE_TIMEOUT); +} + +class LockListViewItem : public TQListViewItem { +public: + LockListViewItem( TQListView *parent, + const TQString &sess, const TQString &loc, int _vt ) + : TQListViewItem( parent ) + , vt( _vt ) + { + setText( 0, sess ); + setText( 1, loc ); + } + + int vt; +}; + +void PasswordDlg::slotSwitchUser() +{ + int p = 0; + DM dm; + + TQDialog dialog( this, "sessbox", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM)) ); + + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), dialog.winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + dialog.setCaption(i18n("Switch User")); + + TQFrame *winFrame = new TQFrame( &dialog ); + if (trinity_desktop_lock_use_system_modal_dialogs) + winFrame->setFrameStyle( TQFrame::NoFrame ); + else + winFrame->setFrameStyle( TQFrame::WinPanel | TQFrame::Raised ); + winFrame->setLineWidth( 2 ); + TQBoxLayout *vbox = new TQVBoxLayout( &dialog ); + vbox->addWidget( winFrame ); + + TQBoxLayout *hbox = new TQHBoxLayout( winFrame, KDialog::marginHint(), KDialog::spacingHint() ); + + TQBoxLayout *vbox1 = new TQVBoxLayout( hbox, KDialog::spacingHint() ); + TQBoxLayout *vbox2 = new TQVBoxLayout( hbox, KDialog::spacingHint() ); + + KPushButton *btn; + + SessList sess; + if (dm.localSessions( sess )) { + + lv = new TQListView( winFrame ); + connect( lv, TQT_SIGNAL(doubleClicked(TQListViewItem *, const TQPoint&, int)), TQT_SLOT(slotSessionActivated()) ); + connect( lv, TQT_SIGNAL(doubleClicked(TQListViewItem *, const TQPoint&, int)), &dialog, TQT_SLOT(accept()) ); + lv->setAllColumnsShowFocus( true ); + lv->addColumn( i18n("Session") ); + lv->addColumn( i18n("Location") ); + lv->setColumnWidthMode( 0, TQListView::Maximum ); + lv->setColumnWidthMode( 1, TQListView::Maximum ); + TQListViewItem *itm = 0; + TQString user, loc; + int ns = 0; + for (SessList::ConstIterator it = sess.begin(); it != sess.end(); ++it) { + DM::sess2Str2( *it, user, loc ); + itm = new LockListViewItem( lv, user, loc, (*it).vt ); + if (!(*it).vt) + itm->setEnabled( false ); + if ((*it).self) { + lv->setCurrentItem( itm ); + itm->setSelected( true ); + } + ns++; + } + int fw = lv->frameWidth() * 2; + TQSize hds( lv->header()->sizeHint() ); + lv->setMinimumWidth( fw + hds.width() + + (ns > 10 ? style().pixelMetric(TQStyle::PM_ScrollBarExtent) : 0 ) ); + lv->setFixedHeight( fw + hds.height() + + itm->height() * (ns < 6 ? 6 : ns > 10 ? 10 : ns) ); + lv->header()->adjustHeaderSize(); + vbox1->addWidget( lv ); + + btn = new KPushButton( KGuiItem(i18n("session", "&Activate"), "fork"), winFrame ); + connect( btn, TQT_SIGNAL(clicked()), TQT_SLOT(slotSessionActivated()) ); + connect( btn, TQT_SIGNAL(clicked()), &dialog, TQT_SLOT(accept()) ); + vbox2->addWidget( btn ); + vbox2->addStretch( 2 ); + } + + if (kapp->authorize("start_new_session") && (p = dm.numReserve()) >= 0) + { + btn = new KPushButton( KGuiItem(i18n("Start &New Session"), "fork"), winFrame ); + connect( btn, TQT_SIGNAL(clicked()), TQT_SLOT(slotStartNewSession()) ); + connect( btn, TQT_SIGNAL(clicked()), &dialog, TQT_SLOT(accept()) ); + if (!p) + btn->setEnabled( false ); + vbox2->addWidget( btn ); + vbox2->addStretch( 1 ); + } + + btn = new KPushButton( KStdGuiItem::cancel(), winFrame ); + connect( btn, TQT_SIGNAL(clicked()), &dialog, TQT_SLOT(reject()) ); + vbox2->addWidget( btn ); + + dialog.setFixedSize( dialog.sizeHint() ); + + int ret = static_cast< LockProcess* >(parent())->execDialog( &dialog ); + if (ret != TQDialog::Rejected) { + TQDialog::reject(); + } +} + +void PasswordDlg::slotSessionActivated() +{ + LockListViewItem *itm = (LockListViewItem *)lv->currentItem(); + if (itm && itm->vt > 0) + DM().switchVT( itm->vt ); +} + +void PasswordDlg::capsLocked() +{ + unsigned int lmask; + Window dummy1, dummy2; + int dummy3, dummy4, dummy5, dummy6; + XQueryPointer(tqt_xdisplay(), DefaultRootWindow( tqt_xdisplay() ), &dummy1, &dummy2, &dummy3, &dummy4, &dummy5, &dummy6, &lmask); + mCapsLocked = lmask & LockMask; + updateLabel(); +} + +#include "lockdlg.moc" diff --git a/kdesktop/lock/lockdlg.h b/kdesktop/lock/lockdlg.h new file mode 100644 index 000000000..2ede5a4fa --- /dev/null +++ b/kdesktop/lock/lockdlg.h @@ -0,0 +1,101 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 1999 Martin R. Jones <[email protected]> +// Copyright (c) 2003 Oswald Buddenhagen <[email protected]> +// + +#ifndef __LOCKDLG_H__ +#define __LOCKDLG_H__ + +#include <kgreeterplugin.h> + +#include <tqdialog.h> +#include <tqstringlist.h> +#include <tqdatetime.h> + +#include "lockprocess.h" + +struct GreeterPluginHandle; +class LockProcess; +class TQFrame; +class TQGridLayout; +class TQLabel; +class KPushButton; +class TQListView; + +//=========================================================================== +// +// Simple dialog for entering a password. +// It does not handle password validation. +// +class PasswordDlg : public TQDialog, public KGreeterPluginHandler +{ + Q_OBJECT + +public: + PasswordDlg(LockProcess *parent, GreeterPluginHandle *plugin); + PasswordDlg(LockProcess *parent, GreeterPluginHandle *plugin, TQDateTime lockStartDateTime); + ~PasswordDlg(); + void init(GreeterPluginHandle *plugin); + virtual void show(); + + // from KGreetPluginHandler + virtual void gplugReturnText( const char *text, int tag ); + virtual void gplugReturnBinary( const char *data ); + virtual void gplugSetUser( const TQString & ); + virtual void gplugStart(); + virtual void gplugActivity(); + virtual void gplugMsgBox( TQMessageBox::Icon type, const TQString &text ); + +protected: + virtual void timerEvent(TQTimerEvent *); + virtual bool eventFilter(TQObject *, TQEvent *); + +private slots: + void slotSwitchUser(); + void slotSessionActivated(); + void slotStartNewSession(); + void slotOK(); + void layoutClicked(); + void slotActivity(); + +protected slots: + virtual void reject(); + +private: + void setLayoutText( const TQString &txt ); + void capsLocked(); + void updateLabel(); + int Reader (void *buf, int count); + bool GRead (void *buf, int count); + bool GWrite (const void *buf, int count); + bool GSendInt (int val); + bool GSendStr (const char *buf); + bool GSendArr (int len, const char *buf); + bool GRecvInt (int *val); + bool GRecvArr (char **buf); + void handleVerify(); + void reapVerify(); + void cantCheck(); + GreeterPluginHandle *mPlugin; + KGreeterPlugin *greet; + TQFrame *frame; + TQGridLayout *frameLayout; + TQLabel *mStatusLabel; + KPushButton *mNewSessButton, *ok, *cancel; + TQPushButton *mLayoutButton; + int mFailedTimerId; + int mTimeoutTimerId; + int mCapsLocked; + bool mUnlockingFailed; + TQStringList layoutsList; + TQStringList::iterator currLayout; + int sPid, sFd; + TQListView *lv; + TQDateTime m_lockStartDT; +}; + +#endif + diff --git a/kdesktop/lock/lockprocess.cc b/kdesktop/lock/lockprocess.cc new file mode 100644 index 000000000..f7dc1c25a --- /dev/null +++ b/kdesktop/lock/lockprocess.cc @@ -0,0 +1,2893 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 1999 Martin R. Jones <[email protected]> +// Copyright (c) 2003 Oswald Buddenhagen <[email protected]> +// Copyright (c) 2010-2013 Timothy Pearson <[email protected]> +// + +//kdesktop keeps running and checks user inactivity +//when it should show screensaver (and maybe lock the session), +//it starts kdesktop_lock, who does all the locking and who +//actually starts the screensaver + +//It's done this way to prevent screen unlocking when kdesktop +//crashes (e.g. because it's set to multiple wallpapers and +//some image will be corrupted). + +#include <config.h> + +#include "lockprocess.h" +#include "lockdlg.h" +#include "infodlg.h" +#include "querydlg.h" +#include "sakdlg.h" +#include "securedlg.h" +#include "autologout.h" +#include "kdesktopsettings.h" + +#include <dmctl.h> +#include <dcopref.h> + +#include <kstandarddirs.h> +#include <tdeapplication.h> +#include <kservicegroup.h> +#include <kdebug.h> +#include <tdemessagebox.h> +#include <tdeglobalsettings.h> +#include <tdelocale.h> +#include <klibloader.h> +#include <kpushbutton.h> +#include <kstdguiitem.h> +#include <kpixmapeffect.h> +#include <kpixmap.h> +#include <twin.h> +#include <twinmodule.h> +#include <kdialog.h> + +#include <tqframe.h> +#include <tqlabel.h> +#include <tqlayout.h> +#include <tqcursor.h> +#include <tqtimer.h> +#include <tqfile.h> +#include <tqsocketnotifier.h> +#include <tqvaluevector.h> +#include <tqtooltip.h> +#include <tqimage.h> +#include <tqregexp.h> +#include <tqpainter.h> +#include <tqeventloop.h> + +#include <tqdatetime.h> + +#include <stdlib.h> +#include <assert.h> +#include <signal.h> +#ifdef HAVE_SETPRIORITY +#include <sys/time.h> +#include <sys/resource.h> +#endif +#include <stdio.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> +#include <ctype.h> +#include <sys/types.h> +#include <fcntl.h> + +#include <kcrash.h> + +#include <linux/stat.h> + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> +#include <X11/Intrinsic.h> + +#ifdef HAVE_DPMS +extern "C" { +#include <X11/Xmd.h> +#ifndef Bool +#define Bool BOOL +#endif +#include <X11/extensions/dpms.h> + +#ifndef HAVE_DPMSINFO_PROTO +Status DPMSInfo ( Display *, CARD16 *, BOOL * ); +#endif +} +#endif + +#ifdef HAVE_XF86MISC +#include <X11/extensions/xf86misc.h> +#endif + +#ifdef HAVE_GLXCHOOSEVISUAL +#include <GL/glx.h> +#endif + +#define LOCK_GRACE_DEFAULT 5000 +#define AUTOLOGOUT_DEFAULT 600 + +#define DESKTOP_WALLPAPER_OBTAIN_TIMEOUT_MS 3000 + +// Setting this define is INSECURE +// Use it for debugging purposes ONLY +// #define KEEP_MOUSE_UNGRABBED 1 + +// These lines are taken on 10/2009 from X.org (X11/XF86keysym.h), defining some special multimedia keys +#define XF86XK_AudioMute 0x1008FF12 +#define XF86XK_AudioRaiseVolume 0x1008FF13 +#define XF86XK_AudioLowerVolume 0x1008FF11 +#define XF86XK_Display 0x1008FF59 + +// These lines are taken on 08/2013 from X.org (X11/XF86keysym.h), defining some special ACPI power keys +#define XF86XK_PowerOff 0x1008FF2A +#define XF86XK_Sleep 0x1008FF2F +#define XF86XK_Suspend 0x1008FFA7 +#define XF86XK_Hibernate 0x1008FFA8 + +#define DPMS_MONITOR_BLANKED(x) ((x == DPMSModeStandby) || (x == DPMSModeSuspend) || (x == DPMSModeOff)) + +static Window gVRoot = 0; +static Window gVRootData = 0; +static Atom gXA_VROOT; +static Atom gXA_SCREENSAVER_VERSION; + +Atom kde_wm_system_modal_notification = 0; +Atom kde_wm_transparent_to_desktop = 0; +Atom kde_wm_transparent_to_black = 0; + +static void segv_handler(int) +{ + kdError(1204) << "A fatal exception was encountered." + << " Trapping and ignoring it so as not to compromise desktop security..." + << kdBacktrace() << endl; + sleep(1); +} + +extern Atom tqt_wm_state; +extern bool trinity_desktop_lock_use_system_modal_dialogs; +extern bool trinity_desktop_lock_delay_screensaver_start; +extern bool trinity_desktop_lock_use_sak; +extern bool trinity_desktop_lock_hide_active_windows; +extern bool trinity_desktop_lock_forced; + +extern bool argb_visual; +extern pid_t kdesktop_pid; + +extern TQXLibWindowList trinity_desktop_lock_hidden_window_list; + +bool trinity_desktop_lock_autohide_lockdlg = TRUE; +bool trinity_desktop_lock_closing_windows = FALSE; +bool trinity_desktop_lock_in_sec_dlg = FALSE; +bool trinity_desktop_hack_active = FALSE; + +#define ENABLE_CONTINUOUS_LOCKDLG_DISPLAY \ +if (!mForceContinualLockDisplayTimer->isActive()) mForceContinualLockDisplayTimer->start(100, FALSE); \ +trinity_desktop_lock_autohide_lockdlg = FALSE; \ +mHackDelayStartupTimer->stop(); + +#define DISABLE_CONTINUOUS_LOCKDLG_DISPLAY \ +mForceContinualLockDisplayTimer->stop(); \ +trinity_desktop_lock_autohide_lockdlg = TRUE; \ +mHackDelayStartupTimer->stop(); + +//=========================================================================== +// +// Screen saver handling process. Handles screensaver window, +// starting screensaver hacks, and password entry. +// +LockProcess::LockProcess() + : TQWidget(0L, "saver window", ((WFlags)(WStyle_StaysOnTop|WStyle_Customize|WStyle_NoBorder))), + mOpenGLVisual(0), + mParent(0), + mShowLockDateTime(false), + mSuspended(false), + mVisibility(false), + mRestoreXF86Lock(false), + mForbidden(false), + mAutoLogout(false), + resizeTimer(NULL), + hackResumeTimer(NULL), + mVkbdProcess(NULL), + mKWinModule(NULL), + mPipeOpen(false), + mPipeOpen_out(false), + mInfoMessageDisplayed(false), + mDialogControlLock(false), + mForceReject(false), + currentDialog(NULL), + mEnsureScreenHiddenTimer(NULL), + mForceContinualLockDisplayTimer(NULL), + mEnsureVRootWindowSecurityTimer(NULL), + mHackDelayStartupTimer(NULL), + mHackDelayStartupTimeout(0), + mHackStartupEnabled(true), + mOverrideHackStartupEnabled(false), + mResizingDesktopLock(false), + mFullyOnlineSent(false), + m_rootPixmap(NULL), + mBackingStartupDelayTimer(0), + m_startupStatusDialog(NULL), + m_mouseDown(0), + m_mousePrevX(0), + m_mousePrevY(0), + m_dialogPrevX(0), + m_dialogPrevY(0), + m_notifyReadyRequested(false), + m_maskWidget(NULL), + m_saverRootWindow(0) +{ +#ifdef KEEP_MOUSE_UNGRABBED + setNFlags(WX11DisableMove|WX11DisableClose|WX11DisableShade|WX11DisableMinimize|WX11DisableMaximize); +#endif + + setupSignals(); + + // Set up atoms + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + kde_wm_transparent_to_desktop = XInternAtom(tqt_xdisplay(), "_TDE_TRANSPARENT_TO_DESKTOP", False); + kde_wm_transparent_to_black = XInternAtom(tqt_xdisplay(), "_TDE_TRANSPARENT_TO_BLACK", False); + + kapp->installX11EventFilter(this); + + mForceContinualLockDisplayTimer = new TQTimer( this ); + mHackDelayStartupTimer = new TQTimer( this ); + mEnsureVRootWindowSecurityTimer = new TQTimer( this ); + + if (!argb_visual) { + // Try to get the root pixmap + if (!m_rootPixmap) m_rootPixmap = new KRootPixmap(this); + connect(m_rootPixmap, TQT_SIGNAL(backgroundUpdated(const TQPixmap &)), this, TQT_SLOT(slotPaintBackground(const TQPixmap &))); + m_rootPixmap->setCustomPainting(true); + m_rootPixmap->start(); + } + + // Get root window attributes + XWindowAttributes rootAttr; + XGetWindowAttributes(tqt_xdisplay(), RootWindow(tqt_xdisplay(), tqt_xscreen()), &rootAttr); + { // trigger creation of QToolTipManager, it does XSelectInput() on the root window + TQWidget w; + TQToolTip::add( &w, "foo" ); + } + XSelectInput( tqt_xdisplay(), tqt_xrootwin(), SubstructureNotifyMask | rootAttr.your_event_mask ); + + // Add non-TDE path + TDEGlobal::dirs()->addResourceType("scrsav", + TDEGlobal::dirs()->kde_default("apps") + + "System/ScreenSavers/"); + + // Add KDE specific screensaver path + TQString relPath="System/ScreenSavers/"; + KServiceGroup::Ptr servGroup = KServiceGroup::baseGroup( "screensavers"); + if (servGroup) + { + relPath=servGroup->relPath(); + kdDebug(1204) << "relPath=" << relPath << endl; + } + TDEGlobal::dirs()->addResourceType("scrsav", + TDEGlobal::dirs()->kde_default("apps") + + relPath); + + // virtual root property + gXA_VROOT = XInternAtom (tqt_xdisplay(), "__SWM_VROOT", False); + gXA_SCREENSAVER_VERSION = XInternAtom (tqt_xdisplay(), "_SCREENSAVER_VERSION", False); + + TQStringList dmopt = + TQStringList::split(TQChar(','), + TQString::fromLatin1( ::getenv( "XDM_MANAGED" ))); + for (TQStringList::ConstIterator it = dmopt.begin(); it != dmopt.end(); ++it) + if ((*it).startsWith("method=")) + mMethod = (*it).mid(7); + +#ifdef KEEP_MOUSE_UNGRABBED + setEnabled(false); +#endif + + greetPlugin.library = 0; + + TDECrash::setCrashHandler(segv_handler); +} + +//--------------------------------------------------------------------------- +// +// Destructor - usual cleanups. +// +LockProcess::~LockProcess() +{ + mControlPipeHandlerThread->terminate(); + mControlPipeHandlerThread->wait(); + delete mControlPipeHandler; +// delete mControlPipeHandlerThread; + + if (resizeTimer != NULL) { + resizeTimer->stop(); + delete resizeTimer; + } + if (hackResumeTimer != NULL) { + hackResumeTimer->stop(); + delete hackResumeTimer; + } + if (mEnsureScreenHiddenTimer != NULL) { + mEnsureScreenHiddenTimer->stop(); + delete mEnsureScreenHiddenTimer; + } + if (mForceContinualLockDisplayTimer != NULL) { + mForceContinualLockDisplayTimer->stop(); + delete mForceContinualLockDisplayTimer; + } + if (mHackDelayStartupTimer != NULL) { + mHackDelayStartupTimer->stop(); + delete mHackDelayStartupTimer; + } + if (mEnsureVRootWindowSecurityTimer != NULL) { + mEnsureVRootWindowSecurityTimer->stop(); + delete mEnsureVRootWindowSecurityTimer; + } + + if (greetPlugin.library) { + if (greetPlugin.info->done) + greetPlugin.info->done(); + greetPlugin.library->unload(); + } + + if (m_rootPixmap) { + m_rootPixmap->stop(); + delete m_rootPixmap; + } + + mPipeOpen = false; + mPipeOpen_out = false; +} + +//--------------------------------------------------------------------------- +// +// Initialization for startup +// This is where instance settings should be set--all objects should have already been created in the constructor above +// +void LockProcess::init(bool child, bool useBlankOnly) +{ + // Get root window size + XWindowAttributes rootAttr; + XGetWindowAttributes(tqt_xdisplay(), RootWindow(tqt_xdisplay(), tqt_xscreen()), &rootAttr); + mRootWidth = rootAttr.width; + mRootHeight = rootAttr.height; + + // Connect all signals + connect( mForceContinualLockDisplayTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(displayLockDialogIfNeeded()) ); + connect( mHackDelayStartupTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(closeDialogAndStartHack()) ); + connect( mEnsureVRootWindowSecurityTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(repaintRootWindowIfNeeded()) ); + connect(tqApp, TQT_SIGNAL(mouseInteraction(XEvent *)), TQT_SLOT(slotMouseActivity(XEvent *))); + connect(&mHackProc, TQT_SIGNAL(processExited(TDEProcess *)), TQT_SLOT(hackExited(TDEProcess *))); + connect(&mSuspendTimer, TQT_SIGNAL(timeout()), TQT_SLOT(suspend())); + +#ifdef HAVE_DPMS + //if the user decided that the screensaver should run independent from + //dpms, we shouldn't check for it, aleXXX + if (KDesktopSettings::dpmsDependent()) { + BOOL on; + CARD16 state; + if (DPMSInfo(tqt_xdisplay(), &state, &on)) { + if (on) { + connect(&mCheckDPMS, TQT_SIGNAL(timeout()), TQT_SLOT(checkDPMSActive())); + // we can save CPU if we stop it as quickly as possible + // but we waste CPU if we check too often -> so take 10s + mCheckDPMS.start(10000); + } + } + } +#endif + +#if (TQT_VERSION-0 >= 0x030200) // XRANDR support + connect( kapp->desktop(), TQT_SIGNAL( resized( int )), TQT_SLOT( desktopResized())); +#endif + + if (!trinity_desktop_lock_use_system_modal_dialogs) { + setWFlags((WFlags)WX11BypassWM); + } + + child_saver = child; + mUseBlankOnly = useBlankOnly; + + mShowLockDateTime = KDesktopSettings::showLockDateTime(); + mlockDateTime = TQDateTime::currentDateTime(); + + mHackDelayStartupTimeout = trinity_desktop_lock_delay_screensaver_start?KDesktopSettings::timeout()*1000:10*1000; + mHackStartupEnabled = trinity_desktop_lock_use_system_modal_dialogs?KDesktopSettings::screenSaverEnabled():true; + + configure(); + + mControlPipeHandlerThread = new TQEventLoopThread(); + mControlPipeHandler = new ControlPipeHandlerObject(); + mControlPipeHandler->mParent = this; + mControlPipeHandler->moveToThread(mControlPipeHandlerThread); + TQObject::connect(mControlPipeHandler, SIGNAL(processCommand(TQString)), this, SLOT(processInputPipeCommand(TQString))); + TQTimer::singleShot(0, mControlPipeHandler, SLOT(run())); + mControlPipeHandlerThread->start(); +} + +static int signal_pipe[2]; + +static void sigterm_handler(int) +{ + if (!trinity_desktop_lock_in_sec_dlg) { + // Exit uncleanly + char tmp = 'U'; + if (::write( signal_pipe[1], &tmp, 1) == -1) { + // Error handler to shut up gcc warnings + } + } +} + +static void sighup_handler(int) +{ + char tmp = 'H'; + if (::write( signal_pipe[1], &tmp, 1) == -1) { + // Error handler to shut up gcc warnings + } +} + +bool LockProcess::closeCurrentWindow() +{ + trinity_desktop_lock_closing_windows = TRUE; + if (currentDialog != NULL) { + mForceReject = true; + if (dynamic_cast<SAKDlg*>(currentDialog)) { + dynamic_cast<SAKDlg*>(currentDialog)->closeDialogForced(); + } + else if (dynamic_cast<SecureDlg*>(currentDialog)) { + dynamic_cast<SecureDlg*>(currentDialog)->closeDialogForced(); + } + else { + currentDialog->close(); + } + } + + if( mDialogs.isEmpty() ) { + trinity_desktop_lock_closing_windows = FALSE; + mForceReject = false; + return false; + } + else { + trinity_desktop_lock_closing_windows = TRUE; + return true; + } +} + +void LockProcess::timerEvent(TQTimerEvent *ev) +{ + if (mAutoLogout && ev->timerId() == mAutoLogoutTimerId) + { + killTimer(mAutoLogoutTimerId); + AutoLogout autologout(this); + execDialog(&autologout); + } +} + +void LockProcess::resizeEvent(TQResizeEvent *) +{ + // +} + +void LockProcess::setupSignals() +{ + struct sigaction act; + // ignore SIGINT + act.sa_handler=SIG_IGN; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGINT); + act.sa_flags = 0; + sigaction(SIGINT, &act, 0L); + // ignore SIGQUIT + act.sa_handler=SIG_IGN; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGQUIT); + act.sa_flags = 0; + sigaction(SIGQUIT, &act, 0L); + // exit uncleanly on SIGTERM + act.sa_handler= sigterm_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGTERM); + act.sa_flags = 0; + sigaction(SIGTERM, &act, 0L); + // SIGHUP forces lock + act.sa_handler= sighup_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGHUP); + act.sa_flags = 0; + sigaction(SIGHUP, &act, 0L); + + if (pipe(signal_pipe) == -1) { + // Error handler to shut up gcc warnings + } + TQSocketNotifier* notif = new TQSocketNotifier(signal_pipe[0], TQSocketNotifier::Read, TQT_TQOBJECT(this) ); + connect( notif, TQT_SIGNAL(activated(int)), TQT_SLOT(signalPipeSignal())); +} + + +void LockProcess::signalPipeSignal() +{ + char tmp; + if (::read( signal_pipe[0], &tmp, 1) == -1) { + // Error handler to shut up gcc warnings + } + if( tmp == 'T' ) { + quitSaver(); + } + else if( tmp == 'H' ) { + if( !mLocked ) + startLock(); + } + else if( tmp == 'U' ) { + // Exit uncleanly + quitSaver(); + exit(1); + } +} + +//--------------------------------------------------------------------------- +bool LockProcess::lock() +{ +#ifdef USE_SECURING_DESKTOP_NOTIFICATION + m_startupStatusDialog = new KSMModalDialog(this); + m_startupStatusDialog->setStatusMessage(i18n("Securing desktop session").append("...")); + m_startupStatusDialog->show(); + m_startupStatusDialog->setActiveWindow(); + tqApp->processEvents(); +#endif + + if (startSaver(true)) { + // In case of a forced lock we don't react to events during + // the dead-time to give the screensaver some time to activate. + // That way we don't accidentally show the password dialog before + // the screensaver kicks in because the user moved the mouse after + // selecting "lock screen", that looks really untidy. + mBusy = true; + if (startLock()) + { + TQTimer::singleShot(1000, this, TQT_SLOT(slotDeadTimePassed())); + return true; + } + stopSaver(); + mBusy = false; + } + return false; +} +//--------------------------------------------------------------------------- +void LockProcess::slotDeadTimePassed() +{ + mBusy = false; +} + +//--------------------------------------------------------------------------- +bool LockProcess::defaultSave() +{ + mLocked = false; + mOverrideHackStartupEnabled = true; + if (startSaver()) { + if (mLockGrace >= 0) + TQTimer::singleShot(mLockGrace, this, TQT_SLOT(startLock())); + return true; + } + return false; +} + +//--------------------------------------------------------------------------- +bool LockProcess::dontLock() +{ + mLocked = false; + return startSaver(); +} + +//--------------------------------------------------------------------------- +void LockProcess::quitSaver() +{ + DISABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (closeCurrentWindow()) { + TQTimer::singleShot( 0, this, SLOT(quitSaver()) ); + return; + } + stopSaver(); + kapp->quit(); +} + +//--------------------------------------------------------------------------- +void LockProcess::startSecureDialog() +{ + if ((backingPixmap.isNull()) && (mBackingStartupDelayTimer < 100)) { + TQTimer::singleShot(10, this, TQT_SLOT(startSecureDialog())); + mBackingStartupDelayTimer++; + return; + } + + setGeometry(0, 0, mRootWidth, mRootHeight); + saverReadyIfNeeded(); + + int ret; + SecureDlg inDlg( this ); + inDlg.setRetInt(&ret); + mBusy = true; + execDialog( &inDlg ); + mBusy = false; + bool forcecontdisp = mForceContinualLockDisplayTimer->isActive(); + if (forcecontdisp) { + DISABLE_CONTINUOUS_LOCKDLG_DISPLAY + } + trinity_desktop_lock_in_sec_dlg = false; + if (ret == 0) { + trinity_desktop_lock_closing_windows = 1; + kapp->quit(); + } + if (ret == 1) { + // In case of a forced lock we don't react to events during + // the dead-time to give the screensaver some time to activate. + // That way we don't accidentally show the password dialog before + // the screensaver kicks in because the user moved the mouse after + // selecting "lock screen", that looks really untidy. + mBusy = true; + trinity_desktop_lock_forced = true; + // Make sure the cursor is not showing busy status + setCursor( tqarrowCursor ); + if (startLock()) + { + if (trinity_desktop_lock_delay_screensaver_start) { + mBusy = false; + } + else { + TQTimer::singleShot(1000, this, TQT_SLOT(slotDeadTimePassed())); + } + if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced && trinity_desktop_lock_use_system_modal_dialogs) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + else { + if (mHackStartupEnabled == true) { + startHack(); + } + else { + if (trinity_desktop_lock_use_system_modal_dialogs == true) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + else { + startHack(); + } + } + } + return; + } + stopSaver(); + mBusy = false; + return; + } + if (ret == 2) { + trinity_desktop_lock_closing_windows = 1; + if (system("ksysguard &") == -1) { + // Error handler to shut up gcc warnings + } + kapp->quit(); + } + if (ret == 3) { + trinity_desktop_lock_closing_windows = 1; + DCOPRef("ksmserver","ksmserver").send("logout", (int)TDEApplication::ShutdownConfirmYes, (int)TDEApplication::ShutdownTypeNone, (int)TDEApplication::ShutdownModeInteractive); + kapp->quit(); + } + // FIXME + // Handle remaining case (switch user) + if (forcecontdisp) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + stopSaver(); +} + +bool LockProcess::runSecureDialog() +{ +#ifdef USE_SECURING_DESKTOP_NOTIFICATION + m_startupStatusDialog = new KSMModalDialog(this); + m_startupStatusDialog->setStatusMessage(i18n("Securing desktop session").append("...")); + m_startupStatusDialog->show(); + m_startupStatusDialog->setActiveWindow(); + tqApp->processEvents(); +#endif + + trinity_desktop_lock_in_sec_dlg = true; + if (startSaver()) { + mBackingStartupDelayTimer = 0; + TQTimer::singleShot(0, this, TQT_SLOT(startSecureDialog())); + return true; + } + else { + return false; + } +} + +//--------------------------------------------------------------------------- +// +// Read and apply configuration. +// +void LockProcess::configure() +{ + // the configuration is stored in kdesktop's config file + if( KDesktopSettings::lock() ) + { + mLockGrace = KDesktopSettings::lockGrace(); + if (mLockGrace < 0) + mLockGrace = 0; + else if (mLockGrace > 300000) + mLockGrace = 300000; // 5 minutes, keep the value sane + } + else + mLockGrace = -1; + + if ( KDesktopSettings::autoLogout() ) + { + mAutoLogout = true; + mAutoLogoutTimeout = KDesktopSettings::autoLogoutTimeout(); + mAutoLogoutTimerId = startTimer(mAutoLogoutTimeout * 1000); // in milliseconds + } + + mPriority = KDesktopSettings::priority(); + if (mPriority < 0) mPriority = 0; + if (mPriority > 19) mPriority = 19; + + mSaver = KDesktopSettings::saver(); + if (mSaver.isEmpty() || mUseBlankOnly) { + mSaver = "KBlankscreen.desktop"; + } + if (!trinity_desktop_lock_use_system_modal_dialogs) { + if (KDesktopSettings::screenSaverEnabled() == false) { + mSaver = ""; + mSaverExec = ""; + } + } + + readSaver(); + + mPlugins = KDesktopSettings::pluginsUnlock(); + if (mPlugins.isEmpty()) { + mPlugins = TQStringList("classic"); + } + mPluginOptions = KDesktopSettings::pluginOptions(); +} + +//--------------------------------------------------------------------------- +// +// Read the command line needed to run the screensaver given a .desktop file. +// +void LockProcess::readSaver() +{ + if (!mSaver.isEmpty()) + { + TQString file = locate("scrsav", mSaver); + + bool opengl = kapp->authorize("opengl_screensavers"); + bool manipulatescreen = kapp->authorize("manipulatescreen_screensavers"); + KDesktopFile config(file, true); + if (config.readEntry("X-TDE-Type").utf8() != 0) + { + TQString saverType = config.readEntry("X-TDE-Type").utf8(); + TQStringList saverTypes = TQStringList::split(";", saverType); + for (uint i = 0; i < saverTypes.count(); i++) + { + if ((saverTypes[i] == "ManipulateScreen") && !manipulatescreen) + { + kdDebug(1204) << "Screensaver is type ManipulateScreen and ManipulateScreen is forbidden" << endl; + mForbidden = true; + } + if ((saverTypes[i] == "OpenGL") && !opengl) + { + kdDebug(1204) << "Screensaver is type OpenGL and OpenGL is forbidden" << endl; + mForbidden = true; + } + if (saverTypes[i] == "OpenGL") + { + mOpenGLVisual = true; + } + } + } + + kdDebug(1204) << "mForbidden: " << (mForbidden ? "true" : "false") << endl; + + if (trinity_desktop_lock_use_system_modal_dialogs) { + if (config.hasActionGroup("InWindow")) + { + config.setActionGroup("InWindow"); + mSaverExec = config.readPathEntry("Exec"); + } + } + else { + if (config.hasActionGroup("Root")) + { + config.setActionGroup("Root"); + mSaverExec = config.readPathEntry("Exec"); + } + } + } +} + +//--------------------------------------------------------------------------- +// +// Create a window to draw our screen saver on. +// +void LockProcess::createSaverWindow() +{ + Visual* visual = CopyFromParent; + XSetWindowAttributes attrs; + XVisualInfo* info = NULL; + int flags = trinity_desktop_lock_use_system_modal_dialogs?0:CWOverrideRedirect; +#ifdef HAVE_GLXCHOOSEVISUAL + if( mOpenGLVisual ) + { + static int attribs[][ 15 ] = + { + #define R GLX_RED_SIZE + #define G GLX_GREEN_SIZE + #define B GLX_BLUE_SIZE + { GLX_RGBA, R, 8, G, 8, B, 8, GLX_DEPTH_SIZE, 8, GLX_DOUBLEBUFFER, GLX_STENCIL_SIZE, 1, None }, + { GLX_RGBA, R, 4, G, 4, B, 4, GLX_DEPTH_SIZE, 4, GLX_DOUBLEBUFFER, GLX_STENCIL_SIZE, 1, None }, + { GLX_RGBA, R, 8, G, 8, B, 8, GLX_DEPTH_SIZE, 8, GLX_DOUBLEBUFFER, None }, + { GLX_RGBA, R, 4, G, 4, B, 4, GLX_DEPTH_SIZE, 4, GLX_DOUBLEBUFFER, None }, + { GLX_RGBA, R, 8, G, 8, B, 8, GLX_DEPTH_SIZE, 8, GLX_STENCIL_SIZE, 1, None }, + { GLX_RGBA, R, 4, G, 4, B, 4, GLX_DEPTH_SIZE, 4, GLX_STENCIL_SIZE, 1, None }, + { GLX_RGBA, R, 8, G, 8, B, 8, GLX_DEPTH_SIZE, 8, None }, + { GLX_RGBA, R, 4, G, 4, B, 4, GLX_DEPTH_SIZE, 4, None }, + { GLX_RGBA, GLX_DEPTH_SIZE, 8, GLX_DOUBLEBUFFER, GLX_STENCIL_SIZE, 1, None }, + { GLX_RGBA, GLX_DEPTH_SIZE, 8, GLX_DOUBLEBUFFER, None }, + { GLX_RGBA, GLX_DEPTH_SIZE, 8, GLX_STENCIL_SIZE, 1, None }, + { GLX_RGBA, GLX_DEPTH_SIZE, 8, None } + #undef R + #undef G + #undef B + }; + for( unsigned int i = 0; i < sizeof( attribs ) / sizeof( attribs[ 0 ] ); ++i ) { + int n_glxfb_configs; + GLXFBConfig *fbc = glXChooseFBConfig( x11Display(), x11Screen(), attribs[ i ], &n_glxfb_configs); + if (!fbc) { + n_glxfb_configs = 0; + } + for( int j = 0; j < n_glxfb_configs; j++ ) { + info = glXGetVisualFromFBConfig(x11Display(), fbc[j]); + if( info ) { + if (argb_visual) { + if (info->depth < 32) { + XFree( info ); + info = NULL; + continue; + } + } + visual = info->visual; + static Colormap colormap = 0; + if( colormap != 0 ) { + XFreeColormap( x11Display(), colormap ); + } + colormap = XCreateColormap( x11Display(), RootWindow( x11Display(), x11Screen()), visual, AllocNone ); + attrs.colormap = colormap; + flags |= CWColormap; + break; + } + } + if (flags & CWColormap) { + break; + } + } + if ( !info ) + { + printf("[WARNING] Unable to locate matching X11 GLX Visual; this OpenGL application may not function correctly!\n"); + } + } +#endif + + attrs.override_redirect = 1; + hide(); + + if (argb_visual) { + // The GL visual selection can return a visual with invalid depth + // Check for this and use a fallback visual if needed + if (info && (info->depth < 32)) { + printf("[WARNING] Unable to locate matching X11 GLX Visual; this OpenGL application may not function correctly!\n"); + XFree( info ); + info = NULL; + flags &= ~CWColormap; + } + + attrs.background_pixel = 0; + attrs.border_pixel = 0; + flags |= CWBackPixel; + flags |= CWBorderPixel; + if (!(flags & CWColormap)) { + if (!info) { + info = new XVisualInfo; + if (!XMatchVisualInfo( x11Display(), x11Screen(), 32, TrueColor, info )) { + printf("[ERROR] Unable to locate matching X11 Visual; this application will not function correctly!\n"); + free(info); + info = NULL; + } + } + if (info) { + visual = info->visual; + attrs.colormap = XCreateColormap( x11Display(), RootWindow( x11Display(), x11Screen()), visual, AllocNone ); + flags |= CWColormap; + } + } + } + if (info) { + XFree( info ); + } + + m_saverRootWindow = XCreateWindow( x11Display(), RootWindow( x11Display(), x11Screen()), x(), y(), width(), height(), 0, x11Depth(), InputOutput, visual, flags, &attrs ); + create( m_saverRootWindow ); + + // Some xscreensaver hacks check for this property + const char *version = "KDE 2.0"; + XChangeProperty (tqt_xdisplay(), winId(), + gXA_SCREENSAVER_VERSION, XA_STRING, 8, PropModeReplace, + (unsigned char *) version, strlen(version)); + + XSetWindowAttributes attr; + attr.event_mask = KeyPressMask | ButtonPressMask | PointerMotionMask | VisibilityChangeMask | ExposureMask; + XChangeWindowAttributes(tqt_xdisplay(), winId(), CWEventMask, &attr); + + // Signal that we want to be transparent to the desktop, not to windows behind us... + XChangeProperty(tqt_xdisplay(), m_saverRootWindow, kde_wm_transparent_to_desktop, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + + // erase(); + + // set NoBackground so that the saver can capture the current + // screen state if necessary + // this is a security risk and has been deactivated--welcome to the 21st century folks! + // setBackgroundMode(TQWidget::NoBackground); + + setGeometry(0, 0, mRootWidth, mRootHeight); + saverReadyIfNeeded(); + + // HACK + // Hide all tooltips and notification windows + { + Window rootWindow = RootWindow(x11Display(), x11Screen()); + Window parent; + Window* children = NULL; + unsigned int noOfChildren = 0; + XWindowAttributes childAttr; + Window childTransient; + + if (XQueryTree(x11Display(), rootWindow, &rootWindow, &parent, &children, &noOfChildren) && noOfChildren>0 ) { + for (unsigned int i=0; i<noOfChildren; i++) { + if (XGetWindowAttributes(x11Display(), children[i], &childAttr) && XGetTransientForHint(x11Display(), children[i], &childTransient)) { + if ((childAttr.map_state == IsViewable) && (childAttr.override_redirect) && (childTransient)) { + if (!trinity_desktop_lock_hidden_window_list.contains(children[i])) { + trinity_desktop_lock_hidden_window_list.append(children[i]); + } + XLowerWindow(x11Display(), children[i]); + XFlush(x11Display()); + } + } + } + } + } + + fullyOnline(); + + kdDebug(1204) << "Saver window Id: " << winId() << endl; +} + +void LockProcess::desktopResized() +{ + // Get root window size + XWindowAttributes rootAttr; + XGetWindowAttributes(tqt_xdisplay(), RootWindow(tqt_xdisplay(), tqt_xscreen()), &rootAttr); + if ((rootAttr.width == mRootWidth) && (rootAttr.height == mRootHeight)) { + return; + } + mRootWidth = rootAttr.width; + mRootHeight = rootAttr.height; + + mBusy = true; + mHackDelayStartupTimer->stop(); + stopHack(); + DISABLE_CONTINUOUS_LOCKDLG_DISPLAY + mResizingDesktopLock = true; + + backingPixmap = TQPixmap(); + + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Temporarily hide the entire screen with a new override redirect window + if (m_maskWidget) { + m_maskWidget->setGeometry(0, 0, mRootWidth, mRootHeight); + } + else { + m_maskWidget = new TQWidget(0, 0, TQt::WStyle_StaysOnTop | TQt::WX11BypassWM); + m_maskWidget->setGeometry(0, 0, mRootWidth, mRootHeight); + m_maskWidget->setBackgroundColor(TQt::black); + m_maskWidget->erase(); + m_maskWidget->show(); + } + XSync(tqt_xdisplay(), False); + saverReadyIfNeeded(); + + if (mEnsureScreenHiddenTimer) { + mEnsureScreenHiddenTimer->stop(); + } + else { + mEnsureScreenHiddenTimer = new TQTimer( this ); + connect( mEnsureScreenHiddenTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotForcePaintBackground()) ); + } + mEnsureScreenHiddenTimer->start(DESKTOP_WALLPAPER_OBTAIN_TIMEOUT_MS, true); + } + + // Resize the background widget + setGeometry(0, 0, mRootWidth, mRootHeight); + XSync(tqt_xdisplay(), False); + saverReadyIfNeeded(); + + // Black out the background widget to hide ugly resize tiling artifacts + if (argb_visual) { + setTransparentBackgroundARGB(); + } + else { + setBackgroundColor(black); + } + erase(); + + // This slot needs to be able to execute very rapidly so as to prevent the user's desktop from ever + // being displayed, so we finish the hack restarting/display prettying operations in a separate timed slot + if (resizeTimer == NULL) { + resizeTimer = new TQTimer( this ); + connect( resizeTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(doDesktopResizeFinish()) ); + } + resizeTimer->start( 100, TRUE ); // 100 millisecond single shot timer; should allow display switching operations to finish before hack is started +} + +void LockProcess::doDesktopResizeFinish() +{ + while (mDialogControlLock == true) { + usleep(100000); + } + mDialogControlLock = true; + if (closeCurrentWindow()) { + TQTimer::singleShot( 0, this, SLOT(doDesktopResizeFinish()) ); + mDialogControlLock = false; + return; + } + mDialogControlLock = false; + + // Restart the hack as the window size is now different + if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_use_system_modal_dialogs) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + else { + if (mHackStartupEnabled == true) { + startHack(); + } + else { + if (trinity_desktop_lock_use_system_modal_dialogs == true) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + else { + startHack(); + } + } + } + + mResizingDesktopLock = false; + mBusy = false; +} + +//--------------------------------------------------------------------------- +// +// Hide the screensaver window +// +void LockProcess::hideSaverWindow() +{ + hide(); + lower(); + removeVRoot(winId()); + XDeleteProperty(tqt_xdisplay(), winId(), gXA_SCREENSAVER_VERSION); + if ( gVRoot ) { + unsigned long vroot_data[1] = { gVRootData }; + XChangeProperty(tqt_xdisplay(), gVRoot, gXA_VROOT, XA_WINDOW, 32, + PropModeReplace, (unsigned char *)vroot_data, 1); + gVRoot = 0; + } + XSync(tqt_xdisplay(), False); +} + +//--------------------------------------------------------------------------- +static int ignoreXError(Display *, XErrorEvent *) +{ + return 0; +} + +//--------------------------------------------------------------------------- +// +// Save the current virtual root window +// +void LockProcess::saveVRoot() +{ + Window rootReturn, parentReturn, *children; + unsigned int numChildren; + Window root = RootWindowOfScreen(ScreenOfDisplay(tqt_xdisplay(), tqt_xscreen())); + + gVRoot = 0; + gVRootData = 0; + + int (*oldHandler)(Display *, XErrorEvent *); + oldHandler = XSetErrorHandler(ignoreXError); + + if (XQueryTree(tqt_xdisplay(), root, &rootReturn, &parentReturn, + &children, &numChildren)) + { + for (unsigned int i = 0; i < numChildren; i++) + { + Atom actual_type; + int actual_format; + unsigned long nitems, bytesafter; + unsigned char *newRoot = 0; + + if ((XGetWindowProperty(tqt_xdisplay(), children[i], gXA_VROOT, 0, 1, + False, XA_WINDOW, &actual_type, &actual_format, &nitems, &bytesafter, + &newRoot) == Success) && newRoot) + { + gVRoot = children[i]; + Window *dummy = (Window*)newRoot; + gVRootData = *dummy; + XFree ((char*) newRoot); + break; + } + } + if (children) + { + XFree((char *)children); + } + } + + XSetErrorHandler(oldHandler); +} + +//--------------------------------------------------------------------------- +// +// Set the virtual root property +// +void LockProcess::setVRoot(Window win, Window vr) +{ + if (gVRoot) { + removeVRoot(gVRoot); + } + + unsigned long rw = RootWindowOfScreen(ScreenOfDisplay(tqt_xdisplay(), tqt_xscreen())); + unsigned long vroot_data[1] = { vr }; + + Window rootReturn; + Window parentReturn; + Window *children = NULL; + unsigned int numChildren; + Window top = win; + while (1) { + if (XQueryTree(tqt_xdisplay(), top, &rootReturn, &parentReturn, &children, &numChildren) == 0) { + printf("[WARNING] XQueryTree() failed!\n"); fflush(stdout); + break; + } + if (children) { + XFree((char *)children); + } + if (parentReturn == rw) { + break; + } + else { + top = parentReturn; + } + } + + XChangeProperty(tqt_xdisplay(), top, gXA_VROOT, XA_WINDOW, 32, PropModeReplace, (unsigned char *)vroot_data, 1); +} + +//--------------------------------------------------------------------------- +// +// Remove the virtual root property +// +void LockProcess::removeVRoot(Window win) +{ + XDeleteProperty (tqt_xdisplay(), win, gXA_VROOT); +} + +//--------------------------------------------------------------------------- +// +// Grab the keyboard. Returns true on success +// +bool LockProcess::grabKeyboard() +{ + int rv = XGrabKeyboard( tqt_xdisplay(), TQApplication::desktop()->winId(), + True, GrabModeAsync, GrabModeAsync, CurrentTime ); + + return (rv == GrabSuccess); +} + +#define GRABEVENTS ButtonPressMask | ButtonReleaseMask | PointerMotionMask | \ + EnterWindowMask | LeaveWindowMask + +//--------------------------------------------------------------------------- +// +// Grab the mouse. Returns true on success +// +bool LockProcess::grabMouse() +{ + HANDLE cursorHandle; + if (trinity_desktop_hack_active) { + cursorHandle = TQCursor(tqblankCursor).handle(); + } + else { + cursorHandle = TQCursor(tqbusyCursor).handle(); + } + int rv = XGrabPointer( tqt_xdisplay(), TQApplication::desktop()->winId(), + True, GRABEVENTS, GrabModeAsync, GrabModeAsync, None, + cursorHandle, CurrentTime ); + + return (rv == GrabSuccess); +} + +//--------------------------------------------------------------------------- +// +// Grab keyboard and mouse. Returns true on success. +// +bool LockProcess::grabInput() +{ + XSync(tqt_xdisplay(), False); + + if (!grabKeyboard()) + { + usleep(100000); + if (!grabKeyboard()) + { + return false; + } + } + +#ifndef KEEP_MOUSE_UNGRABBED + if (!grabMouse()) + { + usleep(100000); + if (!grabMouse()) + { + XUngrabKeyboard(tqt_xdisplay(), CurrentTime); + return false; + } + } +#endif + + lockXF86(); + + return true; +} + +//--------------------------------------------------------------------------- +// +// Release mouse an keyboard grab. +// +void LockProcess::ungrabInput() +{ + XUngrabKeyboard(tqt_xdisplay(), CurrentTime); + XUngrabPointer(tqt_xdisplay(), CurrentTime); + unlockXF86(); +} + +//--------------------------------------------------------------------------- +// +// Set a fully transparent ARGB background image. +// +void LockProcess::setTransparentBackgroundARGB() +{ + // eliminate nasty flicker on first show + TQImage m_grayImage = TQImage( TQApplication::desktop()->width(), TQApplication::desktop()->height(), 32 ); + m_grayImage = m_grayImage.convertDepth(32); + m_grayImage.setAlphaBuffer(false); + m_grayImage.fill(0); // Set the alpha buffer to 0 (fully transparent) + m_grayImage.setAlphaBuffer(true); + TQPixmap m_root; + m_root.resize(mRootWidth, mRootHeight); + TQPainter p; + p.begin( &m_root ); + m_grayImage.setAlphaBuffer(false); + p.drawImage( 0, 0, m_grayImage ); + p.end(); + setBackgroundPixmap( m_root ); +} + +void LockProcess::saverReadyIfNeeded() +{ + if (m_notifyReadyRequested) { + // Make sure the desktop is hidden before notifying the desktop that the saver is running + m_notifyReadyRequested = false; + saverReady(); + } +} + +//--------------------------------------------------------------------------- +// +// Start the screen saver. +// +bool LockProcess::startSaver(bool notify_ready) +{ + if (!child_saver && !grabInput()) + { + kdWarning(1204) << "LockProcess::startSaver() grabInput() failed!!!!" << endl; + return false; + } + mBusy = false; + + // eliminate nasty flicker on first show + setTransparentBackgroundARGB(); + + saveVRoot(); + + if (mParent) { + TQSocketNotifier *notifier = new TQSocketNotifier(mParent, TQSocketNotifier::Read, TQT_TQOBJECT(this), "notifier"); + connect(notifier, TQT_SIGNAL( activated (int)), TQT_SLOT( quitSaver())); + } + createSaverWindow(); + move(0, 0); + show(); + + raise(); + XSync(tqt_xdisplay(), False); + setVRoot( winId(), winId() ); + + if (!trinity_desktop_lock_hide_active_windows) { + if (m_rootPixmap) m_rootPixmap->stop(); + TQPixmap rootWinSnapShot = TQPixmap::grabWindow(TQApplication::desktop()->winId()); + slotPaintBackground(rootWinSnapShot); + } + + if (((!(trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced)) && (!trinity_desktop_lock_in_sec_dlg)) && (mHackStartupEnabled || mOverrideHackStartupEnabled)) { + if (argb_visual) { + setTransparentBackgroundARGB(); + } + else { + if (backingPixmap.isNull()) { + setBackgroundColor(black); + } + else { + setBackgroundPixmap(backingPixmap); + } + } + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + + if (notify_ready) { + m_notifyReadyRequested = false; + saverReady(); + } + } + else { + if (notify_ready) { + m_notifyReadyRequested = true; + } + } + + if (trinity_desktop_lock_in_sec_dlg == FALSE) { + if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced && trinity_desktop_lock_use_system_modal_dialogs) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + else { + if (mHackStartupEnabled || mOverrideHackStartupEnabled) { + mOverrideHackStartupEnabled = false; + startHack(); + } + else { + if (trinity_desktop_lock_use_system_modal_dialogs == true) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + else { + startHack(); + } + } + } + } + return true; +} + +//--------------------------------------------------------------------------- +// +// Stop the screen saver. +// +void LockProcess::stopSaver() +{ + kdDebug(1204) << "LockProcess: stopping saver" << endl; + mHackProc.kill(SIGCONT); + stopHack(); + mSuspended = false; + hideSaverWindow(); + mVisibility = false; + if (!child_saver) { + if (mLocked) + DM().setLock( false ); + ungrabInput(); + const char *out = "GOAWAY!"; + for (TQValueList<int>::ConstIterator it = child_sockets.begin(); it != child_sockets.end(); ++it) + if (write(*it, out, sizeof(out)) == -1) { + // Error handler to shut up gcc warnings + } + } +} + +// private static +TQVariant LockProcess::getConf(void *ctx, const char *key, const TQVariant &dflt) +{ + LockProcess *that = (LockProcess *)ctx; + TQString fkey = TQString::fromLatin1( key ) + '='; + for (TQStringList::ConstIterator it = that->mPluginOptions.begin(); + it != that->mPluginOptions.end(); ++it) + if ((*it).startsWith( fkey )) + return (*it).mid( fkey.length() ); + return dflt; +} + +void LockProcess::cantLock( const TQString &txt) +{ + msgBox( TQMessageBox::Critical, i18n("Will not lock the session, as unlocking would be impossible:\n") + txt ); +} + +#if 0 // placeholders for later +i18n("Cannot start <i>kcheckpass</i>."); +i18n("<i>kcheckpass</i> is unable to operate. Possibly it is not SetUID root."); +#endif + +//--------------------------------------------------------------------------- +// +// Make the screen saver password protected. +// +bool LockProcess::startLock() +{ + for (TQStringList::ConstIterator it = mPlugins.begin(); it != mPlugins.end(); ++it) { + GreeterPluginHandle plugin; + TQString path = KLibLoader::self()->findLibrary( + ((*it)[0] == '/' ? *it : "kgreet_" + *it ).latin1() ); + if (path.isEmpty()) { + kdWarning(1204) << "GreeterPlugin " << *it << " does not exist" << endl; + continue; + } + if (!(plugin.library = KLibLoader::self()->library( path.latin1() ))) { + kdWarning(1204) << "Cannot load GreeterPlugin " << *it << " (" << path << ")" << endl; + continue; + } + if (!plugin.library->hasSymbol( "kgreeterplugin_info" )) { + kdWarning(1204) << "GreeterPlugin " << *it << " (" << path << ") is no valid greet widget plugin" << endl; + plugin.library->unload(); + continue; + } + plugin.info = (kgreeterplugin_info*)plugin.library->symbol( "kgreeterplugin_info" ); + if (plugin.info->method && !mMethod.isEmpty() && mMethod != plugin.info->method) { + kdDebug(1204) << "GreeterPlugin " << *it << " (" << path << ") serves " << plugin.info->method << ", not " << mMethod << endl; + plugin.library->unload(); + continue; + } + if (!plugin.info->init( mMethod, getConf, this )) { + kdDebug(1204) << "GreeterPlugin " << *it << " (" << path << ") refuses to serve " << mMethod << endl; + plugin.library->unload(); + continue; + } + kdDebug(1204) << "GreeterPlugin " << *it << " (" << plugin.info->method << ", " << plugin.info->name << ") loaded" << endl; + greetPlugin = plugin; + mLocked = true; + DM().setLock( true ); + return true; + } + cantLock( i18n("No appropriate greeter plugin configured.") ); + return false; +} + +//--------------------------------------------------------------------------- +// + +void LockProcess::closeDialogAndStartHack() +{ +#ifdef HAVE_DPMS + if (KDesktopSettings::dpmsDependent()) { + BOOL on; + CARD16 state; + if (DPMSInfo(tqt_xdisplay(), &state, &on)) { + //kdDebug() << "checkDPMSActive " << on << " " << state << endl; + if (DPMS_MONITOR_BLANKED(state)) { + // Make sure saver will attempt to start again after DPMS wakeup + // This is related to Bug 1475 + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + // Should not start saver here, because the DPMS check method below would turn it right back off! + // This is related to Bug 1475 + return; + } + } + } +#endif + + // Close any active dialogs + DISABLE_CONTINUOUS_LOCKDLG_DISPLAY + mSuspended = true; + if (closeCurrentWindow()) { + TQTimer::singleShot( 0, this, SLOT(closeDialogAndStartHack()) ); + } + else { + resume(true); + } +} + +void LockProcess::repaintRootWindowIfNeeded() +{ + if (trinity_desktop_lock_use_system_modal_dialogs) { + if (!mHackProc.isRunning()) { + if (argb_visual) { + setTransparentBackgroundARGB(); + erase(); + } + else { + if (backingPixmap.isNull()) { + setBackgroundColor(black); + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + } + else { + bitBlt(this, 0, 0, &backingPixmap); + } + } + } + if (currentDialog == NULL) { + raise(); + } + saverReadyIfNeeded(); + } +} + +bool LockProcess::startHack() +{ + trinity_desktop_hack_active = TRUE; + + if ((mEnsureVRootWindowSecurityTimer) && (!mEnsureVRootWindowSecurityTimer->isActive())) mEnsureVRootWindowSecurityTimer->start(250, FALSE); + + if (currentDialog || (!mDialogs.isEmpty())) + { + // no resuming with dialog visible or when not visible + if (argb_visual) { + setTransparentBackgroundARGB(); + } + else { + if (backingPixmap.isNull()) { + setBackgroundColor(black); + } + else { + setBackgroundPixmap(backingPixmap); + } + } + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + saverReadyIfNeeded(); + return false; + } + + setCursor( tqblankCursor ); + XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, TQCursor(tqblankCursor).handle(), CurrentTime); + + if (mSaverExec.isEmpty()) + { + return false; + } + + if (mHackProc.isRunning()) + { + stopHack(); + } + + mHackProc.clearArguments(); + + TQTextStream ts(&mSaverExec, IO_ReadOnly); + TQString word; + ts >> word; + TQString path = TDEStandardDirs::findExe(word); + + if (!path.isEmpty()) + { + mHackProc << path; + + kdDebug(1204) << "Starting hack: " << path << endl; + + while (!ts.atEnd()) + { + ts >> word; + if (word == "%w") + { + word = word.setNum(winId()); + } + mHackProc << word; + } + + if (!mForbidden) + { + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Make sure we have a nice clean display to start with! + if (argb_visual) { + // Signal that we want to be transparent to a black background... + if (m_saverRootWindow) { + XChangeProperty(tqt_xdisplay(), m_saverRootWindow, kde_wm_transparent_to_black, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + XClearArea(tqt_xdisplay(), m_saverRootWindow, 0, 0, 0, 0, True); + } + setTransparentBackgroundARGB(); + } + else { + if (backingPixmap.isNull()) { + setBackgroundColor(black); + } + else { + setBackgroundPixmap(backingPixmap); + } + } + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + saverReadyIfNeeded(); + mSuspended = false; + } + + if (mHackProc.start() == true) + { +#ifdef HAVE_SETPRIORITY + setpriority(PRIO_PROCESS, mHackProc.pid(), mPriority); +#endif + //bitBlt(this, 0, 0, &mOriginal); + DISABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced) { + // Close any active dialogs + if (closeCurrentWindow()) { + TQTimer::singleShot( 0, this, SLOT(closeCurrentWindow()) ); + } + } + if (m_startupStatusDialog) { m_startupStatusDialog->closeSMDialog(); m_startupStatusDialog=NULL; } + return true; + } + } + else + // we aren't allowed to start the specified screensaver either because it didn't run for some reason + // according to the kiosk restrictions forbid it + { + usleep(100); + TQApplication::syncX(); + if (!trinity_desktop_lock_use_system_modal_dialogs) { + if (argb_visual) { + setTransparentBackgroundARGB(); + } + else { + if (backingPixmap.isNull()) { + setBackgroundColor(black); + } + else { + setBackgroundPixmap(backingPixmap); + } + } + } + if (argb_visual) { + setTransparentBackgroundARGB(); + erase(); + } + else { + if (backingPixmap.isNull()) { + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + } + else { + bitBlt(this, 0, 0, &backingPixmap); + } + } + if (trinity_desktop_lock_use_system_modal_dialogs) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + saverReadyIfNeeded(); + } + } + if (m_startupStatusDialog) { m_startupStatusDialog->closeSMDialog(); m_startupStatusDialog=NULL; } + return false; +} + +//--------------------------------------------------------------------------- +// +void LockProcess::stopHack() +{ + if (mHackProc.isRunning()) + { + mHackProc.kill(); + if (!mHackProc.wait(10)) + { + mHackProc.kill(SIGKILL); + } + } + setCursor( tqarrowCursor ); + + trinity_desktop_hack_active = FALSE; +} + +//--------------------------------------------------------------------------- +// +void LockProcess::hackExited(TDEProcess *) +{ + // Hack exited while we're supposed to be saving the screen. + // Make sure the saver window is black. + trinity_desktop_hack_active = FALSE; + usleep(100); + TQApplication::syncX(); + if (!trinity_desktop_lock_use_system_modal_dialogs) { + if (argb_visual) { + setTransparentBackgroundARGB(); + } + else { + if (backingPixmap.isNull()) { + setBackgroundColor(black); + } + else { + setBackgroundPixmap(backingPixmap); + } + } + } + if (argb_visual) { + if (m_saverRootWindow) { + XDeleteProperty(tqt_xdisplay(), m_saverRootWindow, kde_wm_transparent_to_black); + XClearArea(tqt_xdisplay(), m_saverRootWindow, 0, 0, 0, 0, True); + } + setTransparentBackgroundARGB(); + } + else { + if (backingPixmap.isNull()) { + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + } + else { + bitBlt(this, 0, 0, &backingPixmap); + } + } + if (!mSuspended) { + if (trinity_desktop_lock_use_system_modal_dialogs) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + } + saverReadyIfNeeded(); +} + +void LockProcess::displayLockDialogIfNeeded() +{ + if (m_startupStatusDialog) { + m_startupStatusDialog->closeSMDialog(); + m_startupStatusDialog = NULL; + } + if (!trinity_desktop_lock_in_sec_dlg) { + if (trinity_desktop_lock_use_system_modal_dialogs) { + if (!mBusy) { + mBusy = true; + if (mLocked) { + if (checkPass()) { + trinity_desktop_lock_closing_windows = true; + stopSaver(); + kapp->quit(); + } + } + mBusy = false; + } + } + } +} + +void LockProcess::suspend() +{ + if(!mSuspended) + { + if (trinity_desktop_lock_use_system_modal_dialogs) { + mSuspended = true; + stopHack(); + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + else { + TQString hackStatus; + mHackProc.kill(SIGSTOP); + mSuspended = true; +#if 0 + // wait for the stop signal to take effect + while (hackStatus != "T") { + char hackstat[8192]; + FILE *fp = fopen(TQString("/proc/%1/stat").arg(mHackProc.pid()).ascii(),"r"); + if (fp != NULL) { + fgets (hackstat, 8192, fp); + fclose (fp); + } + hackstat[8191] = 0; + hackStatus = hackstat; + hackStatus = hackStatus.remove(TQRegExp("(*) ", TRUE, TRUE)); + TQStringList hackStatusList = TQStringList::split(" ", hackStatus); + hackStatus = (*(hackStatusList.at(1))); + } +#endif + TQApplication::syncX(); + usleep(100000); // Allow certain bad graphics drivers (*cough* fglrx *cough*) time to actually sync up the display + } + TQApplication::syncX(); + mSavedScreen = TQPixmap::grabWindow( winId()); + } +} + +void LockProcess::resume( bool force ) +{ + if (trinity_desktop_lock_use_sak && (mHackDelayStartupTimer->isActive() || !mHackStartupEnabled)) { + return; + } + if( !force && (!mDialogs.isEmpty() || !mVisibility )) { + // no resuming with dialog visible or when not visible + if (trinity_desktop_lock_use_system_modal_dialogs) { + if (argb_visual) { + setTransparentBackgroundARGB(); + } + else { + if (backingPixmap.isNull()) { + setBackgroundColor(black); + } + else { + setBackgroundPixmap(backingPixmap); + } + } + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + } + else { + setGeometry(0, 0, mRootWidth, mRootHeight); + } + saverReadyIfNeeded(); + return; + } + if ((mSuspended) && (mHackProc.isRunning())) + { + XForceScreenSaver(tqt_xdisplay(), ScreenSaverReset ); + bitBlt( this, 0, 0, &mSavedScreen ); + TQApplication::syncX(); + mHackProc.kill(SIGCONT); + mSuspended = false; + } + else if (mSuspended && trinity_desktop_lock_use_system_modal_dialogs) { + startHack(); + } +} + +//--------------------------------------------------------------------------- +// +// Show the password dialog +// This is called only in the master process +// +bool LockProcess::checkPass() +{ + if (!mDialogs.isEmpty()) { + // Another dialog is already shown + // Abort! + return 0; + } + if (mInfoMessageDisplayed == false) { + if (mAutoLogout) { + killTimer(mAutoLogoutTimerId); + } + + // Make sure we never launch the SAK or login dialog if windows are being closed down + // Otherwise we can get stuck in an irrecoverable state where any attempt to show the login screen is instantly aborted + if (trinity_desktop_lock_closing_windows) { + return 0; + } + + if (trinity_desktop_lock_use_sak) { + // Verify SAK operational status + TDEProcess* checkSAKProcess = new TDEProcess; + *checkSAKProcess << "tdmtsak" << "check"; + checkSAKProcess->start(TDEProcess::Block, TDEProcess::NoCommunication); + int retcode = checkSAKProcess->exitStatus(); + delete checkSAKProcess; + if (retcode != 0) { + trinity_desktop_lock_use_sak = false; + } + } + + if (trinity_desktop_lock_use_sak) { + // Wait for SAK press before continuing... + SAKDlg inDlg( this ); + execDialog( &inDlg ); + if (trinity_desktop_lock_closing_windows) { + return 0; + } + } + + showVkbd(); + PasswordDlg passDlg( this, &greetPlugin, (mShowLockDateTime)?mlockDateTime:TQDateTime()); + int ret = execDialog( &passDlg ); + hideVkbd(); + + if (mForceReject == true) { + ret = TQDialog::Rejected; + } + mForceReject = false; + + XWindowAttributes rootAttr; + XGetWindowAttributes(tqt_xdisplay(), RootWindow(tqt_xdisplay(), + tqt_xscreen()), &rootAttr); + if(( rootAttr.your_event_mask & SubstructureNotifyMask ) == 0 ) + { + kdWarning() << "ERROR: Something removed SubstructureNotifyMask from the root window!!!" << endl; + XSelectInput( tqt_xdisplay(), tqt_xrootwin(), + SubstructureNotifyMask | rootAttr.your_event_mask ); + } + + return ret == TQDialog::Accepted; + } + else { + return 0; + } +} + +static void fakeFocusIn( WId window ) +{ + // We have keyboard grab, so this application will + // get keyboard events even without having focus. + // Fake FocusIn to make Qt realize it has the active + // window, so that it will correctly show cursor in the dialog. + XEvent ev; + memset(&ev, 0, sizeof(ev)); + ev.xfocus.display = tqt_xdisplay(); + ev.xfocus.type = FocusIn; + ev.xfocus.window = window; + ev.xfocus.mode = NotifyNormal; + ev.xfocus.detail = NotifyAncestor; + XSendEvent( tqt_xdisplay(), window, False, NoEventMask, &ev ); +} + +void LockProcess::resumeUnforced() +{ + resume( false ); +} + +int LockProcess::execDialog( TQDialog *dlg ) +{ + currentDialog=dlg; + dlg->adjustSize(); + + TQRect rect = dlg->geometry(); + rect.moveCenter(TDEGlobalSettings::desktopGeometry(TQCursor::pos()).center()); + dlg->move( rect.topLeft() ); + + if (mDialogs.isEmpty()) + { + suspend(); + XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, + TQCursor(tqarrowCursor).handle(), CurrentTime); + } + mDialogs.prepend( dlg ); + fakeFocusIn( dlg->winId()); + if (trinity_desktop_lock_use_system_modal_dialogs) { + if (backingPixmap.isNull()) { + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + } + else { + bitBlt(this, 0, 0, &backingPixmap); + } + } + saverReadyIfNeeded(); + // dlg->exec may generate BadMatch errors, so make sure they are silently ignored + int (*oldHandler)(Display *, XErrorEvent *); + oldHandler = XSetErrorHandler(ignoreXError); + int rt = dlg->exec(); + XSetErrorHandler(oldHandler); + while (mDialogControlLock == true) usleep(100000); + currentDialog = NULL; + mDialogs.remove( dlg ); + if( mDialogs.isEmpty() ) { + HANDLE cursorHandle; + if (trinity_desktop_hack_active) { + cursorHandle = TQCursor(tqblankCursor).handle(); + } + else { + cursorHandle = TQCursor(tqbusyCursor).handle(); + } + XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, + cursorHandle, CurrentTime); + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Slight delay before screensaver resume to allow the dialog window to fully disappear + if (hackResumeTimer == NULL) { + hackResumeTimer = new TQTimer( this ); + connect( hackResumeTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(resumeUnforced()) ); + } + if (mResizingDesktopLock == false) { + hackResumeTimer->start( 10, TRUE ); + } + } + else { + resume( false ); + } + } else { + fakeFocusIn( mDialogs.first()->winId()); + currentDialog = dynamic_cast<TQDialog*>(mDialogs.first()); + } + return rt; +} + +void LockProcess::slotForcePaintBackground() +{ + TQPixmap blankPixmap(mRootWidth, mRootHeight); + blankPixmap.fill(Qt::black); + slotPaintBackground(blankPixmap); + printf("[WARNING] Unable to obtain desktop wallpaper in a timely manner. High system load or possibly a TDE bug!\n"); fflush(stdout); +} + +void LockProcess::slotPaintBackground(const TQPixmap &rpm) +{ + if (argb_visual) { + if (mEnsureScreenHiddenTimer) { + mEnsureScreenHiddenTimer->stop(); + } + return; + } + + if (mEnsureScreenHiddenTimer) { + mEnsureScreenHiddenTimer->stop(); + } + else { + mEnsureScreenHiddenTimer = new TQTimer( this ); + connect( mEnsureScreenHiddenTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotForcePaintBackground()) ); + } + + // Only remove the mask widget once the resize is 100% complete! + if (m_maskWidget) { + delete m_maskWidget; + m_maskWidget = NULL; + XSync(tqt_xdisplay(), False); + } + + TQPixmap pm = rpm; + + if (TQPaintDevice::x11AppDepth() == 32) { + // Remove the alpha components from the image + TQImage correctedImage = pm.convertToImage(); + correctedImage = correctedImage.convertDepth(32); + correctedImage.setAlphaBuffer(true); + int w = correctedImage.width(); + int h = correctedImage.height(); + for (int y = 0; y < h; ++y) { + TQRgb *ls = (TQRgb *)correctedImage.scanLine( y ); + for (int x = 0; x < w; ++x) { + TQRgb l = ls[x]; + int r = int( tqRed( l ) ); + int g = int( tqGreen( l ) ); + int b = int( tqBlue( l ) ); + int a = int( 255 ); + ls[x] = tqRgba( r, g, b, a ); + } + } + pm.convertFromImage(correctedImage); + } + + backingPixmap = pm; + if ((trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced) || (!mHackStartupEnabled)) { + setBackgroundPixmap(backingPixmap); + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + } + saverReadyIfNeeded(); +} + +void LockProcess::preparePopup() +{ + TQWidget *dlg = (TQWidget *)sender(); + mDialogs.prepend( dlg ); + fakeFocusIn( dlg->winId() ); +} + +void LockProcess::cleanupPopup() +{ + TQWidget *dlg = (TQWidget *)sender(); + mDialogs.remove( dlg ); + if ( mDialogs.isEmpty() ) { + fakeFocusIn( mDialogs.first()->winId() ); + } +} + +void LockProcess::doFunctionKeyBroadcast() { + // Provide a clean, pretty display switch by hiding the password dialog here + // This does NOT work with the SAK or system modal dialogs! + if ((!trinity_desktop_lock_use_system_modal_dialogs) && (!trinity_desktop_lock_use_sak)) { + mBusy=true; + TQTimer::singleShot(1000, this, TQT_SLOT(slotDeadTimePassed())); + if (mkeyCode == XKeysymToKeycode(tqt_xdisplay(), XF86XK_Display)) { + while (mDialogControlLock == true) usleep(100000); + mDialogControlLock = true; + currentDialog->close(); // DO NOT use closeCurrentWindow() here! + mDialogControlLock = false; + } + } + + DCOPRef ref( "*", "MainApplication-Interface"); + ref.send("sendFakeKey", DCOPArg(mkeyCode , "unsigned int")); +} + +//--------------------------------------------------------------------------- +// +// X11 Event. +// +bool LockProcess::x11Event(XEvent *event) +{ + // Allow certain very specific keypresses through + // Key: Reason: + // XF86Display You need to be able to see the screen when unlocking your computer + // XF86AudioMute Would be nice to be able to shut your computer up in an emergency while it is locked + // XF86AudioRaiseVolume Ditto + // XF86AudioLowerVolume Ditto + // XF86XK_PowerOff If someone has access to the power button, they can hard power off the machine anyway + // XF86XK_Sleep Ditto + // XF86XK_Suspend Ditto + // XF86XK_Hibernate Ditto + + //if ((event->type == KeyPress) || (event->type == KeyRelease)) { + if (event->type == KeyPress) { + // Multimedia keys + if ((event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_Display)) || \ + (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_AudioMute)) || \ + (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_AudioRaiseVolume)) || \ + (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_AudioLowerVolume))) { + mkeyCode = event->xkey.keycode; + TQTimer::singleShot( 100, this, TQT_SLOT(doFunctionKeyBroadcast()) ); + return true; + } + // ACPI power keys + if ((event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_PowerOff)) || \ + (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_Sleep)) || \ + (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_Suspend)) || \ + (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_Hibernate))) { + mkeyCode = event->xkey.keycode; + TQTimer::singleShot( 100, this, TQT_SLOT(doFunctionKeyBroadcast()) ); + return true; + } + } + + switch (event->type) + { + case ButtonPress: + case MotionNotify: + case ButtonRelease: + if( forwardVkbdEvent( event )) + return true; // filter out + // fall through + case KeyPress: + if ((mHackDelayStartupTimer) && (mHackDelayStartupTimer->isActive())) { + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + if (mBusy || !mDialogs.isEmpty()) + break; + mBusy = true; + if (trinity_desktop_lock_delay_screensaver_start) { + if (mLocked) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + if ((!mLocked) && (!trinity_desktop_lock_in_sec_dlg)) + { + stopSaver(); + kapp->quit(); + } + if (mAutoLogout) // we need to restart the auto logout countdown + { + killTimer(mAutoLogoutTimerId); + mAutoLogoutTimerId = startTimer(mAutoLogoutTimeout); + } + } + else { + if (!mLocked || checkPass()) + { + trinity_desktop_lock_closing_windows = true; + stopSaver(); + kapp->quit(); + } + else if (mAutoLogout) // we need to restart the auto logout countdown + { + killTimer(mAutoLogoutTimerId); + mAutoLogoutTimerId = startTimer(mAutoLogoutTimeout); + } + } + mBusy = false; + return true; + + case VisibilityNotify: + if( event->xvisibility.window == winId()) + { // mVisibility == false means the screensaver is not visible at all + // e.g. when switched to text console + mVisibility = !(event->xvisibility.state == VisibilityFullyObscured); + if(!mVisibility) { + mSuspendTimer.start(2000, true); + } + else + { + mSuspendTimer.stop(); + if (mResizingDesktopLock == false) { + if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced && trinity_desktop_lock_use_system_modal_dialogs) { + // Do nothing + } + else { + if (mHackStartupEnabled == true) { + resume( false ); + } + else { + if (trinity_desktop_lock_use_system_modal_dialogs == true) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + else { + resume( false ); + } + } + } + } + } + if (event->xvisibility.state != VisibilityUnobscured) { + stayOnTop(); + } + } + break; + + case ConfigureNotify: // from SubstructureNotifyMask on the root window + if(event->xconfigure.event == tqt_xrootwin()) { + stayOnTop(); + } + for( TQValueList< VkbdWindow >::Iterator it = mVkbdWindows.begin(); + it != mVkbdWindows.end(); + ++it ) { + if( (*it).id == event->xconfigure.window ) { + (*it).rect = TQRect( event->xconfigure.x, event->xconfigure.y, + event->xconfigure.width, event->xconfigure.height ); + break; + } + } + break; + case MapNotify: // from SubstructureNotifyMask on the root window + windowAdded( event->xmap.window, false ); + if( event->xmap.event == tqt_xrootwin()) + stayOnTop(); + break; + case DestroyNotify: + for( TQValueList< VkbdWindow >::Iterator it = mVkbdWindows.begin(); + it != mVkbdWindows.end(); + ++it ) + if( (*it).id == event->xdestroywindow.window ) { + mVkbdWindows.remove( it ); + break; + } + break; + } + + // We have grab with the grab window being the root window. + // This results in key events being sent to the root window, + // but they should be sent to the dialog if it's visible. + // It could be solved by setFocus() call, but that would mess + // the focus after this process exits. + // Qt seems to be quite hard to persuade to redirect the event, + // so let's simply dupe it with correct destination window, + // and ignore the original one. + if(!mDialogs.isEmpty() && ( event->type == KeyPress || event->type == KeyRelease) + && event->xkey.window != mDialogs.first()->winId()) + { + XEvent ev2 = *event; + ev2.xkey.window = ev2.xkey.subwindow = mDialogs.first()->winId(); + tqApp->x11ProcessEvent( &ev2 ); + return true; + } + + return false; +} + +void LockProcess::stayOnTop() +{ + if(!mDialogs.isEmpty() || !mVkbdWindows.isEmpty()) + { + // this restacking is written in a way so that + // if the stacking positions actually don't change, + // all restacking operations will be no-op, + // and no ConfigureNotify will be generated, + // thus avoiding possible infinite loops + if( !mVkbdWindows.isEmpty()) + XRaiseWindow( tqt_xdisplay(), mVkbdWindows.first().id ); + else + XRaiseWindow( tqt_xdisplay(), mDialogs.first()->winId()); // raise topmost + // and stack others below it + Window* stack = new Window[ mDialogs.count() + mVkbdWindows.count() + 1 ]; + int count = 0; + for( TQValueList< VkbdWindow >::ConstIterator it = mVkbdWindows.begin(); + it != mVkbdWindows.end(); + ++it ) + stack[ count++ ] = (*it).id; + for( TQValueList< TQWidget* >::ConstIterator it = mDialogs.begin(); + it != mDialogs.end(); + ++it ) + stack[ count++ ] = (*it)->winId(); + stack[ count++ ] = winId(); + XRestackWindows( x11Display(), stack, count ); + delete[] stack; + } + else + XRaiseWindow(tqt_xdisplay(), winId()); +} + +void LockProcess::checkDPMSActive() +{ +#ifdef HAVE_DPMS + if (KDesktopSettings::dpmsDependent()) { + BOOL on; + CARD16 state; + if (DPMSInfo(tqt_xdisplay(), &state, &on)) { + //kdDebug() << "checkDPMSActive " << on << " " << state << endl; + if (DPMS_MONITOR_BLANKED(state)) { + suspend(); + } + else if (mSuspended) { + if (mResizingDesktopLock == false) { + resume( true ); + } + } + } + } +#endif +} + +#if defined(HAVE_XF86MISC) && defined(HAVE_XF86MISCSETGRABKEYSSTATE) +// see http://cvsweb.xfree86.org/cvsweb/xc/programs/Xserver/hw/xfree86/common/xf86Events.c#rev3.113 +// This allows enabling the "Allow{Deactivate/Closedown}Grabs" options in XF86Config, +// and kdesktop_lock will still lock the session. +static enum { Unknown, Yes, No } can_do_xf86_lock = Unknown; +void LockProcess::lockXF86() +{ + if( can_do_xf86_lock == Unknown ) + { + int major, minor; + if( XF86MiscQueryVersion( tqt_xdisplay(), &major, &minor ) + && major >= 0 && minor >= 5 ) + can_do_xf86_lock = Yes; + else + can_do_xf86_lock = No; + } + if( can_do_xf86_lock != Yes ) + return; + if( mRestoreXF86Lock ) + return; + if( XF86MiscSetGrabKeysState( tqt_xdisplay(), False ) != MiscExtGrabStateSuccess ) + return; + // success + mRestoreXF86Lock = true; +} + +void LockProcess::unlockXF86() +{ + if( can_do_xf86_lock != Yes ) + return; + if( !mRestoreXF86Lock ) + return; + XF86MiscSetGrabKeysState( tqt_xdisplay(), True ); + mRestoreXF86Lock = false; +} +#else +void LockProcess::lockXF86() +{ +} + +void LockProcess::unlockXF86() +{ +} +#endif + +void LockProcess::msgBox( TQMessageBox::Icon type, const TQString &txt ) +{ + TQDialog box( 0, "messagebox", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM)) ); + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + XChangeProperty(tqt_xdisplay(), box.winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + box.setCaption(i18n("Authentication Subsystem Notice")); + TQFrame *winFrame = new TQFrame( &box ); + if (trinity_desktop_lock_use_system_modal_dialogs) + winFrame->setFrameStyle( TQFrame::NoFrame ); + else + winFrame->setFrameStyle( TQFrame::WinPanel | TQFrame::Raised ); + winFrame->setLineWidth( 2 ); + TQLabel *label1 = new TQLabel( winFrame ); + label1->setPixmap( TQMessageBox::standardIcon( type ) ); + TQLabel *label2 = new TQLabel( txt, winFrame ); + KPushButton *button = new KPushButton( KStdGuiItem::ok(), winFrame ); + button->setDefault( true ); + button->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Preferred ) ); + connect( button, TQT_SIGNAL( clicked() ), &box, TQT_SLOT( accept() ) ); + + TQVBoxLayout *vbox = new TQVBoxLayout( &box ); + vbox->addWidget( winFrame ); + TQGridLayout *grid = new TQGridLayout( winFrame, 2, 2, 10 ); + grid->addWidget( label1, 0, 0, Qt::AlignCenter ); + grid->addWidget( label2, 0, 1, Qt::AlignCenter ); + grid->addMultiCellWidget( button, 1,1, 0,1, Qt::AlignCenter ); + + execDialog( &box ); +} + +static int run_vkbd = -1; +void LockProcess::showVkbd() +{ + if( run_vkbd == - 1 ) { +#ifdef WITH_HAL + int status = system( "hal-find-by-property --key system.formfactor.subtype --string tabletpc" ); +// status = 0; // enable for testing + run_vkbd = ( WIFEXITED( status ) && WEXITSTATUS( status ) == 0 + && !TDEStandardDirs::findExe( "xvkbd" ).isEmpty()) ? 1 : 0; +#else // WITH_HAL + run_vkbd = (!TDEStandardDirs::findExe( "xvkbd" ).isEmpty()); +#endif // WITH_HAL + } + if( run_vkbd ) { + mVkbdWindows.clear(); + mVkbdLastEventWindow = None; + mKWinModule = new KWinModule( NULL, KWinModule::INFO_WINDOWS ); + connect( mKWinModule, TQT_SIGNAL( windowAdded( WId )), TQT_SLOT( windowAdded( WId ))); + mVkbdProcess = new TDEProcess; + *mVkbdProcess << "xvkbd" << "-compact" << "-geometry" << "-0-0" << "-xdm"; + mVkbdProcess->start(); + } +} + +void LockProcess::hideVkbd() +{ + if( mVkbdProcess != NULL ) { + mVkbdProcess->kill(); + delete mVkbdProcess; + mVkbdProcess = NULL; + delete mKWinModule; + mKWinModule = NULL; + mVkbdWindows.clear(); + } +} + +void LockProcess::windowAdded( WId w ) +{ + windowAdded( w, true ); +} + +void LockProcess::windowAdded( WId w, bool managed ) +{ + // KWin::windowInfo may generate BadWindow errors, so make sure they are silently ignored + int (*oldHandler)(Display *, XErrorEvent *); + oldHandler = XSetErrorHandler(ignoreXError); + KWin::WindowInfo info = KWin::windowInfo( w, 0, NET::WM2WindowClass ); + XSetErrorHandler(oldHandler); + + if( info.windowClassClass().lower() != "xvkbd" ) + return; + // Unmanaged windows (i.e. popups) don't currently work anyway, since they + // don't have WM_CLASS set anyway. I could perhaps try tricks with X id + // ranges if really needed. + if( managed ) { + // withdraw the window, wait for it to be withdrawn, reparent it directly + // to root at the right position + XWithdrawWindow( tqt_xdisplay(), w, tqt_xscreen()); + for(;;) { + Atom type; + int format; + unsigned long length, after; + unsigned char *data; + int r = XGetWindowProperty( tqt_xdisplay(), w, tqt_wm_state, 0, 2, + false, AnyPropertyType, &type, &format, + &length, &after, &data ); + bool withdrawn = true; + if ( r == Success && data && format == 32 ) { + TQ_UINT32 *wstate = (TQ_UINT32*)data; + withdrawn = (*wstate == WithdrawnState ); + XFree( (char *)data ); + } + if( withdrawn ) + break; + } + } + XSelectInput( tqt_xdisplay(), w, StructureNotifyMask ); + XWindowAttributes attr_geom; + if( !XGetWindowAttributes( tqt_xdisplay(), w, &attr_geom )) + return; + int x = XDisplayWidth( tqt_xdisplay(), tqt_xscreen()) - attr_geom.width; + int y = XDisplayHeight( tqt_xdisplay(), tqt_xscreen()) - attr_geom.height; + if( managed ) { + XSetWindowAttributes attr; + if (!trinity_desktop_lock_use_system_modal_dialogs) { + attr.override_redirect = True; + XChangeWindowAttributes( tqt_xdisplay(), w, CWOverrideRedirect, &attr ); + } + XReparentWindow( tqt_xdisplay(), w, tqt_xrootwin(), x, y ); + XMapWindow( tqt_xdisplay(), w ); + } + VkbdWindow data; + data.id = w; + data.rect = TQRect( x, y, attr_geom.width, attr_geom.height ); + mVkbdWindows.prepend( data ); +} + +bool LockProcess::forwardVkbdEvent( XEvent* event ) +{ + if( mVkbdProcess == NULL ) + return false; + TQPoint pos; + Time time; + switch( event->type ) + { + case ButtonPress: + case ButtonRelease: + pos = TQPoint( event->xbutton.x, event->xbutton.y ); + time = event->xbutton.time; + break; + case MotionNotify: + pos = TQPoint( event->xmotion.x, event->xmotion.y ); + time = event->xmotion.time; + break; + default: + return false; + } + // vkbd windows are kept topmost, so just find the first one in the position + for( TQValueList< VkbdWindow >::ConstIterator it = mVkbdWindows.begin(); + it != mVkbdWindows.end(); + ++it ) { + if( TQT_TQRECT_OBJECT((*it).rect).contains( pos )) { + // Find the subwindow where the event should actually go. + // Not exactly cheap in the number of X roundtrips but oh well. + Window window = (*it).id; + Window root, child; + int root_x, root_y, x, y; + unsigned int mask; + for(;;) { + if( !XQueryPointer( tqt_xdisplay(), window, &root, &child, &root_x, &root_y, &x, &y, &mask )) + return false; + if( child == None ) + break; + window = child; + } + switch( event->type ) + { + case ButtonPress: + case ButtonRelease: + event->xbutton.x = x; + event->xbutton.y = y; + event->xbutton.subwindow = None; + break; + case MotionNotify: + event->xmotion.x = x; + event->xmotion.y = y; + event->xmotion.subwindow = None; + break; + } + event->xany.window = window; + sendVkbdFocusInOut( window, time ); + XSendEvent( tqt_xdisplay(), window, False, 0, event ); + return true; + } + } + sendVkbdFocusInOut( None, time ); + return false; +} + +// Fake EnterNotify/LeaveNotify events as the mouse moves. They're not sent by X +// because of the grab and having them makes xvkbd highlight the buttons (but +// not needed otherwise it seems). +void LockProcess::sendVkbdFocusInOut( WId window, Time t ) +{ + if( mVkbdLastEventWindow == window ) + return; + if( mVkbdLastEventWindow != None ) { + XEvent e; + e.xcrossing.type = LeaveNotify; + e.xcrossing.display = tqt_xdisplay(); + e.xcrossing.window = mVkbdLastEventWindow; + e.xcrossing.root = tqt_xrootwin(); + e.xcrossing.subwindow = None; + e.xcrossing.time = t; + e.xcrossing.x = 0; + e.xcrossing.y = 0; + e.xcrossing.x_root = -1; + e.xcrossing.y_root = -1; + e.xcrossing.mode = NotifyNormal; + e.xcrossing.detail = NotifyAncestor; + e.xcrossing.same_screen = True; + e.xcrossing.focus = False; + e.xcrossing.state = 0; + XSendEvent( tqt_xdisplay(), mVkbdLastEventWindow, False, 0, &e ); + } + mVkbdLastEventWindow = window; + if( mVkbdLastEventWindow != None ) { + XEvent e; + e.xcrossing.type = EnterNotify; + e.xcrossing.display = tqt_xdisplay(); + e.xcrossing.window = mVkbdLastEventWindow; + e.xcrossing.root = tqt_xrootwin(); + e.xcrossing.subwindow = None; + e.xcrossing.time = t; + e.xcrossing.x = 0; + e.xcrossing.y = 0; + e.xcrossing.x_root = 0; + e.xcrossing.y_root = 0; + e.xcrossing.mode = NotifyNormal; + e.xcrossing.detail = NotifyAncestor; + e.xcrossing.same_screen = True; + e.xcrossing.focus = False; + e.xcrossing.state = 0; + XSendEvent( tqt_xdisplay(), mVkbdLastEventWindow, False, 0, &e ); + } +} + +void LockProcess::slotMouseActivity(XEvent *event) +{ + bool inFrame = 0; + bool inDialog = 0; + XButtonEvent *be = (XButtonEvent *) event; + XMotionEvent *me = (XMotionEvent *) event; + if ((event->type == ButtonPress) && (!mDialogs.isEmpty())) { + // Get geometry including window frame/titlebar + TQRect fgeom = mDialogs.first()->frameGeometry(); + TQRect wgeom = mDialogs.first()->geometry(); + + if (((be->x_root > fgeom.x()) && (be->y_root > fgeom.y())) && ((be->x_root < (fgeom.x()+fgeom.width())) && (be->y_root < (fgeom.y()+fgeom.height())))) { + inFrame = 1; + } + if (((be->x_root > wgeom.x()) && (be->y_root > wgeom.y())) && ((be->x_root < (wgeom.x()+wgeom.width())) && (be->y_root < (wgeom.y()+wgeom.height())))) { + inDialog = 1; + } + + // Clicked inside dialog; set focus + if (inFrame == TRUE) { + WId window = mDialogs.first()->winId(); + XSetInputFocus(tqt_xdisplay(), window, RevertToParent, CurrentTime); + fakeFocusIn(window); + // Why this needs to be repeated I have no idea... + XSetInputFocus(tqt_xdisplay(), window, RevertToParent, CurrentTime); + fakeFocusIn(window); + } + + // Clicked inside window handle (or border); drag window + if ((inFrame == TRUE) && (inDialog == FALSE)) { + TQPoint oldPoint = mDialogs.first()->pos(); + m_mouseDown = 1; + m_dialogPrevX = oldPoint.x(); + m_dialogPrevY = oldPoint.y(); + m_mousePrevX = be->x_root; + m_mousePrevY = be->y_root; + XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, TQCursor(tqsizeAllCursor).handle(), CurrentTime); + } + } + + // Drag the window... + if (event->type == MotionNotify) { + if (m_mouseDown == TRUE) { + int deltaX = me->x_root - m_mousePrevX; + int deltaY = me->y_root - m_mousePrevY; + m_dialogPrevX = m_dialogPrevX + deltaX; + m_dialogPrevY = m_dialogPrevY + deltaY; + if (!mDialogs.isEmpty()) mDialogs.first()->move(m_dialogPrevX, m_dialogPrevY); + + m_mousePrevX = me->x_root; + m_mousePrevY = me->y_root; + } + } + + if (event->type == ButtonRelease) { + m_mouseDown = 0; + XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, TQCursor(tqarrowCursor).handle(), CurrentTime); + } +} + +void LockProcess::processInputPipeCommand(TQString inputcommand) { + TQCString command(inputcommand.ascii()); + TQString to_display; + const char * pin_entry; + + if (command[0] == 'C') { + while (mDialogControlLock == true) usleep(100000); + mDialogControlLock = true; + if (mInfoMessageDisplayed || !trinity_desktop_lock_use_system_modal_dialogs) { + if (currentDialog != NULL) { + mForceReject = true; + closeCurrentWindow(); + } + } + trinity_desktop_lock_closing_windows = false; + mInfoMessageDisplayed = false; + mDialogControlLock = false; + } + if (command[0] == 'T') { + to_display = command.data(); + to_display = to_display.remove(0,1); + // Lock out password dialogs and close any active dialog + while (mDialogControlLock == true) usleep(100000); + mDialogControlLock = true; + if (mInfoMessageDisplayed || !trinity_desktop_lock_use_system_modal_dialogs) { + if (currentDialog != NULL) { + mForceReject = true; + closeCurrentWindow(); + } + } + mInfoMessageDisplayed = true; + mDialogControlLock = false; + // Display info message dialog + InfoDlg inDlg( this ); + inDlg.updateLabel(to_display); + inDlg.setUnlockIcon(); + execDialog( &inDlg ); + mForceReject = false; + trinity_desktop_lock_closing_windows = false; + return; + } + if ((command[0] == 'E') || (command[0] == 'W') || (command[0] == 'I') || (command[0] == 'K')) { + to_display = command.data(); + to_display = to_display.remove(0,1); + // Lock out password dialogs and close any active dialog + while (mDialogControlLock == true) usleep(100000); + mDialogControlLock = true; + if (mInfoMessageDisplayed || !trinity_desktop_lock_use_system_modal_dialogs) { + if (currentDialog != NULL) { + mForceReject = true; + closeCurrentWindow(); + } + } + mInfoMessageDisplayed = true; + mDialogControlLock = false; + // Display info message dialog + InfoDlg inDlg( this ); + inDlg.updateLabel(to_display); + if (command[0] == 'K') inDlg.setKDEIcon(); + if (command[0] == 'I') inDlg.setInfoIcon(); + if (command[0] == 'W') inDlg.setWarningIcon(); + if (command[0] == 'E') inDlg.setErrorIcon(); + execDialog( &inDlg ); + mForceReject = false; + trinity_desktop_lock_closing_windows = false; + return; + } + if (command[0] == 'Q') { + to_display = command.data(); + to_display = to_display.remove(0,1); + // Lock out password dialogs and close any active dialog + while (mDialogControlLock == true) usleep(100000); + mDialogControlLock = true; + if (mInfoMessageDisplayed || !trinity_desktop_lock_use_system_modal_dialogs) { + if (currentDialog != NULL) { + mForceReject = true; + closeCurrentWindow(); + } + } + mInfoMessageDisplayed = true; + mDialogControlLock = false; + // Display query dialog + QueryDlg qryDlg( this ); + qryDlg.updateLabel(to_display); + qryDlg.setUnlockIcon(); + mForceReject = false; + execDialog( &qryDlg ); + if (mForceReject == false) { + pin_entry = qryDlg.getEntry(); + mInfoMessageDisplayed=false; + if (mPipeOpen_out == true) { + if (write(mPipe_fd_out, pin_entry, strlen(pin_entry)+1) == -1) { + // Error handler to shut up gcc warnings + } + if (write(mPipe_fd_out, "\n\r", 3) == -1) { + // Error handler to shut up gcc warnings + } + } + } + mForceReject = false; + trinity_desktop_lock_closing_windows = false; + return; + } +} + +void LockProcess::fullyOnline() { + if (!mFullyOnlineSent) { + if (kdesktop_pid > 0) { + if (kill(kdesktop_pid, SIGUSR2) < 0) { + // The controlling kdesktop process probably died. Commit suicide... + // Exit uncleanly + exit(1); + } + else { + mFullyOnlineSent = true; + } + } + } +} + +void LockProcess::saverReady() { + DCOPRef ref( "kdesktop", "KScreensaverIface"); + ref.send( "saverLockReady" ); +} + +//=========================================================================== +// +// Control pipe handler +// +ControlPipeHandlerObject::ControlPipeHandlerObject() : TQObject() { + mParent = NULL; +} + +ControlPipeHandlerObject::~ControlPipeHandlerObject() { + // +} + +void ControlPipeHandlerObject::run(void) { + int display_number = atoi(TQString(XDisplayString(tqt_xdisplay())).replace(":","").ascii()); + + if (display_number < 0) { + printf("[kdesktop_lock] Warning: unable to create control socket. Interactive logon modules may not function properly.\n"); + TQApplication::eventLoop()->exit(-1); + return; + } + + char fifo_file[PATH_MAX]; + char fifo_file_out[PATH_MAX]; + snprintf(fifo_file, PATH_MAX, FIFO_FILE, display_number); + snprintf(fifo_file_out, PATH_MAX, FIFO_FILE_OUT, display_number); + + /* Create the FIFOs if they do not exist */ + umask(0); + mkdir(FIFO_DIR,0644); + mknod(fifo_file, S_IFIFO|0644, 0); + chmod(fifo_file, 0644); + + mParent->mPipe_fd = open(fifo_file, O_RDONLY | O_NONBLOCK); + if (mParent->mPipe_fd > -1) { + mParent->mPipeOpen = true; + } + + mknod(fifo_file_out, S_IFIFO|0600, 0); + chmod(fifo_file_out, 0600); + + mParent->mPipe_fd_out = open(fifo_file_out, O_RDWR | O_NONBLOCK); + if (mParent->mPipe_fd_out > -1) { + mParent->mPipeOpen_out = true; + } + + if (!mParent->mPipeOpen) { + printf("[kdesktop_lock] Warning: unable to create control socket '%s'. Interactive logon modules may not function properly.\n", fifo_file); + TQApplication::eventLoop()->exit(-1); + return; + } + + int numread; + int retval; + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(mParent->mPipe_fd, &rfds); + TQByteArray readbuf(128); + + while (mParent->mPipeOpen) { + TQString inputcommand = ""; + + // Wait for mParent->mPipe_fd to receive input + retval = select(mParent->mPipe_fd + 1, &rfds, NULL, NULL, NULL); + if (retval < 0) { + // ERROR + } + else if (retval) { + // New data is available + readbuf[0]=' '; + numread = read(mParent->mPipe_fd, readbuf.data(), 128); + readbuf[numread] = 0; + if (numread > 0) { + inputcommand += readbuf; + emit processCommand(inputcommand); + } + } + } + + TQApplication::eventLoop()->exit(0); + return; +} + +#include "lockprocess.moc" diff --git a/kdesktop/lock/lockprocess.h b/kdesktop/lock/lockprocess.h new file mode 100644 index 000000000..dc14aa676 --- /dev/null +++ b/kdesktop/lock/lockprocess.h @@ -0,0 +1,254 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 1999 Martin R. Jones <[email protected]> +// Copyright (c) 2003 Oswald Buddenhagen <[email protected]> +// Copyright (c) 2010-2013 Timothy Pearson <[email protected]> +// + +#ifndef __LOCKENG_H__ +#define __LOCKENG_H__ + +#include <kgreeterplugin.h> + +#include <kprocess.h> +#include <kpixmap.h> +#include <krootpixmap.h> + +#include <tqwidget.h> +#include <tqtimer.h> +#include <tqvaluestack.h> +#include <tqmessagebox.h> +#include <tqpixmap.h> +#include <tqdatetime.h> +#include <tqthread.h> + +#include <X11/Xlib.h> + +class KLibrary; +class KWinModule; +class KSMModalDialog; +class LockProcess; + +struct GreeterPluginHandle { + KLibrary *library; + kgreeterplugin_info *info; +}; + +#define FIFO_DIR "/tmp/tdesocket-global" +#define FIFO_FILE "/tmp/tdesocket-global/kdesktoplockcontrol-%d" +#define FIFO_FILE_OUT "/tmp/tdesocket-global/kdesktoplockcontrol_out-%d" + +typedef TQValueList<Window> TQXLibWindowList; + +//=========================================================================== +// +// Control pipe handler +// +class ControlPipeHandlerObject : public TQObject +{ + Q_OBJECT + + public: + ControlPipeHandlerObject(); + ~ControlPipeHandlerObject(); + + public slots: + void run(); + + signals: + void processCommand(TQString); + + public: + LockProcess* mParent; +}; + +//=========================================================================== +// +// Screen saver handling process. Handles screensaver window, +// starting screensaver hacks, and password entry. +// +class LockProcess + : public TQWidget +{ + Q_OBJECT +public: + LockProcess(); + ~LockProcess(); + + void init(bool child_saver = false, bool useBlankOnly = false); + + bool lock(); + + bool defaultSave(); + + bool dontLock(); + + bool runSecureDialog(); + + void setChildren(TQValueList<int> children) { child_sockets = children; } + void setParent(int fd) { mParent = fd; } + + void msgBox( TQMessageBox::Icon type, const TQString &txt ); + int execDialog( TQDialog* dlg ); + +public slots: + void quitSaver(); + void preparePopup(); + void cleanupPopup(); + void desktopResized(); + void doDesktopResizeFinish(); + void doFunctionKeyBroadcast(); + void slotPaintBackground(const TQPixmap &pm); + void slotForcePaintBackground(); + +protected: + virtual bool x11Event(XEvent *); + virtual void timerEvent(TQTimerEvent *); + virtual void resizeEvent(TQResizeEvent *); + +private slots: + void hackExited(TDEProcess *); + void signalPipeSignal(); + bool startLock(); + void suspend(); + void checkDPMSActive(); + void slotDeadTimePassed(); + void windowAdded( WId ); + void resumeUnforced(); + void displayLockDialogIfNeeded(); + void closeDialogAndStartHack(); + bool closeCurrentWindow(); + void repaintRootWindowIfNeeded(); + void startSecureDialog(); + void slotMouseActivity(XEvent *event); + void processInputPipeCommand(TQString command); + +private: + void configure(); + void readSaver(); + void createSaverWindow(); + void hideSaverWindow(); + void saveVRoot(); + void setVRoot(Window win, Window rw); + void removeVRoot(Window win); + void setTransparentBackgroundARGB(); + bool grabKeyboard(); + bool grabMouse(); + bool grabInput(); + void ungrabInput(); + void cantLock(const TQString &reason); + bool startSaver(bool notify_ready = false); + void stopSaver(); + bool startHack(); + void stopHack(); + void setupSignals(); + bool checkPass(); + void stayOnTop(); + void lockXF86(); + void unlockXF86(); + void showVkbd(); + void hideVkbd(); + void saverReady(); + void saverReadyIfNeeded(); + bool forwardVkbdEvent( XEvent* event ); + void sendVkbdFocusInOut( WId window, Time t ); + void windowAdded( WId window, bool managed ); + void resume( bool force ); + static TQVariant getConf(void *ctx, const char *key, const TQVariant &dflt); + void fullyOnline(); + + bool mLocked; + int mLockGrace; + int mPriority; + bool mBusy; + TDEProcess mHackProc; + int mRootWidth; + int mRootHeight; + TQString mSaverExec; + TQString mSaver; + bool mOpenGLVisual; + bool child_saver; + TQValueList<int> child_sockets; + int mParent; + bool mUseBlankOnly; + bool mShowLockDateTime; + bool mSuspended; + TQTimer mSuspendTimer; + bool mVisibility; + TQTimer mCheckDPMS; + TQValueStack< TQWidget* > mDialogs; + bool mRestoreXF86Lock; + bool mForbidden; + TQStringList mPlugins, mPluginOptions; + TQString mMethod; + GreeterPluginHandle greetPlugin; + TQPixmap mSavedScreen; + int mAutoLogoutTimerId; + int mAutoLogoutTimeout; + bool mAutoLogout; + + TQTimer *resizeTimer; + unsigned int mkeyCode; + + TQTimer *hackResumeTimer; + + TDEProcess* mVkbdProcess; + KWinModule* mKWinModule; + struct VkbdWindow + { + WId id; + TQRect rect; + }; + TQValueList< VkbdWindow > mVkbdWindows; + WId mVkbdLastEventWindow; + + bool mPipeOpen; + int mPipe_fd; + bool mPipeOpen_out; + int mPipe_fd_out; + + bool mInfoMessageDisplayed; + bool mDialogControlLock; + bool mForceReject; + TQDialog *currentDialog; + + TQTimer* mEnsureScreenHiddenTimer; + TQTimer* mForceContinualLockDisplayTimer; + TQTimer* mEnsureVRootWindowSecurityTimer; + TQTimer* mHackDelayStartupTimer; + + int mHackDelayStartupTimeout; + bool mHackStartupEnabled; + bool mOverrideHackStartupEnabled; + bool mResizingDesktopLock; + bool mFullyOnlineSent; + + TQPixmap backingPixmap; + KRootPixmap *m_rootPixmap; + int mBackingStartupDelayTimer; + + KSMModalDialog* m_startupStatusDialog; + + TQDateTime mlockDateTime; + + bool m_mouseDown; + int m_mousePrevX; + int m_mousePrevY; + int m_dialogPrevX; + int m_dialogPrevY; + + bool m_notifyReadyRequested; + + TQWidget* m_maskWidget; + Window m_saverRootWindow; + + ControlPipeHandlerObject* mControlPipeHandler; + TQEventLoopThread* mControlPipeHandlerThread; + + friend class ControlPipeHandlerObject; +}; + +#endif + diff --git a/kdesktop/lock/main.cc b/kdesktop/lock/main.cc new file mode 100644 index 000000000..43534c255 --- /dev/null +++ b/kdesktop/lock/main.cc @@ -0,0 +1,514 @@ +/* This file is part of the KDE project + Copyright (C) 1999 David Faure + Copyright (c) 2003 Oswald Buddenhagen <[email protected]> + Copyright (c) 2010-2012 Timothy Pearson <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <config.h> + +#include "lockprocess.h" +#include "main.h" +#include "kdesktopsettings.h" + +#include <tqfileinfo.h> + +#include <tdecmdlineargs.h> +#include <tdelocale.h> +#include <tdeglobal.h> +#include <kdebug.h> +#include <tdeglobalsettings.h> +#include <dcopref.h> +#include <ksimpleconfig.h> +#include <kstandarddirs.h> + +#include <tdmtsak.h> + +#include <stdlib.h> + +#if defined(Q_WS_X11) && defined(HAVE_XRENDER) && TQT_VERSION >= 0x030300 +#define COMPOSITE +#endif + +#ifdef COMPOSITE +# include <X11/Xlib.h> +# include <X11/extensions/Xrender.h> +# include <fixx11h.h> +# include <dlfcn.h> +#else +# include <X11/Xlib.h> +# include <fixx11h.h> +#endif + +#define OPEN_TDMCONFIG_AND_SET_GROUP \ +if( stat( KDE_CONFDIR "/tdm/tdmdistrc" , &st ) == 0) { \ + tdmconfig = new KSimpleConfig( TQString::fromLatin1( KDE_CONFDIR "/tdm/tdmdistrc" )); \ +} \ +else { \ + tdmconfig = new KSimpleConfig( TQString::fromLatin1( KDE_CONFDIR "/tdm/tdmrc" )); \ +} \ +tdmconfig->setGroup("X-*-Greeter"); + +TQXLibWindowList trinity_desktop_lock_hidden_window_list; + +// [FIXME] Add GUI configuration checkboxes for these three settings (see kdesktoprc [ScreenSaver] UseUnmanagedLockWindows, DelaySaverStart, and UseTDESAK) +bool trinity_desktop_lock_use_system_modal_dialogs = FALSE; +bool trinity_desktop_lock_delay_screensaver_start = FALSE; +bool trinity_desktop_lock_use_sak = FALSE; +bool trinity_desktop_lock_hide_active_windows = FALSE; + +bool trinity_desktop_lock_forced = FALSE; + +bool signalled_forcelock; +bool signalled_dontlock; +bool signalled_securedialog; +bool signalled_blank; +bool signalled_run; +bool in_internal_mode = FALSE; + +bool argb_visual = FALSE; +pid_t kdesktop_pid = -1; + +static void sigusr1_handler(int) +{ + signalled_forcelock = TRUE; +} + +static void sigusr2_handler(int) +{ + signalled_dontlock = TRUE; +} + +static void sigusr3_handler(int) +{ + signalled_securedialog = TRUE; +} + +static void sigusr4_handler(int) +{ + signalled_blank = TRUE; +} + +static void sigusr5_handler(int) +{ + signalled_run = TRUE; +} + +static int trapXErrors(Display *, XErrorEvent *) +{ + return 0; +} + +bool MyApp::x11EventFilter( XEvent *ev ) +{ + if (ev->type == ButtonPress || ev->type == ButtonRelease || ev->type == MotionNotify) { + emit mouseInteraction(ev); + } + if (ev->type == XKeyPress || ev->type == ButtonPress) { + emit activity(); + } + else if (ev->type == MotionNotify) { + time_t tick = time( 0 ); + if (tick != lastTick) { + lastTick = tick; + emit activity(); + } + } + else if (ev->type == MapNotify) { + // HACK + // Hide all tooltips and notification windows + XMapEvent map_event = ev->xmap; + XWindowAttributes childAttr; + Window childTransient; + if (XGetWindowAttributes(map_event.display, map_event.window, &childAttr) && XGetTransientForHint(map_event.display, map_event.window, &childTransient)) { + if((childAttr.map_state == IsViewable) && (childAttr.override_redirect) && (childTransient)) { + if (!trinity_desktop_lock_hidden_window_list.contains(map_event.window)) { + trinity_desktop_lock_hidden_window_list.append(map_event.window); + } + XLowerWindow(map_event.display, map_event.window); + XFlush(map_event.display); + } + } + } + else if (ev->type == VisibilityNotify) { + // HACK + // Hide all tooltips and notification windows + XVisibilityEvent visibility_event = ev->xvisibility; + XWindowAttributes childAttr; + Window childTransient; + if ((visibility_event.state == VisibilityUnobscured) || (visibility_event.state == VisibilityPartiallyObscured)) { + if (XGetWindowAttributes(visibility_event.display, visibility_event.window, &childAttr) && XGetTransientForHint(visibility_event.display, visibility_event.window, &childTransient)) { + if((childAttr.map_state == IsViewable) && (childAttr.override_redirect) && (childTransient)) { + if (!trinity_desktop_lock_hidden_window_list.contains(visibility_event.window)) { + trinity_desktop_lock_hidden_window_list.append(visibility_event.window); + } + XLowerWindow(visibility_event.display, visibility_event.window); + XFlush(visibility_event.display); + } + } + } + } + else if (ev->type == CreateNotify) { + // HACK + // Close all tooltips and notification windows + XCreateWindowEvent create_event = ev->xcreatewindow; + XWindowAttributes childAttr; + Window childTransient; + + // XGetWindowAttributes may generate BadWindow errors, so make sure they are silently ignored + int (*oldHandler)(Display *, XErrorEvent *); + oldHandler = XSetErrorHandler(trapXErrors); + if (XGetWindowAttributes(create_event.display, create_event.window, &childAttr) && XGetTransientForHint(create_event.display, create_event.window, &childTransient)) { + if ((childAttr.override_redirect) && (childTransient)) { + if (!trinity_desktop_lock_hidden_window_list.contains(create_event.window)) { + trinity_desktop_lock_hidden_window_list.append(create_event.window); + } + XLowerWindow(create_event.display, create_event.window); + XFlush(create_event.display); + } + } + XSetErrorHandler(oldHandler); + } + else if (ev->type == DestroyNotify) { + XDestroyWindowEvent destroy_event = ev->xdestroywindow; + if (trinity_desktop_lock_hidden_window_list.contains(destroy_event.window)) { + trinity_desktop_lock_hidden_window_list.remove(destroy_event.window); + } + } +#if 0 + else if (ev->type == CreateNotify) { + // HACK + // Close all tooltips and notification windows + XCreateWindowEvent create_event = ev->xcreatewindow; + XWindowAttributes childAttr; + Window childTransient; + if (XGetWindowAttributes(create_event.display, create_event.window, &childAttr) && XGetTransientForHint(create_event.display, create_event.window, &childTransient)) { + if ((childAttr.override_redirect) && (childTransient)) { + XDestroyWindow(create_event.display, create_event.window); + } + } + } +#endif + return TDEApplication::x11EventFilter( ev ); +} + + +static TDECmdLineOptions options[] = +{ + { "forcelock", I18N_NOOP("Force session locking"), 0 }, + { "dontlock", I18N_NOOP("Only start screensaver"), 0 }, + { "securedialog", I18N_NOOP("Launch the secure dialog"), 0 }, + { "blank", I18N_NOOP("Only use the blank screensaver"), 0 }, + { "internal <pid>", I18N_NOOP("TDE internal command for background process loading"), 0 }, + TDECmdLineLastOption +}; + +void restore_hidden_override_redirect_windows() { + TQXLibWindowList::iterator it; + for (it = trinity_desktop_lock_hidden_window_list.begin(); it != trinity_desktop_lock_hidden_window_list.end(); ++it) { + Window win = *it; + XRaiseWindow(tqt_xdisplay(), win); + } +} + +// ----------------------------------------------------------------------------- + +int main( int argc, char **argv ) +{ + TDELocale::setMainCatalogue("kdesktop"); + + TDECmdLineArgs::init( argc, argv, "kdesktop_lock", I18N_NOOP("KDesktop Locker"), I18N_NOOP("Session Locker for KDesktop"), "2.1" ); + TDECmdLineArgs::addCmdLineOptions( options ); + TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); + + putenv(strdup("SESSION_MANAGER=")); + + TDEApplication::disableAutoDcopRegistration(); // not needed + + XSetErrorHandler(trapXErrors); + + while (1 == 1) { + signalled_forcelock = FALSE; + signalled_dontlock = FALSE; + signalled_securedialog = FALSE; + signalled_blank = FALSE; + signalled_run = FALSE; + + int kdesktop_screen_number = 0; + int starting_screen = 0; + + bool child = false; + int parent_connection = 0; // socket to the parent saver + TQValueList<int> child_sockets; + + if (TDEGlobalSettings::isMultiHead()) + { + Display *dpy = XOpenDisplay(NULL); + if (! dpy) { + fprintf(stderr, + "%s: FATAL ERROR: couldn't open display '%s'\n", + argv[0], XDisplayName(NULL)); + exit(1); + } + + int number_of_screens = ScreenCount(dpy); + starting_screen = kdesktop_screen_number = DefaultScreen(dpy); + int pos; + TQCString display_name = XDisplayString(dpy); + XCloseDisplay(dpy); + kdDebug() << "screen " << number_of_screens << " " << kdesktop_screen_number << " " << display_name << " " << starting_screen << endl; + dpy = 0; + + if ((pos = display_name.findRev('.')) != -1) + display_name.remove(pos, 10); + + TQCString env; + if (number_of_screens != 1) { + for (int i = 0; i < number_of_screens; i++) { + if (i != starting_screen) { + int fd[2]; + if (pipe(fd)) { + perror("pipe"); + break; + } + if (fork() == 0) { + child = true; + kdesktop_screen_number = i; + parent_connection = fd[0]; + // break here because we are the child process, we don't + // want to fork() anymore + break; + } else { + child_sockets.append(fd[1]); + } + } + } + + env.sprintf("DISPLAY=%s.%d", display_name.data(), + kdesktop_screen_number); + kdDebug() << "env " << env << endl; + + if (putenv(strdup(env.data()))) { + fprintf(stderr, + "%s: WARNING: unable to set DISPLAY environment variable\n", + argv[0]); + perror("putenv()"); + } + } + } + +#ifdef COMPOSITE + MyApp app(TDEApplication::openX11RGBADisplay()); + argb_visual = app.isX11CompositionAvailable(); +#else + MyApp app; +#endif + + TDELockFile lock(locateLocal("tmp", "kdesktop_lock_lockfile")); + lock.setStaleTime(0); + TDELockFile::LockResult lockRet = lock.lock(); + if (lockRet != TDELockFile::LockOK) { + // Terminate existing (stale) process if needed + int pid; + TQString hostName; + TQString appName; + if (lock.getLockInfo(pid, hostName, appName)) { + // Verify that the pid in question is an instance of kdesktop_lock + int len; + char procpath[PATH_MAX]; + char fullpath[PATH_MAX]; + snprintf(procpath, sizeof(procpath), "/proc/%d/exe", pid); + len = readlink( procpath, fullpath, sizeof(fullpath) ); + if (len >= 0) { + fullpath[len] = 0; + TQFileInfo fileInfo(fullpath); + if (fileInfo.baseName() == "kdesktop_lock") { + // Verify that pid in question is owned by current user before killing it + uid_t current_uid = geteuid(); + + struct stat info; + if (lstat(procpath, &info) == 0) { + if (info.st_uid == current_uid) { + kill(pid, SIGKILL); + } + } + } + } + } + } + + // Force a relock as a stale lockfile or process may have been dealt with above + if (!lock.isLocked()) { + lockRet = lock.lock(TDELockFile::LockNoBlock | TDELockFile::LockForce); + } + + kdDebug() << "app " << kdesktop_screen_number << " " << starting_screen << " " << child << " " << child_sockets.count() << " " << parent_connection << endl; + app.disableSessionManagement(); + TDEGlobal::locale()->insertCatalogue("libdmctl"); + + struct stat st; + KSimpleConfig* tdmconfig; + OPEN_TDMCONFIG_AND_SET_GROUP + + LockProcess process; + + // Start loading core functions, such as the desktop wallpaper interface + app.processEvents(); + + if (args->isSet( "internal" )) { + kdesktop_pid = atoi(args->getOption( "internal" )); + while (signalled_run == FALSE) { + sigset_t new_mask; + struct sigaction act; + + in_internal_mode = TRUE; + + // handle SIGUSR1 + act.sa_handler= sigusr1_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGUSR1); + act.sa_flags = 0; + sigaction(SIGUSR1, &act, 0L); + // handle SIGUSR2 + act.sa_handler= sigusr2_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGUSR2); + act.sa_flags = 0; + sigaction(SIGUSR2, &act, 0L); + // handle SIGWINCH (an ersatz SIGUSR3) + act.sa_handler= sigusr3_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGWINCH); + act.sa_flags = 0; + sigaction(SIGWINCH, &act, 0L); + // handle SIGTTIN (an ersatz SIGUSR4) + act.sa_handler= sigusr4_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGTTIN); + act.sa_flags = 0; + sigaction(SIGTTIN, &act, 0L); + // handle SIGTTOU (an ersatz SIGUSR5) + act.sa_handler= sigusr5_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGTTOU); + act.sa_flags = 0; + sigaction(SIGTTOU, &act, 0L); + + // initialize the signal masks + sigfillset(&new_mask); + sigdelset(&new_mask,SIGUSR1); + sigdelset(&new_mask,SIGUSR2); + sigdelset(&new_mask,SIGWINCH); + sigdelset(&new_mask,SIGTTIN); + sigdelset(&new_mask,SIGTTOU); + + // let kdesktop know the saver process is ready + if (kill(kdesktop_pid, SIGTTIN) < 0) { + // The controlling kdesktop process probably died. Commit suicide... + return 12; + } + + // wait for SIGUSR1, SIGUSR2, SIGWINCH, SIGTTIN, or SIGTTOU + sigsuspend(&new_mask); + } + } + + // load settings here so that they actually reflect reality + // there is no way to force a reload once KDesktopSettings::instance has been called! + // we need to read from the right rc file - possibly taking screen number in account + KDesktopSettings::instance("kdesktoprc"); + trinity_desktop_lock_use_system_modal_dialogs = !KDesktopSettings::useUnmanagedLockWindows(); + trinity_desktop_lock_delay_screensaver_start = KDesktopSettings::delaySaverStart(); + if (trinity_desktop_lock_use_system_modal_dialogs) { +#ifdef BUILD_TSAK + trinity_desktop_lock_use_sak = tdmconfig->readBoolEntry("UseSAK", true) && KDesktopSettings::useTDESAK(); +#else + trinity_desktop_lock_use_sak = false; +#endif + } + else { + trinity_desktop_lock_use_sak = false; // If SAK is enabled with unmanaged windows, the SAK dialog will never close and will "burn in" the screen + trinity_desktop_lock_delay_screensaver_start = false; // If trinity_desktop_lock_delay_screensaver_start is true with unmanaged windows, the lock dialog may never appear + } + trinity_desktop_lock_hide_active_windows = KDesktopSettings::hideActiveWindowsFromSaver(); + + delete tdmconfig; + + if (args->isSet( "forcelock" ) || (signalled_forcelock == TRUE)) { + trinity_desktop_lock_forced = TRUE; + } + + process.init(child, (args->isSet( "blank" ) || (signalled_blank == TRUE))); + if (!child) { + process.setChildren(child_sockets); + } + else { + process.setParent(parent_connection); + } + + bool rt; + if( (((!child) && (args->isSet( "forcelock" ))) || (signalled_forcelock == TRUE))) { + rt = process.lock(); + } + else if( child || (args->isSet( "dontlock" ) || (signalled_dontlock == TRUE))) { + rt = process.dontLock(); + } + else if( child || (args->isSet( "securedialog" ) || (signalled_securedialog == TRUE))) { + int retcode = tde_sak_verify_calling_process(); + if (retcode == 0) { + rt = process.runSecureDialog(); + } + else { + return 1; + } + } + else { + rt = process.defaultSave(); + } + if (!rt) { + return 0; + } + + if (in_internal_mode == FALSE) { + trinity_desktop_lock_hidden_window_list.clear(); + int ret = app.exec(); + restore_hidden_override_redirect_windows(); + return ret; + } + else { + if (kill(kdesktop_pid, 0) < 0) { + // The controlling kdesktop process probably died. Commit suicide... + return 12; + } + trinity_desktop_lock_hidden_window_list.clear(); + app.exec(); + restore_hidden_override_redirect_windows(); + if (kill(kdesktop_pid, SIGUSR1) < 0) { + // The controlling kdesktop process probably died. Commit suicide... + return 12; + } + + // FIXME + // We should not have to return (restart) at all, + // but it seems that some X11 connections are left active, + // preventing the lock process from restarting properly in the while() loop above. + return 0; + } + } +} + +#include "main.moc" diff --git a/kdesktop/lock/main.h b/kdesktop/lock/main.h new file mode 100644 index 000000000..6caaa0898 --- /dev/null +++ b/kdesktop/lock/main.h @@ -0,0 +1,41 @@ +/* This file is part of the KDE project + Copyright (c) 2003 Oswald Buddenhagen <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _MAIN_H +#define _MAIN_H + +#include <tdeapplication.h> + +#include <time.h> + +class MyApp : public TDEApplication { + Q_OBJECT +public: + MyApp() : TDEApplication(), lastTick( 0 ) {} + MyApp(Display *display, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0, bool allowStyles=true) : TDEApplication(display, visual, colormap, allowStyles), lastTick( 0 ) {} +protected: + bool x11EventFilter( XEvent * ); +signals: + void activity(); + void mouseInteraction(XEvent *event); +private: + time_t lastTick; +}; + +#endif diff --git a/kdesktop/lock/querydlg.cc b/kdesktop/lock/querydlg.cc new file mode 100644 index 000000000..7618a5062 --- /dev/null +++ b/kdesktop/lock/querydlg.cc @@ -0,0 +1,161 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 2010 Timothy Pearson <[email protected]> + +#include <config.h> + +#include "querydlg.h" + +#include <dmctl.h> + +#include <tdeapplication.h> +#include <tdelocale.h> +#include <kpushbutton.h> +#include <kseparator.h> +#include <kstandarddirs.h> +#include <tdeglobalsettings.h> +#include <tdeconfig.h> +#include <kiconloader.h> +#include <tdesu/defaults.h> +#include <kpassdlg.h> +#include <kdebug.h> +#include <kuser.h> +#include <dcopref.h> +#include <tdemessagebox.h> + +#include <tqlayout.h> +#include <tqpushbutton.h> +#include <tqmessagebox.h> +#include <tqsimplerichtext.h> +#include <tqlabel.h> +#include <tqstringlist.h> +#include <tqfontmetrics.h> +#include <tqstyle.h> +#include <tqapplication.h> +#include <tqlistview.h> +#include <tqheader.h> +#include <tqcheckbox.h> + +#include <ctype.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +#include <pwd.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> +#include <fixx11h.h> + +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif + +extern bool trinity_desktop_lock_use_system_modal_dialogs; + +//=========================================================================== +// +// Simple dialog for displaying a password/PIN entry dialog +// +QueryDlg::QueryDlg(LockProcess *parent) + : TQDialog(parent, "query dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), + mUnlockingFailed(false) +{ + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + setCaption(i18n("Information Needed")); + + frame = new TQFrame( this ); + if (trinity_desktop_lock_use_system_modal_dialogs) + frame->setFrameStyle( TQFrame::NoFrame ); + else + frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); + frame->setLineWidth( 2 ); + + mpixLabel = new TQLabel( frame, "pixlabel" ); + mpixLabel->setPixmap(DesktopIcon("unlock")); + + KUser user; + + mStatusLabel = new TQLabel( "<b> </b>", frame ); + //mStatusLabel->setAlignment( TQLabel::AlignCenter ); + mStatusLabel->setAlignment( TQLabel::AlignLeft ); + + KSeparator *sep = new KSeparator( KSeparator::HLine, frame ); + + ok = new KPushButton( i18n("Unl&ock"), frame ); + + TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); + unlockDialogLayout->addWidget( frame ); + + TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + layStatus->addWidget( mStatusLabel ); + + TQHBoxLayout *layPin = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + pin_box = new KPasswordEdit( this, "pin_box" ); + layPin->addWidget( pin_box ); + pin_box->setFocus(); + + TQHBoxLayout *layButtons = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + layButtons->addStretch(); + layButtons->addWidget( ok ); + + frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); + frameLayout->addMultiCellWidget( mpixLabel, 0, 2, 0, 0, Qt::AlignTop ); + frameLayout->addLayout( layStatus, 0, 1 ); + frameLayout->addLayout( layPin, 2, 1 ); + frameLayout->addMultiCellWidget( sep, 3, 3, 0, 1 ); + frameLayout->addMultiCellLayout( layButtons, 4, 4, 0, 1 ); + + connect(ok, TQT_SIGNAL(clicked()), TQT_SLOT(slotOK())); + + installEventFilter(this); + setFixedSize( sizeHint() ); +} + +QueryDlg::~QueryDlg() +{ + hide(); +} + +void QueryDlg::slotOK() +{ + close(); +} + +const char * QueryDlg::getEntry() +{ + return pin_box->password(); +} + +void QueryDlg::updateLabel(TQString &txt) +{ + mStatusLabel->setPaletteForegroundColor(Qt::black); + mStatusLabel->setText("<b>" + txt + "</b>"); +} + +void QueryDlg::setUnlockIcon() +{ + mpixLabel->setPixmap(DesktopIcon("unlock")); +} + +void QueryDlg::setWarningIcon() +{ + mpixLabel->setPixmap(DesktopIcon("messagebox_warning")); +} + +void QueryDlg::show() +{ + TQDialog::show(); + TQApplication::flushX(); +} + +#include "querydlg.moc" diff --git a/kdesktop/lock/querydlg.h b/kdesktop/lock/querydlg.h new file mode 100644 index 000000000..0da557caf --- /dev/null +++ b/kdesktop/lock/querydlg.h @@ -0,0 +1,61 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 2010 Timothy Pearson <[email protected]> +// + +#ifndef __QUERYDLG_H__ +#define __QUERYDLG_H__ + +#include <tqdialog.h> +#include <tqstringlist.h> + +#include <kpassdlg.h> + +#include "lockprocess.h" + +class TQFrame; +class TQGridLayout; +class TQLabel; +class KPushButton; +class TQListView; + +//=========================================================================== +// +// Simple dialog for displaying an query dialog. +// It does not handle password validation. +// +class QueryDlg : public TQDialog +{ + Q_OBJECT + +public: + QueryDlg(LockProcess *parent); + ~QueryDlg(); + virtual void show(); + + void updateLabel( TQString &txt ); + void setUnlockIcon(); + void setWarningIcon(); + const char * getEntry(); + +private slots: + void slotOK(); + +private: + TQFrame *frame; + TQGridLayout *frameLayout; + TQLabel *mStatusLabel; + TQLabel *mpixLabel; + int mCapsLocked; + bool mUnlockingFailed; + TQStringList layoutsList; + TQStringList::iterator currLayout; + int sPid, sFd; + KPushButton *ok; + KPasswordEdit *pin_box; +}; + +#endif + diff --git a/kdesktop/lock/sakdlg.cc b/kdesktop/lock/sakdlg.cc new file mode 100644 index 000000000..1bb8305ef --- /dev/null +++ b/kdesktop/lock/sakdlg.cc @@ -0,0 +1,151 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 2010-2011 Timothy Pearson <[email protected]> + +#include <config.h> + +#include "sakdlg.h" + +#include <dmctl.h> + +#include <tdeapplication.h> +#include <tdelocale.h> +#include <kpushbutton.h> +#include <kseparator.h> +#include <kstandarddirs.h> +#include <tdeglobalsettings.h> +#include <tdeconfig.h> +#include <kiconloader.h> +#include <tdesu/defaults.h> +#include <kpassdlg.h> +#include <kdebug.h> +#include <kuser.h> +#include <dcopref.h> +#include <tdemessagebox.h> +#include <kdialog.h> + +#include <tqlayout.h> +#include <tqpushbutton.h> +#include <tqmessagebox.h> +#include <tqsimplerichtext.h> +#include <tqlabel.h> +#include <tqstringlist.h> +#include <tqfontmetrics.h> +#include <tqstyle.h> +#include <tqapplication.h> +#include <tqlistview.h> +#include <tqheader.h> +#include <tqcheckbox.h> + +#include <ctype.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +#include <pwd.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> +#include <fixx11h.h> + +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif + +extern bool trinity_desktop_lock_use_system_modal_dialogs; +extern bool trinity_desktop_lock_use_sak; + +//=========================================================================== +// +// Simple dialog for displaying an unlock status or recurring error message +// +SAKDlg::SAKDlg(LockProcess *parent) + : TQDialog(parent, "information dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), + mUnlockingFailed(false) +{ + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + setCaption(i18n("Desktop Session Locked")); + + frame = new TQFrame( this ); + if (trinity_desktop_lock_use_system_modal_dialogs) + frame->setFrameStyle( TQFrame::NoFrame ); + else + frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); + frame->setLineWidth( 2 ); + + KSMModalDialogHeader* theader = new KSMModalDialogHeader( frame ); + + KUser user; + + mStatusLabel = new TQLabel( "<b> </b>", frame ); + mStatusLabel->setAlignment( TQLabel::AlignVCenter ); + + TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); + unlockDialogLayout->addWidget( frame ); + + TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + layStatus->addWidget( mStatusLabel ); + + frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); + frameLayout->addMultiCellWidget( theader, 0, 0, 0, 1, AlignTop | AlignLeft ); + frameLayout->addMultiCellLayout( layStatus, 1, 1, 0, 1, AlignLeft | AlignVCenter); + + mStatusLabel->setText("<b>" + i18n("Press Ctrl+Alt+Del to begin.") + "</b><p>" + i18n("This process helps keep your password secure.") + "<br>" + i18n("It prevents unauthorized users from emulating the login screen.")); + + installEventFilter(this); + setFixedSize( sizeHint() ); + + mSAKProcess = new TDEProcess; + *mSAKProcess << "tdmtsak"; + connect(mSAKProcess, TQT_SIGNAL(processExited(TDEProcess*)), this, TQT_SLOT(slotSAKProcessExited())); + mSAKProcess->start(); +} + +void SAKDlg::slotSAKProcessExited() +{ + int retcode = mSAKProcess->exitStatus(); + if (retcode != 0) trinity_desktop_lock_use_sak = false; + hide(); +} + +SAKDlg::~SAKDlg() +{ + if ((mSAKProcess) && (mSAKProcess->isRunning())) { + mSAKProcess->kill(SIGTERM); + delete mSAKProcess; + } + hide(); +} + +void SAKDlg::closeDialogForced() +{ + TQDialog::reject(); +} + +void SAKDlg::reject() +{ + +} + +void SAKDlg::updateLabel(TQString &txt) +{ + mStatusLabel->setPaletteForegroundColor(Qt::black); + mStatusLabel->setText("<b>" + txt + "</b>"); +} + +void SAKDlg::show() +{ + TQDialog::show(); + TQApplication::flushX(); +} + +#include "sakdlg.moc" diff --git a/kdesktop/lock/sakdlg.h b/kdesktop/lock/sakdlg.h new file mode 100644 index 000000000..5810b8771 --- /dev/null +++ b/kdesktop/lock/sakdlg.h @@ -0,0 +1,58 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 2010 Timothy Pearson <[email protected]> +// + +#ifndef __SAKDLG_H__ +#define __SAKDLG_H__ + +#include <tqdialog.h> +#include <tqstringlist.h> + +#include "lockprocess.h" + +class TQFrame; +class TQGridLayout; +class TQLabel; +class KPushButton; +class TQListView; + +//=========================================================================== +// +// Simple dialog for displaying an info message. +// It does not handle password validation. +// +class SAKDlg : public TQDialog +{ + Q_OBJECT + +public: + SAKDlg(LockProcess *parent); + ~SAKDlg(); + virtual void show(); + + void updateLabel( TQString &txt ); + void closeDialogForced(); + +private slots: + void slotSAKProcessExited(); + +protected slots: + virtual void reject(); + +private: + TQFrame *frame; + TQGridLayout *frameLayout; + TQLabel *mStatusLabel; + int mCapsLocked; + bool mUnlockingFailed; + TQStringList layoutsList; + TQStringList::iterator currLayout; + int sPid, sFd; + TDEProcess* mSAKProcess; +}; + +#endif + diff --git a/kdesktop/lock/securedlg.cc b/kdesktop/lock/securedlg.cc new file mode 100644 index 000000000..b38378f2e --- /dev/null +++ b/kdesktop/lock/securedlg.cc @@ -0,0 +1,215 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 2010-2011 Timothy Pearson <[email protected]> + +#include <config.h> + +#include "securedlg.h" + +#include <dmctl.h> + +#include <tdeapplication.h> +#include <tdelocale.h> +#include <kpushbutton.h> +#include <kseparator.h> +#include <kstandarddirs.h> +#include <tdeglobalsettings.h> +#include <tdeconfig.h> +#include <kiconloader.h> +#include <tdesu/defaults.h> +#include <kpassdlg.h> +#include <kdebug.h> +#include <kuser.h> +#include <dcopref.h> +#include <tdemessagebox.h> +#include <kdialog.h> + +#include <tqlayout.h> +#include <tqpushbutton.h> +#include <tqmessagebox.h> +#include <tqsimplerichtext.h> +#include <tqlabel.h> +#include <tqstringlist.h> +#include <tqfontmetrics.h> +#include <tqstyle.h> +#include <tqapplication.h> +#include <tqlistview.h> +#include <tqheader.h> +#include <tqcheckbox.h> + +#include <ctype.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +#include <pwd.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> +#include <fixx11h.h> + +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif + +extern bool trinity_desktop_lock_use_system_modal_dialogs; +extern bool trinity_desktop_lock_use_sak; + +//=========================================================================== +// +// Simple dialog for displaying an unlock status or recurring error message +// +SecureDlg::SecureDlg(LockProcess *parent) + : TQDialog(parent, "information dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), + mUnlockingFailed(false), retInt(NULL) +{ + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + setCaption(i18n("Secure Desktop Area")); + + frame = new TQFrame( this ); + if (trinity_desktop_lock_use_system_modal_dialogs) + frame->setFrameStyle( TQFrame::NoFrame ); + else + frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); + frame->setLineWidth( 2 ); + + KSMModalDialogHeader* theader = new KSMModalDialogHeader( frame ); + + KUser user; + + mLogonStatus = new TQLabel( frame ); + TQString userString = user.fullName(); + if (userString == "") { + userString = user.loginName(); + } + if (userString != "") { + mLogonStatus->setText(i18n("'%1' is currently logged on").arg( user.fullName() )); + } + else { + mLogonStatus->setText(i18n("You are currently logged on")); // We should never get here, and this message is somewhat obtuse, but it is better than displaying two qotation marks with no text between them... + } + + KSeparator *sep = new KSeparator( KSeparator::HLine, frame ); + + mLockButton = new TQPushButton( frame ); + mLockButton->setText(i18n("Lock Session")); + + mTaskButton = new TQPushButton( frame ); + mTaskButton->setText(i18n("Task Manager")); + + mShutdownButton = new TQPushButton( frame ); + mShutdownButton->setText(i18n("Logoff Menu")); + + mCancelButton = new TQPushButton( frame ); + mCancelButton->setText(i18n("Cancel")); + + mSwitchButton = new TQPushButton( frame ); + mSwitchButton->setText(i18n("Switch User")); + mSwitchButton->setEnabled(false); // FIXME + + TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); + unlockDialogLayout->addWidget( frame ); + + TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + layStatus->addWidget( mLogonStatus ); + + TQGridLayout *layPBGrid = new TQGridLayout( 0, 0, KDialog::spacingHint()); + layPBGrid->addWidget( mLockButton, 0, 0 ); + layPBGrid->addWidget( mTaskButton, 0, 1 ); + layPBGrid->addWidget( mShutdownButton, 0, 2 ); + layPBGrid->addWidget( mCancelButton, 0, 3 ); + layPBGrid->addWidget( mSwitchButton, 1, 0 ); + + frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); + frameLayout->addMultiCellWidget( theader, 0, 0, 0, 1, AlignTop | AlignLeft ); + frameLayout->addMultiCellLayout( layStatus, 1, 1, 0, 1, AlignLeft | AlignVCenter); + frameLayout->addMultiCellWidget( sep, 2, 2, 0, 1 ); + frameLayout->addMultiCellLayout( layPBGrid, 3, 3, 0, 1, AlignLeft | AlignVCenter); + + connect(mCancelButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnCancel())); + connect(mLockButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnLock())); + connect(mTaskButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnTask())); + connect(mShutdownButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnShutdown())); + connect(mSwitchButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnSwitchUser())); + + TQSize dlgSz = sizeHint(); + int btnSize = dlgSz.width(); + btnSize = btnSize / 4; + btnSize = btnSize - (KDialog::spacingHint() / 2); + mLockButton->setFixedWidth(btnSize); + mTaskButton->setFixedWidth(btnSize); + mCancelButton->setFixedWidth(btnSize); + mShutdownButton->setFixedWidth(btnSize); + mSwitchButton->setFixedWidth(btnSize); + + installEventFilter(this); + setFixedSize( sizeHint() ); +} + +SecureDlg::~SecureDlg() +{ + hide(); +} + +void SecureDlg::slotBtnCancel() +{ + if (retInt) *retInt = 0; + hide(); +} + +void SecureDlg::slotBtnLock() +{ + if (retInt) *retInt = 1; + hide(); +} + +void SecureDlg::slotBtnTask() +{ + if (retInt) *retInt = 2; + hide(); +} + +void SecureDlg::slotBtnShutdown() +{ + if (retInt) *retInt = 3; + hide(); +} + +void SecureDlg::slotBtnSwitchUser() +{ + if (retInt) *retInt = 4; + hide(); +} + +void SecureDlg::setRetInt(int *i) +{ + retInt = i; +} + +void SecureDlg::closeDialogForced() +{ + if (retInt) *retInt = 0; + TQDialog::reject(); +} + +void SecureDlg::reject() +{ + closeDialogForced(); +} + +void SecureDlg::show() +{ + TQDialog::show(); + TQApplication::flushX(); +} + +#include "securedlg.moc" diff --git a/kdesktop/lock/securedlg.h b/kdesktop/lock/securedlg.h new file mode 100644 index 000000000..d616bf2e7 --- /dev/null +++ b/kdesktop/lock/securedlg.h @@ -0,0 +1,68 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 2010 Timothy Pearson <[email protected]> +// + +#ifndef __SECUREDLG_H__ +#define __SECUREDLG_H__ + +#include <tqdialog.h> +#include <tqstringlist.h> +#include <tqbutton.h> + +#include "lockprocess.h" + +class TQFrame; +class TQGridLayout; +class TQLabel; +class KPushButton; +class TQListView; + +//=========================================================================== +// +// Simple dialog for displaying an info message. +// It does not handle password validation. +// +class SecureDlg : public TQDialog +{ + Q_OBJECT + +public: + SecureDlg(LockProcess *parent); + ~SecureDlg(); + virtual void show(); + + void closeDialogForced(); + void setRetInt(int *); + +private slots: + void slotBtnCancel(); + void slotBtnLock(); + void slotBtnTask(); + void slotBtnShutdown(); + void slotBtnSwitchUser(); + +protected slots: + virtual void reject(); + +private: + TQFrame *frame; + TQGridLayout *frameLayout; + TQLabel *mLogonStatus; + TQButton *mCancelButton; + TQButton *mLockButton; + TQButton *mTaskButton; + TQButton *mShutdownButton; + TQButton *mSwitchButton; + int mCapsLocked; + bool mUnlockingFailed; + TQStringList layoutsList; + TQStringList::iterator currLayout; + int sPid, sFd; + int* retInt; +}; + +#endif + diff --git a/kdesktop/lockeng.cc b/kdesktop/lockeng.cc new file mode 100644 index 000000000..6d7131253 --- /dev/null +++ b/kdesktop/lockeng.cc @@ -0,0 +1,786 @@ +//=========================================================================== +// +// This file is part of the TDE project +// +// Copyright (c) 1999 Martin R. Jones <[email protected]> +// Copyright (c) 2012 Timothy Pearson <[email protected]> +// + + +#include <config.h> + +#include <stdlib.h> + +#include <kstandarddirs.h> +#include <tdeapplication.h> +#include <kservicegroup.h> +#include <kdebug.h> +#include <tdelocale.h> +#include <tqfile.h> +#include <tqtimer.h> +#include <dcopclient.h> +#include <assert.h> + +#include <dbus/dbus-shared.h> +#include <tqdbusdata.h> +#include <tqdbuserror.h> +#include <tqdbusmessage.h> +#include <tqdbusobjectpath.h> +#include <tqdbusproxy.h> + +#include "lockeng.h" +#include "lockeng.moc" +#include "kdesktopsettings.h" + +#define SYSTEMD_LOGIN1_SERVICE "org.freedesktop.login1" +#define SYSTEMD_LOGIN1_PATH "/org/freedesktop/login1" +#define SYSTEMD_LOGIN1_MANAGER_IFACE "org.freedesktop.login1.Manager" +#define SYSTEMD_LOGIN1_SESSION_IFACE "org.freedesktop.login1.Session" +#define SYSTEMD_LOGIN1_SEAT_IFACE "org.freedesktop.login1.Seat" + +#define DBUS_CONN_NAME "kdesktop_lock" + +#include "xautolock_c.h" +extern xautolock_corner_t xautolock_corners[ 4 ]; + +bool trinity_lockeng_sak_available = TRUE; + +SaverEngine* m_masterSaverEngine = NULL; +static void sigusr1_handler(int) +{ + if (m_masterSaverEngine) { + m_masterSaverEngine->slotLockProcessWaiting(); + } +} +static void sigusr2_handler(int) +{ + if (m_masterSaverEngine) { + m_masterSaverEngine->slotLockProcessFullyActivated(); + } +} +static void sigttin_handler(int) +{ + if (m_masterSaverEngine) { + m_masterSaverEngine->slotLockProcessReady(); + } +} + +//=========================================================================== +// +// Screen saver engine. Doesn't handle the actual screensaver window, +// starting screensaver hacks, or password entry. That's done by +// a newly started process. +// +SaverEngine::SaverEngine() + : TQWidget(), + KScreensaverIface(), + mBlankOnly(false), + mSAKProcess(NULL), + mTerminationRequested(false), + mSaverProcessReady(false), + dBusLocal(0), + dBusWatch(0), + systemdSession(0) +{ + struct sigaction act; + + // handle SIGUSR1 + m_masterSaverEngine = this; + act.sa_handler= sigusr1_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGUSR1); + act.sa_flags = 0; + sigaction(SIGUSR1, &act, 0L); + + // handle SIGUSR2 + m_masterSaverEngine = this; + act.sa_handler= sigusr2_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGUSR2); + act.sa_flags = 0; + sigaction(SIGUSR2, &act, 0L); + + // handle SIGTTIN + m_masterSaverEngine = this; + act.sa_handler= sigttin_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGTTIN); + act.sa_flags = 0; + sigaction(SIGTTIN, &act, 0L); + + // Save X screensaver parameters + XGetScreenSaver(tqt_xdisplay(), &mXTimeout, &mXInterval, + &mXBlanking, &mXExposures); + + mState = Waiting; + mXAutoLock = 0; + mEnabled = false; + + connect(&mLockProcess, TQT_SIGNAL(processExited(TDEProcess *)), + TQT_SLOT(lockProcessExited())); + + mSAKProcess = new TDEProcess; + *mSAKProcess << "tdmtsak"; + connect(mSAKProcess, TQT_SIGNAL(processExited(TDEProcess*)), this, TQT_SLOT(slotSAKProcessExited())); + + TQTimer::singleShot( 0, this, TQT_SLOT(handleSecureDialog()) ); + + configure(); + + mLockProcess.clearArguments(); + TQString path = TDEStandardDirs::findExe( "kdesktop_lock" ); + if( path.isEmpty()) + { + kdDebug( 1204 ) << "Can't find kdesktop_lock!" << endl; + } + mLockProcess << path; + mLockProcess << TQString( "--internal" ) << TQString( "%1" ).arg(getpid()); + if (mLockProcess.start() == false ) + { + kdDebug( 1204 ) << "Failed to start kdesktop_lock!" << endl; + } + + dBusConnect(); +} + +//--------------------------------------------------------------------------- +// +// Destructor - usual cleanups. +// +SaverEngine::~SaverEngine() +{ + if (mState == Waiting) { + kill(mLockProcess.pid(), SIGKILL); + } + + mLockProcess.detach(); // don't kill it if we crash + delete mXAutoLock; + + dBusClose(); + + // Restore X screensaver parameters + XSetScreenSaver(tqt_xdisplay(), mXTimeout, mXInterval, mXBlanking, + mXExposures); +} + +//--------------------------------------------------------------------------- + +// This should be called only using DCOP. +void SaverEngine::lock() +{ + bool ok = true; + if (mState != Saving) + { + mSAKProcess->kill(SIGTERM); + ok = startLockProcess( ForceLock ); + // It takes a while for kdesktop_lock to start and lock the screen. + // Therefore delay the DCOP call until it tells kdesktop that the locking is in effect. + // This is done only for --forcelock . + if( ok && mState != Saving ) + { + DCOPClientTransaction* trans = kapp->dcopClient()->beginTransaction(); + mLockTransactions.append( trans ); + } + } + else + { + mLockProcess.kill( SIGHUP ); + } +} + +void SaverEngine::processLockTransactions() +{ + for( TQValueVector< DCOPClientTransaction* >::ConstIterator it = mLockTransactions.begin(); + it != mLockTransactions.end(); + ++it ) + { + TQCString replyType = "void"; + TQByteArray arr; + kapp->dcopClient()->endTransaction( *it, replyType, arr ); + } + mLockTransactions.clear(); +} + +void SaverEngine::saverLockReady() +{ + if( mState != Preparing ) + { + kdDebug( 1204 ) << "Got unexpected saverReady()" << endl; + } + kdDebug( 1204 ) << "Saver Lock Ready" << endl; + processLockTransactions(); +} + +//--------------------------------------------------------------------------- +void SaverEngine::save() +{ + if (mState == Waiting) + { + mSAKProcess->kill(SIGTERM); + startLockProcess( DefaultLock ); + } +} + +//--------------------------------------------------------------------------- +void SaverEngine::quit() +{ + if (mState == Saving || mState == Preparing) + { + stopLockProcess(); + } +} + +//--------------------------------------------------------------------------- +bool SaverEngine::isEnabled() +{ + return mEnabled; +} + +//--------------------------------------------------------------------------- +bool SaverEngine::enable( bool e ) +{ + if ( e == mEnabled ) + return true; + + // If we aren't in a suitable state, we will not reconfigure. + if (mState != Waiting) + return false; + + mEnabled = e; + + if (mEnabled) + { + if ( !mXAutoLock ) { + mXAutoLock = new XAutoLock(); + connect(mXAutoLock, TQT_SIGNAL(timeout()), TQT_SLOT(idleTimeout())); + } + mXAutoLock->setTimeout(mTimeout); + mXAutoLock->setDPMS(true); + //mXAutoLock->changeCornerLockStatus( mLockCornerTopLeft, mLockCornerTopRight, mLockCornerBottomLeft, mLockCornerBottomRight); + + // We'll handle blanking + XSetScreenSaver(tqt_xdisplay(), mTimeout + 10, mXInterval, PreferBlanking, mXExposures); + kdDebug() << "XSetScreenSaver " << mTimeout + 10 << endl; + + mXAutoLock->start(); + + kdDebug(1204) << "Saver Engine started, timeout: " << mTimeout << endl; + } + else + { + if (mXAutoLock) + { + delete mXAutoLock; + mXAutoLock = 0; + } + + XForceScreenSaver(tqt_xdisplay(), ScreenSaverReset ); + XSetScreenSaver(tqt_xdisplay(), 0, mXInterval, PreferBlanking, DontAllowExposures); + kdDebug(1204) << "Saver Engine disabled" << endl; + } + + return true; +} + +//--------------------------------------------------------------------------- +bool SaverEngine::isBlanked() +{ + return (mState != Waiting); +} + +void SaverEngine::enableExports() +{ +#ifdef Q_WS_X11 + kdDebug(270) << k_lineinfo << "activating background exports.\n"; + DCOPClient *client = kapp->dcopClient(); + if (!client->isAttached()) { + client->attach(); + } + TQByteArray data; + TQDataStream args( data, IO_WriteOnly ); + args << 1; + + TQCString appname( "kdesktop" ); + int screen_number = DefaultScreen(tqt_xdisplay()); + if ( screen_number ) + appname.sprintf("kdesktop-screen-%d", screen_number ); + + client->send( appname, "KBackgroundIface", "setExport(int)", data ); +#endif +} + +//--------------------------------------------------------------------------- +void SaverEngine::handleSecureDialog() +{ + // Wait for SAK press + if (!mSAKProcess->isRunning()) mSAKProcess->start(); +} + +void SaverEngine::slotSAKProcessExited() +{ + int retcode = mSAKProcess->exitStatus(); + if ((retcode != 0) && (mSAKProcess->normalExit())) { + trinity_lockeng_sak_available = FALSE; + printf("[kdesktop] SAK driven secure dialog is not available for use (retcode %d). Check tdmtsak for proper functionality.\n", retcode); fflush(stdout); + } + + if ((mSAKProcess->normalExit()) && (trinity_lockeng_sak_available == TRUE)) { + bool ok = true; + if (mState == Waiting) + { + ok = startLockProcess( SecureDialog ); + if( ok && mState != Saving ) + { + } + } + else + { + mLockProcess.kill( SIGHUP ); + } + } +} + +//--------------------------------------------------------------------------- +// +// Read and apply configuration. +// +void SaverEngine::configure() +{ + // If we aren't in a suitable state, we will not reconfigure. + if (mState != Waiting) + return; + + // create a new config obj to ensure we read the latest options + KDesktopSettings::self()->readConfig(); + + bool e = KDesktopSettings::screenSaverEnabled(); + mTimeout = KDesktopSettings::timeout(); + + mEnabled = !e; // force the enable() + + int action; + action = KDesktopSettings::actionTopLeft(); + xautolock_corners[0] = applyManualSettings(action); + action = KDesktopSettings::actionTopRight(); + xautolock_corners[1] = applyManualSettings(action); + action = KDesktopSettings::actionBottomLeft(); + xautolock_corners[2] = applyManualSettings(action); + action = KDesktopSettings::actionBottomRight(); + xautolock_corners[3] = applyManualSettings(action); + + enable( e ); +} + +//--------------------------------------------------------------------------- +// +// Set a variable to indicate only using the blanker and not the saver. +// +void SaverEngine::setBlankOnly( bool blankOnly ) +{ + mBlankOnly = blankOnly; + // FIXME: if running, stop and restart? What about security + // implications of this? +} + +bool SaverEngine::restartDesktopLockProcess() +{ + if (!mLockProcess.isRunning()) { + mSaverProcessReady = false; + mLockProcess.clearArguments(); + TQString path = TDEStandardDirs::findExe( "kdesktop_lock" ); + if( path.isEmpty()) + { + kdDebug( 1204 ) << "Can't find kdesktop_lock!" << endl; + return false; + } + mLockProcess << path; + mLockProcess << TQString( "--internal" ) << TQString( "%1" ).arg(getpid()); + if (mLockProcess.start() == false ) + { + kdDebug( 1204 ) << "Failed to start kdesktop_lock!" << endl; + return false; + } + // Wait for the saver process to signal ready... + int count = 0; + while (!mSaverProcessReady) { + count++; + usleep(100); + if (count > 100) { + return false; + } + } + } + return true; +} + +//--------------------------------------------------------------------------- +// +// Start the screen saver. +// +bool SaverEngine::startLockProcess( LockType lock_type ) +{ + if (mState == Saving) { + return true; + } + + enableExports(); + + kdDebug(1204) << "SaverEngine: starting saver" << endl; + emitDCOPSignal("KDE_start_screensaver()", TQByteArray()); + + if (!restartDesktopLockProcess()) { + return false; + } + + switch( lock_type ) + { + case ForceLock: + mLockProcess.kill(SIGUSR1); // Request forcelock + break; + case DontLock: + mLockProcess.kill(SIGUSR2); // Request dontlock + break; + case SecureDialog: + mLockProcess.kill(SIGWINCH); // Request secure dialog + break; + default: + break; + } + if (mBlankOnly) { + mLockProcess.kill(SIGTTIN); // Request blanking + } + + mLockProcess.kill(SIGTTOU); // Start lock + XSetScreenSaver(tqt_xdisplay(), 0, mXInterval, PreferBlanking, mXExposures); + + mState = Preparing; + if (mXAutoLock) + { + mXAutoLock->stop(); + } + return true; +} + +//--------------------------------------------------------------------------- +// +// Stop the screen saver. +// +void SaverEngine::stopLockProcess() +{ + if (mState == Waiting) + { + kdWarning(1204) << "SaverEngine::stopSaver() saver not active" << endl; + return; + } + kdDebug(1204) << "SaverEngine: stopping lock" << endl; + emitDCOPSignal("KDE_stop_screensaver()", TQByteArray()); + + mTerminationRequested=true; + mLockProcess.kill(); + + if (mEnabled) + { + if (mXAutoLock) + { + mXAutoLock->start(); + } + XForceScreenSaver(tqt_xdisplay(), ScreenSaverReset ); + XSetScreenSaver(tqt_xdisplay(), mTimeout + 10, mXInterval, PreferBlanking, mXExposures); + } + processLockTransactions(); + mState = Waiting; + + if( systemdSession && systemdSession->canSend() ) { + TQValueList<TQT_DBusData> params; + params << TQT_DBusData::fromBool(false); + TQT_DBusMessage reply = systemdSession->sendWithReply("SetIdleHint", params); + } +} + +void SaverEngine::recoverFromHackingAttempt() +{ + // Try to relaunch saver with forcelock + if (!startLockProcess( ForceLock )) { + // Terminate the TDE session ASAP! + // Values are explained at http://lists.kde.org/?l=kde-linux&m=115770988603387 + TQByteArray data; + TQDataStream arg(data, IO_WriteOnly); + arg << (int)0 << (int)0 << (int)2; + if ( ! kapp->dcopClient()->send("ksmserver", "default", "logout(int,int,int)", data) ) { + // Someone got to DCOP before we did + // Try an emergency system logout + system("logout"); + } + } +} + +void SaverEngine::lockProcessExited() +{ + bool abnormalExit = false; + if (mLockProcess.normalExit() == false) { + abnormalExit = true; + } + else { + if (mLockProcess.exitStatus() != 0) { + abnormalExit = true; + } + } + if (mTerminationRequested == true) { + abnormalExit = false; + mTerminationRequested = false; + } + if (abnormalExit == true) { + // PROBABLE HACKING ATTEMPT DETECTED + restartDesktopLockProcess(); + mState = Waiting; + TQTimer::singleShot( 100, this, SLOT(recoverFromHackingAttempt()) ); + } + else { + // Restart the lock process + restartDesktopLockProcess(); + } +} + +void SaverEngine::slotLockProcessWaiting() +{ + // lockProcessWaiting cannot be called directly from a signal handler, as it will hang in certain obscure circumstances + // Instead we use a single-shot timer to immediately call lockProcessWaiting once control has returned to the Qt main loop + TQTimer::singleShot(0, this, SLOT(lockProcessWaiting())); +} + +void SaverEngine::slotLockProcessFullyActivated() +{ + mState = Saving; + + if( systemdSession && systemdSession->canSend() ) { + TQValueList<TQT_DBusData> params; + params << TQT_DBusData::fromBool(true); + TQT_DBusMessage reply = systemdSession->sendWithReply("SetIdleHint", params); + } +} + +void SaverEngine::slotLockProcessReady() +{ + mSaverProcessReady = true; +} + +void SaverEngine::lockProcessWaiting() +{ + kdDebug(1204) << "SaverEngine: lock exited" << endl; + if (trinity_lockeng_sak_available == TRUE) { + handleSecureDialog(); + } + if( mState == Waiting ) + return; + emitDCOPSignal("KDE_stop_screensaver()", TQByteArray()); + if (mEnabled) + { + if (mXAutoLock) + { + mXAutoLock->start(); + } + XForceScreenSaver(tqt_xdisplay(), ScreenSaverReset ); + XSetScreenSaver(tqt_xdisplay(), mTimeout + 10, mXInterval, PreferBlanking, mXExposures); + } + processLockTransactions(); + mState = Waiting; + + if( systemdSession && systemdSession->canSend() ) { + TQValueList<TQT_DBusData> params; + params << TQT_DBusData::fromBool(false); + TQT_DBusMessage reply = systemdSession->sendWithReply("SetIdleHint", params); + } +} + +//--------------------------------------------------------------------------- +// +// XAutoLock has detected the required idle time. +// +void SaverEngine::idleTimeout() +{ + // disable X screensaver + XForceScreenSaver(tqt_xdisplay(), ScreenSaverReset ); + XSetScreenSaver(tqt_xdisplay(), 0, mXInterval, PreferBlanking, DontAllowExposures); + mSAKProcess->kill(SIGTERM); + startLockProcess( DefaultLock ); +} + +xautolock_corner_t SaverEngine::applyManualSettings(int action) +{ + if (action == 0) + { + kdDebug() << "no lock" << endl; + return ca_nothing; + } + else + if (action == 1) + { + kdDebug() << "lock screen" << endl; + return ca_forceLock; + } + else + if (action == 2) + { + kdDebug() << "prevent lock" << endl; + return ca_dontLock; + } + else + { + kdDebug() << "no lock nothing" << endl; + return ca_nothing; + } +} + +/*! + * This function try a reconnect to D-Bus. + * \return boolean with the result of the operation + * \retval true if successful reconnected to D-Bus + * \retval false if unsuccessful + */ +bool SaverEngine::dBusReconnect() { + // close D-Bus connection + dBusClose(); + // init D-Bus conntection + return (dBusConnect()); +} + +/*! + * This function is used to close D-Bus connection. + */ +void SaverEngine::dBusClose() { + if( dBusConn.isConnected() ) { + if( dBusLocal ) { + delete dBusLocal; + dBusLocal = 0; + } + if( dBusWatch ) { + delete dBusWatch; + dBusWatch = 0; + } + if( systemdSession ) { + delete systemdSession; + systemdSession = 0; + } + } + dBusConn.closeConnection(DBUS_CONN_NAME); +} + +/*! + * This function is used to connect to D-Bus. + */ +bool SaverEngine::dBusConnect() { + dBusConn = TQT_DBusConnection::addConnection(TQT_DBusConnection::SystemBus, DBUS_CONN_NAME); + if( !dBusConn.isConnected() ) { + kdError() << "Failed to open connection to system message bus: " << dBusConn.lastError().message() << endl; + TQTimer::singleShot(4000, this, TQT_SLOT(dBusReconnect())); + return false; + } + + // watcher for Disconnect signal + dBusLocal = new TQT_DBusProxy(DBUS_SERVICE_DBUS, DBUS_PATH_LOCAL, DBUS_INTERFACE_LOCAL, dBusConn); + TQObject::connect(dBusLocal, TQT_SIGNAL(dbusSignal(const TQT_DBusMessage&)), + this, TQT_SLOT(handleDBusSignal(const TQT_DBusMessage&))); + + // watcher for NameOwnerChanged signals + dBusWatch = new TQT_DBusProxy(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, dBusConn); + TQObject::connect(dBusWatch, TQT_SIGNAL(dbusSignal(const TQT_DBusMessage&)), + this, TQT_SLOT(handleDBusSignal(const TQT_DBusMessage&))); + + // find already running SystemD + TQT_DBusProxy checkSystemD(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, dBusConn); + if( checkSystemD.canSend() ) { + TQValueList<TQT_DBusData> params; + params << TQT_DBusData::fromString(SYSTEMD_LOGIN1_SERVICE); + TQT_DBusMessage reply = checkSystemD.sendWithReply("NameHasOwner", params); + if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1 && reply[0].toBool() ) { + onDBusServiceRegistered(SYSTEMD_LOGIN1_SERVICE); + } + } + return true; +} + +/*! + * This function handles D-Bus service registering + */ +void SaverEngine::onDBusServiceRegistered(const TQString& service) { + if( service == SYSTEMD_LOGIN1_SERVICE ) { + // get current systemd session + TQT_DBusProxy managerIface(SYSTEMD_LOGIN1_SERVICE, SYSTEMD_LOGIN1_PATH, SYSTEMD_LOGIN1_MANAGER_IFACE, dBusConn); + TQT_DBusObjectPath systemdSessionPath = TQT_DBusObjectPath(); + if( managerIface.canSend() ) { + TQValueList<TQT_DBusData> params; + params << TQT_DBusData::fromUInt32( getpid() ); + TQT_DBusMessage reply = managerIface.sendWithReply("GetSessionByPID", params); + if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1 ) { + systemdSessionPath = reply[0].toObjectPath(); + } + } + // wather for systemd session signals + if( systemdSessionPath.isValid() ) { + systemdSession = new TQT_DBusProxy(SYSTEMD_LOGIN1_SERVICE, systemdSessionPath, SYSTEMD_LOGIN1_SESSION_IFACE, dBusConn); + TQObject::connect(systemdSession, TQT_SIGNAL(dbusSignal(const TQT_DBusMessage&)), + this, TQT_SLOT(handleDBusSignal(const TQT_DBusMessage&))); + } + return; + } +} + +/*! + * This function handles D-Bus service unregistering + */ +void SaverEngine::onDBusServiceUnregistered(const TQString& service) { + if( service == SYSTEMD_LOGIN1_SERVICE ) { + if( systemdSession ) { + delete systemdSession; + systemdSession = 0; + } + return; + } +} + +/*! + * This function handles signals from the D-Bus daemon. + */ +void SaverEngine::handleDBusSignal(const TQT_DBusMessage& msg) { + // dbus terminated + if( msg.path() == DBUS_PATH_LOCAL + && msg.interface() == DBUS_INTERFACE_LOCAL + && msg.member() == "Disconnected" ) { + dBusClose(); + TQTimer::singleShot(1000, this, TQT_SLOT(dBusReconnect())); + return; + } + + // service registered / unregistered + if( msg.path() == DBUS_PATH_DBUS + && msg.interface() == DBUS_INTERFACE_DBUS + && msg.member() == "NameOwnerChanged" ) { + if( msg[1].toString().isEmpty() ) { + // old-owner is empty + onDBusServiceRegistered(msg[0].toString()); + } + if( msg[2].toString().isEmpty() ) { + // new-owner is empty + onDBusServiceUnregistered(msg[0].toString()); + } + return; + } + + // systemd signal Lock() + if( systemdSession && systemdSession->canSend() + && msg.path() == systemdSession->path() + && msg.interface() == SYSTEMD_LOGIN1_SESSION_IFACE + && msg.member() == "Lock") { + lock(); + return; + } + + // systemd signal Unlock() + if( systemdSession && systemdSession->canSend() + && msg.path() == systemdSession->path() + && msg.interface() == SYSTEMD_LOGIN1_SESSION_IFACE + && msg.member() == "Unlock") { + // unlock? + return; + } +} diff --git a/kdesktop/lockeng.h b/kdesktop/lockeng.h new file mode 100644 index 000000000..70bde3281 --- /dev/null +++ b/kdesktop/lockeng.h @@ -0,0 +1,152 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 1999 Martin R. Jones <[email protected]> +// + +#ifndef __LOCKENG_H__ +#define __LOCKENG_H__ + +#include <tqwidget.h> +#include <kprocess.h> +#include <tqvaluevector.h> +#include "KScreensaverIface.h" +#include "xautolock.h" +#include "xautolock_c.h" + +#include <tqdbusconnection.h> + +class DCOPClientTransaction; +class TQT_DBusMessage; +class TQT_DBusProxy; + +//=========================================================================== +/** + * Screen saver engine. Handles screensaver window, starting screensaver + * hacks, and password entry. + */ +class SaverEngine + : public TQWidget, + public KScreensaverIface +{ + Q_OBJECT +public: + SaverEngine(); + ~SaverEngine(); + + /** + * Lock the screen + */ + virtual void lock(); + + /** + * Save the screen + */ + virtual void save(); + + /** + * Quit the screensaver if running + */ + virtual void quit(); + + /** + * return true if the screensaver is enabled + */ + virtual bool isEnabled(); + + /** + * enable/disable the screensaver + */ + virtual bool enable( bool e ); + + /** + * return true if the screen is currently blanked + */ + virtual bool isBlanked(); + + /** + * Read and apply configuration. + */ + virtual void configure(); + + /** + * Enable or disable "blank only" mode. This is useful for + * laptops where one might not want a cpu thirsty screensaver + * draining the battery. + */ + virtual void setBlankOnly( bool blankOnly ); + + /** + * Called by kdesktop_lock when locking is in effect. + */ + virtual void saverLockReady(); + +public slots: + void slotLockProcessWaiting(); + void slotLockProcessFullyActivated(); + void slotLockProcessReady(); + void handleDBusSignal(const TQT_DBusMessage&); + +protected slots: + void idleTimeout(); + void lockProcessExited(); + void lockProcessWaiting(); + +private slots: + void handleSecureDialog(); + void slotSAKProcessExited(); + + /** + * Enable wallpaper exports + */ + void enableExports(); + void recoverFromHackingAttempt(); + + bool dBusReconnect(); + +private: + bool restartDesktopLockProcess(); + void dBusClose(); + bool dBusConnect(); + void onDBusServiceRegistered(const TQString&); + void onDBusServiceUnregistered(const TQString&); + +protected: + enum LockType { DontLock, DefaultLock, ForceLock, SecureDialog }; + bool startLockProcess( LockType lock_type ); + void stopLockProcess(); + bool handleKeyPress(XKeyEvent *xke); + void processLockTransactions(); + xautolock_corner_t applyManualSettings(int); + +protected: + enum State { Waiting, Preparing, Saving }; + bool mEnabled; + + State mState; + XAutoLock *mXAutoLock; + TDEProcess mLockProcess; + int mTimeout; + + // the original X screensaver parameters + int mXTimeout; + int mXInterval; + int mXBlanking; + int mXExposures; + + bool mBlankOnly; // only use the blanker, not the defined saver + TQValueVector< DCOPClientTransaction* > mLockTransactions; + +private: + TDEProcess* mSAKProcess; + bool mTerminationRequested; + bool mSaverProcessReady; + TQT_DBusConnection dBusConn; + TQT_DBusProxy* dBusLocal; + TQT_DBusProxy* dBusWatch; + TQT_DBusProxy* systemdSession; +}; + +#endif + diff --git a/kdesktop/main.cc b/kdesktop/main.cc new file mode 100644 index 000000000..4228df0c8 --- /dev/null +++ b/kdesktop/main.cc @@ -0,0 +1,294 @@ +/* This file is part of the KDE project + Copyright (C) 1999 David Faure (maintainer) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <config.h> +#include <kuniqueapplication.h> +#include <tdelocale.h> +#include <dcopclient.h> +#include <tdeaboutdata.h> +#include <tdecmdlineargs.h> +#include <kopenwith.h> +#include <kcrash.h> +#include <kdebug.h> +#include <tdeglobalsettings.h> +#include <tdeglobal.h> +#include <tdeconfig.h> +#include <kmanagerselection.h> + +#include "desktop.h" +#include "lockeng.h" +#include "init.h" +#include "krootwm.h" +#include "kdesktopsettings.h" +#include "kdesktopapp.h" + +#include <signal.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdlib.h> + +#if defined(Q_WS_X11) && defined(HAVE_XRENDER) && TQT_VERSION >= 0x030300 +#define COMPOSITE +#endif + +#ifdef COMPOSITE +# include <X11/Xlib.h> +# include <X11/extensions/Xrender.h> +# include <fixx11h.h> +# include <dlfcn.h> +#endif + +static const char description[] = + I18N_NOOP("The TDE desktop"); + +static const char version[] = VERSION; + +static TDECmdLineOptions options[] = +{ + { "x-root", I18N_NOOP("Use this if the desktop window appears as a real window"), 0 }, + { "noautostart", I18N_NOOP("Obsolete"), 0 }, + { "waitforkded", I18N_NOOP("Wait for kded to finish building database"), 0 }, +#ifdef COMPOSITE + { "bg-transparency", I18N_NOOP("Enable background transparency"), 0 }, +#endif + TDECmdLineLastOption +}; + +bool argb_visual = false; +KDesktopApp *myApp = NULL; + +// ----------------------------------------------------------------------------- + +int kdesktop_screen_number = 0; +TQCString kdesktop_name, kicker_name, twin_name; + +static void crashHandler(int sigId) +{ + DCOPClient::emergencyClose(); // unregister DCOP + sleep( 1 ); + system("kdesktop &"); // try to restart + fprintf(stderr, "*** kdesktop (%ld) got signal %d\n", (long) getpid(), sigId); + ::exit(1); +} + +static void signalHandler(int sigId) +{ + fprintf(stderr, "*** kdesktop got signal %d (Exiting)\n", sigId); + TDECrash::setEmergencySaveFunction(0); // No restarts any more + // try to cleanup all windows + signal(SIGTERM, SIG_DFL); // next one kills + signal(SIGHUP, SIG_DFL); // next one kills + if (kapp) + kapp->quit(); // turn catchable signals into clean shutdown +} + +void KDesktop::slotUpAndRunning() +{ + // Activate crash recovery + if (getenv("TDE_DEBUG") == NULL) + TDECrash::setEmergencySaveFunction(crashHandler); // Try to restart on crash +} + +extern "C" KDE_EXPORT int kdemain( int argc, char **argv ) +{ + //setup signal handling + signal(SIGTERM, signalHandler); + signal(SIGHUP, signalHandler); + + { + if (TDEGlobalSettings::isMultiHead()) + { + Display *dpy = XOpenDisplay(NULL); + if (! dpy) { + fprintf(stderr, + "%s: FATAL ERROR: couldn't open display '%s'\n", + argv[0], XDisplayName(NULL)); + exit(1); + } + + int number_of_screens = ScreenCount(dpy); + kdesktop_screen_number = DefaultScreen(dpy); + int pos; + TQCString display_name = XDisplayString(dpy); + XCloseDisplay(dpy); + dpy = 0; + + if ((pos = display_name.findRev('.')) != -1) + display_name.remove(pos, 10); + + TQCString env; + if (number_of_screens != 1) { + for (int i = 0; i < number_of_screens; i++) { + if (i != kdesktop_screen_number && fork() == 0) { + kdesktop_screen_number = i; + // break here because we are the child process, we don't + // want to fork() anymore + break; + } + } + + env.sprintf("DISPLAY=%s.%d", display_name.data(), + kdesktop_screen_number); + + if (putenv(strdup(env.data()))) { + fprintf(stderr, + "%s: WARNING: unable to set DISPLAY environment variable\n", + argv[0]); + perror("putenv()"); + } + } + } + } + + TDEGlobal::locale()->setMainCatalogue("kdesktop"); + + if (kdesktop_screen_number == 0) { + kdesktop_name = "kdesktop"; + kicker_name = "kicker"; + twin_name = "twin"; + } else { + kdesktop_name.sprintf("kdesktop-screen-%d", kdesktop_screen_number); + kicker_name.sprintf("kicker-screen-%d", kdesktop_screen_number); + twin_name.sprintf("twin-screen-%d", kdesktop_screen_number); + } + + TDEAboutData aboutData( kdesktop_name, I18N_NOOP("KDesktop"), + version, description, TDEAboutData::License_GPL, + "(c) 1998-2000, The KDesktop Authors"); + aboutData.addAuthor("David Faure", 0, "[email protected]"); + aboutData.addAuthor("Martin Koller", 0, "[email protected]"); + aboutData.addAuthor("Waldo Bastian", 0, "[email protected]"); + aboutData.addAuthor("Luboš Luňák", 0, "[email protected]"); + aboutData.addAuthor("Joseph Wenninger", 0, "[email protected]"); + aboutData.addAuthor("Tim Jansen", 0, "[email protected]"); + aboutData.addAuthor("Benoit Walter", 0, "[email protected]"); + aboutData.addAuthor("Torben Weis", 0, "[email protected]"); + aboutData.addAuthor("Matthias Ettrich", 0, "[email protected]"); + + TDECmdLineArgs::init( argc, argv, &aboutData ); + TDECmdLineArgs::addCmdLineOptions( options ); + + if (!KUniqueApplication::start()) { + fprintf(stderr, "kdesktop is already running!\n"); + exit(0); + } + DCOPClient* cl = new DCOPClient; + cl->attach(); + DCOPRef r( "ksmserver", "ksmserver" ); + r.setDCOPClient( cl ); + r.send( "suspendStartup", TQCString( "kdesktop" )); + delete cl; + + TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); + +#ifdef COMPOSITE + + TDECmdLineArgs *qtargs = TDECmdLineArgs::parsedArgs("qt"); + + if ( args->isSet("bg-transparency")) { + char *display = 0; + if ( qtargs->isSet("display")) + display = qtargs->getOption( "display" ).data(); + + Display *dpy = XOpenDisplay( display ); + if ( !dpy ) { + kdError() << "cannot connect to X server " << display << endl; + exit( 1 ); + } + + int screen = DefaultScreen( dpy ); + + Visual *visual = 0; + int event_base, error_base; + + if ( XRenderQueryExtension( dpy, &event_base, &error_base ) ) { + int nvi; + XVisualInfo templ; + templ.screen = screen; + templ.depth = 32; + templ.c_class = TrueColor; + XVisualInfo *xvi = XGetVisualInfo( dpy, VisualScreenMask + | VisualDepthMask | VisualClassMask, &templ, &nvi ); + + for ( int i = 0; i < nvi; i++ ) { + XRenderPictFormat *format = + XRenderFindVisualFormat( dpy, xvi[i].visual ); + if ( format->type == PictTypeDirect && format->direct.alphaMask ) { + visual = xvi[i].visual; + kdDebug() << "[kdesktop] Found visual with alpha support" << endl; + argb_visual = true; + break; + } + } + } + // The TQApplication ctor used is normally intended for applications not using Qt + // as the primary toolkit (e.g. Motif apps also using Qt), with some slightly + // unpleasant side effects (e.g. #83974). This code checks if qt-copy patch #0078 + // is applied, which allows turning this off. + bool* qt_no_foreign_hack = + static_cast< bool* >( dlsym( RTLD_DEFAULT, "qt_no_foreign_hack" )); + if( qt_no_foreign_hack ) + *qt_no_foreign_hack = true; + // else argb_visual = false ... ? *shrug* + if( argb_visual ) + myApp = new KDesktopApp( dpy, Qt::HANDLE( visual ), 0 ); + else + XCloseDisplay( dpy ); + } + if( myApp == NULL ) + myApp = new KDesktopApp; +#else + myApp = new KDesktopApp; +#endif + myApp->disableSessionManagement(); // Do SM, but don't restart. + + KDesktopSettings::instance(kdesktop_name + "rc"); + + bool x_root_hack = args->isSet("x-root"); + bool wait_for_kded = args->isSet("waitforkded"); + + // This MUST be created before any widgets are created + SaverEngine saver; + + // Do this before forking so that if a dialog box appears it won't + // be covered by other apps. + // And before creating KDesktop too, of course. + testLocalInstallation(); + + // Mark kdeskop as immutable if all of its config modules have been disabled + if (!myApp->config()->isImmutable() && + kapp->authorizeControlModules(KRootWm::configModules()).isEmpty()) + { + myApp->config()->setReadOnly(true); + myApp->config()->reparseConfiguration(); + } + + // for the KDE-already-running check in starttde + TDESelectionOwner kde_running( "_KDE_RUNNING", 0 ); + kde_running.claim( false ); + + KDesktop desktop( x_root_hack, wait_for_kded ); + + args->clear(); + + myApp->dcopClient()->setDefaultObject( "KDesktopIface" ); + + + return myApp->exec(); +} diff --git a/kdesktop/minicli.cpp b/kdesktop/minicli.cpp new file mode 100644 index 000000000..dc1fa94a2 --- /dev/null +++ b/kdesktop/minicli.cpp @@ -0,0 +1,1098 @@ +/* This file is part of the KDE project + + Autocompletion code: + Copyright (C) 2009 Timothy Pearson <[email protected]> + + Copyright (C) 1999-2002,2003 Dawit Alemayehu <[email protected]> + Copyright (C) 2000 Malte Starostik <[email protected]> + Copyright (C) 2003 Sven Leiber <[email protected]> + + Kdesu integration: + Copyright (C) 2000 Geert Jansen <[email protected]> + + Original authors: + Copyright (C) 1997 Matthias Ettrich <[email protected]> + Copyright (C) 1997 Torben Weis [ Added command completion ] + Copyright (C) 1999 Preston Brown <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <pwd.h> +#include <string.h> +#include <errno.h> + +#include <tqvbox.h> +#include <tqlabel.h> +#include <tqbitmap.h> +#include <tqfile.h> +#include <tqslider.h> +#include <tqlayout.h> +#include <tqgroupbox.h> +#include <tqcheckbox.h> +#include <tqregexp.h> +#include <tqwhatsthis.h> +#include <tqstylesheet.h> + +#include <dcopclient.h> +#include <tdelocale.h> +#include <tdemessagebox.h> +#include <kprocess.h> +#include <kcombobox.h> +#include <klineedit.h> +#include <tdeapplication.h> +#include <kdebug.h> +#include <kpassdlg.h> +#include <krun.h> +#include <twin.h> +#include <tdesu/su.h> +#include <kstandarddirs.h> +#include <tdeconfig.h> +#include <kiconloader.h> +#include <kpushbutton.h> +#include <kguiitem.h> +#include <kstdguiitem.h> +#include <kmimetype.h> +#include <kurifilter.h> +#include <tdecompletionbox.h> + +#include "minicli.moc" +#include "minicli_ui.h" +#include "kdesktopsettings.h" + +#define TDESU_ERR strerror(errno) + +Minicli::Minicli( TQWidget *parent, const char *name) + :KDialog( parent, name, false, (WFlags)WType_TopLevel ), + m_autoCheckedRunInTerm(false), m_pURLCompletion(NULL), m_pEXECompletion(NULL) +{ + setPlainCaption( i18n("Run Command") ); + KWin::setIcons( winId(), DesktopIcon("run"), SmallIcon("run") ); + + TQVBoxLayout* mainLayout = new TQVBoxLayout( this, 0, KDialog::spacingHint() ); + m_dlg = new MinicliDlgUI (this); + mainLayout->addWidget(m_dlg); + + m_dlg->lbRunIcon->setPixmap(DesktopIcon("kmenu")); + m_dlg->lbComment->setAlignment( TQt::WordBreak ); + + m_dlg->cbCommand->setDuplicatesEnabled( false ); + m_dlg->cbCommand->setTrapReturnKey( true ); + + // Options button... + m_dlg->pbOptions->setGuiItem (KGuiItem( i18n("&Options >>"), "configure" )); + + // Run button... + m_dlg->pbRun->setGuiItem (KGuiItem( i18n("&Run"), "run" )); + + // Cancel button... + m_dlg->pbCancel->setGuiItem ( KStdGuiItem::cancel() ); + + if (!kapp->authorize("shell_access")) + m_dlg->pbOptions->hide(); + + m_dlg->pbRun->setEnabled(!m_dlg->cbCommand->currentText().isEmpty()); + m_dlg->pbRun->setDefault( true ); + + // Do not show the advanced group box on startup... + m_dlg->gbAdvanced->hide(); + + // URI Filter meta object... + m_filterData = new KURIFilterData(); + + // Create a timer object... + m_parseTimer = new TQTimer(this); + + m_FocusWidget = 0; + + m_prevCached = false; + m_iPriority = 50; + m_iScheduler = StubProcess::SchedNormal; + + m_dlg->leUsername->setText("root"); + + // Autocomplete system + m_filesystemAutocomplete = 0; + m_histfilesystemAutocomplete = 0; + m_systempathAutocomplete = 0; + m_pURLCompletion = new KURLCompletion(KURLCompletion::FileCompletion); + m_pEXECompletion = new KURLCompletion(KURLCompletion::SystemExeCompletion); + //m_pURLCompletion->setCompletionMode( TDEGlobalSettings::completionMode() ); + connect( m_pURLCompletion, TQT_SIGNAL( match(const TQString&) ), TQT_SLOT( slotMatch(const TQString&) )); + connect( m_pEXECompletion, TQT_SIGNAL( match(const TQString&) ), TQT_SLOT( slotEXEMatch(const TQString&) )); + + // Main widget buttons... + connect( m_dlg->pbRun, TQT_SIGNAL(clicked()), this, TQT_SLOT(accept()) ); + connect( m_dlg->pbCancel, TQT_SIGNAL(clicked()), this, TQT_SLOT(reject()) ); + connect( m_dlg->pbOptions, TQT_SIGNAL(clicked()), TQT_SLOT(slotAdvanced()) ); + connect( m_parseTimer, TQT_SIGNAL(timeout()), TQT_SLOT(slotParseTimer()) ); + + connect( m_dlg->cbCommand, TQT_SIGNAL( textChanged( const TQString& ) ), + TQT_SLOT( slotCmdChanged(const TQString&) ) ); + + connect( m_dlg->cbCommand, TQT_SIGNAL( returnPressed() ), + m_dlg->pbRun, TQT_SLOT( animateClick() ) ); + + m_dlg->cbCommand->setHistoryEditorEnabled( true ); + connect( m_dlg->cbCommand, TQT_SIGNAL(removed( const TQString&) ), TQT_SLOT(saveConfig()) ); + + // Advanced group box... + connect(m_dlg->cbPriority, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotChangeScheduler(bool))); + connect(m_dlg->slPriority, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotPriority(int))); + connect(m_dlg->cbRealtime, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotRealtime(bool))); + connect(m_dlg->cbAppcomplete, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotAppcompleteToggled(bool))); + connect(m_dlg->cbAutocomplete, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotAutocompleteToggled(bool))); + connect(m_dlg->cbAutohistory, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotAutohistoryToggled(bool))); + connect(m_dlg->cbRunAsOther, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotChangeUid(bool))); + connect(m_dlg->leUsername, TQT_SIGNAL(lostFocus()), TQT_SLOT(updateAuthLabel())); + connect(m_dlg->cbRunInTerminal, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotTerminal(bool))); + + m_dlg->slPriority->setValue(50); + + loadConfig(); +} + +Minicli::~Minicli() +{ + delete m_filterData; + delete m_pURLCompletion; + delete m_pEXECompletion; +} + +void Minicli::setCommand(const TQString& command) +{ + m_dlg->cbCommand->lineEdit()->setText(command); + m_dlg->cbCommand->lineEdit()->deselect(); + int firstSpace = command.find(' '); + if (firstSpace > 0) { + m_dlg->cbCommand->lineEdit()->setSelection(firstSpace+1, command.length()); + } +} + +TQSize Minicli::sizeHint() const +{ + int maxWidth = tqApp->desktop()->screenGeometry((TQWidget*)this).width(); + if (maxWidth < 603) + { + // a sensible max for smaller screens + maxWidth = (maxWidth > 240) ? 240 : maxWidth; + } + else + { + maxWidth = maxWidth * 2 / 5; + } + + return TQSize(maxWidth, -1); +} + +void Minicli::show() +{ + KWin::setState( winId(), NET::StaysOnTop ); + KDialog::show(); +} + +void Minicli::loadConfig() +{ + TQStringList histList = KDesktopSettings::history(); + int maxHistory = KDesktopSettings::historyLength(); + m_terminalAppList = KDesktopSettings::terminalApps(); + + if (m_terminalAppList.isEmpty()) + m_terminalAppList << "ls"; // Default + + bool block = m_dlg->cbCommand->signalsBlocked(); + m_dlg->cbCommand->blockSignals( true ); + m_dlg->cbCommand->setMaxCount( maxHistory ); + m_dlg->cbCommand->setHistoryItems( histList ); + m_dlg->cbCommand->blockSignals( block ); + + m_dlg->cbAutocomplete->setChecked( KDesktopSettings::miniCLIFilesystemAutoComplete() ); + m_dlg->cbAppcomplete->setChecked( KDesktopSettings::miniCLISystempathAutoComplete() ); + m_dlg->cbAutohistory->setChecked( KDesktopSettings::miniCLIHistoryAndFilesystemAutoComplete() ); + + m_filesystemAutocomplete = KDesktopSettings::miniCLIFilesystemAutoComplete(); + m_systempathAutocomplete = KDesktopSettings::miniCLISystempathAutoComplete(); + m_histfilesystemAutocomplete = KDesktopSettings::miniCLIHistoryAndFilesystemAutoComplete(); + + if (m_histfilesystemAutocomplete == true) { + m_dlg->cbAutocomplete->setDisabled( true ); + } + else { + m_dlg->cbAutocomplete->setDisabled( false ); + } + + TQStringList compList = KDesktopSettings::completionItems(); + if( compList.isEmpty() ) + m_dlg->cbCommand->completionObject()->setItems( histList ); + else + m_dlg->cbCommand->completionObject()->setItems( compList ); + + int mode = KDesktopSettings::completionMode(); + m_dlg->cbCommand->setCompletionMode( (TDEGlobalSettings::Completion) mode ); + + TDECompletionBox* box = m_dlg->cbCommand->completionBox(); + if (box) + box->setActivateOnSelect( false ); + + m_finalFilters = KURIFilter::self()->pluginNames(); + m_finalFilters.remove("kuriikwsfilter"); + + m_middleFilters = m_finalFilters; + m_middleFilters.remove("localdomainurifilter"); + + // Provide username completions. Use saner and configurable maximum values. + int maxEntries = KDesktopSettings::maxUsernameCompletions(); + TQStringList users; + + struct passwd *pw; + setpwent(); + for (int count=0; ((pw = getpwent()) != 0L) && (count < maxEntries); count++) + users << TQString::fromLocal8Bit(pw->pw_name); + endpwent(); + + TDECompletion *completion = new TDECompletion; + completion->setOrder(TDECompletion::Sorted); + completion->insertItems (users); + + m_dlg->leUsername->setCompletionObject(completion, true); + m_dlg->leUsername->setCompletionMode(TDEGlobalSettings::completionMode()); + m_dlg->leUsername->setAutoDeleteCompletionObject( true ); + +} + +void Minicli::saveConfig() +{ + KDesktopSettings::setHistory( m_dlg->cbCommand->historyItems() ); + KDesktopSettings::setTerminalApps( m_terminalAppList ); + //KDesktopSettings::setCompletionItems( m_dlg->cbCommand->completionObject()->items() ); + KDesktopSettings::setCompletionMode( m_dlg->cbCommand->completionMode() ); + KDesktopSettings::setMiniCLIFilesystemAutoComplete( m_filesystemAutocomplete ); + KDesktopSettings::setMiniCLISystempathAutoComplete( m_systempathAutocomplete ); + KDesktopSettings::setMiniCLIHistoryAndFilesystemAutoComplete( m_histfilesystemAutocomplete ); + KDesktopSettings::writeConfig(); +} + +void Minicli::clearHistory() +{ + m_dlg->cbCommand->clearHistory(); + saveConfig(); +} + +void Minicli::accept() +{ + TQString cmd = m_dlg->cbCommand->currentText().stripWhiteSpace(); + if (!cmd.isEmpty() && (cmd[0].isNumber() || (cmd[0] == '(')) && + (TQRegExp("[a-zA-Z\\]\\[]").search(cmd) == -1)) + { + TQString result = calculate(cmd); + if (!result.isEmpty()) + m_dlg->cbCommand->setCurrentText(result); + return; + } + + bool logout = (cmd == "logout"); + bool lock = (cmd == "lock"); + + if( !logout && !lock && runCommand() == 1 ) + return; + + m_dlg->cbCommand->addToHistory( m_dlg->cbCommand->currentText().stripWhiteSpace() ); + reset(); + saveConfig(); + TQDialog::accept(); + + if ( logout ) + { + kapp->propagateSessionManager(); + kapp->requestShutDown(); + } + if ( lock ) + { + TQCString appname( "kdesktop" ); + int kicker_screen_number = tqt_xscreen(); + if ( kicker_screen_number ) + appname.sprintf("kdesktop-screen-%d", kicker_screen_number); + kapp->dcopClient()->send(appname, "KScreensaverIface", "lock()", TQString("")); + } +} + +void Minicli::reject() +{ + reset(); + TQDialog::reject(); +} + +void Minicli::reset() +{ + if( m_dlg->gbAdvanced->isShown() ) + slotAdvanced(); + + bool block = m_dlg->cbCommand->signalsBlocked(); + m_dlg->cbCommand->blockSignals( true ); + m_dlg->cbCommand->clearEdit(); + m_dlg->cbCommand->setFocus(); + m_dlg->cbCommand->reset(); + m_dlg->cbCommand->blockSignals( block ); + m_dlg->pbRun->setEnabled( false ); + + m_iPriority = 50; + m_iScheduler = StubProcess::SchedNormal; + + m_dlg->cbRunInTerminal->setChecked(false); + m_dlg->cbRunAsOther->setChecked(false); + + m_dlg->leUsername->setText("root"); + + m_dlg->cbPriority->setChecked(false); + + m_dlg->slPriority->setValue(m_iPriority); + + m_dlg->cbRealtime->setChecked( m_iScheduler == StubProcess::SchedRealtime ); + m_dlg->lePassword->erase(); + + m_FocusWidget = 0; + m_iconName = TQString::null; + m_prevIconName = TQString::null; + + m_prevCached = false; + updateAuthLabel(); + setIcon(); +} + +void Minicli::keyPressEvent( TQKeyEvent* e ) +{ + if ( e->key() == Qt::Key_Escape ) + { + e->accept(); + m_dlg->pbCancel->animateClick(); + return; + } + + TQDialog::keyPressEvent( e ); +} + +TQString Minicli::terminalCommand (const TQString& cmd, const TQString& args) +{ + TQString terminal = KDesktopSettings::terminalApplication().stripWhiteSpace(); + if (terminal.endsWith("konsole")) + terminal += " --noclose"; + + if( args.isEmpty() ) + terminal += TQString(" -e /bin/sh -c \"%1\"").arg(cmd); + else + terminal += TQString(" -e /bin/sh -c \"%1 %2\"").arg(cmd).arg(args); + + if (!m_terminalAppList.contains(cmd)) + m_terminalAppList << cmd; + + return terminal; +} + +int Minicli::runCommand() +{ + m_parseTimer->stop(); + + // Make sure we have an updated data + parseLine( true ); + + // Ignore empty commands... + if ( m_dlg->cbCommand->currentText().isEmpty() ) + return 1; + + TQString cmd; + KURL uri = m_filterData->uri(); + if ( uri.isLocalFile() && !uri.hasRef() && uri.query().isEmpty() ) + cmd = uri.path(); + else + cmd = uri.url(); + + TQCString asn; + if( tqApp->desktop()->isVirtualDesktop()) + { + asn = TDEStartupInfo::createNewStartupId(); + TDEStartupInfoId id; + id.initId( asn ); + TDEStartupInfoData data; + data.setXinerama( tqApp->desktop()->screenNumber( this )); + TDEStartupInfo::sendChange( id, data ); + } + + // Determine whether the application should be run through + // the command line (terminal) interface... + bool useTerminal = m_dlg->cbRunInTerminal->isChecked(); + + kdDebug (1207) << "Use terminal ? " << useTerminal << endl; + + if (!kapp->authorize("shell_access")) + useTerminal = false; + + if( needsTDEsu() ) + { + TQCString user; + struct passwd *pw; + + if (m_dlg->cbRunAsOther) + { + pw = getpwnam(m_dlg->leUsername->text().local8Bit()); + if (pw == 0L) + { + KMessageBox::sorry( this, i18n("<qt>The user <b>%1</b> " + "does not exist on this system.</qt>").arg(m_dlg->leUsername->text())); + return 1; + } + } + else + { + pw = getpwuid(getuid()); + if (pw == 0L) + { + KMessageBox::error( this, i18n("You do not exist.\n")); + return 1; + } + } + + user = pw->pw_name; + + { + // Scoped. we want this object to go away before the fork + // (maybe not necessary, but can't hurt) according to the cvs log, + // creating the SuProcess object in the parent and using it in the + // child creates crashes, but we need to check password before the + // fork in order to not get in trouble with X for the messagebox + + SuProcess proc_checkpwd; + proc_checkpwd.setUser( user ); + + if (m_dlg->cbPriority->isChecked()) + { + proc_checkpwd.setPriority(m_iPriority); + proc_checkpwd.setScheduler(m_iScheduler); + } + + if (proc_checkpwd.checkInstall(m_dlg->lePassword->password()) != 0) + { + KMessageBox::sorry(this, i18n("Incorrect password; please try again.")); + return 1; + } + } + + TQApplication::flushX(); + + int pid = fork(); + + if (pid < 0) + { + kdError(1207) << "fork(): " << TDESU_ERR << "\n"; + return -1; + } + + if (pid > 0) + return 0; + + // From here on, this is child... + + SuProcess proc; + proc.setUser(user); + + if (m_dlg->cbPriority->isChecked()) + { + proc.setPriority(m_iPriority); + proc.setScheduler(m_iScheduler); + } + + TQCString command; + + if (useTerminal) + command = terminalCommand( cmd, m_filterData->argsAndOptions() ).local8Bit(); + else + { + command = cmd.local8Bit(); + if( m_filterData->hasArgsAndOptions() ) + command += m_filterData->argsAndOptions().local8Bit(); + } + + proc.setCommand(command); + + // Block SIGCHLD because SuProcess::exec() uses waitpid() + sigset_t sset; + sigemptyset(&sset); + sigaddset(&sset, SIGCHLD); + sigprocmask(SIG_BLOCK, &sset, 0L); + proc.setTerminal(true); + proc.setErase(true); + _exit(proc.exec(m_dlg->lePassword->password())); + return 0; + } + else + { + TQString exec; + + // yes, this is a hack, but there is no way of doing it + // through SuProcess without providing the user password + if (m_iPriority < 50) + { + // from tdesu_stub.c + int val = 20 - (int) (((double) m_iPriority) * 40 / 100 + 0.5); + cmd = "nice -n " + TQString::number( val ) + " " + cmd; + } + + if (useTerminal) + { + cmd = terminalCommand( cmd, m_filterData->argsAndOptions() ); + kdDebug(1207) << "Terminal command: " << cmd << endl; + } + else + { + switch( m_filterData->uriType() ) + { + case KURIFilterData::LOCAL_FILE: + case KURIFilterData::LOCAL_DIR: + case KURIFilterData::NET_PROTOCOL: + case KURIFilterData::HELP: + { + // No need for kfmclient, KRun does it all (David) + (void) new KRun( m_filterData->uri(), parentWidget(), asn ); + return 0; + } + case KURIFilterData::EXECUTABLE: + { + if( !m_filterData->hasArgsAndOptions() ) + { + // Look for desktop file + KService::Ptr service = KService::serviceByDesktopName(cmd); + if (service && service->isValid() && service->type() == "Application") + { + notifyServiceStarted(service); + KRun::run(*service, KURL::List(), parentWidget(), asn ); + return 0; + } + } + } + // fall-through to shell case + case KURIFilterData::SHELL: + { + if (kapp->authorize("shell_access")) + { + exec = cmd; + + if( m_filterData->hasArgsAndOptions() ) + cmd += m_filterData->argsAndOptions(); + + break; + } + else + { + KMessageBox::sorry( this, i18n("<center><b>%1</b></center>\n" + "You do not have permission to execute " + "this command.") + .arg( TQStyleSheet::convertFromPlainText(cmd) )); + return 1; + } + } + case KURIFilterData::UNKNOWN: + case KURIFilterData::ERROR: + default: + { + // Look for desktop file + KService::Ptr service = KService::serviceByDesktopName(cmd); + if (service && service->isValid() && service->type() == "Application") + { + notifyServiceStarted(service); + KRun::run(*service, KURL::List(), parentWidget(), asn ); + return 0; + } + + service = KService::serviceByName(cmd); + if (service && service->isValid() && service->type() == "Application") + { + notifyServiceStarted(service); + KRun::run(*service, KURL::List(), parentWidget(), asn ); + return 0; + } + + KMessageBox::sorry( this, i18n("<center><b>%1</b></center>\n" + "Could not run the specified command.") + .arg( TQStyleSheet::convertFromPlainText(cmd) )); + return 1; + } + } + } + + if ( KRun::runCommand( cmd, exec, m_iconName, parentWidget(), asn ) ) + return 0; + else + { + KMessageBox::sorry( this, i18n("<center><b>%1</b></center>\n" + "The specified command does not exist.").arg(cmd) ); + return 1; // Let the user try again... + } + } +} + +void Minicli::notifyServiceStarted(KService::Ptr service) +{ + // Inform other applications (like the quickstarter applet) + // that an application was started + TQByteArray params; + TQDataStream stream(params, IO_WriteOnly); + stream << "minicli" << service->storageId(); + kdDebug() << "minicli appLauncher dcop signal: " << service->storageId() << endl; + TDEApplication::kApplication()->dcopClient()->emitDCOPSignal("appLauncher", + "serviceStartedByStorageId(TQString,TQString)", params); +} + +void Minicli::slotCmdChanged(const TQString& text) +{ + bool isEmpty = text.isEmpty(); + m_dlg->pbRun->setEnabled( !isEmpty ); + + if( isEmpty ) + { + // Reset values to default + m_filterData->setData(KURL()); + + // Empty String is certainly no terminal application + slotTerminal(false); + + // Reset the icon if needed... + const TQPixmap pixmap = DesktopIcon("kmenu"); + + if ( pixmap.serialNumber() != m_dlg->lbRunIcon->pixmap()->serialNumber()) + m_dlg->lbRunIcon->setPixmap(pixmap); + + return; + } + else if ((m_filesystemAutocomplete == true) && ( m_pURLCompletion )) { + // Attempt to autocomplete the entered URL if it starts with the / character, meaning I am looking for something on the filesystem + // Also use autocompletion if it appears that I am using some kind of ioslave, except the http:// ioslave + m_urlCompletionStarted = true; // flag for slotMatch() + + if ((text.startsWith( "/" ) || text.startsWith( "~" ) || (text.contains("://", false) != 0)) && (text.contains("http://", false) == 0)) { + TQString completion = m_pURLCompletion->makeCompletion( text ); + } + } + if ((m_systempathAutocomplete == true) && ( m_pEXECompletion )) { + // Attempt to autocomplete the entered URL if it starts with the / character, meaning I am looking for something on the filesystem + // Also use autocompletion if it appears that I am using some kind of ioslave, except the http:// ioslave + m_exeCompletionStarted = true; // flag for slotEXEMatch() + + if (!((text.startsWith( "/" ) || text.startsWith( "~" ) || (text.contains("://", false) != 0)) && (text.contains("http://", false) == 0))) { + TQString completion = m_pEXECompletion->makeCompletion( text ); + } + } + + m_parseTimer->start(250, true); +} + +// Handle match() from m_pURLCompletion +void Minicli::slotMatch( const TQString &match ) +{ + TQString current_text; + TQStringList histList = KDesktopSettings::history(); + int maxHistory = KDesktopSettings::historyLength(); + int maxAutocompletion = KDesktopSettings::miniCLIAutocompletionLength(); + + if ( match.isEmpty() ) // this case is handled directly + return; + + // Check flag to avoid match() raised by rotation + if ( m_urlCompletionStarted ) { + m_urlCompletionStarted = false; + + if (m_filesystemAutocomplete == true) { + bool block = m_dlg->cbCommand->signalsBlocked(); + m_dlg->cbCommand->blockSignals( true ); + TQStringList items = m_pURLCompletion->allMatches(); + items.sort(); + if (m_histfilesystemAutocomplete == true) { + // Add the history to the list + histList += items; + maxHistory += maxAutocompletion; + } + else { + histList = items; + maxHistory = maxAutocompletion; + } + current_text = m_dlg->cbCommand->currentText(); + //histList.prepend ( current_text ); // Add the current text to the autocompletion list + m_dlg->cbCommand->setMaxCount( maxHistory ); + m_dlg->cbCommand->completionObject()->setItems( histList ); + m_dlg->cbCommand->setCurrentText( current_text ); + m_dlg->cbCommand->blockSignals( block ); + } + } +} + +// Handle match() from m_pEXECompletion +void Minicli::slotEXEMatch( const TQString &match ) +{ + TQString current_text; + TQStringList histList = KDesktopSettings::history(); + int maxHistory = KDesktopSettings::historyLength(); + int maxAutocompletion = KDesktopSettings::miniCLIAutocompletionLength(); + + if ( match.isEmpty() ) // this case is handled directly + return; + + // Check flag to avoid match() raised by rotation + if ( m_exeCompletionStarted ) { + m_exeCompletionStarted = false; + + if (m_systempathAutocomplete == true) { + bool block = m_dlg->cbCommand->signalsBlocked(); + m_dlg->cbCommand->blockSignals( true ); + TQStringList items = m_pEXECompletion->allMatches(); + items.sort(); + if (m_histfilesystemAutocomplete == true) { + // Add the history to the list + histList += items; + maxHistory += maxAutocompletion; + } + else { + histList = items; + maxHistory = maxAutocompletion; + } + current_text = m_dlg->cbCommand->currentText(); + //histList.prepend ( current_text ); // Add the current text to the autocompletion list + m_dlg->cbCommand->setMaxCount( maxHistory ); + m_dlg->cbCommand->completionObject()->setItems( histList ); + m_dlg->cbCommand->setCurrentText( current_text ); + m_dlg->cbCommand->blockSignals( block ); + } + } +} + +void Minicli::slotAdvanced() +{ + if (m_dlg->gbAdvanced->isHidden()) + { + m_dlg->gbAdvanced->show(); + m_dlg->pbOptions->setText(i18n("&Options <<")); + + // Set the focus back to the widget that had it to begin with, i.e. + // do not put the focus on the "Options" button. + m_FocusWidget = focusWidget(); + + if( m_FocusWidget ) + m_FocusWidget->setFocus(); + } + else + { + m_dlg->gbAdvanced->hide(); + m_dlg->pbOptions->setText(i18n("&Options >>")); + + if( m_FocusWidget && m_FocusWidget->parent() != m_dlg->gbAdvanced ) + m_FocusWidget->setFocus(); + } + adjustSize(); +} + +void Minicli::slotParseTimer() +{ + //kdDebug (1207) << "Minicli::slotParseTimer: Timed out..." << endl; + parseLine( false ); +} + +void Minicli::parseLine( bool final ) +{ + TQString cmd = m_dlg->cbCommand->currentText().stripWhiteSpace(); + m_filterData->setData( cmd ); + + if( final ) + KURIFilter::self()->filterURI( *(m_filterData), m_finalFilters ); + else + KURIFilter::self()->filterURI( *(m_filterData), m_middleFilters ); + + bool isTerminalApp = ((m_filterData->uriType() == KURIFilterData::EXECUTABLE) && + m_terminalAppList.contains(m_filterData->uri().url())); + + if( !isTerminalApp ) + { + m_iconName = m_filterData->iconName(); + setIcon(); + } + + if ( isTerminalApp && final && !m_dlg->cbRunInTerminal->isChecked() ) + { + m_terminalAppList.remove( m_filterData->uri().url() ); + isTerminalApp = false; + } + else + { + bool wasAutoChecked = m_autoCheckedRunInTerm; + bool willBeAutoChecked = isTerminalApp && !m_dlg->cbRunInTerminal->isChecked(); + slotTerminal(isTerminalApp || (m_dlg->cbRunInTerminal->isChecked() && !m_autoCheckedRunInTerm)); + if (!wasAutoChecked && willBeAutoChecked) + m_autoCheckedRunInTerm = true; + } + + kdDebug (1207) << "Command: " << m_filterData->uri().url() << endl; + kdDebug (1207) << "Arguments: " << m_filterData->argsAndOptions() << endl; +} + +void Minicli::setIcon () +{ + if( m_iconName.isEmpty() || m_iconName == "unknown" || m_iconName == "kde" ) + m_iconName = TQString::fromLatin1("kmenu"); + + TQPixmap icon; + if ((m_iconName == "exec") && (m_filterData->iconName() == "exec")) { + TQPixmap potentialIcon = m_filterData->customIconPixmap(); + if (!potentialIcon.isNull()) { + icon = potentialIcon; + } + else { + icon = DesktopIcon( m_iconName ); + } + } + else { + icon = DesktopIcon( m_iconName ); + } + + if ( m_iconName == "www" ) + { + // Not using TDEIconEffect::overlay as that requires the same size + // for the icon and the overlay, also the overlay definately doesn't + // have a more that one-bit alpha channel here + TQPixmap overlay( locate ( "icon", KMimeType::favIconForURL( m_filterData->uri() ) + ".png" ) ); + if ( !overlay.isNull() ) + { + int x = icon.width() - overlay.width(); + int y = icon.height() - overlay.height(); + if ( icon.mask() ) + { + TQBitmap mask = *icon.mask(); + bitBlt( &mask, x, y, + overlay.mask() ? TQT_TQPIXMAP(const_cast<TQBitmap *>(overlay.mask())) : &overlay, + 0, 0, overlay.width(), overlay.height(), + overlay.mask() ? OrROP : SetROP ); + icon.setMask(mask); + } + bitBlt( &icon, x, y, &overlay ); + } + } + + m_dlg->lbRunIcon->setPixmap( icon ); +} + +void Minicli::updateAuthLabel() +{ + if ((m_dlg->cbPriority->isChecked() && (m_iPriority > 50)) || + (m_iScheduler != StubProcess::SchedNormal)) + { + if (!m_prevCached && !m_dlg->leUsername->text().isEmpty()) + { + //kdDebug(1207) << k_funcinfo << "Caching: user=" << m_dlg->leUsername->text() << + // ", checked=" << m_dlg->cbRunAsOther->isChecked() << endl; + + m_prevUser = m_dlg->leUsername->text(); + m_prevPass = m_dlg->lePassword->text(); + m_prevChecked = m_dlg->cbRunAsOther->isChecked(); + m_prevCached = true; + } + if (m_dlg->leUsername->text() != TQString::fromLatin1("root")) + m_dlg->lePassword->setText(TQString::null); + m_dlg->leUsername->setText(TQString::fromLatin1("root")); + m_dlg->cbRunAsOther->setChecked(true); + m_dlg->cbRunAsOther->setEnabled(false); + m_dlg->leUsername->setEnabled(false); + m_dlg->lbUsername->setEnabled(true); + m_dlg->lePassword->setEnabled(true); + m_dlg->lbPassword->setEnabled(true); + } + else if (m_dlg->cbRunAsOther->isEnabled() && + m_dlg->cbRunAsOther->isChecked() && !m_dlg->leUsername->text().isEmpty()) + { + m_dlg->lePassword->setEnabled(true); + m_dlg->lbPassword->setEnabled(true); + } + else + { + if (m_prevCached) + { + m_dlg->leUsername->setText(m_prevUser); + m_dlg->lePassword->setText(m_prevPass); + m_dlg->cbRunAsOther->setChecked(m_prevChecked); + m_dlg->leUsername->setEnabled(m_prevChecked); + m_dlg->lbUsername->setEnabled(m_prevChecked); + } + else + { + m_dlg->cbRunAsOther->setChecked(false); + m_dlg->leUsername->setEnabled(false); + m_dlg->lbUsername->setEnabled(false); + } + m_dlg->cbRunAsOther->setEnabled(true); + m_dlg->lePassword->setEnabled(false); + m_dlg->lbPassword->setEnabled(false); + m_prevCached = false; + } +} + +void Minicli::slotTerminal(bool enable) +{ + m_dlg->cbRunInTerminal->setChecked(enable); + m_autoCheckedRunInTerm = false; + + if (enable) + { + m_prevIconName = m_iconName; + m_iconName = TQString::fromLatin1( "konsole" ); + setIcon(); + } + else if (!m_prevIconName.isEmpty()) + { + m_iconName = m_prevIconName; + setIcon(); + } +} + +void Minicli::slotChangeUid(bool enable) +{ + m_dlg->leUsername->setEnabled(enable); + m_dlg->lbUsername->setEnabled(enable); + + if(enable) + { + m_dlg->leUsername->selectAll(); + m_dlg->leUsername->setFocus(); + } + + updateAuthLabel(); +} + +void Minicli::slotChangeScheduler(bool enable) +{ + m_dlg->slPriority->setEnabled(enable); + m_dlg->lbLowPriority->setEnabled(enable); + m_dlg->lbHighPriority->setEnabled(enable); + + updateAuthLabel(); +} + +bool Minicli::needsTDEsu() +{ + return ((m_dlg->cbPriority->isChecked() && ((m_iPriority > 50) || + (m_iScheduler != StubProcess::SchedNormal))) || + (m_dlg->cbRunAsOther->isChecked() && !m_dlg->leUsername->text().isEmpty())); +} + +void Minicli::slotRealtime(bool enabled) +{ + m_iScheduler = enabled ? StubProcess::SchedRealtime : StubProcess::SchedNormal; + + if (enabled) + { + if (KMessageBox::warningContinueCancel(this, + i18n("Running a realtime application can be very dangerous. " + "If the application misbehaves, the system might hang " + "unrecoverably.\nAre you sure you want to continue?"), + i18n("Warning - Run Command"), KGuiItem(i18n("&Run Realtime")),TQString::null,KMessageBox::Notify|KMessageBox::PlainCaption) + != KMessageBox::Continue ) + { + m_iScheduler = StubProcess::SchedNormal; + m_dlg->cbRealtime->setChecked(false); + } + } + + updateAuthLabel(); +} + +void Minicli::slotAutocompleteToggled(bool enabled) +{ + if (enabled) + { + // Enable filesystem autocompletion + m_filesystemAutocomplete = true; + } + else { + // Enable history only autocompletion + m_filesystemAutocomplete = false; + } + + TQString current_text = m_dlg->cbCommand->currentText(); + m_dlg->cbCommand->setCurrentText( current_text ); // Force an update of the autocompletion list +} + +void Minicli::slotAppcompleteToggled(bool enabled) +{ + m_systempathAutocomplete = enabled; + + TQString current_text = m_dlg->cbCommand->currentText(); + m_dlg->cbCommand->setCurrentText( current_text ); // Force an update of the autocompletion list +} + +void Minicli::slotAutohistoryToggled(bool enabled) +{ + if (enabled) + { + // Enable history and filesystem autocompletion + m_histfilesystemAutocomplete = true; + m_filesystemAutocomplete = true; + m_dlg->cbAutocomplete->setChecked( true ); + m_dlg->cbAutocomplete->setDisabled ( true ); + } + else { + // Disable history and filesystem autocompletion + m_histfilesystemAutocomplete = false; + m_dlg->cbAutocomplete->setDisabled ( false ); + } + + TQString current_text = m_dlg->cbCommand->currentText(); + m_dlg->cbCommand->setCurrentText( current_text ); // Force an update of the autocompletion list +} + +void Minicli::slotPriority(int priority) +{ + // Provide a way to easily return to the default priority + if ((priority > 40) && (priority < 60)) + { + priority = 50; + m_dlg->slPriority->setValue(50); + } + + m_iPriority = priority; + + updateAuthLabel(); +} + +TQString Minicli::calculate(const TQString &exp) +{ + TQString result, cmd; + const TQString bc = TDEStandardDirs::findExe("bc"); + if ( !bc.isEmpty() ) + cmd = TQString("echo %1 | %2").arg(TDEProcess::quote(TQString("scale=8; ")+exp), TDEProcess::quote(bc)); + else + cmd = TQString("echo $((%1))").arg(exp); + FILE *fs = popen(TQFile::encodeName(cmd).data(), "r"); + if (fs) + { + { // scope for QTextStream + TQTextStream ts(fs, IO_ReadOnly); + result = ts.read().stripWhiteSpace(); + } + pclose(fs); + } + return result; +} + +void Minicli::fontChange( const TQFont & ) +{ + adjustSize(); +} + +// vim: set et ts=2 sts=2 sw=2: + diff --git a/kdesktop/minicli.h b/kdesktop/minicli.h new file mode 100644 index 000000000..9d92825c7 --- /dev/null +++ b/kdesktop/minicli.h @@ -0,0 +1,130 @@ +/* This file is part of the KDE project + + Copyright (C) 1999-2002,2003 Dawit Alemayehu <[email protected]> + Copyright (C) 2000 Malte Starostik <[email protected]> + Copyright (C) 2003 Sven Leiber <[email protected]> + + Kdesu integration: + Copyright (C) 2000 Geert Jansen <[email protected]> + + Original authors: + Copyright (C) 1997 Matthias Ettrich <[email protected]> + Copyright (C) 1997 Torben Weis [ Added command completion ] + Copyright (C) 1999 Preston Brown <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef MINICLI_H +#define MINICLI_H + +#include <tqstring.h> +#include <tqstringlist.h> + +#include <kdialog.h> +#include <kservice.h> + +#include <kurlcompletion.h> + +class TQTimer; +class TQWidget; +class MinicliDlgUI; +class KURIFilterData; + +class Minicli : public KDialog +{ + Q_OBJECT + +public: + Minicli( TQWidget *parent=0, const char *name=0 ); + virtual ~Minicli(); + + void setCommand(const TQString& command); + void reset(); + void clearHistory(); + + virtual void show(); + virtual TQSize sizeHint() const; + +public slots: + void saveConfig(); + +protected slots: + virtual void accept(); + virtual void reject(); + void updateAuthLabel(); + +protected: + void loadConfig(); + bool needsTDEsu(); + virtual void keyPressEvent( TQKeyEvent* ); + virtual void fontChange( const TQFont & ); + +private slots: + void slotAdvanced(); + void slotParseTimer(); + void slotPriority(int); + void slotRealtime(bool); + void slotAppcompleteToggled(bool); + void slotAutocompleteToggled(bool); + void slotAutohistoryToggled(bool); + void slotTerminal(bool); + void slotChangeUid(bool); + void slotChangeScheduler(bool); + void slotCmdChanged(const TQString&); + void slotMatch( const TQString&); + void slotEXEMatch( const TQString&); + +private: + void setIcon(); + int runCommand(); + void parseLine( bool final ); + TQString terminalCommand (const TQString&, const TQString&); + TQString calculate(const TQString &exp); + void notifyServiceStarted(KService::Ptr service); + + + int m_iPriority; + int m_iScheduler; + + TQString m_iconName; + TQString m_prevIconName; + TQStringList m_terminalAppList; + TQStringList m_middleFilters; + TQStringList m_finalFilters; + + TQTimer* m_parseTimer; + TQWidget* m_FocusWidget; + MinicliDlgUI* m_dlg; + KURIFilterData* m_filterData; + + // Cached values + TQString m_prevUser; + TQString m_prevPass; + bool m_prevChecked; + bool m_prevCached; + bool m_autoCheckedRunInTerm; + + // Autocomplete + KURLCompletion *m_pURLCompletion; + KURLCompletion *m_pEXECompletion; + bool m_filesystemAutocomplete; + bool m_systempathAutocomplete; + bool m_histfilesystemAutocomplete; + bool m_urlCompletionStarted; + bool m_exeCompletionStarted; +}; +#endif diff --git a/kdesktop/minicli_ui.ui b/kdesktop/minicli_ui.ui new file mode 100644 index 000000000..13d3b9736 --- /dev/null +++ b/kdesktop/minicli_ui.ui @@ -0,0 +1,660 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>MinicliDlgUI</class> +<widget class="TQWidget"> + <property name="name"> + <cstring>MinicliDlgUI</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>325</width> + <height>390</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="resizeMode"> + <enum>FreeResize</enum> + </property> + <widget class="TQLayoutWidget" row="4" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KPushButton"> + <property name="name"> + <cstring>pbOptions</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>80</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>pbRun</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>pbCancel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string></string> + </property> + </widget> + </hbox> + </widget> + <widget class="TQLayoutWidget" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer6_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>57</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="TQFrame"> + <property name="name"> + <cstring>gbAdvanced</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <spacer row="6" column="0"> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>30</height> + </size> + </property> + </spacer> + <widget class="TQCheckBox" row="7" column="0" rowspan="1" colspan="4"> + <property name="name"> + <cstring>cbRealtime</cstring> + </property> + <property name="text"> + <string>Run with realtime &scheduling</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qt>Select whether realtime scheduling should be enabled for the application. The scheduler governs which process will run and which will have to wait. Two schedulers are available: +<ul> +<li><em>Normal:</em> This is the standard, timesharing scheduler. It will divide fairly the available processing time between all processes.</li> +<li><em>Realtime:</em>This scheduler will run your application uninterrupted until it gives up the processor. This can be dangerous. An application that does not give up the processor might hang the system. You need root's password to use the scheduler.</li> +</ul> +</qt></string> + </property> + </widget> + <widget class="TQCheckBox" row="8" column="0" rowspan="1" colspan="4"> + <property name="name"> + <cstring>cbAppcomplete</cstring> + </property> + <property name="text"> + <string>Autocomplete shows available &applications</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qt>When enabled, the system shows available applications in the autocompletion area. + </qt></string> + </property> + </widget> + <widget class="TQCheckBox" row="9" column="0" rowspan="1" colspan="4"> + <property name="name"> + <cstring>cbAutocomplete</cstring> + </property> + <property name="text"> + <string>Autocomplete uses &filesystem instead of history</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qt>This selects whether the filesystem or the past command history will be used for autocompletion. + </qt></string> + </property> + </widget> + <widget class="TQCheckBox" row="10" column="0" rowspan="1" colspan="4"> + <property name="name"> + <cstring>cbAutohistory</cstring> + </property> + <property name="text"> + <string>Autocomplete uses &both history and filesystem</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qt>This selects whether the filesystem and the past command history will be used for autocompletion. + </qt></string> + </property> + </widget> + <widget class="TQLabel" row="3" column="1"> + <property name="name"> + <cstring>lbUsername</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>User&name:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>leUsername</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>Enter the user you want to run the application as here.</string> + </property> + </widget> + <widget class="KPasswordEdit" row="4" column="2" rowspan="1" colspan="2"> + <property name="name"> + <cstring>lePassword</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>5</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="whatsThis" stdset="0"> + <string>Enter the password here for the user you specified above.</string> + </property> + </widget> + <widget class="TQLabel" row="4" column="1"> + <property name="name"> + <cstring>lbPassword</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Pass&word:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>lePassword</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>Enter the password here for the user you specified above.</string> + </property> + </widget> + <widget class="TQCheckBox" row="1" column="0" rowspan="1" colspan="4"> + <property name="name"> + <cstring>cbRunInTerminal</cstring> + </property> + <property name="text"> + <string>Run in &terminal window</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Check this option if the application you want to run is a text mode application. The application will then be run in a terminal emulator window.</string> + </property> + </widget> + <widget class="TQLayoutWidget" row="6" column="1"> + <property name="name"> + <cstring>layout30</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>&Priority:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>slPriority</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>The priority that the command will be run with can be set here. From left to right, it goes from low to high. The center position is the default value. For priorities higher than the default, you will need to provide the root password.</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer33</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Minimum</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>9</height> + </size> + </property> + </spacer> + </vbox> + </widget> + <widget class="TQCheckBox" row="5" column="0" rowspan="1" colspan="4"> + <property name="name"> + <cstring>cbPriority</cstring> + </property> + <property name="text"> + <string>Run with a &different priority</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Check this option if you want to run the application with a different priority. A higher priority tells the operating system to give more processing time to your application.</string> + </property> + </widget> + <widget class="KLineEdit" row="3" column="2" rowspan="1" colspan="2"> + <property name="name"> + <cstring>leUsername</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>5</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="whatsThis" stdset="0"> + <string>Enter the user you want to run the application as here.</string> + </property> + </widget> + <widget class="TQLayoutWidget" row="6" column="2" rowspan="1" colspan="2"> + <property name="name"> + <cstring>layout29</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="TQLabel" row="1" column="0"> + <property name="name"> + <cstring>lbLowPriority</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Low</string> + </property> + <property name="whatsThis" stdset="0"> + <string>The priority that the command will be run with can be set here. From left to right, it goes from low to high. The center position is the default value. For priorities higher than the default, you will need to provide the root password.</string> + </property> + </widget> + <widget class="TQLabel" row="1" column="1"> + <property name="name"> + <cstring>lbHighPriority</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>High</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="whatsThis" stdset="0"> + <string>The priority that the command will be run with can be set here. From left to right, it goes from low to high. The center position is the default value. For priorities higher than the default, you will need to provide the root password.</string> + </property> + </widget> + <widget class="TQSlider" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>slPriority</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="lineStep"> + <number>5</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="whatsThis" stdset="0"> + <string>The priority that the command will be run with can be set here. From left to right, it goes from low to high. The center position is the default value. For priorities higher than the default, you will need to provide the root password.</string> + </property> + </widget> + </grid> + </widget> + <widget class="TQCheckBox" row="2" column="0" rowspan="1" colspan="4"> + <property name="name"> + <cstring>cbRunAsOther</cstring> + </property> + <property name="text"> + <string>Run as a different &user</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Check this option if you want to run the application with a different user id. Every process has a user id associated with it. This id code determines file access and other permissions. The password of the user is required to do this.</string> + </property> + </widget> + <spacer row="3" column="0" rowspan="2" colspan="1"> + <property name="name"> + <cstring>spacer6</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </grid> + </widget> + </hbox> + </widget> + <widget class="TQFrame" row="3" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>separator</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + </widget> + <widget class="TQLabel" row="1" column="0"> + <property name="name"> + <cstring>lbCommand</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Com&mand:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>cbCommand</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>Enter the command you wish to execute or the address of the resource you want to open. This can be a remote URL like "www.trinitydesktop.org" or a local one like "~/.tderc".</string> + </property> + </widget> + <widget class="TQLabel" row="0" column="0"> + <property name="name"> + <cstring>lbRunIcon</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string></string> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + </widget> + <widget class="KHistoryCombo" row="1" column="1"> + <property name="name"> + <cstring>cbCommand</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>388</width> + <height>0</height> + </size> + </property> + <property name="whatsThis" stdset="0"> + <string>Enter the command you wish to execute or the address of the resource you want to open. This can be a remote URL like "www.trinitydesktop.org" or a local one like "~/.tderc".</string> + </property> + </widget> + <widget class="TQLabel" row="0" column="1"> + <property name="name"> + <cstring>lbComment</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Enter the name of the application you want to run or the URL you want to view</string> + </property> + <property name="alignment"> + <set>WordBreak|AlignVCenter</set> + </property> + </widget> + </grid> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>cbPriority</sender> + <signal>toggled(bool)</signal> + <receiver>lbLowPriority</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>cbPriority</sender> + <signal>toggled(bool)</signal> + <receiver>slPriority</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>cbPriority</sender> + <signal>toggled(bool)</signal> + <receiver>lbHighPriority</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>cbRunAsOther</sender> + <signal>toggled(bool)</signal> + <receiver>lbUsername</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>cbRunAsOther</sender> + <signal>toggled(bool)</signal> + <receiver>leUsername</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>cbRunAsOther</sender> + <signal>toggled(bool)</signal> + <receiver>lbPassword</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>cbRunAsOther</sender> + <signal>toggled(bool)</signal> + <receiver>lePassword</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>cbPriority</sender> + <signal>toggled(bool)</signal> + <receiver>textLabel1</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>cbCommand</tabstop> + <tabstop>cbRunInTerminal</tabstop> + <tabstop>cbRunAsOther</tabstop> + <tabstop>leUsername</tabstop> + <tabstop>lePassword</tabstop> + <tabstop>cbPriority</tabstop> + <tabstop>slPriority</tabstop> + <tabstop>pbOptions</tabstop> + <tabstop>pbRun</tabstop> + <tabstop>pbCancel</tabstop> +</tabstops> +<includes> + <include location="global" impldecl="in declaration">fixx11h.h</include> + <include location="local" impldecl="in implementation">kdialog.h</include> + <include location="local" impldecl="in implementation">kiconloader.h</include> + <include location="local" impldecl="in implementation">kpassdlg.h</include> + <include location="local" impldecl="in implementation">kcombobox.h</include> + <include location="local" impldecl="in implementation">klineedit.h</include> + <include location="local" impldecl="in implementation">kpushbutton.h</include> +</includes> +<pixmapfunction>BarIcon</pixmapfunction> +<layoutdefaults spacing="3" margin="6"/> +<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/> +<includehints> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpassdlg.h</includehint> + <includehint>kcombobox.h</includehint> +</includehints> +</UI> diff --git a/kdesktop/patterns/CMakeLists.txt b/kdesktop/patterns/CMakeLists.txt new file mode 100644 index 000000000..a6bfa053b --- /dev/null +++ b/kdesktop/patterns/CMakeLists.txt @@ -0,0 +1,17 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +install( FILES + night-rock.desktop night-rock.jpg stonewall2.png + stonewall2.desktop fish.desktop fish.png flowers.desktop + flowers.png pavement.desktop pavement.png rattan.desktop + rattan.png triangles.desktop triangles.png + DESTINATION ${DATA_INSTALL_DIR}/kdesktop/patterns ) diff --git a/kdesktop/patterns/Makefile.am b/kdesktop/patterns/Makefile.am new file mode 100644 index 000000000..edf7ba024 --- /dev/null +++ b/kdesktop/patterns/Makefile.am @@ -0,0 +1,5 @@ +patdir=$(kde_datadir)/kdesktop/patterns +pat_DATA = night-rock.desktop night-rock.jpg stonewall2.png \ + stonewall2.desktop fish.desktop fish.png flowers.desktop \ + flowers.png pavement.desktop pavement.png rattan.desktop rattan.png \ + triangles.desktop triangles.png diff --git a/kdesktop/patterns/fish.desktop b/kdesktop/patterns/fish.desktop new file mode 100644 index 000000000..7644bb0c8 --- /dev/null +++ b/kdesktop/patterns/fish.desktop @@ -0,0 +1,74 @@ +[KDE Desktop Pattern] +Comment=Fish Net +Comment[af]=Visnet +Comment[az]=Balıq Şəbəkəsi +Comment[be]=Сетка Fish +Comment[bn]=মাছ ধরার জাল +Comment[br]=Roued pesk +Comment[ca]=Xarxa de pesca +Comment[cs]=Rybářská síť +Comment[csb]=Rëbackô séc +Comment[cy]=Rhwyd Pysgod +Comment[da]=Fiskenet +Comment[de]=Fischnetz +Comment[el]=Δίχτυ ψαρέματος +Comment[eo]=Fiŝreto +Comment[es]=Red de pesca +Comment[et]=Kalavõrk +Comment[eu]=Arrainetarako sarea +Comment[fa]=تور ماهی +Comment[fi]=Kalaverkko +Comment[fr]=Filet +Comment[fy]=Fisknet +Comment[gl]=Rede de Pesca +Comment[he]=רשת דייגים +Comment[hi]=मछली जाली +Comment[hr]=Ribarska mreža +Comment[hu]=Halászháló +Comment[is]=Net +Comment[it]=Rete da pesca +Comment[ja]=漁網 +Comment[ka]=მეთევზის ბადე +Comment[kk]=Балықшы ауы +Comment[km]=សំណាញ់ +Comment[lo]=ປາ +Comment[lt]=Žuvų tinklas +Comment[lv]=Zivju Tīkls +Comment[mk]=Рибарска мрежа +Comment[mn]=Загас сүлжээ +Comment[ms]=Jala Ikan +Comment[mt]=Xibka +Comment[nb]=Fiskegarn +Comment[nds]=Fischernett +Comment[ne]=फिस नेट +Comment[nl]=Visnet +Comment[nn]=Fiskegarn +Comment[nso]=Sefo ya Dihlapi +Comment[oc]=resèu de pesca +Comment[pa]=ਮੱਛੀ ਨੈੱਟ +Comment[pl]=Sieć rybacka +Comment[pt]=Rede de Pesca +Comment[ro]=Plasă de pescuit +Comment[ru]=Рыбацкая сеть +Comment[se]=Sáibma +Comment[sk]=Ryby a sieť +Comment[sl]=Ribiška mreža +Comment[sr]=Рибарска мрежа +Comment[sr@Latn]=Ribarska mreža +Comment[sv]=Fisknät +Comment[ta]=மீன் வலை +Comment[te]=చేపల వల +Comment[tg]=Таври моҳигирӣ +Comment[th]=แห +Comment[tr]=Balık Ağı +Comment[tt]=Balıqçı Yätmäse +Comment[uk]=Тенета +Comment[uz]=Toʻr +Comment[uz@cyrillic]=Тўр +Comment[ven]=Mulavhu wa khovhe +Comment[vi]=Lưới đánh cá +Comment[wa]=Filet d' pexhe +Comment[zh_CN]=渔网 +Comment[zh_TW]=漁網 +Comment[zu]=I-nethi yofishi +File=fish.png diff --git a/kdesktop/patterns/fish.png b/kdesktop/patterns/fish.png Binary files differnew file mode 100644 index 000000000..33de9be7c --- /dev/null +++ b/kdesktop/patterns/fish.png diff --git a/kdesktop/patterns/flowers.desktop b/kdesktop/patterns/flowers.desktop new file mode 100644 index 000000000..7e57db75c --- /dev/null +++ b/kdesktop/patterns/flowers.desktop @@ -0,0 +1,79 @@ +[KDE Desktop Pattern] +Comment=Flowers +Comment[af]=Blomme +Comment[az]=Çiçəklər +Comment[be]=Кветкі +Comment[bn]=ফুল +Comment[br]=Bleunioù +Comment[ca]=Flors +Comment[cs]=Květiny +Comment[csb]=Kwiôtczi +Comment[cy]=Blodau +Comment[da]=Blomster +Comment[de]=Blumen +Comment[el]=Λουλούδια +Comment[eo]=Floroj +Comment[es]=Flores +Comment[et]=Lilled +Comment[eu]=Loreak +Comment[fa]=گلها +Comment[fi]=Kukat +Comment[fr]=Fleurs +Comment[fy]=Blommen +Comment[ga]=Bláthanna +Comment[gl]=Flores +Comment[he]=פרחים +Comment[hi]=पुष्प +Comment[hr]=Cvijeće +Comment[hu]=Virágok +Comment[id]=Bunga +Comment[is]=Blóm +Comment[it]=Fiori +Comment[ja]=花 +Comment[ka]=ყვავილები +Comment[kk]=Гүлдер +Comment[km]=ផ្កា +Comment[lo]=ດອກໄມ້ +Comment[lt]=Gėlės +Comment[lv]=Puķes +Comment[mk]=Цвеќиња +Comment[mn]=Цэцэг +Comment[ms]=Bunga +Comment[mt]=Fjuri +Comment[nb]=Blomster +Comment[nds]=Blomen +Comment[ne]=फूल +Comment[nl]=Bloemen +Comment[nn]=Blomar +Comment[nso]=Mapolomo +Comment[oc]=Flors +Comment[pa]=ਫੁੱਲ +Comment[pl]=Kwiaty +Comment[pt]=Flores +Comment[pt_BR]=Flores +Comment[ro]=Flori +Comment[ru]=Цветы +Comment[rw]=Indabo +Comment[se]=Lieđit +Comment[sk]=Kvety +Comment[sl]=Rože +Comment[sr]=Цвеће +Comment[sr@Latn]=Cveće +Comment[sv]=Blommor +Comment[ta]=பூக்கள் +Comment[te]=పువ్వులు +Comment[tg]=Гулҳо +Comment[th]=ดอกไม้ +Comment[tr]=Çiçekler +Comment[tt]=Çäçäklär +Comment[uk]=Квіти +Comment[uz]=Gullar +Comment[uz@cyrillic]=Гуллар +Comment[ven]=Maluvha +Comment[vi]=Bông hoa +Comment[wa]=Fleurs +Comment[xh]=Iintyatyambo +Comment[zh_CN]=花 +Comment[zh_TW]=花朵 +Comment[zu]=Izimbali +File=flowers.png diff --git a/kdesktop/patterns/flowers.png b/kdesktop/patterns/flowers.png Binary files differnew file mode 100644 index 000000000..cab6af8eb --- /dev/null +++ b/kdesktop/patterns/flowers.png diff --git a/kdesktop/patterns/night-rock.desktop b/kdesktop/patterns/night-rock.desktop new file mode 100644 index 000000000..4a324e47a --- /dev/null +++ b/kdesktop/patterns/night-rock.desktop @@ -0,0 +1,75 @@ +[KDE Desktop Pattern] +Comment=Night Rock by Tigert +Comment[af]=Nag Klip deur Tigert +Comment[ar]=Night Rock من Tigert +Comment[az]=Tigert'dan Gecə Qayası +Comment[be]=Начная Гара ад Tigert +Comment[bn]=Tigert-এর নাইট রক +Comment[br]=Karreg da noz gant Tigert +Comment[bs]=Night Rock - Tigert +Comment[ca]=Rock nocturn per Tigert +Comment[cs]=Night Rock vytvořil Tigert +Comment[csb]=Nocny Rock (ùs. Tigert) +Comment[cy]=Carreg Nos gan Tigert +Comment[da]=Night Rock af Tigert +Comment[de]=Night Rock +Comment[el]=Night Rock από τον Tigert +Comment[eo]=Nokta roko +Comment[es]=Roca de noche de Tigert +Comment[et]=Night Rock (Tigert) +Comment[eu]=Gaueko Haitza, Tigert-ek egina +Comment[fa]=Night Rock توسط تیگرت +Comment[fi]=Night Rock, tehnyt Tigert +Comment[fr]=Night Rock par Tigert +Comment[fy]=Rots by Nacht, door Tigert +Comment[gl]=Night Rock por Tigert +Comment[he]=סלעים +Comment[hi]=टिगर्ट द्वारा नाइट रॉक +Comment[hr]=Night Rock (izr. Tigert) +Comment[hu]=Tigert éjjeli sziklája +Comment[id]=Batu Malam oleh Tigert +Comment[is]=Night Rock eftir Tigert +Comment[it]=Rock notturno (di Tigert) +Comment[ja]=Tigert による Night Rock +Comment[ka]=კლდე ღამით (Tigert) +Comment[kk]=Түнгі жартас (Tigert) +Comment[km]=សិលារាត្រី ដោយ Tigert +Comment[lo]=ຄຳ່ມັນຯ ໂດຍ Tigert +Comment[lv]=Nakts Roks no Tigerta +Comment[mk]=Ноќен рок од Tigert +Comment[mn]=Шөнийн рок +Comment[ms]=Batuan Malan oleh Tigert +Comment[mt]=Night Rock minn Tigert +Comment[nb]=Nattrock av Tigert +Comment[nds]=Night Rock vun Tigert +Comment[ne]=टिग्रेटद्वारा रातीको रक +Comment[nl]=Rots bij Nacht, door Tigert +Comment[nn]=Nattrock av Tigert +Comment[nso]=Leswika la Bosego ka Tigert +Comment[oc]=Rock nocturn per Tigert +Comment[pa]=ਰਾਤ ਪਹਾੜੀ ਟੀਰਿਰਟ +Comment[pl]=Nocny Rock (wyk. Tigert) +Comment[pt]=Night Rock de Tigert +Comment[pt_BR]=Night Rock por Tigert +Comment[ro]=Piatră întunecată de Tigert +Comment[ru]=Ночная скала (Tigert) +Comment[rw]=Night Rock na Tigert +Comment[se]=Tigert:a idjarocka +Comment[sk]=Nočný kameň od Tigerta +Comment[sl]=Nočni rock Tigerta +Comment[sv]=Nattsten av Tigert +Comment[ta]=டைக்ரட்இன் நைட்ராக் +Comment[tg]=Сахраҳои дар шаб аз Tigert +Comment[th]=ค่ำคืนมัน ๆ โดย Tigert +Comment[tr]=Tigert'dan Gece Kayası +Comment[tt]=Tönge Taw (Tigert tarafınnan) +Comment[uk]=Нічний політ Тайгерта +Comment[uz]=Oqshom qoyasi (Tigert tomonidan) +Comment[uz@cyrillic]=Оқшом қояси (Тигерт томонидан) +Comment[ven]=Vhusiku ha Rock nga Tigert +Comment[vi]=Rock Buổi đêm bởi Tigert +Comment[wa]=Rotche di nute pa Tigert +Comment[zh_CN]=Tigert 的夜色中的岩石 +Comment[zh_TW]=午夜搖滾 (Tigert 繪製) +Comment[zu]=Night Rock ngu-Tigert +File=night-rock.jpg diff --git a/kdesktop/patterns/night-rock.jpg b/kdesktop/patterns/night-rock.jpg Binary files differnew file mode 100644 index 000000000..8a3297be8 --- /dev/null +++ b/kdesktop/patterns/night-rock.jpg diff --git a/kdesktop/patterns/pavement.desktop b/kdesktop/patterns/pavement.desktop new file mode 100644 index 000000000..3ecabd35d --- /dev/null +++ b/kdesktop/patterns/pavement.desktop @@ -0,0 +1,75 @@ +[KDE Desktop Pattern] +Comment=Pavement +Comment[af]=Sypaadjie +Comment[az]=Səki +Comment[be]=Брушчатка +Comment[bn]=ফুটপাথ +Comment[br]=Pavezadur +Comment[ca]=Paviment +Comment[cs]=Dlažba +Comment[csb]=Trotuar +Comment[cy]=Palmant +Comment[da]=Brolægning +Comment[de]=Gehsteig +Comment[el]=Πεζοδρόμιο +Comment[eo]=Pavimo +Comment[es]=Pavimento +Comment[eu]=Zorua +Comment[fa]=سنگفرش +Comment[fi]=Katukivetys +Comment[fr]=Pavés +Comment[fy]=Estrikken +Comment[ga]=Pábháil +Comment[gl]=Pavemento +Comment[he]=ריצוף +Comment[hi]=फर्श +Comment[hr]=Pločnik +Comment[hu]=Járda +Comment[is]=Gangstétt +Comment[it]=Marciapiede +Comment[ja]=歩道 +Comment[ka]=ქვაფენილი +Comment[kk]=Тас алаң +Comment[km]=កម្រាលថ្ម +Comment[lo]=ທາງເດີນ +Comment[lt]=Grindinys +Comment[lv]=Ielas segums +Comment[mk]=Калдрма +Comment[mn]=Явган зам +Comment[ms]=Turapan +Comment[mt]=Bankina +Comment[nb]=Brolegning +Comment[nds]=Börgerstieg +Comment[ne]=शीलास्तर +Comment[nl]=Plavuizen +Comment[oc]=Paviment +Comment[pa]=ਪਾਵੀਮੈਂਟ +Comment[pl]=Chodnik +Comment[pt]=Chão +Comment[pt_BR]=Pavimento +Comment[ro]=Pavaj +Comment[ru]=Мостовая +Comment[rw]=Umuteguro +Comment[se]=Ravdaváccahat +Comment[sk]=Chodník +Comment[sl]=Pločnik +Comment[sr]=Плочник +Comment[sr@Latn]=Pločnik +Comment[sv]=Trottoar +Comment[ta]=நடைபாதை +Comment[te]=తలవరుస +Comment[tg]=Пиёдарав +Comment[th]=ทางเท้า +Comment[tr]=Kaldırım +Comment[tt]=Uram +Comment[uk]=Дорога +Comment[uz]=Yoʻlak +Comment[uz@cyrillic]=Йўлак +Comment[ven]=Ludila +Comment[vi]=Lát gạch hoa +Comment[wa]=Trotwer +Comment[xh]=Umgangatho osecaleni kwendlela +Comment[zh_CN]=人行道 +Comment[zh_TW]=人行道 +Comment[zu]=Unqenqema eceleni komgwaqo +File=pavement.png diff --git a/kdesktop/patterns/pavement.png b/kdesktop/patterns/pavement.png Binary files differnew file mode 100644 index 000000000..7ba9bcf14 --- /dev/null +++ b/kdesktop/patterns/pavement.png diff --git a/kdesktop/patterns/rattan.desktop b/kdesktop/patterns/rattan.desktop new file mode 100644 index 000000000..73c133c08 --- /dev/null +++ b/kdesktop/patterns/rattan.desktop @@ -0,0 +1,40 @@ +[KDE Desktop Pattern] +Comment=Rattan +Comment[bn]=রাটান +Comment[br]=Lien skosat +Comment[cs]=Rákos +Comment[eo]=Plektaĵo +Comment[es]=Rota (planta) +Comment[fa]=چوبدستی +Comment[fi]=Rottinki +Comment[fr]=Rotin +Comment[fy]=Rotan +Comment[ga]=Ratán +Comment[he]=דקלים +Comment[hi]=बेंत +Comment[hu]=Nádfonat +Comment[id]=Rotan +Comment[ja]=籐 (とう) +Comment[ka]=რატანი +Comment[km]=ផ្ដៅ +Comment[lo]=ຫວາຍ +Comment[lv]=Rotangpalma +Comment[mk]=Трска +Comment[ms]=Rotan +Comment[ne]=रेटन +Comment[nl]=Rotan +Comment[pa]=ਰਾਟਾਨ +Comment[pt]=Rota +Comment[ro]=Sac de iută +Comment[rw]=Umukindo +Comment[sk]=Trsť +Comment[sv]=Rotting +Comment[ta]=ரட்டன் +Comment[te]=రట్టాన్ +Comment[th]=หวาย +Comment[uz]=Palma +Comment[uz@cyrillic]=Пальма +Comment[vi]=Cây song mây +Comment[zh_CN]=藤条 +Comment[zh_TW]=藤條 +File=rattan.png diff --git a/kdesktop/patterns/rattan.png b/kdesktop/patterns/rattan.png Binary files differnew file mode 100644 index 000000000..28f600541 --- /dev/null +++ b/kdesktop/patterns/rattan.png diff --git a/kdesktop/patterns/stonewall2.desktop b/kdesktop/patterns/stonewall2.desktop new file mode 100644 index 000000000..c9c49dde9 --- /dev/null +++ b/kdesktop/patterns/stonewall2.desktop @@ -0,0 +1,76 @@ +[KDE Desktop Pattern] +Comment=Stonewall 2 by Tigert +Comment[af]=Klipmuur 2 deur Tigert +Comment[ar]=Stonewall 2 من Tigert +Comment[az]=Tigert'dan Daş Divar 2 +Comment[be]=Каменная сцяна 2 ад Tigert +Comment[bn]=Tigert-এর স্টোনওয়াল ২ +Comment[br]=Moger mein 2 gant Tigert +Comment[ca]=Mur de pedra 2 per Tigert +Comment[cs]=Stonewall 2 vytvořil Tigert +Comment[csb]=Kamny mùr 2 (ùs. Tigert) +Comment[cy]=Stonewall 2 gan Tigert +Comment[da]=Stenmur 2 af Tigert +Comment[de]=Stonewall 2 +Comment[el]=Stonewall 2 από τον Tigert +Comment[eo]=Ŝtonmuro 2 +Comment[es]=Pared de piedra 2 de Tigert +Comment[et]=Stonewall 2 (Tigert) +Comment[eu]=Stonewall 2, Tigertek egina +Comment[fa]=Stonewall ۲ توسط تیگرت +Comment[fi]=Kiviseinä 2, tehnyt Tigert +Comment[fr]=Stonewall 2 par Tigert +Comment[fy]=Stienen muorre 2, troch Tigert +Comment[gl]=Stonewall 2 por Tigert +Comment[he]=חומת אבנים +Comment[hi]=टिगर्ट द्वारा स्टोनवाल 2 +Comment[hr]=Stonewall 2 (izr. Tigert) +Comment[hu]=Tigert 2. kőfala +Comment[id]=Tembok batu 2 oleh Tigert +Comment[is]=Steinveggur 2 eftir Tigert +Comment[it]=Mattoni 2 (di Tigert) +Comment[ja]=Tigert による Stonewall +Comment[ka]=ქვის კედელი 2 (Tigert) +Comment[kk]=Тас дуал 2 (Tigert) +Comment[km]=ជញ្ជាំងថ្ម ២ ដោយ Tigert +Comment[lo]=ກຳແພງຫີນ 2 ໂດຍ Tigert +Comment[lt]=Tigert'o akmens siena 2 +Comment[lv]=Akmens siena 2 no Tigerta +Comment[mk]=Камен ѕид 2 од Tigert +Comment[mn]=Чулуун хана 2 +Comment[ms]=Tembok Batu 2 oleh Tigert +Comment[mt]=Stonewall 2 minn Tigert +Comment[nb]=Steinvegg 2 av Tigert +Comment[nds]=Stonewall 2 vun Tigert +Comment[ne]=टिग्रेटद्वारा स्टोनवाल २ +Comment[nl]=Stenen muur 2, door Tigert +Comment[nn]=Steinvegg 2 av Tigert +Comment[nso]=Stonewall 2 ka Tigert +Comment[oc]=Mur de peira 2 per Tigert +Comment[pa]=ਪੱਥਰੀ ਕੰਧ ਟੀਗਿਰਟ +Comment[pl]=Kamienny mur 2 (wyk. Tigert) +Comment[pt]=Stonewall 2 de Tigert +Comment[pt_BR]=Stonewall 2 por Tigert +Comment[ro]=Zid de piatră 2 de Tigert +Comment[ru]=Каменная стена 2 (Tigert) +Comment[rw]=Stonewall 2 na Tigert +Comment[se]=Tigert:a geađgeseaidni 2 +Comment[sk]=Stonewall 2 od Tigerta +Comment[sl]=Stonewall 2, Tigert +Comment[sv]=Stenmur 2 av Tigert +Comment[ta]=டைக்ரெட்டின் ஸ்டோன்வால் 2 +Comment[tg]=Девори сангии 2 аз Tigert +Comment[th]=กำแพงหิน 2 โดย Tigert +Comment[tr]=Tigert'dan Taşduvar 2 +Comment[tt]=Taşdíwar 2 (Tigert tarafınnan) +Comment[uk]=Кам'яна стіна Тайгерта 2 +Comment[uz]=Tosh devol 2 (Tigert tomonidan) +Comment[uz@cyrillic]=Тош девол 2 (Тигерт томонидан) +Comment[ven]=Luvhondo lwa tombo lwa vhuvhili nga Tigert +Comment[vi]=Tường đá 2 bởi Tigert +Comment[wa]=Meur di pires 2 pa Tigert +Comment[xh]=Stonewall 2 ngu Tigert +Comment[zh_CN]=Tigert 的石墙 2 +Comment[zh_TW]=石牆 2 (Tigert 繪製) +Comment[zu]=Stonewall 2 ngu-Tigert +File=stonewall2.png diff --git a/kdesktop/patterns/stonewall2.png b/kdesktop/patterns/stonewall2.png Binary files differnew file mode 100644 index 000000000..cb9f10f40 --- /dev/null +++ b/kdesktop/patterns/stonewall2.png diff --git a/kdesktop/patterns/triangles.desktop b/kdesktop/patterns/triangles.desktop new file mode 100644 index 000000000..846e698ce --- /dev/null +++ b/kdesktop/patterns/triangles.desktop @@ -0,0 +1,76 @@ +[KDE Desktop Pattern] +Comment=Triangles +Comment[af]=Driehoeke +Comment[ar]=مثلثات +Comment[az]=Üç Bucaqlar +Comment[be]=Трохкутнікі +Comment[bn]=ত্রিভুজ +Comment[br]=Tric'hornioù +Comment[cs]=Trojúhelníky +Comment[csb]=Trzënórtë +Comment[cy]=Trionglau +Comment[da]=Trekanter +Comment[de]=Dreiecke +Comment[el]=Τρίγωνα +Comment[eo]=Trianguloj +Comment[es]=Triángulos +Comment[eu]=Triangeluak +Comment[fa]=مثلثها +Comment[fi]=Kolmiot +Comment[fy]=Trijehoeken +Comment[ga]=Triantáin +Comment[gl]=Triángulos +Comment[he]=משולשים +Comment[hi]=त्रिभुज +Comment[hr]=Trokuti +Comment[hu]=Háromszögek +Comment[id]=Segi Tiga +Comment[is]=Þríhyrningar +Comment[it]=Triangoli +Comment[ja]=三角 +Comment[ka]=სამკუთხედები +Comment[kk]=Үшбұрыштар +Comment[km]=ត្រីកោណ +Comment[lo]=ສາມລ່ງມ +Comment[lt]=Trikampiai +Comment[lv]=Trīsstūri +Comment[mk]=Триаголници +Comment[mn]=Гурвалжин +Comment[ms]=Segi Tiga +Comment[mt]=Triangoli +Comment[nb]=Trekanter +Comment[nds]=Dre'ecks +Comment[ne]=त्रिभुज +Comment[nl]=Driehoeken +Comment[nn]=Trekantar +Comment[nso]=Dikhutlotharo +Comment[pa]=ਤਿਕੋਣਾਂ +Comment[pl]=Trójkąty +Comment[pt]=Triângulos +Comment[pt_BR]=Triângulos +Comment[ro]=Triunghiuri +Comment[ru]=Треугольники +Comment[rw]=Mpandeshatu +Comment[se]=Golmmehat +Comment[sk]=Trojuholníky +Comment[sl]=Trikotniki +Comment[sr]=Троуглови +Comment[sr@Latn]=Trouglovi +Comment[sv]=Trianglar +Comment[ta]=முக்கோணங்கள் +Comment[te]=త్రికొణాలు +Comment[tg]=Секунҷаҳо +Comment[th]=สามเหลี่ยม +Comment[tr]=Üçgenler +Comment[tt]=Öçpoçmaq +Comment[uk]=Трикутники +Comment[uz]=Uchburchaklar +Comment[uz@cyrillic]=Учбурчаклар +Comment[ven]=Thiriengele +Comment[vi]=Tam giác +Comment[wa]=Triyangues +Comment[xh]=Oonxantathu +Comment[zh_CN]=三角形 +Comment[zh_TW]=三角形 +Comment[zu]=Onxantathu +File=triangles.png diff --git a/kdesktop/patterns/triangles.png b/kdesktop/patterns/triangles.png Binary files differnew file mode 100644 index 000000000..cde9068eb --- /dev/null +++ b/kdesktop/patterns/triangles.png diff --git a/kdesktop/pics/CMakeLists.txt b/kdesktop/pics/CMakeLists.txt new file mode 100644 index 000000000..1afbf83d8 --- /dev/null +++ b/kdesktop/pics/CMakeLists.txt @@ -0,0 +1,16 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +tde_install_icons( error ) + +install( FILES + ksslogo.png splash.png + DESTINATION ${DATA_INSTALL_DIR}/kdesktop/pics ) diff --git a/kdesktop/pics/Makefile.am b/kdesktop/pics/Makefile.am new file mode 100644 index 000000000..e70a08590 --- /dev/null +++ b/kdesktop/pics/Makefile.am @@ -0,0 +1,9 @@ +# Makefile.am of tdebase/kdesktop/pics + +pics_DATA = ksslogo.png splash.png splash2.png kde2.xbm + +picsdir = $(kde_datadir)/kdesktop/pics + +EXTRA_DIST = $(pics_DATA) + +KDE_ICON = error diff --git a/kdesktop/pics/cr32-app-error.png b/kdesktop/pics/cr32-app-error.png Binary files differnew file mode 100644 index 000000000..1de7a6fda --- /dev/null +++ b/kdesktop/pics/cr32-app-error.png diff --git a/kdesktop/pics/ksslogo.png b/kdesktop/pics/ksslogo.png Binary files differnew file mode 100644 index 000000000..953ecdddb --- /dev/null +++ b/kdesktop/pics/ksslogo.png diff --git a/kdesktop/pics/splash.png b/kdesktop/pics/splash.png Binary files differnew file mode 100644 index 000000000..c32afcc1e --- /dev/null +++ b/kdesktop/pics/splash.png diff --git a/kdesktop/pixmapserver.cc b/kdesktop/pixmapserver.cc new file mode 100644 index 000000000..7a480cdb6 --- /dev/null +++ b/kdesktop/pixmapserver.cc @@ -0,0 +1,254 @@ +/* vi: ts=8 sts=4 sw=4 + * + * This file is part of the KDE project, module kdesktop. + * Copyright (C) 1999 Geert Jansen <[email protected]> + * + * You can Freely distribute this program under the GNU General Public + * License. See the file "COPYING" for the exact licensing terms. + * + * + * Shared pixmap server for KDE. + * + * 5 Dec 99: Geert Jansen: + * + * Initial implementation using the X11 selection mechanism. + */ + +#include <assert.h> + + +#include <tdeapplication.h> +#include <kdebug.h> + +#include <X11/X.h> +#include <X11/Xlib.h> + +#include "pixmapserver.h" + +#ifndef None +#define None 0L +#endif + +#ifdef __GNUC__ +#define ID __PRETTY_FUNCTION__ << ": " +#else +#define ID "KPixmapServer: " +#endif + + +KPixmapServer::KPixmapServer() + : TQWidget(0L, "shpixmap comm window") +{ + kapp->installX11EventFilter(this); + pixmap = XInternAtom(tqt_xdisplay(), "PIXMAP", false); +} + + +KPixmapServer::~KPixmapServer() +{ + SelectionIterator it; + for (it=m_Selections.begin(); it!=m_Selections.end(); it++) + XSetSelectionOwner(tqt_xdisplay(), it.key(), None, CurrentTime); + + DataIterator it2; + for (it2=m_Data.begin(); it2!=m_Data.end(); it2++) + delete it2.data().pixmap; +} + + +void KPixmapServer::add(TQString name, TQPixmap *pm, bool overwrite) +{ + if (m_Names.contains(name)) + { + if (overwrite) + remove(name); + else return; + } + + TQString str = TQString("KDESHPIXMAP:%1").arg(name); + Atom sel = XInternAtom(tqt_xdisplay(), str.latin1(), false); + KPixmapInode pi; + pi.handle = pm->handle(); + pi.selection = sel; + m_Names[name] = pi; + + TDESelectionInode si; + si.name = name; + si.handle = pm->handle(); + m_Selections[sel] = si; + + DataIterator it = m_Data.find(pm->handle()); + if (it == m_Data.end()) + { + KPixmapData data; + data.pixmap = pm; + data.usecount = 0; + data.refcount = 1; + m_Data[pm->handle()] = data; + } else + it.data().refcount++; + + XSetSelectionOwner(tqt_xdisplay(), sel, winId(), CurrentTime); +} + + +void KPixmapServer::remove(TQString name) +{ + // Remove the name + NameIterator it = m_Names.find(name); + if (it == m_Names.end()) + return; + KPixmapInode pi = it.data(); + m_Names.remove(it); + + // Remove and disown the selection + SelectionIterator it2 = m_Selections.find(pi.selection); + assert(it2 != m_Selections.end()); + m_Selections.remove(it2); + XSetSelectionOwner(tqt_xdisplay(), pi.selection, None, CurrentTime); + + // Decrease refcount on data + DataIterator it3 = m_Data.find(pi.handle); + assert(it3 != m_Data.end()); + it3.data().refcount--; + if (!it3.data().refcount && !it3.data().usecount) + { + delete it3.data().pixmap; + m_Data.remove(it3); + } +} + + +TQStringList KPixmapServer::list() +{ + TQStringList lst; + NameIterator it; + for (it=m_Names.begin(); it!=m_Names.end(); it++) + lst += it.key(); + return lst; +} + + +void KPixmapServer::setOwner(TQString name) +{ + NameIterator it = m_Names.find(name); + if (it == m_Names.end()) + return; + + XSetSelectionOwner(tqt_xdisplay(), it.data().selection, winId(), CurrentTime); +} + + +bool KPixmapServer::x11Event(XEvent *event) +{ + // Handle SelectionRequest events by which a X client can request a + // shared pixmap. + + if (event->type == SelectionRequest) + { + XSelectionRequestEvent *ev = &event->xselectionrequest; + + // Build negative reply + XEvent reply; + reply.type = SelectionNotify; + reply.xselection.display = tqt_xdisplay(); + reply.xselection.requestor = ev->requestor; + reply.xselection.selection = ev->selection; + reply.xselection.target = pixmap; + reply.xselection.property = None; + reply.xselection.time = ev->time; + + // Check if we know about this selection + Atom sel = ev->selection; + SelectionIterator it = m_Selections.find(sel); + if (it == m_Selections.end()) + return false; + TDESelectionInode si = it.data(); + + // Only convert to pixmap + if (ev->target != pixmap) + { + kdDebug(1204) << ID << "illegal target\n"; + XSendEvent(tqt_xdisplay(), ev->requestor, false, 0, &reply); + return true; + } + + // Check if there is no transaction in progress to the same property + if (m_Active.contains(ev->property)) + { + kdDebug(1204) << ID << "selection is busy.\n"; + XSendEvent(tqt_xdisplay(), ev->requestor, false, 0, &reply); + return true; + } + + // Check if the selection was not deleted + DataIterator it2 = m_Data.find(si.handle); + if (it2 == m_Data.end()) + { + kdDebug(1204) << ID << "selection has been deleted.\n"; + XSendEvent(tqt_xdisplay(), ev->requestor, false, 0, &reply); + return true; + } + + kdDebug(1204) << ID << "request for " << si.name << "\n"; + + // All OK: pass the pixmap handle. + XChangeProperty(tqt_xdisplay(), ev->requestor, ev->property, pixmap, + 32, PropModeReplace, (unsigned char *) &si.handle, 1); + it2.data().usecount++; + m_Active[ev->property] = si.handle; + + // Request PropertyNotify events for the target window + // XXX: The target window better not be handled by us! + XSelectInput(tqt_xdisplay(), ev->requestor, PropertyChangeMask); + + // Acknowledge to the client and return + reply.xselection.property = ev->property; + XSendEvent(tqt_xdisplay(), ev->requestor, false, 0, &reply); + return true; + } + + // ICCCM says that the target property is to be deleted by the + // requestor. We are notified of this by a PropertyNotify. Only then, we + // can actually delete the pixmap if it was removed. + + if (event->type == PropertyNotify) + { + XPropertyEvent *ev = &event->xproperty; + + AtomIterator it = m_Active.find(ev->atom); + if (it == m_Active.end()) + return false; + HANDLE handle = it.data(); + m_Active.remove(it); + + DataIterator it2 = m_Data.find(handle); + assert(it2 != m_Data.end()); + it2.data().usecount--; + if (!it2.data().usecount && !it2.data().refcount) + { + delete it2.data().pixmap; + m_Data.remove(it2); + } + return true; + } + + // Handle SelectionClear events. + + if (event->type == SelectionClear) + { + XSelectionClearEvent *ev = &event->xselectionclear; + + SelectionIterator it = m_Selections.find(ev->selection); + if (it == m_Selections.end()) + return false; + + emit selectionCleared(it.data().name); + return true; + } + + // Process further + return false; +} + +#include "pixmapserver.moc" diff --git a/kdesktop/pixmapserver.h b/kdesktop/pixmapserver.h new file mode 100644 index 000000000..3084cd0a3 --- /dev/null +++ b/kdesktop/pixmapserver.h @@ -0,0 +1,124 @@ +/* vi: ts=8 sts=4 sw=4 + * + * This file is part of the KDE project, module kdesktop. + * Copyright (C) 1999 Geert Jansen <[email protected]> + * + * You can Freely distribute this program under the GNU General Public + * License. See the file "COPYING" for the exact licensing terms. + */ + +#ifndef __PixmapServer_h_Included__ +#define __PixmapServer_h_Included__ + +#include <tqwindowdefs.h> + +#include <tqwidget.h> +#include <tqmap.h> + +#include <X11/X.h> +#include <X11/Xlib.h> + +/** + * Used internally by KPixmapServer. + */ + +struct KPixmapInode +{ + Qt::HANDLE handle; + Atom selection; +}; + +struct KPixmapData +{ + TQPixmap *pixmap; + int usecount; + int refcount; +}; + +struct TDESelectionInode +{ + Qt::HANDLE handle; + TQString name; +}; + +/** + * KPixmapServer: Share pixmaps between X clients with deletion and + * multi-server capabilities. + * The sharing is implemented using X11 Selections. + * + * @author Geert Jansen <[email protected]> + */ +class KPixmapServer: public TQWidget +{ + Q_OBJECT + +public: + KPixmapServer(); + ~KPixmapServer(); + + /** + * Adds a pixmap to this server. This will make it available to all + * other X clients on the current display. + * + * You must never delete a pixmap that you add()'ed. The pixmap is + * deleted when you call remove() and after all clients have stopped + * using it. + * + * You can add the same pixmap under multiple names. + * + * @param name An X11-wide unique identifier for the pixmap. + * @param pm A pointer to the pixmap. + * @param overwrite Should an pixmap with the same name be overwritten? + */ + void add(TQString name, TQPixmap *pm, bool overwrite=true); + + /** + * Remove a pixmap from the server. This will delete the pixmap after + * all clients have stopped using it. + * + * @param name The name of the shared pixmap. + */ + void remove(TQString name); + + /** + * List all pixmaps currently served by this server. + * + * @return A TQStringList containing all the shared pixmaps. + */ + TQStringList list(); + + /** + * Re-set ownership of the selection providing the shared pixmap. + * + * @param name The name of the shared pixmap. + */ + void setOwner(TQString name); + +signals: + /** + * This signal is emitted when the selection providing the named pixmap + * is disowned. This means that said pixmap won't be served anymore by + * this server, though it can be served by another. You can re-aqcuire + * the selection by calling setOwner(). + */ + void selectionCleared(TQString name); + +protected: + bool x11Event(XEvent *); + +private: + Atom pixmap; + + TQMap<TQString,KPixmapInode> m_Names; + TQMap<Atom,TDESelectionInode> m_Selections; + TQMap<HANDLE,KPixmapData> m_Data; + TQMap<Atom,HANDLE> m_Active; + + typedef TQMap<TQString,KPixmapInode>::Iterator NameIterator; + typedef TQMap<Atom,TDESelectionInode>::Iterator SelectionIterator; + typedef TQMap<HANDLE,KPixmapData>::Iterator DataIterator; + typedef TQMap<Atom,HANDLE>::Iterator AtomIterator; +}; + + +#endif // __PixmapServer_h_Included__ diff --git a/kdesktop/programs/CMakeLists.txt b/kdesktop/programs/CMakeLists.txt new file mode 100644 index 000000000..e89527a1e --- /dev/null +++ b/kdesktop/programs/CMakeLists.txt @@ -0,0 +1,14 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +install( FILES + xearth.desktop xglobe.desktop xplanet.desktop + DESTINATION ${DATA_INSTALL_DIR}/kdesktop/programs ) diff --git a/kdesktop/programs/Makefile.am b/kdesktop/programs/Makefile.am new file mode 100644 index 000000000..abf5c0b31 --- /dev/null +++ b/kdesktop/programs/Makefile.am @@ -0,0 +1,2 @@ +progdir=$(kde_datadir)/kdesktop/programs +prog_DATA = xearth.desktop xglobe.desktop xplanet.desktop diff --git a/kdesktop/programs/xearth.desktop b/kdesktop/programs/xearth.desktop new file mode 100644 index 000000000..36af7e78b --- /dev/null +++ b/kdesktop/programs/xearth.desktop @@ -0,0 +1,81 @@ +[TDE Desktop Program] +Comment=XEarth by Kirk Johnson +Comment[af]=XEarth deur Kirk Johnson +Comment[ar]=XEarth من تأليف Kirk Johnson +Comment[az]=Kirk Johnson'dan XEarth +Comment[be]=Зямля (Kirk Johnson) +Comment[bn]=কার্ক জনসন-এর এক্স-আর্থ +Comment[br]=XEarth gant Kirk Johnson +Comment[ca]=XEarth per Kirk Johnson +Comment[cs]=XEarth vytvořil Kirk Johnson +Comment[csb]=XEarth (ùs. Kirk Johnson) +Comment[cy]=XEarth gan Kirk Johnson +Comment[da]=XEarth af Kirk Johnson +Comment[de]=XEarth +Comment[el]=XEarth από τον Kirk Johnson +Comment[eo]=XTero +Comment[es]=XEarth de Kirk Johnson +Comment[et]=XEarth (Kirk Johnson) +Comment[eu]=XEarth, Kirk Johnsonek egina +Comment[fa]=XEarth توسط کیرک جانسون +Comment[fi]=XEarth, tehnyt Kirk Johnson +Comment[fr]=XEarth par Kirk Johnson +Comment[fy]=XEarth, troch Kirk Johnson +Comment[ga]=XEarth le Kirk Johnson +Comment[gl]=XEarth por Kirk Johnson +Comment[he]=XEarth מאת Kirk Johnson +Comment[hi]=किर्क जॉनसन द्वारा एक्स-अर्थ +Comment[hr]=XEarth (izr. Kirka Johnsona) +Comment[hu]=Kirk Johnson földgömbje +Comment[id]=XEarth oleh Kirk Johnson +Comment[is]=XJörð eftir Kirk Johnson +Comment[it]=XEarth (di Kirk Johnson) +Comment[ja]=Kirk Johnson による XEarth +Comment[ka]=Xდედამიწა (Kirk Johnson) +Comment[kk]=XEarth (Kirk Johnson) +Comment[km]=XEarth ដោយ Kirk Johnson +Comment[lo]=ເເຜນທີ່ໂລກ ໂດຍ Kirk Johnson +Comment[lt]=Kirk Johnson'o XEarth +Comment[lv]=XEarth no Kirk Johnson +Comment[mk]=X-Земја од Kirk Johnson +Comment[mn]=XEarth +Comment[ms]=XEarth oleh Kirk Johnson +Comment[mt]=XEarth minn Kirk Johnson +Comment[nb]=XEarth av Kirk Johnson +Comment[nds]=XEarth vun Kirk Johnson +Comment[ne]=किर्क जोहान्सनद्वारा X अर्थ +Comment[nl]=XEarth, door Kirk Johnson +Comment[nn]=XEarth av Kirk Johnson +Comment[nso]=XLefase ka Kirk Johnson +Comment[oc]=XEarth per Kirk Johnson +Comment[pa]=ਕਿਰਕ ਜਾਨਸਨ ਵਲੋਂ XEarth +Comment[pl]=XEarth autorstwa Kirka Johnsona +Comment[pt]=XEarth de Kirk Johnson +Comment[pt_BR]=XEarth por Kirk Johnson +Comment[ro]=XEarth de Kirk Johnson +Comment[ru]=XEarth (Kirk Johnson) +Comment[rw]=XEarth na Kirk Johnson +Comment[se]=Kirk Johnson:a XEarth +Comment[sk]=XEarth od Kirka Johnsona +Comment[sl]=XEarth avtorja Kirka Johnsona +Comment[ss]=XEarth ngu Kirk Johnson +Comment[sv]=Xearth av Kirk Johnson +Comment[ta]=கிர்க் ஜான்சனின் Xஎர்த் +Comment[tg]=XEarth аз Kirk Johnson +Comment[th]=แผนที่โลก โดยเคิร์ก จอห์นสัน +Comment[tr]=Kirk Johnson'dan XEarth +Comment[tt]=XEarth, Kirk Johnson tarafınnan +Comment[uk]=XEarth Кірка Джонсона +Comment[uz]=XEarth (Kirik Jonson tomonidan) +Comment[uz@cyrillic]=XEarth (Кирик Жонсон томонидан) +Comment[ven]=Shango la X nga Kirk Johnson +Comment[vi]=Trái Đất X bởi Kirk Johnson +Comment[wa]=XDaegn pa Kirk Johnson +Comment[xh]=XEarth ngu Kirk Johnson +Comment[zh_CN]=Kirk Johnson 的 XEarth +Comment[zh_TW]=XEarth (Kirk Johnson 繪製) +Comment[zu]=XEarth ngu-Kirk Johnson +Executable=xearth +Command=xearth -size %x,%y -ppm > %f +PreviewCommand=xearth -size %x,%y -nomarkers -ppm > %f +Refresh=10 diff --git a/kdesktop/programs/xglobe.desktop b/kdesktop/programs/xglobe.desktop new file mode 100644 index 000000000..01b8244be --- /dev/null +++ b/kdesktop/programs/xglobe.desktop @@ -0,0 +1,81 @@ +[TDE Desktop Program] +Comment=XGlobe by Thorsten Scheuermann +Comment[af]=XGlobe deur Thorsten Scheuermann +Comment[ar]=XGlobe من تأليف Thorsten Scheuermann +Comment[az]=Thorsten Scheuermann'dan XGlobe +Comment[be]=Глобус (Thorsten Scheuermann) +Comment[bn]=থর্সটেন শিউয়ারমান-এর এক্স-গ্লোব +Comment[br]=XGlobe gant Thorsten Scheuermann +Comment[ca]=XGlobe per en Thorsten Scheuermann +Comment[cs]=XGlobe vytvořil Thorsten Scheuermann +Comment[csb]=XGlobe (ùs. Thorsten Scheuermann) +Comment[cy]=XGlobe gan Thorsten Scheuermann +Comment[da]=XGlobe af Thorsten Scheuermann +Comment[de]=XGlobe +Comment[el]=XGlobe από τον Thorsten Scheuermann +Comment[eo]=XGlobo +Comment[es]=XGlobe por Thorsten Scheuermann +Comment[et]=XGlobe (Thorsten Scheuermann) +Comment[eu]=XGlobe, Thorsten Scheuermannek egina +Comment[fa]=XGlobe توسط تورستن شرمن +Comment[fi]=XGlobe, tehnyt Thorsten Scheuermann +Comment[fr]=XGlobe par Thorsten Scheuermann +Comment[fy]=XGlobe, troch Thorsten Scheuermann +Comment[ga]=XGlobe le Thorsten Scheuermann +Comment[gl]=XGlobe por Thorsten Scheuermann +Comment[he]=XGlobe מאת Thorsten Scheuermann +Comment[hi]=थार्स्टन शर्मन द्वारा एक्स-ग्लोब +Comment[hr]=XGlobe (izr. Thorsten Scheuermann) +Comment[hu]=Thorsten Scheuermann földgömbje +Comment[id]=XGlobe oleh Thorsten Scheuermann +Comment[is]=XHnöttur eftir Thorsten Scheuermann +Comment[it]=XGlobe (di Thorsten Scheuermann) +Comment[ja]=Thorsten Scheuermann による XGlobe +Comment[ka]=Xგლობუსი (Thorsten Scheuermann) +Comment[kk]=XGlobe (Thorsten Scheuermann) +Comment[km]=XGlobe ដោយ Thorsten Scheuermann +Comment[lo]=ລູກໂລກ ໂດຍ Thorsten Scheuermann +Comment[lt]=Thorsten Scheuermann'o XGlobe +Comment[lv]=XGlobe no Thorsten Scheuermann +Comment[mk]=X-Глобус од Thorsten Scheuermann +Comment[mn]=XGlobe +Comment[ms]=XGlobe oleh Thorsten Scheuermann +Comment[mt]=XGlobe minn Thorsten Scheuermann +Comment[nb]=XGlobe av Thorsten Scheuermann +Comment[nds]=XGlobe vun Thorsten Scheuermann +Comment[ne]=थर्स्टर सेचरम्यानद्वारा X ग्लोब +Comment[nl]=XGlobe, door Thorsten Scheuermann +Comment[nn]=XGlobe av Thorsten Scheuermann +Comment[nso]=XGlobe ka Thorsten Scheuermann +Comment[oc]=XGlobe per Thorsten Scheuermann +Comment[pa]=ਥੋਰਸਟੀਨ ਸਚੀਉਰਮਨ ਵਲੋਂ XGlobe +Comment[pl]=XGlobe autorstwa Thorstena Scheuermanna +Comment[pt]=XGlobe de Thorsten Scheuermann +Comment[pt_BR]=XGlobe por Thorsten Scheuermann +Comment[ro]=XGlobe de Thorsten Scheuermann +Comment[ru]=XGlobe (Thorsten Scheuermann) +Comment[rw]=XGlobe na Thorsten Scheuermann +Comment[se]=Thorsten Scheuermann:a XGlobe +Comment[sk]=XGlobe od Thorstena Scheuermanna +Comment[sl]=XGlobe avtorja Thorstena Scheuermanna +Comment[ss]=XGlobe ngu Thorsten Scheuermann +Comment[sv]=Xglobe av Thorsten Scheuermann +Comment[ta]=த்ராஸ்டன் ஸ்யூர்மானின் எக்ஸ் க்ளோப் +Comment[tg]=XGlobe аз Thorsten Scheuermann +Comment[th]=ลูกโลก โดย Thorsten Scheuermann +Comment[tr]=Thorsten Scheuermann'dan XGlobe +Comment[tt]=XGlobe, Thorsten Scheuermann tarafınnan +Comment[uk]=XGlobe Торстена Шоєрмана +Comment[uz]=XGlobe (Torsten Shoyerman tomonidan) +Comment[uz@cyrillic]=XGlobe (Торстен Шойерман томонидан) +Comment[ven]=Lifhasi la X nga Thorsten Scheuermann +Comment[vi]=Qủa cầu X bởi Thorsten Scheuermann +Comment[wa]=XGlobe pa Thorsten Scheuermann +Comment[xh]=XGlobe ngu Thorsten Scheuermann +Comment[zh_CN]=Thorsten Scheuermann 的 XGlobe +Comment[zh_TW]=XGlobe (Thorsten Scheuermann 繪製) +Comment[zu]=XGlobe ngu-Thorsten Scheuermann +Executable=xglobe +Command=xglobe -dump -once -size %x,%y -nomarkers && mv xglobe-dump.bmp %f +PreviewCommand=xglobe -nomarkers -nolabel -dump -once -size %x,%y && mv xglobe-dump.bmp %f +Refresh=10 diff --git a/kdesktop/programs/xplanet.desktop b/kdesktop/programs/xplanet.desktop new file mode 100644 index 000000000..8ee5b0980 --- /dev/null +++ b/kdesktop/programs/xplanet.desktop @@ -0,0 +1,80 @@ +[TDE Desktop Program] +Command=xplanet --geometry %xx%y --num_times 1 --output %f.jpg && mv %f.jpg %f +Comment=XPlanet by Hari Nair +Comment[af]=XPlaneet deur Hari Nair +Comment[ar]=XPlanet من تليف Hari Nair +Comment[az]=Hari Nair'dan XPlanet +Comment[be]=Планета (Hari Nair) +Comment[bn]=হরি নায়ার-এর এক্স-প্ল্যানেট +Comment[br]=XPlanet gant Hari Nair +Comment[ca]=XPlanet per en Hari Nair +Comment[cs]=XPlanet od Hariho Naira +Comment[csb]=XPlanet (ùs.Hari Neir) +Comment[cy]=XPlanet gan Hari Nair +Comment[da]=XPlanet af Hari Nair +Comment[de]=XPlanet +Comment[el]=XPlanet του Hari Nair +Comment[eo]=XPlanedo de Hari Nair +Comment[es]=XPlanet de Hari Nair +Comment[et]=XPlanet (Hari Nair) +Comment[eu]=XPlanet Hari Nair-ek egina +Comment[fa]=XPlanet توسط هاری نیر +Comment[fi]=XPlanet, tehnyt Hari Nair +Comment[fr]=XPlanet par Hari Nair +Comment[fy]=XPlanet, troch Hari Nair +Comment[ga]=XPlanet le Hari Nair +Comment[gl]=XPlanet por Hari Nair +Comment[he]=XPlanet מאת הארי נייר +Comment[hi]=हरी नायर द्वारा एक्स-प्लेनेट +Comment[hr]=XPlanet (izr. Hari Nair) +Comment[hu]=Hari Nair XPlanetje +Comment[id]=,XPlanet by Hari Nair +Comment[is]=XPlánetur eftir Hari Nair +Comment[it]=XPlanet (di Hari Nair) +Comment[ja]=Hari Nair による XPlanet +Comment[ka]=Xპლანეტა (Hari Nair) +Comment[kk]=XPlanet (Hari Nair) +Comment[km]=XPlanet ដោយ Hari Nair +Comment[lo]=ອາວະກາດ ໂດຍ Hari Nair +Comment[lt]=Hari Nair'o XPlanet +Comment[lv]=XPlanet no Hari Nair +Comment[mk]=XПланета од Hari Nair +Comment[mn]=XPlanet +Comment[ms]=XPlanet oleh Hari Nair +Comment[mt]=XPlanet minn Hari Nair +Comment[nb]=XPlanet av Hari Nair +Comment[nds]=XPlanet vun Hari Nair +Comment[ne]=हरि नैरद्वारा X प्लानेट +Comment[nl]=XPlanet, door Hari Nair +Comment[nn]=XPlanet av Hari Nair +Comment[nso]=XPlanet ka Hari Nair +Comment[pa]=ਹੇਰੀ ਨਾਇਰ ਵਲੋਂ XPlanet +Comment[pl]=XPlanet autorstwa Hari Neir +Comment[pt]=XPlanet de Hari Nair +Comment[pt_BR]=XPlanet por Hari Nair +Comment[ro]=XPlanet de Hari Nair +Comment[ru]=XPlanet (Hari Nair) +Comment[rw]=XPlanet na Hari Nair +Comment[se]=Hari Naira XPlanet +Comment[sk]=XPlanet od Hari Nair +Comment[sl]=XPlanet Harija Naira +Comment[ss]=XPlanet ngu Hari Nair +Comment[sv]=Xplanet av Hari Nair +Comment[ta]=ஹரி நாயரின் Xப்ளானட் +Comment[tg]=XPlanet аз Hari Nair +Comment[th]=ดาวเคราะห์ โดย Hari Nair +Comment[tr]=Hari Nair'dan XPlanet +Comment[tt]=XPlanet, Hari Nair tarafınnan +Comment[uk]=XPlanet від Hari Nair +Comment[uz]=XPlanet (Xari Neyr tomonidan) +Comment[uz@cyrillic]=XPlanet (Хари Нейр томонидан) +Comment[ven]=Pulanete ya X nga Hari Nair +Comment[vi]=Hành tinh X bởi Hari Nair +Comment[wa]=XPlanete pa Hari Nair +Comment[xh]=XPlanet ngu Hari Nair +Comment[zh_CN]=Hari Nair 的 XPlanet +Comment[zh_TW]=XPlanet (Hari Nair 繪製) +Comment[zu]=XPlanet ngu-Hari Nair +Executable=xplanet +PreviewCommand=xplanet --geometry %xx%y --num_times 1 --output %f.jpg && mv %f.jpg %f +Refresh=10 diff --git a/kdesktop/startupid.cpp b/kdesktop/startupid.cpp new file mode 100644 index 000000000..6dd89b126 --- /dev/null +++ b/kdesktop/startupid.cpp @@ -0,0 +1,301 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Lubos Lunak <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <config.h> + +#include "startupid.h" +#include "tdelaunchsettings.h" + +#include <kiconloader.h> +#include <tqcursor.h> +#include <tdeapplication.h> +#include <tqimage.h> +#include <tqbitmap.h> +#include <tdeconfig.h> +#include <X11/Xlib.h> + +#define KDE_STARTUP_ICON "kmenu" + +#ifdef HAVE_XCURSOR +#include <X11/Xcursor/Xcursor.h> +#endif + +enum kde_startup_status_enum { StartupPre, StartupIn, StartupDone }; +static kde_startup_status_enum kde_startup_status = StartupPre; +static Atom kde_splash_progress; + +StartupId::StartupId( TQWidget* parent, const char* name ) + : TQWidget( parent, name ), + startup_info( TDEStartupInfo::CleanOnCantDetect ), + startup_widget( NULL ), + blinking( true ), + bouncing( false ) + { + hide(); // is TQWidget only because of x11Event() + if( kde_startup_status == StartupPre ) + { + kde_splash_progress = XInternAtom( tqt_xdisplay(), "_KDE_SPLASH_PROGRESS", False ); + XWindowAttributes attrs; + XGetWindowAttributes( tqt_xdisplay(), tqt_xrootwin(), &attrs); + XSelectInput( tqt_xdisplay(), tqt_xrootwin(), attrs.your_event_mask | SubstructureNotifyMask); + kapp->installX11EventFilter( this ); + } + connect( &update_timer, TQT_SIGNAL( timeout()), TQT_SLOT( update_startupid())); + connect( &startup_info, + TQT_SIGNAL( gotNewStartup( const TDEStartupInfoId&, const TDEStartupInfoData& )), + TQT_SLOT( gotNewStartup( const TDEStartupInfoId&, const TDEStartupInfoData& ))); + connect( &startup_info, + TQT_SIGNAL( gotStartupChange( const TDEStartupInfoId&, const TDEStartupInfoData& )), + TQT_SLOT( gotStartupChange( const TDEStartupInfoId&, const TDEStartupInfoData& ))); + connect( &startup_info, + TQT_SIGNAL( gotRemoveStartup( const TDEStartupInfoId&, const TDEStartupInfoData& )), + TQT_SLOT( gotRemoveStartup( const TDEStartupInfoId& ))); + } + +StartupId::~StartupId() + { + stop_startupid(); + } + +void StartupId::configure() + { + startup_info.setTimeout( TDELaunchSettings::timeout()); + blinking = TDELaunchSettings::blinking(); + bouncing = TDELaunchSettings::bouncing(); + } + +void StartupId::gotNewStartup( const TDEStartupInfoId& id_P, const TDEStartupInfoData& data_P ) + { + TQString icon = data_P.findIcon(); + current_startup = id_P; + startups[ id_P ] = icon; + start_startupid( icon ); + } + +void StartupId::gotStartupChange( const TDEStartupInfoId& id_P, const TDEStartupInfoData& data_P ) + { + if( current_startup == id_P ) + { + TQString icon = data_P.findIcon(); + if( !icon.isEmpty() && icon != startups[ current_startup ] ) + { + startups[ id_P ] = icon; + start_startupid( icon ); + } + } + } + +void StartupId::gotRemoveStartup( const TDEStartupInfoId& id_P ) + { + startups.remove( id_P ); + if( startups.count() == 0 ) + { + current_startup = TDEStartupInfoId(); // null + if( kde_startup_status == StartupIn ) + start_startupid( KDE_STARTUP_ICON ); + else + stop_startupid(); + return; + } + current_startup = startups.begin().key(); + start_startupid( startups[ current_startup ] ); + } + +bool StartupId::x11Event( XEvent* e ) + { + if( e->type == ClientMessage && e->xclient.window == tqt_xrootwin() + && e->xclient.message_type == kde_splash_progress ) + { + const char* s = e->xclient.data.b; + if( strcmp( s, "kicker" ) == 0 && kde_startup_status == StartupPre ) + { + kde_startup_status = StartupIn; + if( startups.count() == 0 ) + start_startupid( KDE_STARTUP_ICON ); + // 60(?) sec timeout - shouldn't be hopefully needed anyway, ksmserver should have it too + TQTimer::singleShot( 60000, this, TQT_SLOT( finishKDEStartup())); + } + else if( strcmp( s, "session ready" ) == 0 && kde_startup_status < StartupDone ) + TQTimer::singleShot( 2000, this, TQT_SLOT( finishKDEStartup())); + } + return false; + } + +void StartupId::finishKDEStartup() + { + kde_startup_status = StartupDone; + kapp->removeX11EventFilter( this ); + if( startups.count() == 0 ) + stop_startupid(); + } + +void StartupId::stop_startupid() + { + delete startup_widget; + startup_widget = NULL; + if( blinking ) + for( int i = 0; + i < NUM_BLINKING_PIXMAPS; + ++i ) + pixmaps[ i ] = TQPixmap(); // null + update_timer.stop(); + } + +static TQPixmap scalePixmap( const TQPixmap& pm, int w, int h ) +{ +#if TQT_VERSION >= 0x030200 + TQPixmap result( 20, 20, pm.depth() ); + result.setMask( TQBitmap( 20, 20, true ) ); + TQPixmap scaled( pm.convertToImage().smoothScale( w, h ) ); + copyBlt( &result, (20 - w) / 2, (20 - h) / 2, &scaled, 0, 0, w, h ); + return result; +#else + Q_UNUSED(w); + Q_UNUSED(h); + return pm; +#endif +} + +void StartupId::start_startupid( const TQString& icon_P ) + { + + const TQColor startup_colors[ StartupId::NUM_BLINKING_PIXMAPS ] + = { Qt::black, Qt::darkGray, Qt::lightGray, Qt::white, Qt::white }; + + + TQPixmap icon_pixmap = TDEGlobal::iconLoader()->loadIcon( icon_P, TDEIcon::Small, 0, + TDEIcon::DefaultState, 0, true ); // return null pixmap if not found + if( icon_pixmap.isNull()) + icon_pixmap = SmallIcon( "exec" ); + if( startup_widget == NULL ) + { + startup_widget = new TQWidget( NULL, NULL, WX11BypassWM ); + XSetWindowAttributes attr; + attr.save_under = True; // useful saveunder if possible to avoid redrawing + XChangeWindowAttributes( tqt_xdisplay(), startup_widget->winId(), CWSaveUnder, &attr ); + } + startup_widget->resize( icon_pixmap.width(), icon_pixmap.height()); + if( blinking ) + { + startup_widget->clearMask(); + int window_w = icon_pixmap.width(); + int window_h = icon_pixmap.height(); + for( int i = 0; + i < NUM_BLINKING_PIXMAPS; + ++i ) + { + pixmaps[ i ] = TQPixmap( window_w, window_h ); + pixmaps[ i ].fill( startup_colors[ i ] ); + bitBlt( &pixmaps[ i ], 0, 0, &icon_pixmap ); + } + color_index = 0; + } + else if( bouncing ) + { + startup_widget->resize( 20, 20 ); + pixmaps[ 0 ] = scalePixmap( icon_pixmap, 16, 16 ); + pixmaps[ 1 ] = scalePixmap( icon_pixmap, 14, 18 ); + pixmaps[ 2 ] = scalePixmap( icon_pixmap, 12, 20 ); + pixmaps[ 3 ] = scalePixmap( icon_pixmap, 18, 14 ); + pixmaps[ 4 ] = scalePixmap( icon_pixmap, 20, 12 ); + frame = 0; + } + else + { + if( icon_pixmap.mask() != NULL ) + startup_widget->setMask( *icon_pixmap.mask()); + else + startup_widget->clearMask(); + startup_widget->setBackgroundPixmap( icon_pixmap ); + startup_widget->erase(); + } + update_startupid(); + } + +namespace +{ +const int X_DIFF = 15; +const int Y_DIFF = 15; +const int color_to_pixmap[] = { 0, 1, 2, 3, 2, 1 }; +const int frame_to_yoffset[] = + { + -5, -1, 2, 5, 8, 10, 12, 13, 15, 15, 15, 15, 14, 12, 10, 8, 5, 2, -1, -5 + }; +const int frame_to_pixmap[] = + { + 0, 0, 0, 1, 2, 2, 1, 0, 3, 4, 4, 3, 0, 1, 2, 2, 1, 0, 0, 0 + }; +} + +void StartupId::update_startupid() + { + int yoffset = 0; + if( blinking ) + { + startup_widget->setBackgroundPixmap( pixmaps[ color_to_pixmap[ color_index ]] ); + if( ++color_index >= ( sizeof( color_to_pixmap ) / sizeof( color_to_pixmap[ 0 ] ))) + color_index = 0; + } + else if( bouncing ) + { + yoffset = frame_to_yoffset[ frame ]; + TQPixmap pm = pixmaps[ frame_to_pixmap[ frame ] ]; + startup_widget->setBackgroundPixmap( pm ); + if ( pm.mask() != NULL ) + startup_widget->setMask( *pm.mask() ); + else + startup_widget->clearMask(); + if ( ++frame >= ( sizeof( frame_to_yoffset ) / sizeof( frame_to_yoffset[ 0 ] ) ) ) + frame = 0; + } + Window dummy1, dummy2; + int x, y; + int dummy3, dummy4; + unsigned int dummy5; + if( !XQueryPointer( tqt_xdisplay(), tqt_xrootwin(), &dummy1, &dummy2, &x, &y, &dummy3, &dummy4, &dummy5 )) + { + startup_widget->hide(); + update_timer.start( 100, true ); + return; + } + TQPoint c_pos( x, y ); + int cursor_size = 0; +#ifdef HAVE_XCURSOR + cursor_size = XcursorGetDefaultSize( tqt_xdisplay()); +#endif + int X_DIFF; + if( cursor_size <= 16 ) + X_DIFF = 8 + 7; + else if( cursor_size <= 32 ) + X_DIFF = 16 + 7; + else if( cursor_size <= 48 ) + X_DIFF = 24 + 7; + else + X_DIFF = 32 + 7; + int Y_DIFF = X_DIFF; + if( startup_widget->x() != c_pos.x() + X_DIFF + || startup_widget->y() != c_pos.y() + Y_DIFF + yoffset ) + startup_widget->move( c_pos.x() + X_DIFF, c_pos.y() + Y_DIFF + yoffset ); + startup_widget->show(); + XRaiseWindow( tqt_xdisplay(), startup_widget->winId()); + update_timer.start( bouncing ? 30 : 100, true ); + TQApplication::flushX(); + } + +#include "startupid.moc" diff --git a/kdesktop/startupid.h b/kdesktop/startupid.h new file mode 100644 index 000000000..893d0b8db --- /dev/null +++ b/kdesktop/startupid.h @@ -0,0 +1,66 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Lubos Lunak <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __startup_h__ +#define __startup_h__ + +#include <sys/types.h> + +#include <tqwidget.h> +#include <tqpixmap.h> +#include <tqstring.h> +#include <tqtimer.h> +#include <tqmap.h> +#include <tdestartupinfo.h> + +class TQStyle; + +class StartupId + : public TQWidget + { + Q_OBJECT + public: + StartupId( TQWidget* parent = 0, const char* name = 0 ); + virtual ~StartupId(); + void configure(); + protected: + virtual bool x11Event( XEvent* e ); + void start_startupid( const TQString& icon ); + void stop_startupid(); + protected slots: + void update_startupid(); + void gotNewStartup( const TDEStartupInfoId& id, const TDEStartupInfoData& data ); + void gotStartupChange( const TDEStartupInfoId& id, const TDEStartupInfoData& data ); + void gotRemoveStartup( const TDEStartupInfoId& id ); + void finishKDEStartup(); + protected: + TDEStartupInfo startup_info; + TQWidget* startup_widget; + TQTimer update_timer; + TQMap< TDEStartupInfoId, TQString > startups; // TQString == pixmap + TDEStartupInfoId current_startup; + bool blinking; + bool bouncing; + unsigned int color_index; + unsigned int frame; + enum { NUM_BLINKING_PIXMAPS = 5 }; + TQPixmap pixmaps[ NUM_BLINKING_PIXMAPS ]; + }; + +#endif diff --git a/kdesktop/tdefileividesktop.cpp b/kdesktop/tdefileividesktop.cpp new file mode 100644 index 000000000..18ba4c156 --- /dev/null +++ b/kdesktop/tdefileividesktop.cpp @@ -0,0 +1,242 @@ +/* This file is proposed to be part of the KDE base. + * Copyright (C) 2003 Laur Ivan <[email protected]> + * + * Many thanks to: + * - Bernardo Hung <[email protected]> for the enhanced shadow + * algorithm (currently used) + * - Tim Jansen <[email protected]> for the API updates and fixes. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <stdio.h> + +#include <tqcolor.h> +#include <tqpalette.h> +#include <tqstring.h> +#include <tqpainter.h> +#include <tqstyle.h> +#include <kwordwrap.h> +#include <kiconview.h> +#include <kdebug.h> +#include <tdeglobalsettings.h> + +#include <kshadowengine.h> +#include "kdesktopshadowsettings.h" +#include "tdefileividesktop.h" + +//#define DEBUG + +/* Changelog: + */ + +KFileIVIDesktop::KFileIVIDesktop(KonqIconViewWidget *iconview, KFileItem* fileitem, + int size, KShadowEngine *shadow) : + KFileIVI(iconview, fileitem, size), + m_selectedImage(0L), + m_normalImage(0L), + _selectedUID(0), + _normalUID(0) +{ + m_shadow = shadow; + oldText = ""; + + calcRect( text() ); // recalculate rect including shadow +} + +KFileIVIDesktop::~KFileIVIDesktop() +{ + delete m_selectedImage; + delete m_normalImage; +} + +void KFileIVIDesktop::calcRect( const TQString& _text ) +{ + TDEIconViewItem::calcRect( _text ); + + if ( !iconView() || !m_shadow || + !wordWrap() || !( static_cast<KDesktopShadowSettings *> + ( m_shadow->shadowSettings() ) )->isEnabled() ) + return; + + int spread = shadowThickness(); + TQRect itemTextRect = textRect(); + TQRect itemRect = rect(); + + itemTextRect.setBottom( itemTextRect.bottom() + spread ); + itemTextRect.setRight( itemTextRect.right() + spread ); + itemRect.setBottom( itemRect.bottom() + spread ); + itemRect.setRight( itemRect.right() + spread ); + + setTextRect( itemTextRect ); + setItemRect( itemRect ); +} + +void KFileIVIDesktop::paintItem( TQPainter *p, const TQColorGroup &cg) +{ + TQColorGroup colors = updateColors(cg); + + TQIconView* view = iconView(); + Q_ASSERT( view ); + + if ( !view ) + return; + + if ( !wordWrap() ) + return; + + p->save(); + + // draw the pixmap as in TDEIconViewItem::paintItem(...) + paintPixmap(p, colors); + + // + // Paint the text as shadowed if the shadow is available + // + if (m_shadow != 0L && (static_cast<KDesktopShadowSettings *> (m_shadow->shadowSettings()))->isEnabled()) + drawShadowedText(p, colors); + else { + paintFontUpdate(p); + paintText(p, colors); + } + + p->restore(); + + paintOverlay(p); + paintOverlayProgressBar(p); +} + +bool KFileIVIDesktop::shouldUpdateShadow(bool selected) +{ + unsigned long uid = (static_cast<KDesktopShadowSettings *> (m_shadow->shadowSettings()))->UID(); + TQString wrapped = wordWrap()->wrappedString(); + + if (wrapped != oldText){ + oldText = wrapped; + _selectedUID = _normalUID = 0; + } + + if (selected == true) + return (uid != _selectedUID); + else + return (uid != _normalUID); + + return false; +} + + + +void KFileIVIDesktop::drawShadowedText( TQPainter *p, const TQColorGroup &cg ) +{ + bool drawRoundedRect = TDEGlobalSettings::iconUseRoundedRect(); + + int textX; + if (drawRoundedRect == true) + textX = textRect( FALSE ).x() + 4; + else + textX = textRect( FALSE ).x() + 2; + int textY = textRect( FALSE ).y(); + int align = ((TDEIconView *) iconView())->itemTextPos() == TQIconView::Bottom + ? AlignHCenter : AlignAuto; + bool rebuild = shouldUpdateShadow(isSelected()); + + KDesktopShadowSettings *settings = (KDesktopShadowSettings *) (m_shadow->shadowSettings()); + + unsigned long uid = settings->UID(); + + p->setFont(iconView()->font()); + paintFontUpdate(p); + TQColor shadow; + TQColor text; + int spread = shadowThickness(); + + if ( isSelected() && settings->selectionType() != KShadowSettings::InverseVideoOnSelection ) { + text = cg.highlightedText(); + TQRect rect = textRect( false ); + rect.setRight( rect.right() - spread ); + rect.setBottom( rect.bottom() - spread + 1 ); + if (drawRoundedRect == true) { + p->setBrush( TQBrush( cg.highlight() ) ); + p->setPen( TQPen( cg.highlight() ) ); + p->drawRoundRect( rect, + 1000 / rect.width(), + 1000 / rect.height() ); + } + else { + p->fillRect( textRect( false ), cg.highlight() ); + } + } + else { + // use shadow + if ( isSelected() ) { + // inverse text and shadow colors + shadow = settings->textColor(); + text = settings->bgColor(); + if ( rebuild ) { + setSelectedImage( buildShadow( p, align, shadow ) ); + _selectedUID = uid; + } + } + else { + text = settings->textColor(); + shadow = ( settings->bgColor().isValid() ) ? settings->bgColor() : + ( tqGray( text.rgb() ) > 127 ) ? black : white; + if (rebuild) { + setNormalImage(buildShadow(p, align, shadow)); + _normalUID = uid; + } + } + + // draw the shadow + int shadowX = textX - spread + settings->offsetX(); + int shadowY = textY - spread + settings->offsetY(); + + p->drawImage(shadowX, shadowY, + (isSelected()) ? *selectedImage() : *normalImage(), + 0, 0, -1, -1, DITHER_FLAGS); + } + + // draw the text + p->setPen(text); + wordWrap()->drawText( p, textX, textY, align | KWordWrap::Truncate ); +} + + +TQImage *KFileIVIDesktop::buildShadow( TQPainter *p, const int align, + TQColor &shadowColor ) +{ + TQPainter pixPainter; + int spread = shadowThickness(); + + TQPixmap textPixmap(textRect( FALSE ).width() + spread * 2 + 2, + textRect( FALSE ).height() + spread * 2 + 2); + + textPixmap.fill(TQColor(0,0,0)); + textPixmap.setMask( textPixmap.createHeuristicMask(TRUE) ); + + pixPainter.begin(&textPixmap); + pixPainter.setPen(white); // get the pen from the root painter + pixPainter.setFont(p->font()); // get the font from the root painter + wordWrap()->drawText( &pixPainter, spread, spread, align | KWordWrap::Truncate ); + pixPainter.end(); + + return new TQImage(m_shadow->makeShadow(textPixmap, shadowColor)); +} + +int KFileIVIDesktop::shadowThickness() const +{ + return ( ( m_shadow->shadowSettings()->thickness() + 1 ) >> 1 ) + 1; +} + diff --git a/kdesktop/tdefileividesktop.h b/kdesktop/tdefileividesktop.h new file mode 100644 index 000000000..46f77f636 --- /dev/null +++ b/kdesktop/tdefileividesktop.h @@ -0,0 +1,122 @@ +/* This file is proposed to be part of the KDE base. + * Copyright (C) 2003 Laur Ivan <[email protected]> + * + * Many thanks to: + * - Bernardo Hung <[email protected]> for the enhanced shadow + * algorithm (currently used) + * - Tim Jansen <[email protected]> for the API updates and fixes. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef TDEFILE_IVI_DESKTOP +#define TDEFILE_IVI_DESKTOP + +#include <tqcolor.h> +#include <tqpixmap.h> +#include <tqimage.h> +#include <tqstring.h> +#include <tdefileivi.h> + +/* + * The dither flags used to display the shadow image + */ +#define DITHER_FLAGS (Qt::DiffuseAlphaDither | Qt::ColorOnly | Qt::AvoidDither) + + +class TQFont; +class KShadowEngine; + +/** + * This class replaces KFileIVI in the desktop only. + * If the shadow object is NULL, then the class should behave almost identical + * to its parent. + * @since 3.2 + */ +class KFileIVIDesktop : public KFileIVI +{ + public: + /** + * Constructor. It replicates the KFileIVI constructor and adds an + * optional shadow object. + * @param iconview the parent (iconview) + * @param fileitem the item theis object is supposed to draw + * @param size the default size of the drawn object + * @param shadow reference to the shadow object + */ + KFileIVIDesktop(KonqIconViewWidget *iconview, KFileItem* fileitem, int + size, KShadowEngine *shadow = 0L); + + /** + * Default destructor. Doesn't really do anything. + */ + ~KFileIVIDesktop(); + + protected: + /** + * Reimplements TDEIconView::calcRect to take the shadow metrics + * into account + */ + virtual void calcRect( const TQString& _text ); + + /** + * Paints this item. Takes care of using the normal or alpha + * blending methods depending on the configuration. + * @param p the painter for drawing the item + * @param cg the base color group + */ + virtual void paintItem(TQPainter *p, const TQColorGroup &cg); + + /** + + * Draws the shadow text. + * @param p the painter for drawing the item + * @param cg the base color group + */ + virtual void drawShadowedText(TQPainter *p, const TQColorGroup &cg); + + /** + * Builds the shadow. As the algorithm is pretty slow (at pixel level), + * This method is triggered only if the configuration has changed. + * @param p the painter for drawing the item + * @param align the shadow alignment + * @param shadowColor the shadow color + */ + virtual TQImage *buildShadow(TQPainter *p, const int align, TQColor &shadowColor); + + protected: + void setNormalImage(TQImage *newImage) { delete m_normalImage; m_normalImage = newImage; }; + void setSelectedImage(TQImage *newImage) { delete m_selectedImage; m_selectedImage = newImage; }; + + TQImage *normalImage() { return m_normalImage; }; + TQImage *selectedImage() { return m_selectedImage; }; + + private: + bool shouldUpdateShadow(bool selected); + int shadowThickness() const; + + KShadowEngine *m_shadow; + + TQImage *m_selectedImage; + TQImage *m_normalImage; + + TQString oldText; + + unsigned long _selectedUID; + unsigned long _normalUID; + +}; + +#endif diff --git a/kdesktop/tdelaunch.kcfg b/kdesktop/tdelaunch.kcfg new file mode 100644 index 000000000..0bd19a0d2 --- /dev/null +++ b/kdesktop/tdelaunch.kcfg @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <kcfgfile name="tdelaunchrc" /> + <!-- generated by TDEConfig XTraKtor --> + + <group name="BusyCursorSettings"> + <entry key="Timeout" type="Int"> + <default>30</default> + <label></label> + <whatsthis></whatsthis> + <!-- startupid.cpp:58 --> + <!-- startup_info.setTimeout( c.readUnsignedNumEntry( "Timeout", 30 )); --> + </entry> + <entry key="Blinking" type="Bool"> + <default>false</default> + <label></label> + <whatsthis></whatsthis> + <!-- startupid.cpp:59 --> + <!-- blinking = c.readBoolEntry( "Blinking", false ); --> + </entry> + <entry key="Bouncing" type="Bool"> + <default>false</default> + <label></label> + <whatsthis></whatsthis> + <!-- startupid.cpp:60 --> + <!-- bouncing = c.readBoolEntry( "Bouncing", true ); --> + </entry> + </group> + <group name="FeedbackStyle"> + <entry key="BusyCursor" type="Bool"> + <default>false</default> + <label></label> + <whatsthis></whatsthis> + </entry> + </group> + +</kcfg> diff --git a/kdesktop/tdelaunchsettings.kcfgc b/kdesktop/tdelaunchsettings.kcfgc new file mode 100644 index 000000000..f7043920a --- /dev/null +++ b/kdesktop/tdelaunchsettings.kcfgc @@ -0,0 +1,4 @@ +File=tdelaunch.kcfg +ClassName=TDELaunchSettings +Singleton=true +Mutators=true diff --git a/kdesktop/xautolock.cc b/kdesktop/xautolock.cc new file mode 100644 index 000000000..3c7e62670 --- /dev/null +++ b/kdesktop/xautolock.cc @@ -0,0 +1,289 @@ +//---------------------------------------------------------------------------- +// +// This file is part of the KDE project +// +// Copyright (c) 1999 Martin R. Jones <[email protected]> +// Copyright (c) 2003 Lubos Lunak <[email protected]> +// +// KDE screensaver engine +// + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "xautolock.h" +#include "xautolock.moc" + +#include <tdeapplication.h> +#include <kdebug.h> + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <ctime> +#include "xautolock_c.h" + +#ifdef HAVE_DPMS +extern "C" { +#include <X11/Xmd.h> +#ifndef Bool +#define Bool BOOL +#endif +#include <X11/extensions/dpms.h> + +#ifndef HAVE_DPMSINFO_PROTO +Status DPMSInfo ( Display *, CARD16 *, BOOL * ); +#endif +} +#endif + +int xautolock_useXidle = 0; +int xautolock_useMit = 0; +xautolock_corner_t xautolock_corners[ 4 ]; + +static XAutoLock* self = NULL; + +extern "C" { +static int catchFalseAlarms(Display *, XErrorEvent *) +{ + return 0; +} +} + +//=========================================================================== +// +// Detect user inactivity. +// Named XAutoLock after the program that it is based on. +// +XAutoLock::XAutoLock() +{ + self = this; + xautolock_useXidle = 0; + xautolock_useMit = 0; +#ifdef HAVE_XIDLE + int dummy1; + xautolock_useXidle = XidleQueryExtension( tqt_xdisplay(), &dummy1, &dummy1 ); +#endif +#ifdef HAVE_XSCREENSAVER + int dummy2; + if( !xautolock_useXidle ) + xautolock_useMit = XScreenSaverQueryExtension( tqt_xdisplay(), &dummy2, &dummy2 ); +#endif + if( !xautolock_useXidle && !xautolock_useMit ) + { + kapp->installX11EventFilter( this ); + int (*oldHandler)(Display *, XErrorEvent *); + oldHandler = XSetErrorHandler(catchFalseAlarms); + XSync(tqt_xdisplay(), False ); + xautolock_initDiy( tqt_xdisplay()); + XSync(tqt_xdisplay(), False ); + XSetErrorHandler(oldHandler); + } + + mTimeout = DEFAULT_TIMEOUT; + mDPMS = true; + resetTrigger(); + + time(&mLastTimeout); + mActive = false; + + mTimerId = startTimer( CHECK_INTERVAL ); + +} + +//--------------------------------------------------------------------------- +// +// Destructor. +// +XAutoLock::~XAutoLock() +{ + self = NULL; +} + +//--------------------------------------------------------------------------- +// +// The time in seconds of continuous inactivity. +// +void XAutoLock::setTimeout(int t) +{ + mTimeout = t; + resetTrigger(); +} + +void XAutoLock::setDPMS(bool s) +{ +#ifdef HAVE_DPMS + BOOL on; + CARD16 state; + DPMSInfo( tqt_xdisplay(), &state, &on ); + if (!on) + s = false; +#endif + mDPMS = s; +} + +//--------------------------------------------------------------------------- +// +// Start watching Activity +// +void XAutoLock::start() +{ + resetTrigger(); + time(&mLastTimeout); + mActive = true; +} + +//--------------------------------------------------------------------------- +// +// Stop watching Activity +// +void XAutoLock::stop() +{ + mActive = false; +} + +//--------------------------------------------------------------------------- +// +// Reset the trigger time. +// +void XAutoLock::resetTrigger() +{ + mTrigger = time(0) + mTimeout; +} + +//--------------------------------------------------------------------------- +// +// Move the trigger time in order to postpone (repeat) emitting of timeout(). +// +void XAutoLock::postpone() +{ + mTrigger = time(0) + 60; // delay by 60sec +} + +//--------------------------------------------------------------------------- +// +// Set the remaining time to 't', if it's shorter than already set. +// +void XAutoLock::setTrigger( time_t t ) +{ + if( t < mTrigger ) + mTrigger = t; +} + +//--------------------------------------------------------------------------- +// +// Process new windows and check the mouse. +// +void XAutoLock::timerEvent(TQTimerEvent *ev) +{ + if (ev->timerId() != mTimerId) + { + return; + } + + int (*oldHandler)(Display *, XErrorEvent *) = NULL; + if( !xautolock_useXidle && !xautolock_useMit ) + { // only the diy way needs special X handler + XSync( tqt_xdisplay(), False ); + oldHandler = XSetErrorHandler(catchFalseAlarms); + } + + xautolock_processQueue(); + + time_t now = time(0); + if ((now > mLastTimeout && now - mLastTimeout > TIME_CHANGE_LIMIT) || + (mLastTimeout > now && mLastTimeout - now > TIME_CHANGE_LIMIT+1)) + { + /* the time has changed in one large jump. This could be because + the date was changed, or the machine was suspended. We'll just + reset the triger. */ + resetTrigger(); + } + + mLastTimeout = now; + + xautolock_queryIdleTime( tqt_xdisplay()); + xautolock_queryPointer( tqt_xdisplay()); + + if( !xautolock_useXidle && !xautolock_useMit ) + XSetErrorHandler(oldHandler); + + bool activate = false; + + //kdDebug() << now << " " << mTrigger << endl; + if (now >= mTrigger) + { + resetTrigger(); + activate = true; + } + +#ifdef HAVE_DPMS + BOOL on; + CARD16 state; + DPMSInfo( tqt_xdisplay(), &state, &on ); + + //kdDebug() << "DPMSInfo " << state << " " << on << endl; + // If DPMS is active, it makes XScreenSaverQueryInfo() report idle time + // that is always smaller than DPMS timeout (X bug I guess). So if DPMS + // saving is active, simply always activate our saving too, otherwise + // this could prevent locking from working. + if(state == DPMSModeStandby || state == DPMSModeSuspend || state == DPMSModeOff) + activate = true; + if(!on && mDPMS) { + activate = false; +#ifdef HAVE_XSCREENSAVER + XForceScreenSaver(tqt_xdisplay(), ScreenSaverReset ); +#endif + resetTrigger(); + } +#endif + +#ifdef HAVE_XSCREENSAVER + static XScreenSaverInfo* mitInfo = 0; + if (!mitInfo) mitInfo = XScreenSaverAllocInfo (); + if (XScreenSaverQueryInfo (tqt_xdisplay(), DefaultRootWindow (tqt_xdisplay()), mitInfo)) { + //kdDebug() << "XScreenSaverQueryInfo " << mitInfo->state << " " << ScreenSaverDisabled << endl; + if (mitInfo->state == ScreenSaverDisabled) + activate = false; + } +#endif + + if(mActive && activate) + emit timeout(); +} + +bool XAutoLock::x11Event( XEvent* ev ) +{ + xautolock_processEvent( ev ); +// don't futher process key events that were received only because XAutoLock wants them + if( ev->type == KeyPress && !ev->xkey.send_event + && !xautolock_useXidle && !xautolock_useMit + && !TQWidget::find( ev->xkey.window )) + return true; + return false; +} + +bool XAutoLock::ignoreWindow( WId w ) +{ + if( w != tqt_xrootwin() && TQWidget::find( w )) + return true; + return false; +} + +extern "C" +void xautolock_resetTriggers() +{ + self->resetTrigger(); +} + +extern "C" +void xautolock_setTrigger( time_t t ) +{ + self->setTrigger( t ); +} + +extern "C" +int xautolock_ignoreWindow( Window w ) +{ + return self->ignoreWindow( w ); +} diff --git a/kdesktop/xautolock.h b/kdesktop/xautolock.h new file mode 100644 index 000000000..5684ce6ef --- /dev/null +++ b/kdesktop/xautolock.h @@ -0,0 +1,77 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 1999 Martin R. Jones <[email protected]> +// + +#ifndef __XAUTOLOCK_H__ +#define __XAUTOLOCK_H__ + +#include <tqwidget.h> + +#include <X11/Xlib.h> + +//=========================================================================== +// +// Detect user inactivity. +// Named XAutoLock after the program that it is based on. +// +class XAutoLock : public TQWidget +{ + Q_OBJECT +public: + XAutoLock(); + ~XAutoLock(); + + //----------------------------------------------------------------------- + // + // The time in seconds of continuous inactivity. + // + void setTimeout(int t); + + void setDPMS(bool s); + + //----------------------------------------------------------------------- + // + // Start watching Activity + // + void start(); + + //----------------------------------------------------------------------- + // + // Stop watching Activity + // + void stop(); + + //----------------------------------------------------------------------- + // + // Should be called only from a slot connected to the timeout() signal. Will + // result in the timeout() signal being emitted again with a delay (i.e. postponed). + // + void postpone(); + + // internal + void resetTrigger(); + // internal + void setTrigger( time_t ); + // internal + bool ignoreWindow( WId ); + +signals: + void timeout(); + +protected: + virtual void timerEvent(TQTimerEvent *ev); + virtual bool x11Event( XEvent* ); + +protected: + int mTimerId; + int mTimeout; + time_t mTrigger; + bool mActive; + time_t mLastTimeout; + bool mDPMS; +}; + +#endif diff --git a/kdesktop/xautolock_c.h b/kdesktop/xautolock_c.h new file mode 100644 index 000000000..a53ad9377 --- /dev/null +++ b/kdesktop/xautolock_c.h @@ -0,0 +1,76 @@ +/***************************************************************************** + * + * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) + * + * Content: This file is part of version 2.x of xautolock. It takes care + * of most OS dependencies, and defines the program's default + * settings. + * + * Please send bug reports etc. to [email protected]. + * + * -------------------------------------------------------------------------- + * + * Copyright 1990,1992-1999,2001-2002 by Stefan De Troch and Michel Eyckmans. + * + * Versions 2.0 and above of xautolock are available under version 2 of the + * GNU GPL. Earlier versions are available under other conditions. For more + * information, see the License file. + * + *****************************************************************************/ + +#ifndef __xautolock_c_h +#define __xautolock_c_h + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_XSCREENSAVER +#define HasScreenSaver +#include <X11/extensions/scrnsaver.h> +#endif + +/* I'd first need to get my hands on this */ +#undef HAVE_XIDLE +#undef HasXidle + +#define DEFAULT_TIMEOUT 600 + +#define CHECK_INTERVAL 5000 /* ms */ + +#define CREATION_DELAY 30 /* should be > 10 and + < min (45,(MIN_MINUTES*30)) */ +#define TIME_CHANGE_LIMIT 120 /* if the time changes by more + than x secs then we will + assume someone has changed + date or machine has suspended */ + +#define cornerSize 5 + +#define cornerDelay 5 + +#define cornerRedelay 5 + +typedef enum { ca_nothing, ca_dontLock, ca_forceLock } xautolock_corner_t; + +#ifdef __cplusplus +extern "C" +{ +#endif +void xautolock_processEvent( XEvent* ev ); +void xautolock_queryIdleTime( Display* d); +void xautolock_processQueue( void ); +void xautolock_queryPointer (Display* d); +void xautolock_initDiy (Display* d); +void xautolock_resetTriggers( void ); +void xautolock_setTrigger( time_t ); +int xautolock_ignoreWindow( Window ); +extern int xautolock_useXidle; +extern int xautolock_useMit; +extern xautolock_corner_t xautolock_corners[ 4 ]; +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/kdesktop/xautolock_diy.c b/kdesktop/xautolock_diy.c new file mode 100644 index 000000000..b9df2f895 --- /dev/null +++ b/kdesktop/xautolock_diy.c @@ -0,0 +1,289 @@ +/***************************************************************************** + * + * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) + * + * Content: This file is part of version 2.x of xautolock. It implements + * the stuff used when the program is not using a screen saver + * extension and thus has to use the good old "do it yourself" + * approach for detecting user activity. + * + * The basic idea is that we initially traverse the window tree, + * selecting SubstructureNotify on all windows and adding each + * window to a temporary list. About +- 30 seconds later, we + * scan this list, now asking for KeyPress events. The delay + * is needed in order to interfere as little as possible with + * the event propagation mechanism. Whenever a new window is + * created by an application, a similar process takes place. + * + * Please send bug reports etc. to [email protected]. + * + * -------------------------------------------------------------------------- + * + * Copyright 1990,1992-1999,2001-2002 by Stefan De Troch and Michel Eyckmans. + * + * Versions 2.0 and above of xautolock are available under version 2 of the + * GNU GPL. Earlier versions are available under other conditions. For more + * information, see the License file. + * + *****************************************************************************/ + +#include <X11/Xlib.h> +#include <stdlib.h> +#include <time.h> + +#include "xautolock_c.h" + +static void selectEvents (Window window, Bool substructureOnly); + +/* + * Window queue management. + */ +typedef struct item +{ + Window window; + time_t creationtime; + struct item* next; +} xautolock_anItem, *xautolock_item; + +static struct +{ + Display* display; + struct item* head; + struct item* tail; +} queue; + +static void +addToQueue (Window window) +{ + xautolock_item newItem = malloc(sizeof(xautolock_anItem)); + + newItem->window = window; + newItem->creationtime = time (0); + newItem->next = 0; + + if (!queue.head) queue.head = newItem; + if ( queue.tail) queue.tail->next = newItem; + + queue.tail = newItem; +} + +static void +processQueue (time_t age) +{ + if (queue.head) + { + time_t now = time (0); + xautolock_item current = queue.head; + + while (current && current->creationtime + age < now) + { + selectEvents (current->window, False); + queue.head = current->next; + free (current); + current = queue.head; + } + + if (!queue.head) queue.tail = 0; + } +} + +/* + * Function for selecting all interesting events on a given + * (tree of) window(s). + */ +static void +selectEvents (Window window, Bool substructureOnly) +{ + Window root; /* root window of the window */ + Window parent; /* parent of the window */ + Window* children; /* children of the window */ + unsigned nofChildren = 0; /* number of children */ + unsigned i; /* loop counter */ + XWindowAttributes attribs; /* attributes of the window */ + + if( xautolock_ignoreWindow( window )) + return; + /* + * Start by querying the server about the root and parent windows. + */ + if (!XQueryTree (queue.display, window, &root, &parent, + &children, &nofChildren)) + { + return; + } + + if (nofChildren) (void) XFree ((char*) children); + + /* + * Build the appropriate event mask. The basic idea is that we don't + * want to interfere with the normal event propagation mechanism if + * we don't have to. + * + * On the root window, we need to ask for both substructureNotify + * and KeyPress events. On all other windows, we always need + * substructureNotify, but only need Keypress if some other client + * also asked for them, or if they are not being propagated up the + * window tree. + */ +#if 0 + if (substructureOnly) + { + (void) XSelectInput (queue.display, window, SubstructureNotifyMask); + } + else + { + if (parent == None) /* the *real* rootwindow */ + { + attribs.all_event_masks = + attribs.do_not_propagate_mask = KeyPressMask; + } + else if (!XGetWindowAttributes (queue.display, window, &attribs)) +#else + { + if (!XGetWindowAttributes (queue.display, window, &attribs)) +#endif + { + return; + } + +#if 0 + (void) XSelectInput (queue.display, window, + SubstructureNotifyMask + | ( ( attribs.all_event_masks + | attribs.do_not_propagate_mask) + & KeyPressMask)); +#else + { + int mask = SubstructureNotifyMask | attribs.your_event_mask; + if( !substructureOnly ) + { + mask |= ( ( attribs.all_event_masks + | attribs.do_not_propagate_mask) + & KeyPressMask ); + } + (void) XSelectInput (queue.display, window, mask ); + } +#endif + + } + + /* + * Now ask for the list of children again, since it might have changed + * in between the last time and us selecting SubstructureNotifyMask. + * + * There is a (very small) chance that we might process a subtree twice: + * child windows that have been created after our XSelectinput() has + * been processed but before we get to the XQueryTree() bit will be + * in this situation. This is harmless. It could be avoided by using + * XGrabServer(), but that'd be an impolite thing to do, and since it + * isn't required... + */ + if (!XQueryTree (queue.display, window, &root, &parent, + &children, &nofChildren)) + { + return; + } + + /* + * Now do the same thing for all children. + */ + for (i = 0; i < nofChildren; ++i) + { + selectEvents (children[i], substructureOnly); + } + + if (nofChildren) (void) XFree ((char*) children); +} + +#if 0 +/* + * Function for processing any events that have come in since + * last time. It is crucial that this function does not block + * in case nothing interesting happened. + */ +void +processEvents (void) +{ + while (XPending (queue.display)) + { + XEvent event; + + if (XCheckMaskEvent (queue.display, SubstructureNotifyMask, &event)) + { + if (event.type == CreateNotify) + { + addToQueue (event.xcreatewindow.window); + } + } + else + { + (void) XNextEvent (queue.display, &event); + } + + /* + * Reset the triggers if and only if the event is a + * KeyPress event *and* was not generated by XSendEvent(). + */ + if ( event.type == KeyPress + && !event.xany.send_event) + { + resetTriggers (); + } + } + + /* + * Check the window queue for entries that are older than + * CREATION_DELAY seconds. + */ + processQueue ((time_t) CREATION_DELAY); +} +#else +void xautolock_processEvent( XEvent* event ) +{ + if (event->type == CreateNotify) + { + addToQueue (event->xcreatewindow.window); + } + /* + * Reset the triggers if and only if the event is a + * KeyPress event *and* was not generated by XSendEvent(). + */ + if ( event->type == KeyPress + && !event->xany.send_event) + { + xautolock_resetTriggers (); + } +} + +void xautolock_processQueue() +{ + /* + * Check the window queue for entries that are older than + * CREATION_DELAY seconds. + */ + processQueue ((time_t) CREATION_DELAY); +} +#endif + + +/* + * Function for initialising the whole shebang. + */ +void +xautolock_initDiy (Display* d) +{ + int s; + + queue.display = d; + queue.tail = 0; + queue.head = 0; + + for (s = -1; ++s < ScreenCount (d); ) + { + Window root = RootWindowOfScreen (ScreenOfDisplay (d, s)); + addToQueue (root); +#if 0 + selectEvents (root, True); +#endif + } +} diff --git a/kdesktop/xautolock_engine.c b/kdesktop/xautolock_engine.c new file mode 100644 index 000000000..1825b7fe2 --- /dev/null +++ b/kdesktop/xautolock_engine.c @@ -0,0 +1,419 @@ +/***************************************************************************** + * + * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) + * + * Content: This file is part of version 2.x of xautolock. It implements + * the program's core functions. + * + * Please send bug reports etc. to [email protected]. + * + * -------------------------------------------------------------------------- + * + * Copyright 1990,1992-1999,2001-2002 by Stefan De Troch and Michel Eyckmans. + * + * Versions 2.0 and above of xautolock are available under version 2 of the + * GNU GPL. Earlier versions are available under other conditions. For more + * information, see the License file. + * + *****************************************************************************/ + +#include <X11/Xlib.h> +#include <time.h> + +#include "xautolock_c.h" + +/* + * Function for querying the idle time from the server. + * Only used if either the Xidle or the Xscreensaver + * extension is present. + */ +void +xautolock_queryIdleTime (Display* d) +{ + Time idleTime = 0; /* millisecs since last input event */ + +#ifdef HasXidle + if (xautolock_useXidle) + { + XGetIdleTime (d, &idleTime); + } + else +#endif /* HasXIdle */ + { +#ifdef HasScreenSaver + if( xautolock_useMit ) + { + static XScreenSaverInfo* mitInfo = 0; + if (!mitInfo) mitInfo = XScreenSaverAllocInfo (); + XScreenSaverQueryInfo (d, DefaultRootWindow (d), mitInfo); + idleTime = mitInfo->idle; + } + else +#endif /* HasScreenSaver */ + { + d = d; /* shut up */ + return; /* DIY */ + } + } + + if (idleTime < CHECK_INTERVAL ) + { + xautolock_resetTriggers (); + } +} + +/* + * Function for monitoring pointer movements. This implements the + * `corners' feature and as a side effect also tracks pointer + * related user activity. The latter actually is only needed when + * we're using the DIY mode of operations, but it's much simpler + * to do it unconditionally. + */ +void +xautolock_queryPointer (Display* d) +{ + Window dummyWin; /* as it says */ + int dummyInt; /* as it says */ + unsigned mask; /* modifier mask */ + int rootX; /* as it says */ + int rootY; /* as it says */ + int corner; /* corner index */ + time_t now; /* as it says */ + time_t newTrigger; /* temporary storage */ + int i; /* loop counter */ + static Window root; /* root window the pointer is on */ + static Screen* screen; /* screen the pointer is on */ + static unsigned prevMask = 0; /* as it says */ + static int prevRootX = -1; /* as it says */ + static int prevRootY = -1; /* as it says */ + static Bool firstCall = True; /* as it says */ + + /* + * Have a guess... + */ + if (firstCall) + { + firstCall = False; + root = DefaultRootWindow (d); + screen = ScreenOfDisplay (d, DefaultScreen (d)); + } + + /* + * Find out whether the pointer has moved. Using XQueryPointer for this + * is gross, but it also is the only way never to mess up propagation + * of pointer events. + */ + if (!XQueryPointer (d, root, &root, &dummyWin, &rootX, &rootY, + &dummyInt, &dummyInt, &mask)) + { + /* + * Pointer has moved to another screen, so let's find out which one. + */ + for (i = -1; ++i < ScreenCount (d); ) + { + if (root == RootWindow (d, i)) + { + screen = ScreenOfDisplay (d, i); + break; + } + } + } + + if ( rootX == prevRootX + && rootY == prevRootY + && mask == prevMask) + { + xautolock_corner_t* corners = xautolock_corners; + /* + * If the pointer has not moved since the previous call and + * is inside one of the 4 corners, we act according to the + * contents of the "corners" array. + * + * If rootX and rootY are less than zero, don't lock even if + * ca_forceLock is set in the upper-left corner. Why? 'cause + * on initial server startup, if (and only if) the pointer is + * never moved, XQueryPointer() can return values less than + * zero (only some servers, Openwindows 2.0 and 3.0 in + * particular). + */ + if ( (corner = 0, + rootX <= cornerSize && rootX >= 0 + && rootY <= cornerSize && rootY >= 0) + || (corner++, + rootX >= WidthOfScreen (screen) - cornerSize - 1 + && rootY <= cornerSize) + || (corner++, + rootX <= cornerSize + && rootY >= HeightOfScreen (screen) - cornerSize - 1) + || (corner++, + rootX >= WidthOfScreen (screen) - cornerSize - 1 + && rootY >= HeightOfScreen (screen) - cornerSize - 1)) + { + now = time (0); + + switch (corners[corner]) + { + case ca_forceLock: +#if 0 + newTrigger = now + (useRedelay ? cornerRedelay : cornerDelay) - 1; +#else + newTrigger = now; +#endif + +#if 0 + if (newTrigger < lockTrigger) + { + setLockTrigger (newTrigger - now); + } +#else + xautolock_setTrigger( newTrigger ); +#endif + break; + + case ca_dontLock: + xautolock_resetTriggers (); + +#ifdef __GNUC__ + default: ; /* Makes gcc -Wall shut up. */ +#endif /* __GNUC__ */ + } + } + } + else + { +#if 0 + useRedelay = False; +#endif + prevRootX = rootX; + prevRootY = rootY; + prevMask = mask; + + xautolock_resetTriggers (); + } +} + +#if 0 +/* + * Support for deciding whether to lock or kill. + */ +void +evaluateTriggers (Display* d) +{ + static time_t prevNotification = 0; + time_t now = 0; + + /* + * Obvious things first. + * + * The triggers are being moved all the time while in disabled + * mode in order to make absolutely sure we cannot run into + * trouble by an enable message coming in at an odd moment. + * Otherwise we possibly might lock or kill too soon. + */ + if (disabled) + { + resetTriggers (); + } + + /* + * Next, wait for (or kill, if we were so told) the previous + * locker (if any). Note that this must also be done while in + * disabled mode. Not only to avoid a potential zombie proces + * hanging around until we are re-enabled, but also to prevent + * us from incorrectly setting a kill trigger at the moment + * when we are finally re-enabled. + */ +#ifdef VMS + if (vmsStatus == 0) + { +#else /* VMS */ + if (lockerPid) + { +#if !defined (UTEKV) && !defined (SYSV) && !defined (SVR4) + union wait status; /* childs process status */ +#else /* !UTEKV && !SYSV && !SVR4 */ + int status = 0; /* childs process status */ +#endif /* !UTEKV && !SYSV && !SVR4 */ + + if (unlockNow && !disabled) + { + (void) kill (lockerPid, SIGTERM); + } + +#if !defined (UTEKV) && !defined (SYSV) && !defined (SVR4) + if (wait3 (&status, WNOHANG, 0)) +#else /* !UTEKV && !SYSV && !SVR4 */ + if (waitpid (-1, &status, WNOHANG)) +#endif /* !UTEKV && !SYSV && !SVR4 */ + { + /* + * If the locker exited normally, we disable any pending kill + * trigger. Otherwise, we assume that it either has crashed or + * was not able to lock the display because of an existing + * locker (which may have been started manually). In both of + * the later cases, disabling the kill trigger would open a + * loop hole. + */ + if ( WIFEXITED (status) + && WEXITSTATUS (status) == EXIT_SUCCESS) + { + disableKillTrigger (); + } + + useRedelay = True; + lockerPid = 0; + } +#endif /* VMS */ + + setLockTrigger (lockTime); + + /* + * No return here! The pointer may be sitting in a corner, while + * parameter settings may be such that we need to start another + * locker without further delay. If you think this cannot happen, + * consider the case in which the locker simply crashed. + */ + } + + unlockNow = False; + + /* + * Note that the above lot needs to be done even when we're in + * disabled mode, since we may have entered said mode with an + * active locker around. + */ + if (disabled) return; + + /* + * Is it time to run the killer command? + */ + now = time (0); + + if (killTrigger && now >= killTrigger) + { + /* + * There is a dirty trick here. On the one hand, we don't want + * to block until the killer returns, but on the other one + * we don't want to have it interfere with the wait() stuff we + * do to keep track of the locker. To obtain both, the killer + * command has already been patched by KillerChecker() so that + * it gets backgrounded by the shell started by system(). + * + * For the time being, VMS users are out of luck: their xautolock + * will indeed block until the killer returns. + */ + (void) system (killer); + setKillTrigger (killTime); + } + + /* + * Now trigger the notifier if required. + */ + if ( notifyLock + && now + notifyMargin >= lockTrigger + && prevNotification < now - notifyMargin - 1) + { + if (notifierSpecified) + { + /* + * Here we use the same dirty trick as for the killer command. + */ + (void) system (notifier); + } + else + { + (void) XBell (d, bellPercent); + (void) XSync (d, 0); + } + + prevNotification = now; + } + + /* + * Finally fire up the locker if time has somehow come. + */ + if ( lockNow + || now >= lockTrigger) + { +#ifdef VMS + if (vmsStatus != 0) +#else /* VMS */ + if (!lockerPid) +#endif /* VMS */ + { + switch (lockerPid = vfork ()) + { + case -1: + lockerPid = 0; + break; + + case 0: + (void) close (ConnectionNumber (d)); +#ifdef VMS + vmsStatus = 0; + lockerPid = lib$spawn ((lockNow ? &nowLockerDescr : &lockerDescr), + 0, 0, &1, 0, 0, &vmsStatus); + + if (!(lockerPid & 1)) exit (lockerPid); + +#ifdef SLOW_VMS + (void) sleep (SLOW_VMS_DELAY); +#endif /* SLOW_VMS */ +#else /* VMS */ + (void) execl ("/bin/sh", "/bin/sh", "-c", + (lockNow ? nowLocker : locker), 0); +#endif /* VMS */ + _exit (EXIT_FAILURE); + + default: + /* + * In general xautolock should keep its fingers off the real + * screensaver because no universally acceptable policy can + * be defined. In no case should it decide to disable or enable + * it all by itself. Setting the screensaver policy is something + * the locker should take care of. After all, xautolock is not + * supposed to know what the "locker" does and doesn't do. + * People might be using xautolock for totally different + * purposes (which, by the way, is why it will accept a + * different set of X resources after being renamed). + * + * Nevertheless, simply resetting the screensaver is a + * convenience action that aids many xlock users, and doesn't + * harm anyone (*). The problem with older versions of xlock + * is that they can be told to replace (= disable) the real + * screensaver, but forget to reset that same screensaver if + * it was already active at the time xlock starts. I guess + * xlock initially wasn't designed to be run without a user + * actually typing the comand ;-). + * + * (*) Well, at least it used not to harm anyone, but with the + * advent of DPMS monitors, it now can mess up the power + * saving setup. Hence we better make it optional. + * + * Also, some xlock versions also unconditionally call + * XResetScreenSaver, yielding the same kind of problems + * with DPMS that xautolock did. The latest and greatest + * xlocks also have a -resetsaver option for this very + * reason. You may want to upgrade. + */ + if (resetSaver) (void) XResetScreenSaver(d); + + setLockTrigger (lockTime); + (void) XSync (d,0); + } + + /* + * Once the locker is running, all that needs to be done is to + * set the killTrigger if needed. Notice that this must be done + * even if we actually failed to start the locker. Otherwise + * the error would "propagate" from one feature to another. + */ + if (killerSpecified) setKillTrigger (killTime); + + useRedelay = False; + } + + lockNow = False; + } +} +#endif |