diff options
| author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-09-07 19:42:15 +0000 | 
|---|---|---|
| committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-09-07 19:42:15 +0000 | 
| commit | 9cc1e2c1aa2629d499e7555acd4906d6cc989cf9 (patch) | |
| tree | 2a737f47bb029688c2f5ebef76869903cf4b4eec | |
| parent | eaa51fec106463800192924168eaf9f03f188655 (diff) | |
| download | tdebase-9cc1e2c1.tar.gz tdebase-9cc1e2c1.zip | |
Merged in remaining kdebase bugfixes from the Chakra project
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1172677 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
33 files changed, 1728 insertions, 83 deletions
| diff --git a/kcontrol/info/memory.cpp b/kcontrol/info/memory.cpp index df7bcc6fa..7bfe52948 100644 --- a/kcontrol/info/memory.cpp +++ b/kcontrol/info/memory.cpp @@ -153,10 +153,10 @@ KMemoryWidget::KMemoryWidget(TQWidget * parent, const char *name)  	    break;  	case SWAP_MEM:  	    vbox->addSpacing(SPACING); -	    title = i18n("Total swap memory:"); +	    title = i18n("Total swap space:");  	    break;  	case FREESWAP_MEM: -	    title = i18n("Free swap memory:"); +	    title = i18n("Free swap space:");  	    break;  	default:  	    title = ""; @@ -197,27 +197,26 @@ KMemoryWidget::KMemoryWidget(TQWidget * parent, const char *name)  	case MEM_RAM_AND_HDD:  	    title = i18n("Total Memory");  	    hint = i18n("This graph gives you an overview of the " -			"<b>total sum of physical and virtual memory</b> " -			"in your system."); +			"usage of <b>all available memory</b> (the sum of " +			"physical memory and swap space) in your system.");  	    break;  	case MEM_RAM:  	    title = i18n("Physical Memory");  	    hint = i18n("This graph gives you an overview of " -			"the <b>usage of physical memory</b> in your system." +			"the usage of <b>physical memory</b> in your system."  			"<p>Most operating systems (including Linux) "  			"will use as much of the available physical " -			"memory as possible as disk cache, " -			"to speed up the system performance. " -			"<p>This means that if you have a small amount " +			"memory as possible for a disk cache, " +			"to speed up the reading and writing of files. " +			"<p>This means that if you are seeing a small amount "  			"of <b>Free Physical Memory</b> and a large amount of " -			"<b>Disk Cache Memory</b>, your system is well " -			"configured."); +			"<b>Disk Cache</b>, your system is well configured.");  	    break;  	case MEM_HDD:  	    title = i18n("Swap Space"); -	    hint = i18n("The swap space is the <b>virtual memory</b> " +	    hint = i18n("Swap space is the <b>virtual memory</b> "  			"available to the system. " -			"<p>It will be used on demand and is provided " +			"<p>It will be used when needed, and is provided "  			"through one or more swap partitions and/or swap files.");  	    break;  	default: @@ -312,10 +311,10 @@ bool KMemoryWidget::Display_Graph(int widgetindex,  	last_used = *used;  #ifdef HAVE_LONG_LONG -    	percent = (((long long)last_used) * 100) / total; +	percent = (((long long)last_used) * 1000 + 5) / (total * 10);  #else  	/* prevent integer overflow with usage of double type */ -	percent = (int) ((((double)last_used) * 100) / total); +	percent = (int) ((((double)last_used) * 1000 + 5) / (total * 10));  #endif      	if (count) @@ -400,11 +399,11 @@ void KMemoryWidget::update_Values()      if (!ram_colors_initialized) {  		ram_colors_initialized = true;  		ram_text[0] = i18n("Application Data"); -		ram_colors[0] = COLOR_USED_MEMORY; /* used+shared */ +		ram_colors[0] = COLOR_USED_DATA; /* used+shared */  		ram_text[1] = i18n("Disk Buffers"); -		ram_colors[1] = TQColor(24,131,5); /* buffer */ +		ram_colors[1] = COLOR_USED_BUFFER; /* buffers */  		ram_text[2] = i18n("Disk Cache"); -		ram_colors[2] = TQColor(33,180,7); /* cached */ +		ram_colors[2] = COLOR_USED_CACHE; /* cached */  		ram_text[3] = i18n("Free Physical Memory");  		ram_colors[3] = COLOR_FREE_MEMORY; /* free */      } @@ -425,24 +424,20 @@ void KMemoryWidget::update_Values()  		      used, swap_colors, swap_text);      /* RAM + SWAP usage: */ -    if (Memory_Info[SWAP_MEM] == NO_MEMORY_INFO || -	Memory_Info[FREESWAP_MEM] == NO_MEMORY_INFO) -	    Memory_Info[SWAP_MEM] = Memory_Info[FREESWAP_MEM] = 0; -	   -    used[1] = Memory_Info[SWAP_MEM] - Memory_Info[FREESWAP_MEM]; -    used[2] = Memory_Info[FREE_MEM] + Memory_Info[FREESWAP_MEM]; -    used[0] = (Memory_Info[TOTAL_MEM]+Memory_Info[SWAP_MEM])-used[1]-used[2]; +    /* used[0] already contains the amount of used swap */ +    used[2] = Memory_Info[FREE_MEM] + ZERO_IF_NO_INFO(Memory_Info[FREESWAP_MEM]); +    used[1] = Memory_Info[TOTAL_MEM] - Memory_Info[FREE_MEM];      if (!all_colors_initialized) {  		all_colors_initialized = true; -		all_text[0] = i18n("Used Physical Memory"); -		all_colors[0] = COLOR_USED_MEMORY; /* used ram */ -		all_text[1] = i18n("Used Swap"); -		all_colors[1] = COLOR_USED_SWAP; /* used swap */ -		all_text[2] = i18n("Total Free Memory"); +		all_text[0] = i18n("Used Memory (swap part)"); +		all_colors[0] = COLOR_USED_SWAP; /* used swap */ +		all_text[1] = i18n("Used Memory (physical part)"); +		all_colors[1] = COLOR_USED_RAM; /* used ram */ +		all_text[2] = i18n("Free Memory (total)");  		all_colors[2] = COLOR_FREE_MEMORY; /* free ram+swap*/      }      Display_Graph(MEM_RAM_AND_HDD, 3, -		  ok1	? Memory_Info[TOTAL_MEM] + Memory_Info[SWAP_MEM] +		  ok1 ? Memory_Info[TOTAL_MEM] + ZERO_IF_NO_INFO(Memory_Info[SWAP_MEM])  		  	: NO_MEMORY_INFO,  		  used, all_colors, all_text);  } diff --git a/kcontrol/info/memory.h b/kcontrol/info/memory.h index 975b851f5..1387f5ac3 100644 --- a/kcontrol/info/memory.h +++ b/kcontrol/info/memory.h @@ -20,8 +20,11 @@ typedef unsigned long long t_memsize;  typedef unsigned long t_memsize;  #endif -#define COLOR_USED_MEMORY TQColor(255,0,0) -#define COLOR_USED_SWAP   TQColor(255,134,64) +#define COLOR_USED_SWAP   TQColor(255,0,0) +#define COLOR_USED_DATA   TQColor(255,180,88) +#define COLOR_USED_BUFFER TQColor(184,200,0) +#define COLOR_USED_CACHE  TQColor(156,192,0) +#define COLOR_USED_RAM    TQColor(220,200,88)  #define COLOR_FREE_MEMORY TQColor(127,255,212)  class KMemoryWidget:public KCModule { diff --git a/kdesktop/krootwm.cc b/kdesktop/krootwm.cc index 58eb78a9f..a423471bb 100644 --- a/kdesktop/krootwm.cc +++ b/kdesktop/krootwm.cc @@ -131,7 +131,10 @@ KRootWm::KRootWm(KDesktop* _desktop) : TQObject(_desktop)    if (kapp->authorize("run_command"))    {       new KAction(i18n("Run Command..."), "run", 0, m_pDesktop, TQT_SLOT( slotExecuteCommand() ), m_actionCollection, "exec" ); +     new KAction(i18n("Konsole ..." ), "terminal", CTRL+Key_T, this, TQT_SLOT( slotOpenTerminal() ), +	m_actionCollection, "open_terminal" );    } +    if (!KGlobal::config()->isImmutable())    {       new KAction(i18n("Configure Desktop..."), "configure", 0, this, TQT_SLOT( slotConfigureDesktop() ), @@ -322,6 +325,12 @@ void KRootWm::buildMenus()              file->insertSeparator();          } +        action = m_actionCollection->action("open_terminal"); +        if (action) +        { +            action->plug( file ); +        } +          action = m_actionCollection->action("lock");          if (action)              action->plug( file ); @@ -396,6 +405,10 @@ void KRootWm::buildMenus()         needSeparator = true;      } +    action = m_actionCollection->action("open_terminal"); +    if (action) +	action->plug( desktopMenu ); +      if (needSeparator)      {          desktopMenu->insertSeparator(); @@ -723,6 +736,22 @@ TQStringList KRootWm::configModules() {    return args;  } +void KRootWm::slotOpenTerminal() +{ +    // kdDebug() << "KRootWm::slotOpenTerminal" << endl; +    KProcess* p = new KProcess; +    Q_CHECK_PTR(p); + +    KConfigGroupSaver gs(KGlobal::config(), "General"); +    TQString terminal = KGlobal::config()->readPathEntry("TerminalApplication", "konsole"); + +    *p << terminal; + +    p->start(KProcess::DontCare); + +    delete p; +} +  void KRootWm::slotConfigureDesktop() {    if (!m_configDialog)    { diff --git a/kdesktop/krootwm.h b/kdesktop/krootwm.h index 960d0e53c..007da9bf3 100644 --- a/kdesktop/krootwm.h +++ b/kdesktop/krootwm.h @@ -119,6 +119,7 @@ public slots:    void slotPopulateSessions();    void slotSessionActivated( int );    void slotNewSession(); +  void slotOpenTerminal();    void slotLockNNewSession();  private: diff --git a/kmenuedit/kcontroleditui.rc b/kmenuedit/kcontroleditui.rc index 18bc04fcb..8e621a98a 100644 --- a/kmenuedit/kcontroleditui.rc +++ b/kmenuedit/kcontroleditui.rc @@ -8,6 +8,7 @@   <Action name="newsubmenu" />   <Separator/>   <Action name="file_save"/> + <Action name="file_save_and_quit"/>    <Separator/>   <Action name="file_quit"/>  </Menu> diff --git a/kmenuedit/kmenuedit.cpp b/kmenuedit/kmenuedit.cpp index 9474d85eb..37ab13676 100644 --- a/kmenuedit/kmenuedit.cpp +++ b/kmenuedit/kmenuedit.cpp @@ -67,6 +67,8 @@ void KMenuEdit::setupActions()      if (!m_controlCenter)         (void)new KAction(i18n("New S&eparator"), "menu_new_sep", 0, actionCollection(), "newsep"); +    (void)new KAction(i18n("Save && Quit"), "filesave_and_close", 0, this, TQT_SLOT( slotSave_and_close()), actionCollection(), "file_save_and_quit"); +      m_actionDelete = 0;      KStdAction::save(this, TQT_SLOT( slotSave() ), actionCollection()); @@ -141,6 +143,12 @@ void KMenuEdit::slotSave()      m_tree->save();  } +void KMenuEdit::slotSave_and_close() +{ +    if (m_tree->save()) +        close(); +} +  bool KMenuEdit::queryClose()  {      if (!m_tree->dirty()) return true; diff --git a/kmenuedit/kmenuedit.h b/kmenuedit/kmenuedit.h index 08c89a6be..bc9bd13c1 100644 --- a/kmenuedit/kmenuedit.h +++ b/kmenuedit/kmenuedit.h @@ -46,6 +46,7 @@ protected:  protected slots:      void slotSave(); +    void slotSave_and_close();      void slotChangeView();      void slotConfigureToolbars();  protected: diff --git a/kmenuedit/kmenueditui.rc b/kmenuedit/kmenueditui.rc index 66330e740..eb8c3ae00 100644 --- a/kmenuedit/kmenueditui.rc +++ b/kmenuedit/kmenueditui.rc @@ -9,6 +9,7 @@   <Action name="newsep" />   <Separator/>   <Action name="file_save"/> + <Action name="file_save_and_quit"/>   <Separator/>   <Action name="file_quit"/>  </Menu> diff --git a/kmenuedit/pixmaps/cr22-action-filesave_and_close.png b/kmenuedit/pixmaps/cr22-action-filesave_and_close.pngBinary files differ new file mode 100644 index 000000000..7d4b6f365 --- /dev/null +++ b/kmenuedit/pixmaps/cr22-action-filesave_and_close.png diff --git a/konsole/konsole/TEmulation.cpp b/konsole/konsole/TEmulation.cpp index 8dd6da437..39aeab542 100644 --- a/konsole/konsole/TEmulation.cpp +++ b/konsole/konsole/TEmulation.cpp @@ -395,6 +395,11 @@ void TEmulation::copySelection() {    TQApplication::clipboard()->setText(t);  } +TQString TEmulation::getSelection() { +  if (connected) return scr->getSelText(true); +  return TQString::null; +} +  void TEmulation::streamHistory(TQTextStream* stream) {    scr->streamHistory(stream);  } diff --git a/konsole/konsole/TEmulation.h b/konsole/konsole/TEmulation.h index 7d3ba65d6..a5f432175 100644 --- a/konsole/konsole/TEmulation.h +++ b/konsole/konsole/TEmulation.h @@ -59,6 +59,7 @@ public slots: // signals incoming from TEWidget    virtual void clearSelection();    virtual void copySelection(); +  virtual TQString getSelection();    virtual void onSelectionBegin(const int x, const int y, const bool columnmode);    virtual void onSelectionExtend(const int x, const int y);    virtual void setSelection(const bool preserve_line_breaks); diff --git a/konsole/konsole/konsole.cpp b/konsole/konsole/konsole.cpp index 9c292daa2..e8dacbe5e 100644 --- a/konsole/konsole/konsole.cpp +++ b/konsole/konsole/konsole.cpp @@ -114,6 +114,7 @@ Time to start a requirement list.  #include <knotifydialog.h>  #include <kprinter.h>  #include <kaccelmanager.h> +#include <kurifilter.h>  #include <kaction.h>  #include <kshell.h> @@ -268,6 +269,7 @@ Konsole::Konsole(const char* name, int histon, bool menubaron, bool tabbaron, bo  ,sessionNumberMapper(0)  ,sl_sessionShortCuts(0)  ,s_workDir(workdir) +,m_filterData(0)  {    isRestored = b_inRestore;    connect( &m_closeTimeout, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotCouldNotClose())); @@ -346,6 +348,8 @@ Konsole::Konsole(const char* name, int histon, bool menubaron, bool tabbaron, bo  Konsole::~Konsole()  { +    delete m_filterData; +      sessions.first();      while(sessions.current())      { @@ -718,6 +722,11 @@ void Konsole::makeGUI()        m_copyClipboard->plug(m_rightButton);        m_pasteClipboard->plug(m_rightButton); + +      m_openSelection = new KPopupMenu(this); +      m_rightButton->insertItem( i18n("&Open.."), m_openSelection ); +      connect(m_openSelection, TQT_SIGNAL(aboutToShow()), TQT_SLOT(slotOpenSelection())); +        if (m_signals)           m_rightButton->insertItem(i18n("&Send Signal"), m_signals); @@ -3950,6 +3959,34 @@ void Konsole::slotFindHistory()    m_finddialog->result();  } +void Konsole::slotOpenSelection() +{ +  delete m_filterData; + +  m_openSelection->clear(); +  disconnect(m_openSelection, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotOpenURI(int))); + +  TQString selection = se->getEmulation()->getSelection(); +  TQString curdir = baseURL().path(); + +  if ( TQFile::exists( curdir + selection ) ) { +     selectedURL = TQString(curdir + selection); +  } else { +     selectedURL = TQString(selection); +  } + +  m_filterData = new KURIFilterData( selectedURL ); +  KURIFilter::self()->filterURI( *(m_filterData) ); +  m_openSelection->insertItem( SmallIconSet( m_filterData->iconName() ),i18n( "%1" ).arg(m_filterData->uri().url()), 1 ); + +  connect(m_openSelection, TQT_SIGNAL(activated(int)), TQT_SLOT(slotOpenURI(int))); +} + +void Konsole::slotOpenURI(int) +{ +  (void) new KRun( m_filterData->uri() ); +} +  void Konsole::slotFindNext()  {    if( !m_finddialog ) { diff --git a/konsole/konsole/konsole.h b/konsole/konsole/konsole.h index 5b6702412..4ca704a9b 100644 --- a/konsole/konsole/konsole.h +++ b/konsole/konsole/konsole.h @@ -61,6 +61,7 @@ class KSelectAction;  class KRadioAction;  class KTabWidget;  class TQToolButton; +class KURIFilterData;  // Defined in main.C  const char *konsole_shell(TQStrList &args); @@ -200,6 +201,9 @@ private slots:    void loadScreenSessions();    void updateFullScreen(bool on); +  void slotOpenSelection(); +  void slotOpenURI(int n); +    void slotSaveSettings();    void slotSaveSessionsProfile();    void slotConfigureNotifications(); @@ -362,6 +366,7 @@ private:    KAction       *m_print;    KAction       *m_quit;    KAction       *m_tabDetachSession; +  KPopupMenu    *m_openSelection;    KActionCollection *m_shortcuts; @@ -372,6 +377,7 @@ private:    bool         m_find_first;    bool         m_find_found;    TQString      m_find_pattern; +  TQString  selectedURL;    int cmd_serial;    int cmd_first_screen; @@ -435,6 +441,7 @@ private:    TQString  s_workDir;    TQColor    m_tabColor; +  KURIFilterData* m_filterData;  };  class TQSpinBox; diff --git a/ksmserver/legacy.cpp b/ksmserver/legacy.cpp index a8f439745..773cd514d 100644 --- a/ksmserver/legacy.cpp +++ b/ksmserver/legacy.cpp @@ -220,7 +220,7 @@ void KSMServer::storeLegacySession( KConfig* config )      for (WindowMap::ConstIterator it = legacyWindows.begin(); it != legacyWindows.end(); ++it) {          if ( (*it).type != SM_ERROR) {              if( excludeApps.contains( (*it).wmclass1.lower()) -                || excludeApps.contains( (*it).wmclass2.lower())) +                || excludeApps.contains( (*it).wmclass2.lower()) || (*it).wmCommand[0] == "compiz" || (*it).wmCommand[0] == "beryl" || (*it).wmCommand[0] == "aquamarine" || (*it).wmCommand[0] == "beryl-manager" || (*it).wmCommand[0] == "beryl-settings" || (*it).wmCommand[0] == "kde-window-decorator" || (*it).wmCommand[0] == "emerald")                  continue;              if ( !(*it).wmCommand.isEmpty() && !(*it).wmClientMachine.isEmpty() ) {                  count++; diff --git a/ksysguard/ksysguardd/Linux/netdev.c b/ksysguard/ksysguardd/Linux/netdev.c index 867678642..bba927e19 100644 --- a/ksysguard/ksysguardd/Linux/netdev.c +++ b/ksysguard/ksysguardd/Linux/netdev.c @@ -35,65 +35,85 @@  #define MON_SIZE	128 -#define CALC( a, b, c, d, e ) \ +#define CALC( a, b, c, d, e, f ) \  { \ -  NetDevs[ i ].a = a - NetDevs[ i ].Old##a; \ -  NetDevs[ i ].Old##a = a; \ +  if (f){ \ +    NetDevs[ i ].a = a - NetDevs[ i ].Old##a; \ +    NetDevs[ i ].Old##a = a; \ +  } \ +  else{ \ +    NetDevs[ i ].a = a; \ +  } \  } -#define REGISTERSENSOR( a, b, c, d, e ) \ +#define REGISTERSENSOR( a, b, c, d, e, f ) \  { \    snprintf( mon, MON_SIZE, "network/interfaces/%s/%s", tag, b ); \    registerMonitor( mon, "integer", printNetDev##a, printNetDev##a##Info, NetDevSM ); \  } -#define UNREGISTERSENSOR( a, b, c, d, e ) \ +#define UNREGISTERSENSOR( a, b, c, d, e, f ) \  { \    snprintf( mon, MON_SIZE, "network/interfaces/%s/%s", NetDevs[ i ].name, b ); \    removeMonitor( mon ); \  } -#define DEFMEMBERS( a, b, c, d, e ) \ -unsigned long long Old##a; \ -unsigned long long a; \ -unsigned long a##Scale; +#define DEFMEMBERS( a, b, c, d, e, f ) \ +signed long long Old##a; \ +signed long long a; \ +signed long a##Scale; -#define DEFVARS( a, b, c, d, e ) \ -unsigned long long a; +#define DEFVARS( a, b, c, d, e, f ) \ +signed long long a; + +/*The sixth variable is 1 if the quantity variation must be provided, 0 if the absolute value must be provided */  #define FORALL( a ) \ -  a( recBytes, "receiver/data", "Received Data", "kBytes/s", 1024 ) \ -  a( recPacks, "receiver/packets", "Received Packets", "1/s", 1 ) \ -  a( recErrs, "receiver/errors", "Receiver Errors", "1/s", 1 ) \ -  a( recDrop, "receiver/drops", "Receiver Drops", "1/s", 1 ) \ -  a( recFifo, "receiver/fifo", "Receiver FIFO Overruns", "1/s", 1 ) \ -  a( recFrame, "receiver/frame", "Receiver Frame Errors", "1/s", 1 ) \ -  a( recCompressed, "receiver/compressed", "Received Compressed Packets", "1/s", 1 ) \ -  a( recMulticast, "receiver/multicast", "Received Multicast Packets", "1/s", 1 ) \ -  a( sentBytes, "transmitter/data", "Sent Data", "kBytes/s", 1024 ) \ -  a( sentPacks, "transmitter/packets", "Sent Packets", "1/s", 1 ) \ -  a( sentErrs, "transmitter/errors", "Transmitter Errors", "1/s", 1 ) \ -  a( sentDrop, "transmitter/drops", "Transmitter Drops", "1/s", 1 ) \ -  a( sentFifo, "transmitter/fifo", "Transmitter FIFO overruns", "1/s", 1 ) \ -  a( sentColls, "transmitter/collisions", "Transmitter Collisions", "1/s", 1 ) \ -  a( sentCarrier, "transmitter/carrier", "Transmitter Carrier losses", "1/s", 1 ) \ -  a( sentCompressed, "transmitter/compressed", "Transmitter Compressed Packets", "1/s", 1 ) - -#define SETZERO( a, b, c, d, e ) \ +  a( recBytes, "receiver/data", "Received Data", "kBytes/s", 1024, 1) \ +  a( recPacks, "receiver/packets", "Received Packets", "1/s", 1, 1 ) \ +  a( recErrs, "receiver/errors", "Receiver Errors", "1/s", 1, 1 ) \ +  a( recDrop, "receiver/drops", "Receiver Drops", "1/s", 1, 1 ) \ +  a( recFifo, "receiver/fifo", "Receiver FIFO Overruns", "1/s", 1, 1 ) \ +  a( recFrame, "receiver/frame", "Receiver Frame Errors", "1/s", 1, 1 ) \ +  a( recCompressed, "receiver/compressed", "Received Compressed Packets", "1/s", 1, 1 ) \ +  a( recMulticast, "receiver/multicast", "Received Multicast Packets", "1/s", 1, 1 ) \ +  a( sentBytes, "transmitter/data", "Sent Data", "kBytes/s", 1024, 1 ) \ +  a( sentPacks, "transmitter/packets", "Sent Packets", "1/s", 1, 1 ) \ +  a( sentErrs, "transmitter/errors", "Transmitter Errors", "1/s", 1, 1 ) \ +  a( sentDrop, "transmitter/drops", "Transmitter Drops", "1/s", 1, 1 ) \ +  a( sentFifo, "transmitter/fifo", "Transmitter FIFO overruns", "1/s", 1, 1 ) \ +  a( sentColls, "transmitter/collisions", "Transmitter Collisions", "1/s", 1, 1 ) \ +  a( sentCarrier, "transmitter/carrier", "Transmitter Carrier losses", "1/s", 1, 1 ) \ +  a( sentCompressed, "transmitter/compressed", "Transmitter Compressed Packets", "1/s", 1, 1 ) + +#define FORALLWIFI( a ) \ + a( linkQuality, "wifi/quality", "Link Quality", "", 1, 0) \ + a( signalLevel, "wifi/signal", "Signal Level", "dBm", 1, 0) \ + a( noiseLevel, "wifi/noise", "Noise Level", "dBm", 1, 0) \ + a( nwid, "wifi/nwid", "Rx Invalid Nwid Packets", "1/s", 1, 1) \ + a( RxCrypt, "wifi/crypt", "Rx Invalid Crypt Packets", "1/s", 1, 1) \ + a( frag, "wifi/frag", "Rx Invalid Frag Packets", "1/s", 1, 1) \ + a( retry, "wifi/retry", "Tx Excessive Retries Packets", "1/s", 1, 1) \ + a( misc, "wifi/misc", "Invalid Misc Packets", "1/s", 1, 1) \ + a( beacon, "wifi/beacon", "Missed Beacon", "1/s", 1, 1) + +#define SETZERO( a, b, c, d, e, f ) \  a = 0; -#define SETMEMBERZERO( a, b, c, d, e ) \ +#define SETMEMBERZERO( a, b, c, d, e, f ) \  NetDevs[ i ].a = 0; \  NetDevs[ i ].a##Scale = e; -#define DECLAREFUNC( a, b, c, d, e ) \ +#define DECLAREFUNC( a, b, c, d, e, f ) \  void printNetDev##a( const char* cmd ); \  void printNetDev##a##Info( const char* cmd );  typedef struct  {    FORALL( DEFMEMBERS ) +  FORALLWIFI( DEFMEMBERS )    char name[ 32 ]; +  int wifi;  } NetDevInfo;  /* We have observed deviations of up to 5% in the accuracy of the timer @@ -106,6 +126,7 @@ static struct SensorModul* NetDevSM;  #define NETDEVBUFSIZE 4096  static char NetDevBuf[ NETDEVBUFSIZE ]; +static char NetDevWifiBuf[ NETDEVBUFSIZE ];  static int NetDevCnt = 0;  static int Dirty = 0;  static int NetDevOk = 0; @@ -117,15 +138,17 @@ static NetDevInfo NetDevs[ MAXNETDEVS ];  void processNetDev( void );  FORALL( DECLAREFUNC ) +FORALLWIFI( DECLAREFUNC )  static int processNetDev_( void )  { -  int i; +  int i,j;    char format[ 32 ];    char devFormat[ 16 ];    char buf[ 1024 ];    char tag[ 64 ];    char* netDevBufP = NetDevBuf; +  char* netDevWifiBufP = NetDevWifiBuf;    sprintf( format, "%%%d[^\n]\n", (int)sizeof( buf ) - 1 );    sprintf( devFormat, "%%%ds", (int)sizeof( tag ) - 1 ); @@ -147,8 +170,8 @@ static int processNetDev_( void )          FORALL( DEFVARS );          *pos = '\0';          FORALL( SETZERO ); -        sscanf( buf + 7, "%llu %llu %llu %llu %llu %llu %llu %llu "  -                "%llu %llu %llu %llu %llu %llu %llu %llu", +        sscanf( buf + 7, "%lli %lli %lli %lli %lli %lli %lli %lli "  +                "%lli %lli %lli %lli %lli %lli %lli %lli",                  &recBytes, &recPacks, &recErrs, &recDrop, &recFifo,                  &recFrame, &recCompressed, &recMulticast,                  &sentBytes, &sentPacks, &sentErrs, &sentDrop, @@ -168,6 +191,44 @@ static int processNetDev_( void )    if ( i != NetDevCnt )      return -1; +  /*Update the values for the wifi interfaces*/ +  if ( *netDevWifiBufP=='\0')  /*there is no /proc/net/wireless file*/ +    return 0; + +  /* skip 2 first lines */ +  for ( i = 0; i < 2; i++ ) { +    sscanf( netDevWifiBufP, format, buf ); +    buf[ sizeof( buf ) - 1 ] = '\0'; +    netDevWifiBufP += strlen( buf ) + 1;  /* move netDevWifiBufP to next line */ +  } + +  for ( j = 0; sscanf( netDevWifiBufP, format, buf ) == 1; ++j ) { +    buf[ sizeof( buf ) - 1 ] = '\0'; +    netDevWifiBufP += strlen( buf ) + 1;  /* move netDevWifiBufP to next line */ + +    if ( sscanf( buf, devFormat, tag ) ) { +      char* pos = strchr( tag, ':' ); +      if ( pos ) { +        FORALLWIFI( DEFVARS ); +        *pos = '\0'; + +       for (i = 0 ; i < NetDevCnt ; ++i){ /*find the corresponding interface*/ +           if ( strcmp(tag,NetDevs[ i ].name)==0){ +               break; +           } +        } +       sscanf( buf + 12, " %lli. %lli. %lli. %lli %lli %lli %lli %lli %lli", +                &linkQuality, &signalLevel, &noiseLevel, &nwid, +                &RxCrypt, &frag,  &retry, &misc, &beacon ); +       signalLevel -= 256; /*the units are dBm*/ +       noiseLevel -= 256; +        FORALLWIFI( CALC ); +      } +    } +  } + + +    /* save exact time inverval between this and the last read of     * /proc/net/dev */    timeInterval = currSampling.tv_sec - lastSampling.tv_sec + @@ -200,12 +261,13 @@ void processNetDev( void )  void initNetDev( struct SensorModul* sm )  { -  int i; +  int i,j;    char format[ 32 ];    char devFormat[ 16 ];    char buf[ 1024 ];    char tag[ 64 ];    char* netDevBufP = NetDevBuf; +  char* netDevWifiBufP = NetDevWifiBuf;    NetDevSM = sm; @@ -233,8 +295,8 @@ void initNetDev( struct SensorModul* sm )          *pos = '\0';          strlcpy( NetDevs[ i ].name, tag, sizeof( NetDevs[ i ].name ) );          FORALL( REGISTERSENSOR ); -        sscanf( pos + 1, "%llu %llu %llu %llu %llu %llu %llu %llu"  -                "%llu %llu %llu %llu %llu %llu %llu %llu", +        sscanf( pos + 1, "%lli %lli %lli %lli %lli %lli %lli %lli"  +                "%lli %lli %lli %lli %lli %lli %lli %lli",                  &NetDevs[ i ].recBytes, &NetDevs[ i ].recPacks,                  &NetDevs[ i ].recErrs, &NetDevs[ i ].recDrop,                  &NetDevs[ i ].recFifo, &NetDevs[ i ].recFrame, @@ -247,6 +309,39 @@ void initNetDev( struct SensorModul* sm )  			}        FORALL( SETMEMBERZERO );      } + +  } + +  /* detect the wifi interfaces*/ +   /* skip 2 first lines */ +  for ( i = 0; i < 2; i++ ) { +    sscanf( netDevWifiBufP, format, buf ); +    buf[ sizeof( buf ) - 1 ] = '\0'; +    netDevWifiBufP += strlen( buf ) + 1;  /* move netDevWifiBufP to next line */ +  } + +  for ( j = 0; sscanf( netDevWifiBufP, format, buf ) == 1; ++j ) { +    buf[ sizeof( buf ) - 1 ] = '\0'; +    netDevWifiBufP += strlen( buf ) + 1;  /* move netDevWifiBufP to next line */ + +    if ( sscanf( buf, devFormat, tag ) ) { +      char * pos = strchr( tag, ':' ); +      if ( pos ) { +        char mon[ MON_SIZE ]; +        *pos = '\0'; +       /*find and tag the corresponding NetDev as wifi enabled. +        At the end of the loop,  i is the index of the device.  +        This variable i is used in some macro */ +       for (i = 0 ; i < NetDevCnt ; ++i){  +           if ( strcmp(tag,NetDevs[ i ].name)==0){ +               NetDevs[ i ].wifi = 1; +               break; +           } +        } +        FORALLWIFI( REGISTERSENSOR ); +      } +      FORALLWIFI( SETMEMBERZERO );  /* the variable i must point to the corrrect NetDevs[i]*/ +    }    }    /* Call processNetDev to elimitate initial peek values. */ @@ -260,6 +355,8 @@ void exitNetDev( void )    for ( i = 0; i < NetDevCnt; ++i ) {      char mon[ MON_SIZE ];      FORALL( UNREGISTERSENSOR ); +    if (NetDevs[ i ].wifi) +       FORALLWIFI( UNREGISTERSENSOR );    }    NetDevCnt = 0;  } @@ -320,6 +417,20 @@ int updateNetDev( void )    Dirty = 1; +  /* We read the informations about the wifi from /proc/net/wireless and store it into NetDevWifiBuf */ +  if ( ( fd = open( "/proc/net/wireless", O_RDONLY ) ) < 0 ) { +    /* /proc/net/wireless may not exist on some machines. */ +    NetDevWifiBuf[0]='\0'; +  } + +  if ( ( n = read( fd, NetDevWifiBuf, NETDEVBUFSIZE - 1 ) ) == NETDEVBUFSIZE - 1 ) { +    log_error( "Internal buffer too small to read \'/proc/net/wireless\'" ); +    close( fd ); +    return -1; +  } +  close( fd ); +  NetDevWifiBuf[ n ] = '\0'; +    return 0;  } @@ -331,7 +442,7 @@ void checkNetDev( void )    initNetDev( NetDevSM );  } -#define PRINTFUNC( a, b, c, d, e ) \ +#define PRINTFUNC( a, b, c, d, e, f ) \  void printNetDev##a( const char* cmd ) \  { \    int i; \ @@ -350,8 +461,11 @@ void printNetDev##a( const char* cmd ) \   \    for ( i = 0; i < MAXNETDEVS; ++i ) \      if ( strcmp( NetDevs[ i ].name, dev ) == 0) { \ -      fprintf( CurrentClient, "%lu\n", (unsigned long) \ +      if (f) \ +         fprintf( CurrentClient, "%li\n", (long) \                 ( NetDevs[ i ].a / ( NetDevs[ i ].a##Scale * timeInterval ) ) ); \ +      else \ +         fprintf( CurrentClient, "%li\n", (long) NetDevs[ i ].a ); \        return; \      } \   \ @@ -365,3 +479,4 @@ void printNetDev##a##Info( const char* cmd ) \  }  FORALL( PRINTFUNC ) +FORALLWIFI( PRINTFUNC ) diff --git a/kwin/KWinInterface.h b/kwin/KWinInterface.h index eff3a88f2..2af0d03ff 100644 --- a/kwin/KWinInterface.h +++ b/kwin/KWinInterface.h @@ -23,6 +23,9 @@ class KWinInterface : virtual public DCOPObject      virtual void nextDesktop() = 0;      virtual void previousDesktop() = 0;      virtual void circulateDesktopApplications() = 0; +    virtual void updateOverlappingShadows(unsigned long window) = 0; +    virtual void setShadowed(unsigned long window, bool shadowed) = 0; +      // kompmgr stuff      virtual void startKompmgr() = 0;      virtual void stopKompmgr() = 0; diff --git a/kwin/activation.cpp b/kwin/activation.cpp index f80a00f9a..c0f578634 100644 --- a/kwin/activation.cpp +++ b/kwin/activation.cpp @@ -227,6 +227,13 @@ void Workspace::setActiveClient( Client* c, allowed_t )          active_client->setActive( false, !c || !c->isModal() || c != active_client->transientFor() );          }      active_client = c; +    if (set_active_client_recursion == 1) +        { +        // Only unset next_active_client if activateClient() wasn't called by +        // Client::setActive() to set the active window to null before +        // activating another window. +        next_active_client = NULL; +        }      Q_ASSERT( c == NULL || c->isActive());      if( active_client != NULL )          last_active_client = active_client; @@ -324,6 +331,7 @@ void Workspace::takeActivity( Client* c, int flags, bool handled )          Client* modal = c->findModal();          if( modal != NULL && modal != c )	              {  +            next_active_client = modal;              if( !modal->isOnDesktop( c->desktop()))                  {                  modal->setDesktop( c->desktop()); @@ -351,11 +359,14 @@ void Workspace::takeActivity( Client* c, int flags, bool handled )              c->setActive( true );              focusToNull();              } +	if( c->wantsInput()) +	    next_active_client = c;          flags &= ~ActivityFocus;          handled = false; // no point, can't get clicks          }      if( !c->isShown( true )) // shouldn't happen, call activateClient() if needed          { +	next_active_client = c;          kdWarning( 1212 ) << "takeActivity: not shown" << endl;          return;          } @@ -856,7 +867,45 @@ void Client::setActive( bool act, bool updateOpacity_)      updateShadowSize();      if ( active ) +    {          Notify::raise( Notify::Activate ); +        if (options->shadowEnabled(true)) +            { +            if (options->shadowEnabled(false)) +                { +                // Wait for inactive shadow to expose occluded windows and give +                // them a chance to redraw before painting the active shadow +                removeShadow(); +                drawDelayedShadow(); +                if (!isDesktop() && +                       this != workspace()->topClientOnDesktop(desktop())) +                    // If the newly activated window's isn't the desktop, wait +                    // for its shadow to draw, then redraw any shadows +                    // overlapping it. +                    drawOverlappingShadows(true); +                } +            else +                drawShadow(); +            } +        } +    else +        { +        removeShadow(); + +        if (options->shadowEnabled(false)) +            if (this == workspace()->topClientOnDesktop(desktop())) +                { +                /* If the newly deactivated window is the top client on the +                 * desktop, then the newly activated window is below it; ensure +                 * that the deactivated window's shadow draws after the +                 * activated window's shadow. +                 */ +                if ((shadowAfterClient = workspace()->activeClient())) +                    drawShadowAfter(shadowAfterClient); +                } +            else +                drawDelayedShadow(); +        }      if( !active )          cancelAutoRaise(); diff --git a/kwin/client.cpp b/kwin/client.cpp index 5f281f2ab..0d2c5cfbf 100644 --- a/kwin/client.cpp +++ b/kwin/client.cpp @@ -11,9 +11,12 @@ License. See the file "COPYING" for the exact licensing terms.  #include "client.h" +#include <math.h> +  #include <tqapplication.h>  #include <tqpainter.h>  #include <tqdatetime.h> +#include <tqimage.h>  #include <kprocess.h>  #include <unistd.h>  #include <kstandarddirs.h> @@ -39,9 +42,25 @@ extern Time qt_x_time;  extern Atom qt_window_role;  extern Atom qt_sm_client_id; +// wait 200 ms before drawing shadow after move/resize +static const int SHADOW_DELAY = 200; +  namespace KWinInternal  { +/* TODO: Remove this once X has real translucency. + * + * A list of the regions covered by all shadows and the Clients to which they + * belong. Used to redraw shadows when a window overlapping or underlying a + * shadow is moved, resized, or hidden. + */ +struct ShadowRegion +    { +    TQRegion region; +    Client *client; +    }; +static TQValueList<ShadowRegion> shadowRegions; +  /*   Creating a client: @@ -100,6 +119,13 @@ Client::Client( Workspace *ws )      autoRaiseTimer = 0;      shadeHoverTimer = 0; +    shadowDelayTimer = new TQTimer(this); +    opacityCache = &activeOpacityCache; +    shadowAfterClient = NULL; +    shadowWidget = NULL; +    shadowMe = true; +    connect(shadowDelayTimer, TQT_SIGNAL(timeout()), TQT_SLOT(drawShadow())); +      // set the initial mapping state      mapping_state = WithdrawnState;      desk = 0; // no desktop yet @@ -145,7 +171,7 @@ Client::Client( Workspace *ws )      maxmode_restore = MaximizeRestore;      cmap = None; -     +      frame_geometry = TQRect( 0, 0, 100, 100 ); // so that decorations don't start with size being (0,0)      client_size = TQSize( 100, 100 );      custom_opacity = false; @@ -188,6 +214,8 @@ void Client::releaseWindow( bool on_shutdown )      if (!custom_opacity) setOpacity(FALSE);      if (moveResizeMode)         leaveMoveResize(); +    removeShadow(); +    drawIntersectingShadows();      finishWindowRules();      ++postpone_geometry_updates;      // grab X during the release to make removing of properties, setting to withdrawn state @@ -248,6 +276,8 @@ void Client::destroyClient()      StackingUpdatesBlocker blocker( workspace());      if (moveResizeMode)         leaveMoveResize(); +    removeShadow(); +    drawIntersectingShadows();      finishWindowRules();      ++postpone_geometry_updates;      setModal( false ); @@ -304,6 +334,7 @@ void Client::updateDecoration( bool check_workspace_pos, bool force )      if( do_show )          decoration->widget()->show();      updateFrameExtents(); +    updateOpacityCache();      }  void Client::destroyDecoration() @@ -434,6 +465,12 @@ void Client::resizeDecoration( const TQSize& s )          TQResizeEvent e( s, oldsize );          TQApplication::sendEvent( decoration->widget(), &e );          } +    if (!moveResizeMode && options->shadowEnabled(isActive())) +        { +        // If the user is manually resizing, let Client::leaveMoveResize() +        // decide when to redraw the shadow +        updateOpacityCache(); +        }      }  bool Client::noBorder() const @@ -471,6 +508,7 @@ void Client::updateShape()          noborder = true;          updateDecoration( true );          } +    updateOpacityCache();      if ( shape() )          {          XShapeCombineShape(qt_xdisplay(), frameId(), ShapeBounding, @@ -862,6 +900,16 @@ void Client::setShade( ShadeMode mode )          XMapWindow( qt_xdisplay(), wrapperId());          XMapWindow( qt_xdisplay(), window());          XDeleteProperty (qt_xdisplay(), client, atoms->net_wm_window_shade); +	if (options->shadowEnabled(false)) +        { +    	    for (ClientList::ConstIterator it = transients().begin(); +        	it != transients().end(); ++it) +        	{ +            	    (*it)->removeShadow(); +            	    (*it)->drawDelayedShadow(); +                } +        } +          if ( isActive() )              workspace()->requestFocus( this );          } @@ -946,6 +994,589 @@ void Client::updateVisibility()          }      } +void Client::setShadowed(bool shadowed) +{ +    bool wasShadowed; + +    wasShadowed = isShadowed(); +    shadowMe = options->shadowEnabled(isActive()) ? shadowed : false; + +    if (shadowMe) { +        if (!wasShadowed) +            drawShadow(); +    } +    else { +        if (wasShadowed) { +            removeShadow(); + +            if (!activeOpacityCache.isNull()) +                activeOpacityCache.resize(0); +            if (!inactiveOpacityCache.isNull()) +                inactiveOpacityCache.resize(0); +        } +    } +} + +void Client::updateOpacityCache() +{ +    if (!activeOpacityCache.isNull()) +        activeOpacityCache.resize(0); +    if (!inactiveOpacityCache.isNull()) +        inactiveOpacityCache.resize(0); + +    if (!moveResizeMode) { +        // If the user is manually resizing, let Client::finishMoveResize() +        // decide when to redraw the shadow +        removeShadow(); +        drawIntersectingShadows(); +        if (options->shadowEnabled(isActive())) +            drawDelayedShadow(); +    } +} + +/*! +   Redraw shadows that were previously occluding or occluded by this window, +   to avoid visual glitches. + */ +void Client::drawIntersectingShadows() { +    //Client *reshadowClient; +    TQRegion region; +    //TQPtrList<Client> reshadowClients; +    TQValueList<Client *> reshadowClients; +    TQValueListIterator<ShadowRegion> it; +    TQValueListIterator<Client *> it2; + +    if (!options->shadowEnabled(false)) +        // No point in redrawing overlapping/overlapped shadows if only the +        // active window has a shadow. +        return; + +    region = shapeBoundingRegion; + +    // Generate list of Clients whose shadows need to be redrawn. That is, +    // those that are currently intersecting or intersected by other windows or +    // shadows. +    for (it = shadowRegions.begin(); it != shadowRegions.end(); ++it) +        if ((isOnAllDesktops() || (*it).client->isOnCurrentDesktop()) && +                !(*it).region.intersect(region).isEmpty()) +            reshadowClients.append((*it).client); + +    // Redraw shadows for each of the Clients in the list generated above +    for (it2 = reshadowClients.begin(); it2 != reshadowClients.end(); +            ++it2) { +        (*it2)->removeShadow(); +        (*it2)->drawDelayedShadow(); +    } +} + +/*! +   Redraw shadows that are above the current window in the stacking order. +   Furthermore, redraw them in the same order as they come in the stacking order +   from bottom to top. + */ +void Client::drawOverlappingShadows(bool waitForMe) +{ +    Client *aClient; +    TQRegion region; +    TQValueList<Client *> reshadowClients; +    ClientList stacking_order; +    ClientList::ConstIterator it; +    TQValueListIterator<ShadowRegion> it2; +    TQValueListIterator<Client *> it3; + +    if (!options->shadowEnabled(false)) +        // No point in redrawing overlapping/overlapped shadows if only the +        // active window has a shadow. +        return; + +    region = shapeBoundingRegion; + +    stacking_order = workspace()->stackingOrder(); +    for (it = stacking_order.fromLast(); it != stacking_order.end(); --it) { +        // Find the position of this window in the stacking order. +        if ((*it) == this) +            break; +    } +    ++it; +    while (it != stacking_order.end()) { +        if ((*it)->windowType() == NET::Dock) { +            // This function is only interested in windows whose shadows don't +            // have weird stacking rules. +            ++it; +            continue; +        } + +        // Generate list of Clients whose shadows need to be redrawn. That is, +        // those that are currently overlapping or overlapped by other windows +        // or shadows. The list should be in order from bottom to top in the +        // stacking order. +        for (it2 = shadowRegions.begin(); it2 != shadowRegions.end(); ++it2) { +            if ((*it2).client == (*it)) { +                if ((isOnAllDesktops() || (*it2).client->isOnCurrentDesktop()) +                        && !(*it2).region.intersect(region).isEmpty()) +                    reshadowClients.append((*it2).client); +            } +        } +        ++it; +    } + +    // Redraw shadows for each of the Clients in the list generated above +    for (it3 = reshadowClients.begin(); it3 != reshadowClients.end(); ++it3) { +        (*it3)->removeShadow(); +        if (it3 == reshadowClients.begin()) { +            if (waitForMe) +                (*it3)->drawShadowAfter(this); +            else +                (*it3)->drawDelayedShadow(); +        } +        else { +            --it3; +            aClient = (*it3); +            ++it3; +            (*it3)->drawShadowAfter(aClient); +        } +    } +} + +/*! +   Draw shadow after some time has elapsed, to give recently exposed windows a +   chance to repaint before a shadow gradient is drawn over them. + */ +void Client::drawDelayedShadow() +{ +    shadowDelayTimer->stop(); +    shadowDelayTimer->start(SHADOW_DELAY, true); +} + +/*! +   Draw shadow immediately after the specified Client's shadow finishes drawing. + */ +void Client::drawShadowAfter(Client *after) +{ +    shadowAfterClient = after; +    connect(after, TQT_SIGNAL(shadowDrawn()), TQT_SLOT(drawShadow())); +} + +/*! +   Draw a shadow under this window and XShape the shadow accordingly. + */ +void Client::drawShadow() +{ +    Window shadows[2]; +    XRectangle *shapes; +    int i, count, ordering; + +    // If we are waiting for another Client's shadow to be drawn, stop waiting now +    if (shadowAfterClient != NULL) { +        disconnect(shadowAfterClient, TQT_SIGNAL(shadowDrawn()), this, TQT_SLOT(drawShadow())); +        shadowAfterClient = NULL; +    } + +    if (!isOnCurrentDesktop()) +        return; + +    /* Store this window's ShapeBoundingRegion even if shadows aren't drawn for +     * this type of window. Otherwise, drawIntersectingShadows() won't update +     * properly when this window is moved/resized/hidden/closed. +     */ +    shapes = XShapeGetRectangles(qt_xdisplay(), frameId(), ShapeBounding, +            &count, &ordering); +    if (!shapes) +        // XShape extension not supported +        shapeBoundingRegion = TQRegion(x(), y(), width(), height()); +    else { +        shapeBoundingRegion = TQRegion(); +        for (i = 0; i < count; i++) { +            // Translate XShaped window into a TQRegion +            TQRegion shapeRectangle(shapes[i].x, shapes[i].y, shapes[i].width, +                    shapes[i].height); +            shapeBoundingRegion += shapeRectangle; +        } +        if (isShade()) +            // Since XResize() doesn't change a window's XShape regions, ensure that +            // shapeBoundingRegion is not taller than the window's shaded height, +            // or the bottom shadow will appear to be missing +            shapeBoundingRegion &= TQRegion(0, 0, width(), height()); +        shapeBoundingRegion.translate(x(), y()); +    } + +    if (!isShadowed() || hidden || isMinimized() || +            maximizeMode() == MaximizeFull || +            !options->shadowWindowType(windowType())) { +        XFree(shapes); + +        // Tell whatever Clients are listening that this Client's shadow has been drawn. +        // It hasn't, but there's no sense waiting for something that won't happen. +        emit shadowDrawn(); + +        return; +    } + +    removeShadow(); + +    TQMemArray<QRgb> pixelData; +    TQPixmap shadowPixmap; +    TQRect shadow; +    TQRegion exposedRegion; +    ShadowRegion shadowRegion; +    int thickness, xOffset, yOffset; + +    thickness = options->shadowThickness(isActive()); +    xOffset = options->shadowXOffset(isActive()); +    yOffset = options->shadowYOffset(isActive()); +    opacityCache = active? &activeOpacityCache : &inactiveOpacityCache; + +    shadow.setRect(x() - thickness + xOffset, y() - thickness + yOffset, +            width() + thickness * 2, height() + thickness * 2); +    shadowPixmap.resize(shadow.size()); + +    // Create a fake drop-down shadow effect via blended Xwindows +    shadowWidget = new TQWidget(0, 0, WStyle_Customize | WX11BypassWM); +    shadowWidget->setGeometry(shadow); +    XSelectInput(qt_xdisplay(), shadowWidget->winId(), +            ButtonPressMask | ButtonReleaseMask | StructureNotifyMask); +    shadowWidget->installEventFilter(this); + +    if (!shapes) { +        // XShape extension not supported +        exposedRegion = getExposedRegion(shapeBoundingRegion, shadow.x(), +                shadow.y(), shadow.width(), shadow.height(), thickness, +                xOffset, yOffset); +        shadowRegion.region = exposedRegion; +        shadowRegion.client = this; +        shadowRegions.append(shadowRegion); + +        if (opacityCache->isNull()) +            imposeRegionShadow(shadowPixmap, shapeBoundingRegion, +                    exposedRegion, thickness, +                    options->shadowOpacity(isActive())); +        else +            imposeCachedShadow(shadowPixmap, exposedRegion); +    } +    else { +        TQMemArray<TQRect> exposedRects; +        TQMemArray<TQRect>::Iterator it, itEnd; +        XRectangle *shadowShapes; + +        exposedRegion = getExposedRegion(shapeBoundingRegion, shadow.x(), +                shadow.y(), shadow.width(), shadow.height(), thickness, +                xOffset, yOffset); +        shadowRegion.region = exposedRegion; +        shadowRegion.client = this; +        shadowRegions.append(shadowRegion); + +        // XShape the shadow +        exposedRects = exposedRegion.rects(); +        i = 0; +        itEnd = exposedRects.end(); +        shadowShapes = new XRectangle[exposedRects.count()]; +        for (it = exposedRects.begin(); it != itEnd; ++it) { +            shadowShapes[i].x = (*it).x(); +            shadowShapes[i].y = (*it).y(); +            shadowShapes[i].width = (*it).width(); +            shadowShapes[i].height = (*it).height(); +            i++; +        } +        XShapeCombineRectangles(qt_xdisplay(), shadowWidget->winId(), +                ShapeBounding, -x() + thickness - xOffset, +                -y() + thickness - yOffset, shadowShapes, i, ShapeSet, +                Unsorted); +        delete [] shadowShapes; + +        if (opacityCache->isNull()) +            imposeRegionShadow(shadowPixmap, shapeBoundingRegion, +                    exposedRegion, thickness, +                    options->shadowOpacity(isActive())); +        else +            imposeCachedShadow(shadowPixmap, exposedRegion); +    } + +    XFree(shapes); + +    // Set the background pixmap +    //shadowPixmap.convertFromImage(shadowImage); +    shadowWidget->setErasePixmap(shadowPixmap); + +    // Restack shadows under this window so that shadows drawn for a newly +    // focused (but not raised) window don't overlap any windows above it. +    if (isDock()) { +        ClientList stacking_order = workspace()->stackingOrder(); +        for (ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it) +            if ((*it)->isDesktop()) +                { +                ++it; +                shadows[0] = (*it)->frameId(); +                shadows[1] = shadowWidget->winId(); +                } +    } +    else { +        shadows[0] = frameId(); +        if (shadowWidget != NULL) +            shadows[1] = shadowWidget->winId(); +    } + +    XRestackWindows(qt_xdisplay(), shadows, 2); + +    // Don't use TQWidget::show() so we don't confuse QEffects, thus causing +    // broken focus. +    XMapWindow(qt_xdisplay(), shadowWidget->winId()); + +    // Tell whatever Clients are listening that this Client's shadow has been drawn. +    emit shadowDrawn(); +} + +/*! +   Remove shadow under this window. + */ +void Client::removeShadow() +{ +    TQValueList<ShadowRegion>::Iterator it; + +    shadowDelayTimer->stop(); + +    if (shadowWidget != NULL) { +        for (it = shadowRegions.begin(); it != shadowRegions.end(); ++it) +            if ((*it).client == this) { +                shadowRegions.remove(it); +                break; +            } +        delete shadowWidget; +        shadowWidget = NULL; +    } +} + +/*! +   Calculate regions in which the shadow will be visible given the window's +   origin, height and width and the shadow's thickness, and X- and Y-offsets. + */ +TQRegion Client::getExposedRegion(TQRegion occludedRegion, int x, int y, int w, +        int h, int thickness, int xOffset, int yOffset) +{ +    TQRegion exposedRegion; + +    exposedRegion = TQRegion(x, y, w, h); +    exposedRegion -= occludedRegion; + +    if (thickness > 0) { +        // Limit exposedRegion to include only where a shadow of the specified +        // thickness will be drawn +        TQMemArray<TQRect> occludedRects; +        TQMemArray<TQRect>::Iterator it, itEnd; +        TQRegion shadowRegion; + +        occludedRects = occludedRegion.rects(); +        itEnd = occludedRects.end(); +        for (it = occludedRects.begin(); it != itEnd; ++it) { +            // Expand each of the occluded region's shape rectangles to contain +            // where a shadow of the specified thickness will be drawn. Create +            // a new TQRegion that contains the expanded occluded region +            it->setTop(it->top() - thickness + yOffset); +            it->setLeft(it->left() - thickness + xOffset); +            it->setRight(it->right() + thickness + xOffset); +            it->setBottom(it->bottom() + thickness + yOffset); +            shadowRegion += TQRegion(*it); +        } +        exposedRegion -= exposedRegion - shadowRegion; +    } + +    return exposedRegion; +} + +/*! +   Draw shadow gradient around this window using cached opacity values. + */ +void Client::imposeCachedShadow(TQPixmap &pixmap, TQRegion exposed) +{ +    QRgb pixel; +    double opacity; +    int red, green, blue, pixelRed, pixelGreen, pixelBlue; +    int subW, subH, w, h, x, y, zeroX, zeroY; +    TQImage image; +    TQMemArray<TQRect>::Iterator it, itEnd; +    TQMemArray<TQRect> rectangles; +    TQPixmap subPixmap; +    Window rootWindow; +    int thickness, windowX, windowY, xOffset, yOffset; + +    rectangles = exposed.rects(); +    rootWindow = qt_xrootwin(); +    thickness = options->shadowThickness(isActive()); +    windowX = this->x(); +    windowY = this->y(); +    xOffset = options->shadowXOffset(isActive()); +    yOffset = options->shadowYOffset(isActive()); +    options->shadowColour(isActive()).rgb(&red, &green, &blue); +    w = pixmap.width(); +    h = pixmap.height(); + +    itEnd = rectangles.end(); +    for (it = rectangles.begin(); it != itEnd; ++it) { +        subW = (*it).width(); +        subH = (*it).height(); +        subPixmap = TQPixmap::grabWindow(rootWindow, (*it).x(), (*it).y(), +                subW, subH); +        zeroX = (*it).x() - windowX + thickness - xOffset; +        zeroY = (*it).y() - windowY + thickness - yOffset; +        image = subPixmap.convertToImage(); + +        for (x = 0; x < subW; x++) { +            for (y = 0; y < subH; y++) { +                opacity = (*(opacityCache))[(zeroY + y) * w + zeroX + x]; +                pixel = image.pixel(x, y); +                pixelRed = qRed(pixel); +                pixelGreen = qGreen(pixel); +                pixelBlue = qBlue(pixel); +                image.setPixel(x, y, +                        qRgb((int)(pixelRed + (red - pixelRed) * opacity), +                            (int)(pixelGreen + (green - pixelGreen) * opacity), +                            (int)(pixelBlue + (blue - pixelBlue) * opacity))); +            } +        } + +        subPixmap.convertFromImage(image); +        bitBlt(&pixmap, zeroX, zeroY, &subPixmap); +    } +} + +/*! +   Draw shadow around this window using calculated opacity values. + */ +void Client::imposeRegionShadow(TQPixmap &pixmap, TQRegion occluded, +        TQRegion exposed, int thickness, double maxOpacity) +{ +    register int distance, intersectCount, i, j, x, y; +    QRgb pixel; +    double decay, factor, opacity; +    int red, green, blue, pixelRed, pixelGreen, pixelBlue; +    int halfMaxIntersects, lineIntersects, maxIntersects, maxY; +    int irBottom, irLeft, irRight, irTop, yIncrement; +    int subW, subH, w, h, zeroX, zeroY; +    TQImage image; +    TQMemArray<TQRect>::Iterator it, itEnd; +    TQMemArray<TQRect> rectangles; +    TQPixmap subPixmap; +    Window rootWindow; +    int windowX, windowY, xOffset, yOffset; + +    rectangles = exposed.rects(); +    rootWindow = qt_xrootwin(); +    windowX = this->x(); +    windowY = this->y(); +    xOffset = options->shadowXOffset(isActive()); +    yOffset = options->shadowYOffset(isActive()); +    options->shadowColour(isActive()).rgb(&red, &green, &blue); +    maxIntersects = thickness * thickness * 4 + (thickness * 4) + 1; +    halfMaxIntersects = maxIntersects / 2; +    lineIntersects = thickness * 2 + 1; +    factor = maxIntersects / maxOpacity; +    decay = (lineIntersects / 0.0125 - factor) / pow((double)maxIntersects, 3.0); +    w = pixmap.width(); +    h = pixmap.height(); +    xOffset = options->shadowXOffset(isActive()); +    yOffset = options->shadowYOffset(isActive()); + +    opacityCache->resize(0); +    opacityCache->resize(w * h); +    occluded.translate(-windowX + thickness, -windowY + thickness); + +    itEnd = rectangles.end(); +    for (it = rectangles.begin(); it != itEnd; ++it) { +        subW = (*it).width(); +        subH = (*it).height(); +        subPixmap = TQPixmap::grabWindow(rootWindow, (*it).x(), (*it).y(), +                subW, subH); +        maxY = subH; +        zeroX = (*it).x() - windowX + thickness - xOffset; +        zeroY = (*it).y() - windowY + thickness - yOffset; +        image = subPixmap.convertToImage(); + +        intersectCount = 0; +        opacity = -1; +        y = 0; +        yIncrement = 1; +        for (x = 0; x < subW; x++) { +            irLeft = zeroX + x - thickness; +            irRight = zeroX + x + thickness; + +            while (y != maxY) { +                // horizontal row about to leave the intersect region, not +                // necessarily the top row +                irTop = zeroY + y - thickness * yIncrement; +                // horizontal row that just came into the intersect region, +                // not necessarily the bottom row +                irBottom = zeroY + y + thickness * yIncrement; + +                if (opacity == -1) { +                    // If occluded pixels caused an intersect count to be +                    // skipped, recount it +                    intersectCount = 0; + +                    for (j = irTop; j != irBottom; j += yIncrement) { +                        // irTop is not necessarily larger than irBottom and +                        // yIncrement isn't necessarily positive +                        for (i = irLeft; i <= irRight; i++) { +                            if (occluded.contains(TQPoint(i, j))) +                                intersectCount++; +                        } +                    } +                } +                else { +                    if (intersectCount < 0) +                        intersectCount = 0; + +                    for (i = irLeft; i <= irRight; i++) { +                        if (occluded.contains(TQPoint(i, irBottom))) +                            intersectCount++; +                    } +                } + +                distance = maxIntersects - intersectCount; +                opacity = intersectCount / (factor + pow((double)distance, 3.0) * decay); + +                (*(opacityCache))[(zeroY + y) * w + zeroX + x] = opacity; +                pixel = image.pixel(x, y); +                pixelRed = qRed(pixel); +                pixelGreen = qGreen(pixel); +                pixelBlue = qBlue(pixel); +                image.setPixel(x, y, +                        qRgb((int)(pixelRed + (red - pixelRed) * opacity), +                            (int)(pixelGreen + (green - pixelGreen) * opacity), +                            (int)(pixelBlue + (blue - pixelBlue) * opacity))); + +                for (i = irLeft; i <= irRight; i++) { +                    if (occluded.contains(TQPoint(i, irTop))) +                        intersectCount--; +                } + +                y += yIncrement; +            } +            y -= yIncrement; + +            irTop += yIncrement; +            for (j = irTop; j != irBottom; j += yIncrement) { +                if (occluded.contains(TQPoint(irLeft, j))) +                    intersectCount--; +            } +            irRight++; +            for (j = irTop; j != irBottom; j += yIncrement) { +                if (occluded.contains(TQPoint(irRight, j))) +                    intersectCount++; +            } + +            yIncrement *= -1; +            if (yIncrement < 0) +                // Scan Y-axis bottom-up for next X-coordinate iteration +                maxY = -1; +            else +                // Scan Y-axis top-down for next X-coordinate iteration +                maxY = subH; +        } + +        subPixmap.convertFromImage(image); +        bitBlt(&pixmap, zeroX, zeroY, &subPixmap); +    } +} +  /*!    Sets the client window's mapping state. Possible values are    WithdrawnState, IconicState, NormalState. @@ -989,6 +1620,8 @@ void Client::rawShow()          XMapWindow( qt_xdisplay(), wrapper );          XMapWindow( qt_xdisplay(), client );          } +    if (options->shadowEnabled(isActive())) +        drawDelayedShadow();      }  /*! @@ -1004,6 +1637,8 @@ void Client::rawHide()  // which won't be missed, so this shouldn't be a problem. The chance the real UnmapNotify  // will be missed is also very minimal, so I don't think it's needed to grab the server  // here. +    removeShadow(); +    drawIntersectingShadows();      XSelectInput( qt_xdisplay(), wrapper, ClientWinMask ); // avoid getting UnmapNotify      XUnmapWindow( qt_xdisplay(), frame );      XUnmapWindow( qt_xdisplay(), wrapper ); diff --git a/kwin/client.h b/kwin/client.h index 306873a1e..1c4d45f51 100644 --- a/kwin/client.h +++ b/kwin/client.h @@ -200,6 +200,19 @@ class Client : public TQObject, public KDecorationDefines          void updateDecoration( bool check_workspace_pos, bool force = false );          void checkBorderSizes(); +    // drop shadow +        bool isShadowed() const; +        void setShadowed(bool shadowed); +        Window shadowId() const; +        // Aieee, a friend function! Unpleasant, yes, but it's needed by +        // raiseClient() to redraw a window's shadow when it is active prior to +        // being raised. +        friend void Workspace::raiseClient(Client *); +        // Wouldn't you know it, friend functions breed. This one's needed to +        // enable a DCOP function that causes all shadows obscuring a changed +        // window to be redrawn. +        friend void Workspace::updateOverlappingShadows(WId); +      // shape extensions          bool shape() const;          void updateShape(); @@ -312,6 +325,8 @@ class Client : public TQObject, public KDecorationDefines          void autoRaise();          void shadeHover();          void shortcutActivated(); +	void updateOpacityCache(); +      private:          friend class Bridge; // FRAME @@ -348,12 +363,29 @@ class Client : public TQObject, public KDecorationDefines          bool buttonReleaseEvent( Window w, int button, int state, int x, int y, int x_root, int y_root );          bool motionNotifyEvent( Window w, int state, int x, int y, int x_root, int y_root ); +    // drop shadows +	void drawIntersectingShadows(); +	void drawOverlappingShadows(bool waitForMe); +	TQRegion getExposedRegion(TQRegion occludedRegion, int x, int y, +	    int w, int h, int thickness, int xOffset, int yOffset); +	void imposeCachedShadow(TQPixmap &pixmap, TQRegion exposed); +	void imposeRegionShadow(TQPixmap &pixmap, TQRegion occluded, +	    TQRegion exposed, int thickness, double maxOpacity = 0.75); +          void processDecorationButtonPress( int button, int state, int x, int y, int x_root, int y_root );      private slots:          void pingTimeout();          void processKillerExited();          void demandAttentionKNotify(); +	void drawShadow(); +	void drawShadowAfter(Client *after); +	void drawDelayedShadow(); +	void removeShadow(); + +    signals: +	void shadowDrawn(); +      private:      // ICCCM 4.1.3.1, 4.1.4 , NETWM 2.5.1 @@ -531,6 +563,16 @@ class Client : public TQObject, public KDecorationDefines          bool pending_geometry_update;          bool shade_geometry_change;          int border_left, border_right, border_top, border_bottom; + +        Client* shadowAfterClient; +        TQWidget* shadowWidget; +        TQMemArray<double> activeOpacityCache; +        TQMemArray<double> inactiveOpacityCache; +        TQMemArray<double>* opacityCache; +        TQRegion shapeBoundingRegion; +        TQTimer* shadowDelayTimer; +        bool shadowMe; +          TQRegion _mask;          static bool check_active_modal; // see Client::checkActiveModal()          KShortcut _shortcut; @@ -880,6 +922,16 @@ inline void Client::plainResize( const TQSize& s, ForceGeometry_t force )      plainResize( s.width(), s.height(), force );      } +inline bool Client::isShadowed() const +    { +    return shadowMe; +    } + +inline Window Client::shadowId() const +    { +    return shadowWidget != NULL ? shadowWidget->winId() : None; +    } +  inline void Client::resizeWithChecks( const TQSize& s, ForceGeometry_t force )      {      resizeWithChecks( s.width(), s.height(), force ); diff --git a/kwin/events.cpp b/kwin/events.cpp index ba6321a7c..a30e915e1 100644 --- a/kwin/events.cpp +++ b/kwin/events.cpp @@ -1078,6 +1078,217 @@ int qtToX11State( Qt::ButtonState state )  // for the decoration window cannot be (easily) intercepted as X11 events  bool Client::eventFilter( TQObject* o, TQEvent* e )      { +    if (o == shadowWidget) +        { +        if (e->type() == TQEvent::MouseButtonRelease) +            { +            int buttonMask, buttonPressed, x, y, x_root, y_root; +            unsigned int mask; +            TQMouseEvent *qe = (TQMouseEvent *)e; +            Window inner_window, parent_window, pointer_window, root_window; +            XButtonEvent xe; + +            removeShadow(); +            switch (qe->button()) +                { +                case Qt::MidButton: +                    buttonMask = Button2Mask; +                    buttonPressed = Button2; +                    break; +                case Qt::RightButton: +                    buttonMask = Button3Mask; +                    buttonPressed = Button3; +                    break; +                default: +                    buttonMask = Button1Mask; +                    buttonPressed = Button1; +                    break; +                } + +            // find the window under the cursor that should receive the +            // simulated events +            root_window = qt_xrootwin(); +            XQueryPointer(qt_xdisplay(), root_window, &root_window, +                    &pointer_window, &x_root, &y_root, &x, &y, &mask); + +            if (pointer_window != None) +                { +                // Save the child window immediately under the window +                // decoration, if any. This is so that we can send an event to +                // the immediate descendant of a window's window decoration, +                // which causes KWin to refocus windows properly +                parent_window = pointer_window; +                XQueryPointer(qt_xdisplay(), parent_window, &root_window, +                        &pointer_window, &x_root, &y_root, &x, &y, &mask); +                inner_window = pointer_window; + +                while (pointer_window != None) +                    { +                    // Recursively query for the child window under the pointer, +                    // using the returned child window as the parent window for +                    // the subsequent query. When no child window is left, we've +                    // found the child that will receive the simulated event +                    parent_window = pointer_window; +                    XQueryPointer(qt_xdisplay(), parent_window, &root_window, +                            &pointer_window, &x_root, &y_root, &x, &y, &mask); +                    } +                pointer_window = parent_window; +                } +            else +                inner_window = None; + +            // simulate a mouse button press +            xe.type = ButtonPress; +            xe.display = qt_xdisplay(); +            xe.root = qt_xrootwin(); +            xe.subwindow = None; +            xe.time = CurrentTime; +            xe.x = x; +            xe.y = y; +            xe.x_root = x_root; +            xe.y_root = y_root; +            xe.state = 0; +            xe.button = buttonPressed; +            xe.same_screen = True; +            if (inner_window != None && inner_window != pointer_window) +                { +                xe.window = inner_window; +                XSendEvent(qt_xdisplay(), inner_window, True, ButtonPressMask, +                        (XEvent *)&xe); +                } +            xe.window = pointer_window; +            XSendEvent(qt_xdisplay(), pointer_window, True, ButtonPressMask, +                    (XEvent *)&xe); + +            // simulate a mouse button release +            xe.type = ButtonRelease; +            xe.display = qt_xdisplay(); +            xe.root = qt_xrootwin(); +            xe.subwindow = None; +            xe.time = CurrentTime; +            xe.x = x; +            xe.y = y; +            xe.x_root = x_root; +            xe.y_root = y_root; +            xe.state = buttonMask; +            xe.button = buttonPressed; +            xe.same_screen = True; +            if (inner_window != None && inner_window != pointer_window) +                { +                xe.window = inner_window; +                XSendEvent(qt_xdisplay(), inner_window, True, ButtonReleaseMask, +                        (XEvent *)&xe); +                } +            xe.window = pointer_window; +            XSendEvent(qt_xdisplay(), pointer_window, True, ButtonReleaseMask, +                    (XEvent *)&xe); + +            drawDelayedShadow(); + +            return true; +            } +        else if (e->type() == TQEvent::Wheel) +            { +            int x, y, x_root, y_root; +            unsigned int buttonMask, buttonPressed, mask; +            TQWheelEvent *wheelEvent = (TQWheelEvent *)e; +            Window inner_window, parent_window, pointer_window, +                root_window; +            XButtonEvent xe; + +            removeShadow(); + +            // state and button parameters passed to XSendEvent depend on the +            // direction in which the mouse wheel was rolled +            buttonMask = wheelEvent->delta() > 0 ? Button4Mask : Button5Mask; +            buttonPressed = wheelEvent->delta() > 0 ? Button4 : Button5; + +            // find the window under the cursor that should receive the +            // simulated events +            root_window = qt_xrootwin(); +            XQueryPointer(qt_xdisplay(), root_window, &root_window, +                    &pointer_window, &x_root, &y_root, &x, &y, &mask); + +            if (pointer_window != None) +                { +                // Save the child window immediately under the window +                // decoration, if any. This is so that we can send an event to +                // the immediate descendant of a window's window decoration, +                // which causes KWin to refocus windows properly +                parent_window = pointer_window; +                XQueryPointer(qt_xdisplay(), parent_window, &root_window, +                        &pointer_window, &x_root, &y_root, &x, &y, &mask); +                inner_window = pointer_window; + +                while (pointer_window != None) +                    { +                    // Recursively query for the child window under the pointer, +                    // using the returned child window as the parent window for +                    // the subsequent query. When no child window is left, we've +                    // found the child that will receive the simulated event +                    parent_window = pointer_window; +                    XQueryPointer(qt_xdisplay(), parent_window, &root_window, +                            &pointer_window, &x_root, &y_root, &x, &y, &mask); +                    } +                pointer_window = parent_window; +                } +            else +                inner_window = None; + +            // simulate a mouse button press +            xe.type = ButtonPress; +            xe.display = qt_xdisplay(); +            xe.root = qt_xrootwin(); +            xe.subwindow = None; +            xe.time = CurrentTime; +            xe.x = x; +            xe.y = y; +            xe.x_root = x_root; +            xe.y_root = y_root; +            xe.state = 0; +            xe.same_screen = True; +            if (inner_window != None && inner_window != pointer_window) +                { +                xe.button = buttonPressed; +                xe.window = inner_window; +                XSendEvent(qt_xdisplay(), inner_window, True, ButtonPressMask, +                        (XEvent *)&xe); +                } +            xe.button = buttonPressed; +            xe.window = pointer_window; +            XSendEvent(qt_xdisplay(), pointer_window, True, ButtonPressMask, +                    (XEvent *)&xe); + +            // simulate a mouse button release +            xe.type = ButtonRelease; +            xe.display = qt_xdisplay(); +            xe.root = qt_xrootwin(); +            xe.subwindow = None; +            xe.time = CurrentTime; +            xe.x = x; +            xe.y = y; +            xe.x_root = x_root; +            xe.y_root = y_root; +            xe.same_screen = True; +            if (inner_window != None && inner_window != pointer_window) +                { +                xe.window = inner_window; +                xe.state = buttonMask; +                xe.button = buttonPressed; +                XSendEvent(qt_xdisplay(), inner_window, True, ButtonReleaseMask, +                        (XEvent *)&xe); +                } +            xe.state = buttonMask; +            xe.button = buttonPressed; +            xe.window = pointer_window; +            XSendEvent(qt_xdisplay(), pointer_window, True, ButtonReleaseMask, +                    (XEvent *)&xe); + +            drawDelayedShadow(); + +            return true; +            } +        }      if( decoration == NULL          || o != decoration->widget())          return false; diff --git a/kwin/geometry.cpp b/kwin/geometry.cpp index f531bdfb8..3fd278360 100644 --- a/kwin/geometry.cpp +++ b/kwin/geometry.cpp @@ -1063,6 +1063,15 @@ void Client::checkDirection( int new_diff, int old_diff, TQRect& rect, const TQR                  rect.moveLeft( area.right() - 5 );              }          } +    if (!moveResizeMode && options->shadowEnabled(isActive())) +        { +        // If the user is manually resizing, let Client::leaveMoveResize() +        // decide when to redraw the shadow +        removeShadow(); +        drawIntersectingShadows(); +        if (options->shadowEnabled(isActive())) +            drawDelayedShadow(); +        }      }  /*! @@ -2322,6 +2331,7 @@ bool Client::startMoveResize()          }      if ( maximizeMode() != MaximizeRestore )          resetMaximize(); +    removeShadow();      moveResizeMode = true;      workspace()->setClientIsMoving(this);      initialMoveResizeGeom = moveResizeGeom = geometry(); @@ -2390,6 +2400,11 @@ void Client::leaveMoveResize()      moveResizeMode = false;      delete eater;      eater = 0; +    if (options->shadowEnabled(isActive())) +        { +        drawIntersectingShadows(); +        updateOpacityCache(); +        }      }  // This function checks if it actually makes sense to perform a restricted move/resize. diff --git a/kwin/kcmkwin/kwindecoration/kwindecoration.cpp b/kwin/kcmkwin/kwindecoration/kwindecoration.cpp index 68aec85ff..193450086 100644 --- a/kwin/kcmkwin/kwindecoration/kwindecoration.cpp +++ b/kwin/kcmkwin/kwindecoration/kwindecoration.cpp @@ -28,6 +28,8 @@  */  #include <assert.h> +#include <math.h> +  #include <tqdir.h>  #include <tqfileinfo.h>  #include <tqlayout.h> @@ -39,8 +41,10 @@  #include <tqlabel.h>  #include <tqfile.h>  #include <tqslider.h> +#include <tqspinbox.h>  #include <kapplication.h> +#include <kcolorbutton.h>  #include <kcombobox.h>  #include <kdebug.h>  #include <kdesktopfile.h> @@ -153,6 +157,164 @@ KWinDecorationModule::KWinDecorationModule(TQWidget* parent, const char* name, c  	preview->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding);  	tabWidget->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Maximum); +	// Page 3 (Window Shadows) +	TQHBox *inactiveShadowColourHBox, *shadowColourHBox; +	TQHBox *inactiveShadowOpacityHBox, *shadowOpacityHBox; +	TQHBox *inactiveShadowXOffsetHBox, *shadowXOffsetHBox; +	TQHBox *inactiveShadowYOffsetHBox, *shadowYOffsetHBox; +	TQHBox *inactiveShadowThicknessHBox, *shadowThicknessHBox; +	TQLabel *inactiveShadowColourLabel, *shadowColourLabel; +	TQLabel *inactiveShadowOpacityLabel, *shadowOpacityLabel; +	TQLabel *inactiveShadowXOffsetLabel, *shadowXOffsetLabel; +	TQLabel *inactiveShadowYOffsetLabel, *shadowYOffsetLabel; +	TQLabel *inactiveShadowThicknessLabel, *shadowThicknessLabel; + +	shadowPage = new TQVBox(tabWidget); +	shadowPage->setSpacing(KDialog::spacingHint()); +	shadowPage->setMargin(KDialog::marginHint()); + +	cbWindowShadow = new TQCheckBox( +			i18n("&Draw a drop shadow under windows"), shadowPage); +	TQWhatsThis::add(cbWindowShadow, +			i18n("Enabling this checkbox will allow you to choose a kind of " +				 "drop shadow to draw under each window.")); + +	activeShadowSettings = new TQGroupBox(1, Qt::Horizontal, +			i18n("Active Window Shadow"), shadowPage); +	inactiveShadowSettings = new TQGroupBox(1, Qt::Horizontal, +			i18n("Inactive Window Shadows"), shadowPage); +	whichShadowSettings = new TQGroupBox(3, Qt::Horizontal, +			i18n("Draw Shadow Under Normal Windows And..."), shadowPage); + +	cbShadowDocks = new TQCheckBox(i18n("Docks and &panels"), +			whichShadowSettings); +	connect(cbShadowDocks, TQT_SIGNAL(toggled(bool)), +			TQT_SLOT(slotSelectionChanged())); +	cbShadowOverrides = new TQCheckBox(i18n("O&verride windows"), +			whichShadowSettings); +	connect(cbShadowOverrides, TQT_SIGNAL(toggled(bool)), +			TQT_SLOT(slotSelectionChanged())); +	cbShadowTopMenus = new TQCheckBox(i18n("&Top menu"), +			whichShadowSettings); +	connect(cbShadowTopMenus, TQT_SIGNAL(toggled(bool)), +			TQT_SLOT(slotSelectionChanged())); +	cbInactiveShadow = new TQCheckBox( +			i18n("Draw shadow under &inactive windows"), inactiveShadowSettings); +	connect(cbInactiveShadow, TQT_SIGNAL(toggled(bool)), +			TQT_SLOT(slotSelectionChanged())); + +	shadowColourHBox = new TQHBox(activeShadowSettings); +	shadowColourHBox->setSpacing(KDialog::spacingHint()); +	shadowColourLabel = new TQLabel(i18n("Colour:"), shadowColourHBox); +	shadowColourButton = new KColorButton(shadowColourHBox); +	connect(shadowColourButton, TQT_SIGNAL(changed(const TQColor &)), TQT_SLOT(slotSelectionChanged())); + +	inactiveShadowColourHBox = new TQHBox(inactiveShadowSettings); +	inactiveShadowColourHBox->setSpacing(KDialog::spacingHint()); +	inactiveShadowColourLabel = new TQLabel(i18n("Colour:"), inactiveShadowColourHBox); +	inactiveShadowColourButton = new KColorButton(inactiveShadowColourHBox); +	connect(inactiveShadowColourButton, TQT_SIGNAL(changed(const TQColor &)), TQT_SLOT(slotSelectionChanged())); + +	shadowOpacityHBox = new TQHBox(activeShadowSettings); +	shadowOpacityHBox->setSpacing(KDialog::spacingHint()); +	shadowOpacityLabel = new TQLabel(i18n("Maximum opacity:"), shadowOpacityHBox); +	shadowOpacitySlider = new TQSlider(1, 100, 10, 50, Qt::Horizontal, +			shadowOpacityHBox); +	shadowOpacitySlider->setTickmarks(TQSlider::Below); +	shadowOpacitySlider->setTickInterval(10); +	shadowOpacitySpinBox = new TQSpinBox(1, 100, 1, shadowOpacityHBox); +	shadowOpacitySpinBox->setSuffix(" %"); +	connect(shadowOpacitySlider, TQT_SIGNAL(valueChanged(int)), shadowOpacitySpinBox, +			TQT_SLOT(setValue(int))); +	connect(shadowOpacitySpinBox, TQT_SIGNAL(valueChanged(int)), shadowOpacitySlider, +			TQT_SLOT(setValue(int))); +	connect(shadowOpacitySlider, TQT_SIGNAL(valueChanged(int)), +			TQT_SLOT(slotSelectionChanged())); + +	inactiveShadowOpacityHBox = new TQHBox(inactiveShadowSettings); +	inactiveShadowOpacityHBox->setSpacing(KDialog::spacingHint()); +	inactiveShadowOpacityLabel = new TQLabel(i18n("Maximum opacity:"), +			inactiveShadowOpacityHBox); +	inactiveShadowOpacitySlider = new TQSlider(1, 100, 10, 50, Qt::Horizontal, +			inactiveShadowOpacityHBox); +	inactiveShadowOpacitySlider->setTickmarks(TQSlider::Below); +	inactiveShadowOpacitySlider->setTickInterval(10); +	inactiveShadowOpacitySpinBox = new TQSpinBox(1, 100, 1, +			inactiveShadowOpacityHBox); +	inactiveShadowOpacitySpinBox->setSuffix(" %"); +	connect(inactiveShadowOpacitySlider, TQT_SIGNAL(valueChanged(int)), +			inactiveShadowOpacitySpinBox, +			TQT_SLOT(setValue(int))); +	connect(inactiveShadowOpacitySpinBox, TQT_SIGNAL(valueChanged(int)), +			inactiveShadowOpacitySlider, +			TQT_SLOT(setValue(int))); +	connect(inactiveShadowOpacitySlider, TQT_SIGNAL(valueChanged(int)), +			TQT_SLOT(slotSelectionChanged())); + +	shadowXOffsetHBox = new TQHBox(activeShadowSettings); +	shadowXOffsetHBox->setSpacing(KDialog::spacingHint()); +	shadowXOffsetLabel = new TQLabel( +			i18n("Offset rightward (may be negative):"), +			shadowXOffsetHBox); +	shadowXOffsetSpinBox = new TQSpinBox(-1024, 1024, 1, shadowXOffsetHBox); +	shadowXOffsetSpinBox->setSuffix(i18n(" pixels")); +	connect(shadowXOffsetSpinBox, TQT_SIGNAL(valueChanged(int)), +			TQT_SLOT(slotSelectionChanged())); + +	inactiveShadowXOffsetHBox = new TQHBox(inactiveShadowSettings); +	inactiveShadowXOffsetHBox->setSpacing(KDialog::spacingHint()); +	inactiveShadowXOffsetLabel = new TQLabel( +			i18n("Offset rightward (may be negative):"), +			inactiveShadowXOffsetHBox); +	inactiveShadowXOffsetSpinBox = new TQSpinBox(-1024, 1024, 1, +			inactiveShadowXOffsetHBox); +	inactiveShadowXOffsetSpinBox->setSuffix(i18n(" pixels")); +	connect(inactiveShadowXOffsetSpinBox, TQT_SIGNAL(valueChanged(int)), +			TQT_SLOT(slotSelectionChanged())); + +	shadowYOffsetHBox = new TQHBox(activeShadowSettings); +	shadowYOffsetHBox->setSpacing(KDialog::spacingHint()); +	shadowYOffsetLabel = new TQLabel( +			i18n("Offset downward (may be negative):"), +			shadowYOffsetHBox); +	shadowYOffsetSpinBox = new TQSpinBox(-1024, 1024, 1, shadowYOffsetHBox); +	shadowYOffsetSpinBox->setSuffix(i18n(" pixels")); +	connect(shadowYOffsetSpinBox, TQT_SIGNAL(valueChanged(int)), +			TQT_SLOT(slotSelectionChanged())); + +	inactiveShadowYOffsetHBox = new TQHBox(inactiveShadowSettings); +	inactiveShadowYOffsetHBox->setSpacing(KDialog::spacingHint()); +	inactiveShadowYOffsetLabel = new TQLabel( +			i18n("Offset downward (may be negative):"), +			inactiveShadowYOffsetHBox); +	inactiveShadowYOffsetSpinBox = new TQSpinBox(-1024, 1024, 1, +			inactiveShadowYOffsetHBox); +	inactiveShadowYOffsetSpinBox->setSuffix(i18n(" pixels")); +	connect(inactiveShadowYOffsetSpinBox, TQT_SIGNAL(valueChanged(int)), +			TQT_SLOT(slotSelectionChanged())); + +	shadowThicknessHBox = new TQHBox(activeShadowSettings); +	shadowThicknessHBox->setSpacing(KDialog::spacingHint()); +	shadowThicknessLabel = new TQLabel( +			i18n("Thickness to either side of window:"), +			shadowThicknessHBox); +	shadowThicknessSpinBox = new TQSpinBox(1, 100, 1, +			shadowThicknessHBox); +	shadowThicknessSpinBox->setSuffix(i18n(" pixels")); +	connect(shadowThicknessSpinBox, TQT_SIGNAL(valueChanged(int)), +			TQT_SLOT(slotSelectionChanged())); + +	inactiveShadowThicknessHBox = new TQHBox(inactiveShadowSettings); +	inactiveShadowThicknessHBox->setSpacing(KDialog::spacingHint()); +	inactiveShadowThicknessLabel = new TQLabel( +			i18n("Thickness to either side of window:"), +			inactiveShadowThicknessHBox); +	inactiveShadowThicknessSpinBox = new TQSpinBox(1, 100, 1, +			inactiveShadowThicknessHBox); +	inactiveShadowThicknessSpinBox->setSuffix(i18n(" pixels")); +	connect(inactiveShadowThicknessSpinBox, TQT_SIGNAL(valueChanged(int)), +			TQT_SLOT(slotSelectionChanged())); +  	// Load all installed decorations into memory  	// Set up the decoration lists and other UI settings  	findDecorations(); @@ -162,6 +324,7 @@ KWinDecorationModule::KWinDecorationModule(TQWidget* parent, const char* name, c  	tabWidget->insertTab( pluginPage, i18n("&Window Decoration") );  	tabWidget->insertTab( buttonPage, i18n("&Buttons") ); +	tabWidget->insertTab( shadowPage, i18n("&Shadows") );  	connect( buttonPositionWidget, TQT_SIGNAL(changed()), this, TQT_SLOT(slotButtonsChanged()) ); // update preview etc.  	connect( buttonPositionWidget, TQT_SIGNAL(changed()), this, TQT_SLOT(slotSelectionChanged()) ); // emit changed()... @@ -171,7 +334,12 @@ KWinDecorationModule::KWinDecorationModule(TQWidget* parent, const char* name, c  	connect( cbUseCustomButtonPositions, TQT_SIGNAL(clicked()), TQT_SLOT(slotSelectionChanged()) );  	connect(cbUseCustomButtonPositions, TQT_SIGNAL(toggled(bool)), buttonPositionWidget, TQT_SLOT(setEnabled(bool)));  	connect(cbUseCustomButtonPositions, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotButtonsChanged()) ); + 	connect(cbWindowShadow, TQT_SIGNAL(toggled(bool)), activeShadowSettings, TQT_SLOT(setEnabled(bool))); + 	connect(cbWindowShadow, TQT_SIGNAL(toggled(bool)), inactiveShadowSettings, TQT_SLOT(setEnabled(bool))); + 	connect(cbWindowShadow, TQT_SIGNAL(toggled(bool)), whichShadowSettings, TQT_SLOT(setEnabled(bool))); +  	connect( cbShowToolTips, TQT_SIGNAL(clicked()), TQT_SLOT(slotSelectionChanged()) ); +	connect( cbWindowShadow, TQT_SIGNAL(clicked()), TQT_SLOT(slotSelectionChanged()) );  	connect( cBorder, TQT_SIGNAL( activated( int )), TQT_SLOT( slotBorderChanged( int )));  //	connect( cbUseMiniWindows, TQT_SIGNAL(clicked()), TQT_SLOT(slotSelectionChanged()) ); @@ -465,6 +633,28 @@ void KWinDecorationModule::readConfig( KConfig* conf )              border_size = BorderNormal;          checkSupportedBorderSizes(); +	// Shadows tab +	// =========== +	bool shadowEnabled = conf->readBoolEntry("ShadowEnabled", false); + 	cbWindowShadow->setChecked(shadowEnabled); +	activeShadowSettings->setEnabled(shadowEnabled); +	inactiveShadowSettings->setEnabled(shadowEnabled); +	whichShadowSettings->setEnabled(shadowEnabled); +	shadowColourButton->setColor(conf->readColorEntry("ShadowColour", &Qt::black)); + 	shadowOpacitySlider->setValue((int)ceil(conf->readDoubleNumEntry("ShadowOpacity", 0.70) * 100)); + 	shadowXOffsetSpinBox->setValue(conf->readNumEntry("ShadowXOffset", 0)); + 	shadowYOffsetSpinBox->setValue(conf->readNumEntry("ShadowYOffset", 10)); + 	cbShadowDocks->setChecked(conf->readBoolEntry("ShadowDocks", false)); + 	cbShadowOverrides->setChecked(conf->readBoolEntry("ShadowOverrides", false)); + 	cbShadowTopMenus->setChecked(conf->readBoolEntry("ShadowTopMenus", false)); + 	shadowThicknessSpinBox->setValue(conf->readNumEntry("ShadowThickness", 10)); + 	cbInactiveShadow->setChecked(conf->readBoolEntry("InactiveShadowEnabled", false)); + 	inactiveShadowColourButton->setColor(conf->readColorEntry("InactiveShadowColour", &Qt::black)); + 	inactiveShadowOpacitySlider->setValue((int)ceil(conf->readDoubleNumEntry("InactiveShadowOpacity", 0.70) * 100)); + 	inactiveShadowXOffsetSpinBox->setValue(conf->readNumEntry("InactiveShadowXOffset", 0)); + 	inactiveShadowYOffsetSpinBox->setValue(conf->readNumEntry("InactiveShadowYOffset", 5)); + 	inactiveShadowThicknessSpinBox->setValue(conf->readNumEntry("InactiveShadowThickness", 5)); +  	emit KCModule::changed(false);  } @@ -489,6 +679,27 @@ void KWinDecorationModule::writeConfig( KConfig* conf )  	conf->writeEntry("ButtonsOnRight", buttonPositionWidget->buttonsRight() );          conf->writeEntry("BorderSize", border_size ); +	// Shadow settings +	conf->writeEntry("ShadowEnabled", cbWindowShadow->isChecked()); +	conf->writeEntry("ShadowColour", shadowColourButton->color()); +	conf->writeEntry("ShadowOpacity", shadowOpacitySlider->value() / 100.0); +	conf->writeEntry("ShadowXOffset", shadowXOffsetSpinBox->value()); +	conf->writeEntry("ShadowYOffset", shadowYOffsetSpinBox->value()); +	conf->writeEntry("ShadowThickness", shadowThicknessSpinBox->value()); +	conf->writeEntry("ShadowDocks", cbShadowDocks->isChecked()); +	conf->writeEntry("ShadowOverrides", cbShadowOverrides->isChecked()); +	conf->writeEntry("ShadowTopMenus", cbShadowTopMenus->isChecked()); +	conf->writeEntry("InactiveShadowEnabled", cbInactiveShadow->isChecked()); +	conf->writeEntry("InactiveShadowColour", inactiveShadowColourButton->color()); +	conf->writeEntry("InactiveShadowOpacity", +			inactiveShadowOpacitySlider->value() / 100.0); +	conf->writeEntry("InactiveShadowXOffset", +			inactiveShadowXOffsetSpinBox->value()); +	conf->writeEntry("InactiveShadowYOffset", +			inactiveShadowYOffsetSpinBox->value()); +	conf->writeEntry("InactiveShadowThickness", +			inactiveShadowThicknessSpinBox->value()); +  	oldLibraryName = currentLibraryName;  	currentLibraryName = libName; @@ -541,6 +752,7 @@ void KWinDecorationModule::defaults()  	cbUseCustomButtonPositions->setChecked( false );  	buttonPositionWidget->setEnabled( false );  	cbShowToolTips->setChecked( true ); +	cbWindowShadow->setChecked( false );  //	cbUseMiniWindows->setChecked( false);  // Don't set default for now  //	decorationList->setSelected( @@ -552,6 +764,21 @@ void KWinDecorationModule::defaults()          border_size = BorderNormal;          checkSupportedBorderSizes(); +	shadowColourButton->setColor(Qt::black); +	shadowOpacitySlider->setValue(70); +	shadowXOffsetSpinBox->setValue(0); +	shadowYOffsetSpinBox->setValue(10); +	shadowThicknessSpinBox->setValue(10); +	cbShadowDocks->setChecked(false); +	cbShadowOverrides->setChecked(false); +	cbShadowTopMenus->setChecked(false); +	cbInactiveShadow->setChecked(false); +	inactiveShadowColourButton->setColor(Qt::black); +	inactiveShadowOpacitySlider->setValue(70); +	inactiveShadowXOffsetSpinBox->setValue(0); +	inactiveShadowYOffsetSpinBox->setValue(5); +	inactiveShadowThicknessSpinBox->setValue(5); +  	// Set plugin defaults  	emit pluginDefaults();  } diff --git a/kwin/kcmkwin/kwindecoration/kwindecoration.h b/kwin/kcmkwin/kwindecoration/kwindecoration.h index c4a123352..53b3ed6ae 100644 --- a/kwin/kcmkwin/kwindecoration/kwindecoration.h +++ b/kwin/kcmkwin/kwindecoration/kwindecoration.h @@ -127,6 +127,19 @@ class KWinDecorationModule : public KCModule, virtual public KWinDecorationIface  		// Page 2  		ButtonPositionWidget *buttonPositionWidget;  		TQVBox*	 buttonPage; + +		// Page 3 +		TQVBox *shadowPage; +		KColorButton *inactiveShadowColourButton, *shadowColourButton; +		TQCheckBox *cbShadowDocks, *cbShadowOverrides, *cbShadowTopMenus; +		TQCheckBox *cbInactiveShadow, *cbWindowShadow; +		TQGroupBox *activeShadowSettings, *inactiveShadowSettings; +		TQGroupBox *whichShadowSettings; +		TQSlider *inactiveShadowOpacitySlider, *shadowOpacitySlider; +		TQSpinBox *inactiveShadowOpacitySpinBox, *shadowOpacitySpinBox; +		TQSpinBox *inactiveShadowXOffsetSpinBox, *shadowXOffsetSpinBox; +		TQSpinBox *inactiveShadowYOffsetSpinBox, *shadowYOffsetSpinBox; +		TQSpinBox *inactiveShadowThicknessSpinBox, *shadowThicknessSpinBox;  }; diff --git a/kwin/layers.cpp b/kwin/layers.cpp index 40a7583a4..8d942c731 100644 --- a/kwin/layers.cpp +++ b/kwin/layers.cpp @@ -134,37 +134,89 @@ void Workspace::propagateClients( bool propagate_new_clients )                                  // when passig pointers around.      // restack the windows according to the stacking order +#if 0      Window* new_stack = new Window[ stacking_order.count() + 2 ];      int pos = 0; +#endif +    NET::WindowType t; +    Window shadow; +    Window *dock_shadow_stack, *window_stack; +    int i, numDocks, pos, topmenu_space_pos; +  +    dock_shadow_stack = new Window[ stacking_order.count() * 2 ]; +    window_stack = new Window[ stacking_order.count() * 2 + 2 ]; +    i = 0; +    pos = 0; +    topmenu_space_pos = 1; // not 0, that's supportWindow !!! +      // Stack all windows under the support window. The support window is      // not used for anything (besides the NETWM property), and it's not shown,      // but it was lowered after kwin startup. Stacking all clients below      // it ensures that no client will be ever shown above override-redirect      // windows (e.g. popups). +#if 0      new_stack[ pos++ ] = supportWindow->winId();      int topmenu_space_pos = 1; // not 0, that's supportWindow !!! +#endif +    window_stack[pos++] = supportWindow->winId();      for( ClientList::ConstIterator it = stacking_order.fromLast();           it != stacking_order.end();           --it )          { +#if 0          new_stack[ pos++ ] = (*it)->frameId();          if( (*it)->belongsToLayer() >= DockLayer )              topmenu_space_pos = pos; -        } +#endif +	t = (*it)->windowType(); +	switch (t) +		{ +		case NET::Dock: +		    window_stack[pos++] = (*it)->frameId(); +		    if ((shadow = (*it)->shadowId()) != None) +		    dock_shadow_stack[i++] = shadow; +		break; +		case NET::Desktop: +		    numDocks = i; +		    for (i = 0; i < numDocks; i++) +		    // Shadows for dock windows go just above the desktop +		    window_stack[pos++] = dock_shadow_stack[i]; +		    window_stack[pos++] = (*it)->frameId(); +		break; +		case NET::TopMenu: +		    topmenu_space_pos = pos; +		    // fall through +		default: +		    window_stack[pos++] = (*it)->frameId(); +		    if ((shadow = (*it)->shadowId()) != None) +			// If the current window also has a shadow, place it +			// immediately under the current window +			window_stack[pos++] = shadow; +		} +    	}      if( topmenu_space != NULL )          { // make sure the topmenu space is below all topmenus, fullscreens, etc.          for( int i = pos;               i > topmenu_space_pos;               --i ) +#if 0              new_stack[ i ] = new_stack[ i - 1 ];          new_stack[ topmenu_space_pos ] = topmenu_space->winId(); +#endif +            window_stack[ i ] = window_stack[ i - 1 ]; +	window_stack[ topmenu_space_pos ] = topmenu_space->winId();          ++pos;          }      // TODO isn't it too inefficient to restart always all clients?      // TODO don't restack not visible windows?      assert( new_stack[ 0 ] = supportWindow->winId()); +#if 0      XRestackWindows(qt_xdisplay(), new_stack, pos);      delete [] new_stack; +#endif +    XRestackWindows(qt_xdisplay(), window_stack, pos); +    delete [] dock_shadow_stack; +    delete [] window_stack;      if ( propagate_new_clients )          { @@ -342,6 +394,11 @@ void Workspace::raiseClient( Client* c )      unconstrained_stacking_order.remove( c );      unconstrained_stacking_order.append( c ); +    if (options->shadowEnabled(c->isActive())) +        { +        c->removeShadow(); +        c->drawDelayedShadow(); +        }      if( !c->isSpecialWindow())          { diff --git a/kwin/lib/kdecoration.h b/kwin/lib/kdecoration.h index b4f62d6f8..f41f19041 100644 --- a/kwin/lib/kdecoration.h +++ b/kwin/lib/kdecoration.h @@ -97,6 +97,7 @@ public:          LowerOp,          FullScreenOp,          NoBorderOp, +	ShadowOp,          NoOp,          SetupWindowShortcutOp,          ApplicationRulesOp     ///< @since 3.5 @@ -116,7 +117,7 @@ public:  	ColorHandle,     ///< The color for the resize handle  	NUM_COLORS  	}; -     +      /**       * These flags specify which settings changed when rereading settings.       * Each setting in class KDecorationOptions specifies its matching flag. @@ -130,7 +131,7 @@ public:          SettingTooltips   = 1 << 4, ///< The tooltip setting was changed          SettingBorder     = 1 << 5  ///< The border size setting was changed          }; -         +      /**       * Border size. KDecorationOptions::preferredBorderSize() returns       * one of these values. @@ -261,7 +262,7 @@ public:      * The changed flags for this setting is SettingTooltips.      */      bool showTooltips() const; -     +      /**       * The preferred border size selected by the user, e.g. for accessibility       * reasons, or when using high resolution displays. It's up to the decoration @@ -322,9 +323,9 @@ class KWIN_EXPORT KDecoration  	 * Destroys the KDecoration.  	 */  	virtual ~KDecoration(); -	 +  	// requests from decoration -	 +  	/**  	 * Returns the KDecorationOptions object, which is used to access  	 * configuration settings for the decoration. @@ -417,7 +418,7 @@ class KWIN_EXPORT KDecoration  	 * to support older code). For a description of all window types,  	 * see the definition of the NET::WindowType type. Note that  	 * some window types never have decorated windows. -	 *  +	 *  	 * An example of usage:  	 * @code  	 * const unsigned long supported_types = NET::NormalMask | NET::DesktopMask @@ -671,7 +672,7 @@ class KWIN_EXPORT KDecoration  	/**  	 * This function is called to reset the decoration on settings changes.  	 * It is usually invoked by calling KDecorationFactory::resetDecorations(). -	 *  +	 *  	 * @param changed Specifies which settings were changed, given by the SettingXXX masks  	 */          virtual void reset( unsigned long changed ); diff --git a/kwin/manage.cpp b/kwin/manage.cpp index e56a877b4..df385867a 100644 --- a/kwin/manage.cpp +++ b/kwin/manage.cpp @@ -372,6 +372,7 @@ bool Client::manage( Window w, bool isMapped )          setSkipTaskbar( session->skipTaskbar, true );          setSkipPager( session->skipPager );          setShade( session->shaded ? ShadeNormal : ShadeNone ); +        setShadowed( session->shadowed );          if( session->maximized != MaximizeRestore )              {              maximize( (MaximizeMode) session->maximized ); diff --git a/kwin/options.cpp b/kwin/options.cpp index 5f0190347..cab703051 100644 --- a/kwin/options.cpp +++ b/kwin/options.cpp @@ -193,7 +193,24 @@ unsigned long Options::updateSettings()      if (resetKompmgr)          config->writeEntry("ResetKompmgr",FALSE); -     +     // window drop shadows +    config->setGroup("Style"); +    shadow_colour = config->readColorEntry("ShadowColour", &Qt::black); +    shadow_docks = config->readBoolEntry("ShadowDocks", false); +    shadow_overrides = config->readBoolEntry("ShadowOverrides", false); +    shadow_topMenus = config->readBoolEntry("ShadowTopMenus", false); +    shadow_inactive_colour = config->readColorEntry("InactiveShadowColour", &Qt::black); +    shadow_inactive_enabled = config->readBoolEntry("InactiveShadowEnabled", false); +    shadow_inactive_opacity = config->readDoubleNumEntry("InactiveShadowOpacity", 0.70); +    shadow_inactive_thickness = config->readNumEntry("InactiveShadowThickness", 5); +    shadow_inactive_x_offset = config->readNumEntry("InactiveShadowXOffset", 0); +    shadow_inactive_y_offset = config->readNumEntry("InactiveShadowYOffset", 5); +    shadow_enabled = config->readBoolEntry("ShadowEnabled", false); +    shadow_opacity = config->readDoubleNumEntry("ShadowOpacity", 0.70); +    shadow_thickness = config->readNumEntry("ShadowThickness", 10); +    shadow_x_offset = config->readNumEntry("ShadowXOffset", 0); +    shadow_y_offset = config->readNumEntry("ShadowYOffset", 10); +      // Read button tooltip animation effect from kdeglobals      // Since we want to allow users to enable window decoration tooltips @@ -243,6 +260,8 @@ Options::WindowOperation Options::windowOperation(const TQString &name, bool res          return HMaximizeOp;      else if (name == "Lower")          return LowerOp; +    else if (name == "Shadow") +        return ShadowOp;      return NoOp;      } @@ -285,6 +304,69 @@ bool Options::showGeometryTip()      return show_geometry_tip;      } +TQColor &Options::shadowColour(bool active) +    { +    return active ? shadow_colour : shadow_inactive_colour; +    } + +bool Options::shadowWindowType(NET::WindowType t) +    { +    bool retval; + +    switch (t) +        { +        case NET::Dialog: +        case NET::Normal: +            retval = true; +            break; +        case NET::Desktop: +        case NET::Menu: +        case NET::Toolbar: +            retval = false; +            break; +        case NET::Dock: +            retval = shadow_docks; +            break; +        case NET::Override: +            retval = shadow_overrides; +            break; +        case NET::TopMenu: +            retval = shadow_topMenus; +            break; +        default: +            retval = false; +            break; +        } + +    return retval; +    } + +bool Options::shadowEnabled(bool active) +    { +    return active ? shadow_enabled : +        (shadow_enabled && shadow_inactive_enabled); +    } + +double Options::shadowOpacity(bool active) +    { +    return active ? shadow_opacity : shadow_inactive_opacity; +    } + +int Options::shadowThickness(bool active) +    { +    return active ? shadow_thickness : shadow_inactive_thickness; +    } + +int Options::shadowXOffset(bool active) +    { +    return active ? shadow_x_offset : shadow_inactive_x_offset; +    } + +int Options::shadowYOffset(bool active) +    { +    return active ? shadow_y_offset : shadow_inactive_y_offset; +    } +  int Options::electricBorders()      {      return electric_borders; diff --git a/kwin/options.h b/kwin/options.h index 82dc6cdc1..dbaa8855f 100644 --- a/kwin/options.h +++ b/kwin/options.h @@ -268,6 +268,45 @@ class Options : public KDecorationOptions          */          bool showGeometryTip(); +        /** +        * @returns A TQColor representing the colour that window drop shadows should +        *          be. +        */ +        TQColor &shadowColour(bool active=true); + +        /** +        * @returns true if shadows should be drawn around windows of the +        *          specified type +        */ +        bool shadowWindowType(NET::WindowType t); + +        /** +        * @returns true if window shadows should be drawn +        */ +        bool shadowEnabled(bool active=true); + +        /** +        * @returns Window shadow's opacity between 0.01 and 1.00. +        */ +        double shadowOpacity(bool active=true); + +        /** +        * @returns How thick a shadow should be to either side of of a window. +        */ +        int shadowThickness(bool active=true); + +        /** +        * @returns Number of pixels along the X-axis by which to offset window +        *          shadows. +        */ +        int shadowXOffset(bool active=true); + +        /** +        * @returns Number of pixels along the Y-axis by which to offset window +        *          shadows. +        */ +        int shadowYOffset(bool active=true); +          enum { ElectricDisabled = 0, ElectricMoveOnly = 1, ElectricAlways = 2 };          /**          * @returns true if electric borders are enabled. With electric borders @@ -336,6 +375,21 @@ class Options : public KDecorationOptions          bool show_geometry_tip;          bool topmenus;          bool desktop_topmenu; +        TQColor shadow_colour; +        TQColor shadow_inactive_colour; +        bool shadow_docks; +        bool shadow_overrides; +        bool shadow_topMenus; +        bool shadow_inactive_enabled; +        bool shadow_enabled; +        double shadow_inactive_opacity; +        double shadow_opacity; +        int shadow_inactive_thickness; +        int shadow_thickness; +        int shadow_inactive_x_offset; +        int shadow_x_offset; +        int shadow_inactive_y_offset; +        int shadow_y_offset;          // List of window classes for which not to use focus stealing prevention          TQStringList ignoreFocusStealingClasses; diff --git a/kwin/sm.cpp b/kwin/sm.cpp index d13c6b18b..31cada7e0 100644 --- a/kwin/sm.cpp +++ b/kwin/sm.cpp @@ -106,6 +106,7 @@ void Workspace::storeSession( KConfig* config, SMSavePhase phase )              // the config entry is called "sticky" for back. comp. reasons              config->writeEntry( TQString("sticky")+n, c->isOnAllDesktops() );              config->writeEntry( TQString("shaded")+n, c->isShade() ); +            config->writeEntry( TQString("shadowed")+n, c->isShadowed() );              // the config entry is called "staysOnTop" for back. comp. reasons              config->writeEntry( TQString("staysOnTop")+n, c->keepAbove() );              config->writeEntry( TQString("keepBelow")+n, c->keepBelow() ); @@ -172,6 +173,7 @@ void Workspace::loadSessionInfo()          info->minimized = config->readBoolEntry( TQString("iconified")+n, FALSE );          info->onAllDesktops = config->readBoolEntry( TQString("sticky")+n, FALSE );          info->shaded = config->readBoolEntry( TQString("shaded")+n, FALSE ); +        info->shadowed = config->readBoolEntry( TQString("shadowed")+n, TRUE );          info->keepAbove = config->readBoolEntry( TQString("staysOnTop")+n, FALSE  );          info->keepBelow = config->readBoolEntry( TQString("keepBelow")+n, FALSE  );          info->skipTaskbar = config->readBoolEntry( TQString("skipTaskbar")+n, FALSE  ); @@ -39,6 +39,7 @@ struct SessionInfo      bool minimized;      bool onAllDesktops;      bool shaded; +    bool shadowed;      bool keepAbove;      bool keepBelow;      bool skipTaskbar; diff --git a/kwin/useractions.cpp b/kwin/useractions.cpp index 88bfaf035..e825ac846 100644 --- a/kwin/useractions.cpp +++ b/kwin/useractions.cpp @@ -65,6 +65,7 @@ TQPopupMenu* Workspace::clientPopup()          advanced_popup->insertItem( SmallIconSet( "window_fullscreen" ),              i18n("&Fullscreen")+'\t'+keys->shortcut("Window Fullscreen").seq(0).toString(), Options::FullScreenOp );          advanced_popup->insertItem( i18n("&No Border")+'\t'+keys->shortcut("Window No Border").seq(0).toString(), Options::NoBorderOp ); +	advanced_popup->insertItem( i18n("Shad&ow"), Options::ShadowOp );          advanced_popup->insertItem( SmallIconSet("key_bindings"),              i18n("Window &Shortcut...")+'\t'+keys->shortcut("Setup Window Shortcut").seq(0).toString(), Options::SetupWindowShortcutOp );          advanced_popup->insertItem( SmallIconSet( "wizard" ), i18n("&Special Window Settings..."), Options::WindowRulesOp ); @@ -172,6 +173,10 @@ void Workspace::clientPopupAboutToShow()      advanced_popup->setItemEnabled( Options::FullScreenOp, active_popup_client->userCanSetFullScreen() );      advanced_popup->setItemChecked( Options::NoBorderOp, active_popup_client->noBorder() );      advanced_popup->setItemEnabled( Options::NoBorderOp, active_popup_client->userCanSetNoBorder() ); +     +    advanced_popup->setItemEnabled( Options::ShadowOp, (options->shadowWindowType(active_popup_client->windowType()) && options->shadowEnabled(active_popup_client->isActive())) ); +    advanced_popup->setItemChecked( Options::ShadowOp, active_popup_client->isShadowed() ); +          popup->setItemEnabled( Options::MinimizeOp, active_popup_client->isMinimizable() );      popup->setItemEnabled( Options::CloseOp, active_popup_client->isCloseable() );      if (options->useTranslucency) @@ -398,6 +403,9 @@ void Workspace::performWindowOperation( Client* c, Options::WindowOperation op )          case Options::ShadeOp:              c->performMouseCommand( Options::MouseShade, TQCursor::pos());              break; +        case Options::ShadowOp: +            c->setShadowed( !c->isShadowed() ); +            break;          case Options::OnAllDesktopsOp:              c->setOnAllDesktops( !c->isOnAllDesktops() );              break; diff --git a/kwin/workspace.cpp b/kwin/workspace.cpp index bc8914f5b..fe8ad8faa 100644 --- a/kwin/workspace.cpp +++ b/kwin/workspace.cpp @@ -90,6 +90,7 @@ Workspace::Workspace( bool restore )      rules_updates_disabled( false ),      active_client     (0),      last_active_client     (0), +    next_active_client     (0),      most_recently_raised (0),      movingClient(0),      pending_take_activity ( NULL ), @@ -699,6 +700,24 @@ void Workspace::updateFocusChains( Client* c, FocusChainChange change )          }      } +void Workspace::updateOverlappingShadows(unsigned long window) +    { +    Client *client; +     +    if ((client = findClient(WindowMatchPredicate((WId)window)))) +        // Redraw overlapping shadows without waiting for the specified window +        // to redraw its own shadow +        client->drawOverlappingShadows(false); +    } + +void Workspace::setShadowed(unsigned long window, bool shadowed) +    { +    Client *client; +     +    if ((client = findClient(WindowMatchPredicate((WId)window)))) +        client->setShadowed(shadowed); +    } +  void Workspace::updateCurrentTopMenu()      {      if( !managingTopMenus()) diff --git a/kwin/workspace.h b/kwin/workspace.h index d369497da..55043276e 100644 --- a/kwin/workspace.h +++ b/kwin/workspace.h @@ -231,6 +231,8 @@ class Workspace : public TQObject, public KWinInterface, public KDecorationDefin          void unclutterDesktop();          void doNotManage(TQString);          bool setCurrentDesktop( int new_desktop ); +        void updateOverlappingShadows(WId window); +        void setShadowed(WId window, bool shadowed);          void nextDesktop();          void previousDesktop();          void circulateDesktopApplications(); @@ -518,6 +520,7 @@ class Workspace : public TQObject, public KWinInterface, public KDecorationDefin          Client* active_client;          Client* last_active_client; +        Client* next_active_client; // will be active after active_client deactivates          Client* most_recently_raised; // used _only_ by raiseOrLowerClient()          Client* movingClient;          Client* pending_take_activity; @@ -704,7 +707,15 @@ inline bool Workspace::initializing() const  inline Client* Workspace::activeClient() const      { -    return active_client; +    // next_active_client is a kludge for drop shadows. If a window that is +    // activated is not also raised (i.e. when focus follows mouse), then the +    // newly activated window and its shadow won't cover visual artifacts that +    // might exist in the inactive window's shadow. We work around this by +    // (re)drawing the inactive window's shadow after the active window's shadow +    // is drawn, but to do that the inactive window needs to know which window +    // will become active next. next_active_client is a Client pointer for that +    // purpose. +    return next_active_client != NULL ? next_active_client : active_client;      }  inline Client* Workspace::mostRecentlyActivatedClient() const | 
