freedesktop docking

Harald Hoyer harald at redhat.de
Thu Sep 26 11:27:10 BST 2002


Hi,

Please lay aside all "RH is evil" and "Double click sucks" discussions.
We do not want to dump KDE nor do we want to be destructive or insult
s.o. So please consider (if not already in CVS) these two attached
patches, which I developed and are already in the RH KDE rpms.

1) kdebase-dock
- modifies kicker to understand the System Tray protocol (used by
GNOME)  described here
http://www.freedesktop.org/standards/systemtray.html
2) kdelibs-dock
- modifies the kwin class to emit System Tray protocol events if not run
under the KDE WM kwin

2) will work under GNOME after the gnome developers fixed their panel
code to display the icon correctly.

I hope you, Than Ngo and myself can create a constructive relationship,
that KDE on RH will not be "crippleware" and third party KDE apps
compile sanely on RH.

Yours
Harald

-- 
Harald Hoyer, Software Developer   Tel. : +49-711-96437-0
Red Hat GmbH                       Fax. : +49-711-96437-111
Hauptstaetterstr. 58               Email: Harald.Hoyer at redhat.de        
D-70178 Stuttgart                  Web  : http://www.redhat.de/

-------------- next part --------------
--- kdebase-3.0.2/kicker/applets/systemtray/systemtrayapplet.cpp.dock	2002-07-29 19:54:48.000000000 +0200
+++ kdebase-3.0.2/kicker/applets/systemtray/systemtrayapplet.cpp	2002-07-29 20:41:02.000000000 +0200
@@ -94,6 +93,46 @@
              this, SLOT( systemTrayWindowAdded(WId) ) );
     connect( kwin_module, SIGNAL( systemTrayWindowRemoved(WId) ),
              this, SLOT( updateTrayWindows() ) );
+
+    QCString screenstr;
+    screenstr.setNum(qt_xscreen());
+    QCString trayatom = "_NET_SYSTEM_TRAY_S" + screenstr;
+
+    Display *display = qt_xdisplay();
+    
+    net_system_tray_selection = XInternAtom( display,
+					     trayatom, FALSE );
+    net_system_tray_opcode = XInternAtom( display,
+					  "_NET_SYSTEM_TRAY_OPCODE", FALSE );
+
+    // Acquire system tray
+    XSetSelectionOwner(display,
+                       net_system_tray_selection,
+                       winId(),
+                       CurrentTime);
+
+    WId root = qt_xrootwin();
+
+    if (XGetSelectionOwner (display, net_system_tray_selection) \
+	== winId())
+      {
+	XClientMessageEvent xev;
+	
+	xev.type = ClientMessage;
+	xev.window = root
+;
+	xev.message_type = XInternAtom (display, "MANAGER", False);
+	xev.format = 32;
+	xev.data.l[0] = CurrentTime;
+	xev.data.l[1] = net_system_tray_selection;
+	xev.data.l[2] = winId();
+	xev.data.l[3] = 0;        /* manager specific data */
+	xev.data.l[4] = 0;        /* manager specific data */
+	
+	XSendEvent (display, root,
+		    False, StructureNotifyMask, (XEvent *)&xev);
+
+      } 
 }
 
 SystemTrayApplet::~SystemTrayApplet()
@@ -102,6 +141,21 @@
     m_Wins.clear();
 }
 
+bool SystemTrayApplet::x11Event( XEvent *e ) 
+{
+#define SYSTEM_TRAY_REQUEST_DOCK    0
+#define SYSTEM_TRAY_BEGIN_MESSAGE   1
+#define SYSTEM_TRAY_CANCEL_MESSAGE  2
+    if ( e->type == ClientMessage ) {
+      if ( e->xclient.message_type == net_system_tray_opcode && \
+           e->xclient.data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
+        systemTrayWindowAdded(e->xclient.data.l[2]);
+        return true;
+      }
+    }
+    return KPanelApplet::x11Event( e ) ;
+}
+
 void SystemTrayApplet::mousePressEvent(QMouseEvent* e)
 {
     propagateMouseEvent(e);
--- kdebase-3.0.2/kicker/applets/systemtray/systemtrayapplet.h.dock	2002-07-29 19:58:35.000000000 +0200
+++ kdebase-3.0.2/kicker/applets/systemtray/systemtrayapplet.h	2002-07-29 20:34:48.000000000 +0200
@@ -76,6 +76,7 @@
     void mouseDoubleClickEvent(QMouseEvent*);
     void mouseMoveEvent(QMouseEvent*);
     void propagateMouseEvent(QMouseEvent*);
+    bool x11Event( XEvent *e );
 
 protected slots:
     void systemTrayWindowAdded( WId );
@@ -86,7 +87,8 @@
 private:
     KXEmbedList m_Wins;
     KWinModule *kwin_module;
-
+    Atom net_system_tray_selection;
+    Atom net_system_tray_opcode;
 };
 
 #endif
