aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libLumina/LuminaX11.cpp108
-rw-r--r--libLumina/LuminaX11.h4
-rw-r--r--libLumina/libLumina.pro2
-rw-r--r--lumina-desktop/LSession.cpp4
4 files changed, 115 insertions, 3 deletions
diff --git a/libLumina/LuminaX11.cpp b/libLumina/LuminaX11.cpp
index a6e68ebb..e79915d4 100644
--- a/libLumina/LuminaX11.cpp
+++ b/libLumina/LuminaX11.cpp
@@ -28,8 +28,10 @@
#include <xcb/xcb_ewmh.h>
#include <xcb/xcb_icccm.h>
#include <xcb/xcb_image.h>
+#include <xcb/xcb_aux.h>
#include <xcb/composite.h>
#include <xcb/damage.h>
+//#include <xcb/render.h>
#define DEBUG 0
@@ -1595,6 +1597,112 @@ bool LXCB::UnembedWindow(WId win){
return true;
}
+// ===== startSystemTray() =====
+WId LXCB::startSystemTray(int screen){
+ qDebug() << "Starting System Tray:" << screen;
+ //Setup the freedesktop standards compliance
+
+ //Get the appropriate atom for this screen
+ QString str = QString("_NET_SYSTEM_TRAY_S%1").arg(QString::number(screen));
+ //qDebug() << "Default Screen Atom Name:" << str;
+ xcb_intern_atom_reply_t *treply = xcb_intern_atom_reply(QX11Info::connection(), \
+ xcb_intern_atom(QX11Info::connection(), 0, str.length(), str.toLocal8Bit()), NULL);
+ xcb_intern_atom_reply_t *oreply = xcb_intern_atom_reply(QX11Info::connection(), \
+ xcb_intern_atom(QX11Info::connection(), 0, 28, "_NET_SYSTEM_TRAY_ORIENTATION"), NULL);
+ xcb_intern_atom_reply_t *vreply = xcb_intern_atom_reply(QX11Info::connection(), \
+ xcb_intern_atom(QX11Info::connection(), 0, 23, "_NET_SYSTEM_TRAY_VISUAL"), NULL);
+ if(treply==0){
+ qDebug() << " - ERROR: Could not initialize _NET_SYSTEM_TRAY_S<num> atom";
+ return 0;
+ }
+ if(oreply==0){
+ qDebug() << " - ERROR: Could not initialize _NET_SYSTEM_TRAY_ORIENTATION atom";
+ return 0;
+ }
+ if(vreply==0){
+ qDebug() << " - ERROR: Could not initialize _NET_SYSTEM_TRAY_VISUAL atom";
+ return 0;
+ }
+ xcb_atom_t _NET_SYSTEM_TRAY_S = treply->atom;
+ xcb_atom_t _NET_SYSTEM_TRAY_ORIENTATION = oreply->atom;
+ xcb_atom_t _NET_SYSTEM_TRAY_VISUAL = vreply->atom;
+ free(treply); //done with atom generation
+ free(oreply);
+ free(vreply);
+
+ //Make sure that there is no other system tray running
+ xcb_get_selection_owner_reply_t *ownreply = xcb_get_selection_owner_reply(QX11Info::connection(), \
+ xcb_get_selection_owner_unchecked(QX11Info::connection(), _NET_SYSTEM_TRAY_S), NULL);
+ if(ownreply==0){
+ qWarning() << " - Could not get owner selection reply";
+ return 0;
+ }
+ if(ownreply->owner != 0){
+ free(ownreply);
+ qWarning() << " - An alternate system tray is currently in use";
+ return 0;
+ }
+ free(ownreply);
+
+ //Create a simple window to register as the tray (not visible - just off the screen)
+ xcb_screen_t *root_screen = xcb_aux_get_screen(QX11Info::connection(), QX11Info::appScreen());
+ uint32_t params[] = {1};
+ WId LuminaSessionTrayID = xcb_generate_id(QX11Info::connection()); //need a new ID
+ xcb_create_window(QX11Info::connection(), root_screen->root_depth, \
+ LuminaSessionTrayID, root_screen->root, -1, -1, 1, 1, 0, \
+ XCB_WINDOW_CLASS_INPUT_OUTPUT, root_screen->root_visual, \
+ XCB_CW_OVERRIDE_REDIRECT, params);
+
+ //Now register this widget as the system tray
+ xcb_set_selection_owner(QX11Info::connection(), LuminaSessionTrayID, _NET_SYSTEM_TRAY_S, XCB_CURRENT_TIME);
+ //Make sure that it was registered properly
+ ownreply = xcb_get_selection_owner_reply(QX11Info::connection(), \
+ xcb_get_selection_owner_unchecked(QX11Info::connection(), _NET_SYSTEM_TRAY_S), NULL);
+
+ if(ownreply==0 || ownreply->owner != LuminaSessionTrayID){
+ if(ownreply!=0){ free(ownreply); }
+ qWarning() << " - Could not register the system tray";
+ xcb_destroy_window(QX11Info::connection(), LuminaSessionTrayID);
+ return 0;
+ }
+ free(ownreply); //done with structure
+
+ //Now register the orientation of the system tray
+ uint32_t orient = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
+ xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, LuminaSessionTrayID, \
+ _NET_SYSTEM_TRAY_ORIENTATION, XCB_ATOM_CARDINAL, 32, 1, &orient);
+
+ //Now set the visual ID for the system tray (same as the root window, but TrueColor)
+ xcb_visualtype_t *type = xcb_aux_find_visual_by_attrs(root_screen, XCB_VISUAL_CLASS_TRUE_COLOR, 32);
+ if(type!=0){
+ xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, LuminaSessionTrayID, \
+ _NET_SYSTEM_TRAY_VISUAL, XCB_ATOM_VISUALID, 32, 1, &type->visual_id);
+ }else{
+ qWarning() << " - Could not set TrueColor visual for system tray";
+ }
+
+ //Finally, send out an X event letting others know that the system tray is up and running
+ xcb_client_message_event_t event;
+ event.response_type = XCB_CLIENT_MESSAGE;
+ event.format = 32;
+ event.window = root_screen->root;
+ event.type = EWMH.MANAGER; //MANAGER atom
+ event.data.data32[0] = CurrentTime;
+ event.data.data32[1] = _NET_SYSTEM_TRAY_S; //_NET_SYSTEM_TRAY_S atom
+ event.data.data32[2] = LuminaSessionTrayID;
+ event.data.data32[3] = 0;
+ event.data.data32[4] = 0;
+
+ xcb_send_event(QX11Info::connection(), 0, root_screen->root, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
+
+ //Success
+ return LuminaSessionTrayID;
+}
+
+// ===== closeSystemTray() =====
+void LXCB::closeSystemTray(WId trayID){
+ xcb_destroy_window(QX11Info::connection(), trayID);
+}
// === SetScreenWorkArea() ===
/*void LXCB::SetScreenWorkArea(unsigned int screen, QRect rect){
diff --git a/libLumina/LuminaX11.h b/libLumina/LuminaX11.h
index df2a78d2..7d7585e6 100644
--- a/libLumina/LuminaX11.h
+++ b/libLumina/LuminaX11.h
@@ -164,6 +164,10 @@ public:
uint EmbedWindow(WId win, WId container); //returns the damage ID (or 0 for an error)
bool UnembedWindow(WId win);
+ //System Tray Management
+ WId startSystemTray(int screen = 0); //Startup the system tray (returns window ID for tray)
+ void closeSystemTray(WId); //Close the system tray
+
};
#endif \ No newline at end of file
diff --git a/libLumina/libLumina.pro b/libLumina/libLumina.pro
index d7df7960..e811aada 100644
--- a/libLumina/libLumina.pro
+++ b/libLumina/libLumina.pro
@@ -59,7 +59,7 @@ equals(LINUX_DISTRIBUTION, "Debian"): {
INCLUDEPATH += $$PREFIX/include
-LIBS += -lX11 -lc -lXrender -lXcomposite -lxcb -lxcb-ewmh -lxcb-icccm -lxcb-image -lxcb-composite -lxcb-damage
+LIBS += -lX11 -lc -lXrender -lXcomposite -lxcb -lxcb-ewmh -lxcb-icccm -lxcb-image -lxcb-composite -lxcb-damage -lxcb-render
include.path=$$PREFIX/include/
include.files=LuminaXDG.h \
diff --git a/lumina-desktop/LSession.cpp b/lumina-desktop/LSession.cpp
index 8286bdd6..2dd841df 100644
--- a/lumina-desktop/LSession.cpp
+++ b/lumina-desktop/LSession.cpp
@@ -773,7 +773,7 @@ QList<WId> LSession::currentTrayApps(WId visualTray){
void LSession::startSystemTray(){
if(SystemTrayID!=0){ return; }
RunningTrayApps.clear(); //nothing running yet
- SystemTrayID = LX11::startSystemTray(0);
+ SystemTrayID = XCB->startSystemTray(0);
TrayStopping = false;
if(SystemTrayID!=0){
XSelectInput(QX11Info::display(), SystemTrayID, InputOutput); //make sure TrayID events get forwarded here
@@ -801,7 +801,7 @@ void LSession::stopSystemTray(bool detachall){
}
}
//Now close down the tray backend
- LX11::closeSystemTray(SystemTrayID);
+ XCB->closeSystemTray(SystemTrayID);
SystemTrayID = 0;
TrayDmgEvent = 0;
TrayDmgError = 0;
bgstack15