-------------- next part --------------
--- kdelibs-3.0.2/kdecore/kwin.cpp.dock	2002-03-01 15:52:04.000000000 +0100
+++ kdelibs-3.0.2/kdecore/kwin.cpp	2002-08-05 16:03:18.000000000 +0200
@@ -53,6 +53,7 @@
 static bool atoms_created = FALSE;
 extern Atom qt_wm_protocols;
 extern Atom qt_wm_state;
+extern Time qt_x_time;
 
 // Fix for --enable-final. This gets undefined at the end of this file.
 #ifndef None
@@ -180,11 +181,91 @@
 
 void KWin::setSystemTrayWindowFor( WId trayWin, WId forWin )
 {
-    NETWinInfo info( qt_xdisplay(), trayWin, qt_xrootwin(), 0 );
-    if ( !forWin )
+  bool is_kde = true;
+    Display *xdisplay = qt_xdisplay();
+
+    NETRootInfo rootinfo( xdisplay, NET::SupportingWMCheck );
+    const char *wmname = rootinfo.wmName();
+    if ((!wmname) || strncmp("KWin", wmname, 4)) {
+      is_kde = false;
+    }
+
+    if ( !forWin ) {
 	forWin = qt_xrootwin();
+    }
+
+    NETWinInfo info( xdisplay, trayWin, qt_xrootwin(), 0 );
     info.setKDESystemTrayWinFor( forWin );
+
+    if (! is_kde) {
+      static Atom net_system_tray_selection;
+      static Atom net_system_tray_opcode;
+      static bool atoms_created = false;
+
+      if (!atoms_created){
+	const int max = 20;
+	Atom* atoms[max];
+	const char* names[max];
+	Atom atoms_return[max];
+	int n = 0;
+
+	QCString screenstr;
+	screenstr.setNum(qt_xscreen());
+	QCString trayatom = "_NET_SYSTEM_TRAY_S" + screenstr;
+
+	atoms[n] = &net_system_tray_selection;
+	names[n++] = trayatom;
+
+	atoms[n] = &net_system_tray_opcode;
+	names[n++] = "_NET_SYSTEM_TRAY_OPCODE";
+
+	// we need a const_cast for the shitty X API
+	XInternAtoms( xdisplay, const_cast<char**>(names), n, 
+		      FALSE, atoms_return );
+
+	for (int i = 0; i < n; i++ )
+	    *atoms[i] = atoms_return[i];
+
+	atoms_created = True;
+      }
+
+      XGrabServer (xdisplay);
+      Window manager_window = XGetSelectionOwner (xdisplay,
+						  net_system_tray_selection);
+      
+      if ( manager_window != None ) {
+	XSelectInput (xdisplay,
+		      manager_window, StructureNotifyMask);
+      }
+      
+
+      XUngrabServer (xdisplay);
+      XFlush (xdisplay);	
+
+      if ( manager_window != None ) {
+
+#define SYSTEM_TRAY_REQUEST_DOCK    0
+#define SYSTEM_TRAY_BEGIN_MESSAGE   1
+#define SYSTEM_TRAY_CANCEL_MESSAGE  2
+         
+	XClientMessageEvent ev;
+	memset(&ev, 0, sizeof(ev));
+	ev.type = ClientMessage;
+	ev.window = trayWin;
+	ev.message_type = net_system_tray_opcode;
+	ev.format = 32;
+	ev.data.l[0] = qt_x_time;
+	ev.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
+	ev.data.l[2] = trayWin;
+	
+	XSendEvent (xdisplay,
+		    manager_window, false, NoEventMask, (XEvent *)&ev);
+
+	XSync (xdisplay, False);
+      }
+    }
 }
+
 void KWin::setActiveWindow( WId win)
 {
     NETRootInfo info( qt_xdisplay(), 0 );


More information about the kde-core-devel mailing list