diff --git a/atoms.cpp b/atoms.cpp index 6b96134406..26fd434165 100644 --- a/atoms.cpp +++ b/atoms.cpp @@ -8,8 +8,15 @@ Atoms::Atoms() wm_protocols = XInternAtom(qt_xdisplay(), "WM_PROTOCOLS", FALSE); wm_delete_window = XInternAtom(qt_xdisplay(), "WM_DELETE_WINDOW", FALSE); wm_take_focus = XInternAtom(qt_xdisplay(), "WM_TAKE_FOCUS", FALSE); - + // compatibility kwm_win_icon = XInternAtom(qt_xdisplay(), "KWM_WIN_ICON", FALSE); + + net_number_of_desktops = XInternAtom(qt_xdisplay(), "_NET_NUMBER_OF_DESKTOPS", False); + net_current_desktop = XInternAtom(qt_xdisplay(), "_NET_CURRENT_DESKTOP", False); + net_active_window = XInternAtom(qt_xdisplay(), "_NET_ACTIVE_WINDOW", False); + + net_client_list = XInternAtom(qt_xdisplay(), "_NET_CLIENT_LIST", False); + net_client_list_stacking = XInternAtom(qt_xdisplay(), "_NET_CLIENT_LIST_STACKIN", False); } diff --git a/atoms.h b/atoms.h index 437dd3cb39..0f5fd9e6f6 100644 --- a/atoms.h +++ b/atoms.h @@ -10,6 +10,12 @@ public: Atom wm_delete_window; Atom wm_take_focus; Atom kwm_win_icon; // compatibility + + Atom net_number_of_desktops; + Atom net_current_desktop; + Atom net_active_window; + Atom net_client_list; + Atom net_client_list_stacking; }; diff --git a/client.cpp b/client.cpp index 45bd8b3d8b..60f621f064 100644 --- a/client.cpp +++ b/client.cpp @@ -58,173 +58,6 @@ static void sendClientMessage(Window w, Atom a, long x){ } -static int _getprop(Window w, Atom a, Atom type, long len, unsigned char **p){ - Atom real_type; - int format; - unsigned long n, extra; - int status; - - status = XGetWindowProperty(qt_xdisplay(), w, a, 0L, len, False, type, &real_type, &format, &n, &extra, p); - if (status != Success || *p == 0) - return -1; - if (n == 0) - XFree((char*) *p); - /* could check real_type, format, extra here... */ - return n; -} -static bool getDoubleProperty(Window w, Atom a, long &result1, long &result2){ - long *p = 0; - - if (_getprop(w, a, a, 2L, (unsigned char**)&p) <= 0){ - return FALSE; - } - - result1 = p[0]; - result2 = p[1]; - XFree((char *) p); - return TRUE; -} -QPixmap KWM::miniIcon(Window w, int width, int height){ - QPixmap result; - Pixmap p = None; - Pixmap p_mask = None; - - long tmp[2] = {None, None}; - if (!getDoubleProperty(w, atoms->kwm_win_icon, tmp[0], tmp[1])){ - XWMHints *hints = XGetWMHints(qt_xdisplay(), w); - if (hints && (hints->flags & IconPixmapHint)){ - p = hints->icon_pixmap; - } - if (hints && (hints->flags & IconMaskHint)){ - p_mask = hints->icon_mask; - } - if (hints) - XFree((char*)hints); - } - else { - p = (Pixmap) tmp[0]; - p_mask = (Pixmap) tmp[1]; - } - - if (p != None){ - Window root; - int x, y; - unsigned int w = 0; - unsigned int h = 0; - unsigned int border_w, depth; - XGetGeometry(qt_xdisplay(), p, - &root, - &x, &y, &w, &h, &border_w, &depth); - if (w > 0 && h > 0){ - QPixmap pm(w, h, depth); - XCopyArea(qt_xdisplay(), p, pm.handle(), - qt_xget_temp_gc(depth==1), - 0, 0, w, h, 0, 0); - if (p_mask != None){ - QBitmap bm(w, h); - XCopyArea(qt_xdisplay(), p_mask, bm.handle(), - qt_xget_temp_gc(TRUE), - 0, 0, w, h, 0, 0); - pm.setMask(bm); - } - if (width > 0 && height > 0 && (w > (unsigned int)width - || h > (unsigned int) height)){ - // scale - QWMatrix m; - m.scale(width/(float)w, height/(float)h); - result = pm.xForm(m); - } - else - result = pm; - } - } - else { - XWMHints *hints = XGetWMHints(qt_xdisplay(), w); - if (hints && - (hints->flags & WindowGroupHint) - && hints->window_group != None - && hints->window_group != w){ - Window wg = hints->window_group; - XFree((char*)hints); - return miniIcon(wg, width, height); - } - if (hints) - XFree((char*)hints); - Window trans = None; - if (XGetTransientForHint(qt_xdisplay(), w, &trans)){ - if (trans != w) - return miniIcon(trans, width, height); - } - } - return result; -} - -QPixmap KWM::icon(Window w, int width, int height){ - QPixmap result; - Pixmap p = None; - Pixmap p_mask = None; - - XWMHints *hints = XGetWMHints(qt_xdisplay(), w); - if (hints && (hints->flags & IconPixmapHint)){ - p = hints->icon_pixmap; - } - if (hints && (hints->flags & IconMaskHint)){ - p_mask = hints->icon_mask; - } - if (hints) - XFree((char*)hints); - - if (p != None){ - Window root; - int x, y; - unsigned int w = 0; - unsigned int h = 0; - unsigned int border_w, depth; - XGetGeometry(qt_xdisplay(), p, - &root, - &x, &y, &w, &h, &border_w, &depth); - if (w > 0 && h > 0){ - QPixmap pm(w, h, depth); - XCopyArea(qt_xdisplay(), p, pm.handle(), - qt_xget_temp_gc(depth==1), - 0, 0, w, h, 0, 0); - if (p_mask != None){ - QBitmap bm(w, h); - XCopyArea(qt_xdisplay(), p_mask, bm.handle(), - qt_xget_temp_gc(TRUE), - 0, 0, w, h, 0, 0); - pm.setMask(bm); - } - if (width > 0 && height > 0 && (w > (unsigned int)width - || h > (unsigned int) height)){ - // scale - QWMatrix m; - m.scale(width/(float)w, height/(float)h); - result = pm.xForm(m); - } - else - result = pm; - } - } - else { - XWMHints *hints = XGetWMHints(qt_xdisplay(), w); - if (hints && - (hints->flags & WindowGroupHint) - && hints->window_group != None - && hints->window_group != w){ - XFree((char*)hints); - return icon(hints->window_group, width, height); - } - if (hints) - XFree((char*)hints); - Window trans = None; - if (XGetTransientForHint(qt_xdisplay(), w, &trans)){ - if (trans != w) - return icon(trans, width, height); - } - } - return result; -} /*! \class WindowWrapper client.h @@ -493,10 +326,11 @@ void Client::manage( bool isMapped ) // ### TODO check XGetWMHints() for initial mapping state, icon, etc. pp. // assume window wants to be visible on the current desktop - desk = workspace()->currentDesktop(); + desk = KWM::desktop( win ); //workspace()->currentDesktop(); setMappingState( NormalState ); - desk = workspace()->currentDesktop(); - show(); + if ( isOnDesktop( workspace()->currentDesktop() ) ) { + show(); + } if ( options->focusPolicyIsReasonable() ) workspace()->requestFocus( this ); @@ -639,7 +473,7 @@ bool Client::unmapNotify( XUnmapEvent& e ) // maybe we will be destroyed soon. Check this first. XEvent ev; QApplication::syncX(); - if ( XCheckTypedWindowEvent (qt_xdisplay(), win, + if ( XCheckTypedWindowEvent (qt_xdisplay(), win, DestroyNotify, &ev) ){ workspace()->destroyClient( this ); return TRUE; @@ -1451,8 +1285,10 @@ void Client::setSticky( bool b ) if ( is_sticky == b ) return; is_sticky = b; - if ( !is_sticky ) + if ( !is_sticky ) { desk = workspace()->currentDesktop(); + KWM::moveToDesktop( win, desk );//##### compatibility + } stickyChange( is_sticky ); } diff --git a/client.h b/client.h index b1314aae9a..e68ac546c1 100644 --- a/client.h +++ b/client.h @@ -2,6 +2,7 @@ #define CLIENT_H #include "options.h" +#include #include #include #include @@ -12,13 +13,6 @@ class Workspace; class Client; -class KWM -{ -public: - static QPixmap miniIcon(Window w, int width=0, int height=0); - static QPixmap icon(Window w, int width=0, int height=0); -}; - class WindowWrapper : public QWidget { Q_OBJECT diff --git a/options.cpp b/options.cpp index e24f0cd52b..9065704baf 100644 --- a/options.cpp +++ b/options.cpp @@ -57,20 +57,24 @@ void Options::reload() // normal colors colors[Frame] = Qt::lightGray; colors[Frame] = config->readColorEntry("frame", &colors[Frame]); - colors[Handle] = config->readColorEntry("handle", &colors[Frame]); + colors[Handle] = QColor( 140, 140, 140 ); + colors[Handle] = config->readColorEntry("handle", &colors[Handle]); + colors[ButtonBg] = QColor(163,163,163 ); colors[ButtonBg] = config->readColorEntry("buttonBackgroundDown", &colors[Frame]); + colors[ButtonBlend] = QColor(0,0,0); colors[ButtonBlend] = config->readColorEntry("buttonBlendDown", - &colors[ButtonBg]); + &colors[ButtonBlend]); colors[TitleBar] = Qt::darkBlue; colors[TitleBar] = config->readColorEntry("activeBackground", &colors[TitleBar]); + colors[TitleBlend] = colors[ TitleBar ]; colors[TitleBlend] = config->readColorEntry("activeBlend", - &colors[TitleBar]); + &colors[TitleBlend]); colors[Font] = Qt::white; colors[Font] = config->readColorEntry("activeForeground", &colors[Font]); - colors[ButtonFg] = Qt::lightGray; + colors[ButtonFg] = QColor(144,170,191); colors[ButtonFg] = config->readColorEntry("buttonForegroundDown", &colors[ButtonFg]); @@ -82,6 +86,7 @@ void Options::reload() readColorEntry("inactiveBackground", &colors[TitleBar+KWINCOLORS]); colors[TitleBlend+KWINCOLORS] = config->readColorEntry("inactiveBlend", &colors[TitleBar+KWINCOLORS]); + colors[ButtonBg+KWINCOLORS] = QColor(163,163,163); colors[ButtonBg+KWINCOLORS] = config->readColorEntry("buttonBackground", &colors[ButtonBg]); diff --git a/stdclient.cpp b/stdclient.cpp index 77e96a88d5..b9d81c0d23 100644 --- a/stdclient.cpp +++ b/stdclient.cpp @@ -136,7 +136,7 @@ static const char * pinup_xpm[] = { " ", " ", " ", -" "}; +" "}; static const char * pindown_xpm[] = { /* width height num_colors chars_per_pixel */ @@ -162,7 +162,7 @@ static const char * pindown_xpm[] = { " ...... ", " ", " ", -" "}; +" "}; static QPixmap* close_pix = 0; static QPixmap* maximize_pix = 0; @@ -183,7 +183,7 @@ static void create_pixmaps() normalize_pix = new QPixmap( normalize_xpm ); pinup_pix = new QPixmap( pinup_xpm ); pindown_pix = new QPixmap( pindown_xpm ); - + } @@ -232,7 +232,7 @@ StdClient::StdClient( Workspace *ws, WId w, QWidget *parent, const char *name ) button[1]->setIconSet( isSticky()?*pindown_pix:*pinup_pix ); connect( button[1], SIGNAL( clicked() ), this, ( SLOT( toggleSticky() ) ) ); button[2]->hide(); - + button[3]->setIconSet( *minimize_pix ); connect( button[3], SIGNAL( clicked() ), this, ( SLOT( iconify() ) ) ); button[4]->setIconSet( *maximize_pix ); diff --git a/tabbox.cpp b/tabbox.cpp index 547caaa62c..377b163ef1 100644 --- a/tabbox.cpp +++ b/tabbox.cpp @@ -154,7 +154,7 @@ void TabBox::paintContents() if ( currentClient() ) { QString s; if (!client->isOnDesktop(workspace()->currentDesktop())){ - //TODO s = KWM::desktopName(client->desktop); + s = KWM::desktopName(client->desktop()); s.append(": "); } diff --git a/workspace.cpp b/workspace.cpp index 9497673f8f..51a583008a 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -30,6 +30,7 @@ static Client* clientFactory( Workspace *ws, WId w ) } if ( s == "Kicker" ) { Client * c = new NoBorderClient( ws, w); + c->setSticky( TRUE ); return c; } @@ -61,6 +62,7 @@ Workspace::Workspace() grabKey(XK_Tab, ControlMask); grabKey(XK_Tab, ControlMask | ShiftMask); + } Workspace::Workspace( WId rootwin ) @@ -85,7 +87,6 @@ Workspace::Workspace( WId rootwin ) grabKey(XK_Tab, Mod1Mask | ShiftMask); grabKey(XK_Tab, ControlMask); grabKey(XK_Tab, ControlMask | ShiftMask); - } void Workspace::init() @@ -94,7 +95,10 @@ void Workspace::init() active_client = 0; should_get_focus = 0; desktop_client = 0; - current_desktop = 1; + current_desktop = 0; + number_of_desktops = 0; + setNumberOfDesktops( 4 ); // TODO options + setCurrentDesktop( 1 ); unsigned int i, nwins; Window dw1, dw2, *wins; @@ -126,6 +130,7 @@ void Workspace::init() XFree((void *) wins); XUngrabServer( qt_xdisplay() ); popup = 0; + propagateClients(); } Workspace::~Workspace() @@ -184,6 +189,7 @@ bool Workspace::workspaceEvent( XEvent * e ) clients.append( c ); if ( c != desktop_client ) stacking_order.append( c ); + propagateClients(); } bool result = c->windowEvent( e ); if ( c == desktop_client ) @@ -238,6 +244,9 @@ bool Workspace::workspaceEvent( XEvent * e ) break; case FocusOut: break; + case ClientMessage: + return clientMessage(e->xclient); + break; default: break; } @@ -288,6 +297,7 @@ bool Workspace::destroyClient( Client* c) c->invalidateWindow(); delete c; clientHidden( c ); + propagateClients(); return TRUE; } @@ -432,7 +442,7 @@ bool Workspace::keyRelease(XKeyEvent key) tab_box->hide(); control_grab = False; if ( tab_box->currentDesktop() != -1 ) - switchDesktop( tab_box->currentDesktop() ); + setCurrentDesktop( tab_box->currentDesktop() ); } } return FALSE; @@ -556,7 +566,9 @@ void Workspace::grabKey(KeySym keysym, unsigned int mod){ Informs the workspace about the active client, i.e. the client that has the focus (or None if no client has the focus). This functions is called by the client itself that gets focus. It has no other - effect than fixing the focus chain and the return value of activeClient() + effect than fixing the focus chain and the return value of + activeClient(). And of course, to propagate the active client to the + world. */ void Workspace::setActiveClient( Client* c ) { @@ -569,6 +581,11 @@ void Workspace::setActiveClient( Client* c ) focus_chain.remove( c ); focus_chain.append( c ); } + WId w = active_client? active_client->window() : 0; + XChangeProperty(qt_xdisplay(), qt_xrootwin(), + atoms->net_active_window, XA_WINDOW, 32, + PropModeReplace, (unsigned char *)&w, 1); + } @@ -767,6 +784,8 @@ void Workspace::raiseClient( Client* c ) if ( c->transientFor() ) raiseClient( findClient( c->transientFor() ) ); + + propagateClients( TRUE ); } @@ -814,8 +833,15 @@ void Workspace::setDesktopClient( Client* c) } } -void Workspace::switchDesktop( int new_desktop ){ - if (new_desktop == current_desktop ) + +/*! + Sets the current desktop to \a new_desktop + + Shows/Hides windows according to the stacking order and finally + propages the new desktop to the world + */ +void Workspace::setCurrentDesktop( int new_desktop ){ + if (new_desktop == current_desktop || new_desktop < 1 || new_desktop > number_of_desktops ) return; /* @@ -837,6 +863,11 @@ void Workspace::switchDesktop( int new_desktop ){ } current_desktop = new_desktop; + + XChangeProperty(qt_xdisplay(), qt_xrootwin(), + atoms->net_current_desktop, XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)¤t_desktop, 1); + KWM::switchToDesktop( current_desktop ); // ### compatibility } @@ -880,3 +911,65 @@ QWidget* Workspace::desktopWidget() { return desktop_widget; } + +/*! + Sets the number of virtual desktops to \a n + */ +void Workspace::setNumberOfDesktops( int n ) +{ + if ( n == number_of_desktops ) + return; + number_of_desktops = n; + XChangeProperty(qt_xdisplay(), qt_xrootwin(), + atoms->net_number_of_desktops, XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)&number_of_desktops, 1); +} + +/*! + Handles client messages sent to the workspace + */ +bool Workspace::clientMessage( XClientMessageEvent msg ) +{ + if ( msg.message_type == atoms->net_active_window ) { + Client * c = findClient( msg.data.l[0] ); + if ( c ) { + activateClient( c ); + return TRUE; + } + } else if ( msg.message_type == atoms->net_current_desktop ) { + setCurrentDesktop( msg.data.l[0] ); + return TRUE; + } + + return FALSE; +} + +/*! + Propagates the managed clients to the world + */ +void Workspace::propagateClients( bool onlyStacking ) +{ + WId* cl; + int i; + if ( !onlyStacking ) { + WId* cl = new WId[ clients.count()]; + i = 0; + for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it ) { + cl[i++] = (*it)->window(); + } + XChangeProperty(qt_xdisplay(), qt_xrootwin(), + atoms->net_client_list, XA_WINDOW, 32, + PropModeReplace, (unsigned char *)cl, clients.count()); + delete [] cl; + } + + cl = new WId[ stacking_order.count()]; + i = 0; + for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it) { + cl[i++] = (*it)->window(); + } + XChangeProperty(qt_xdisplay(), qt_xrootwin(), + atoms->net_client_list_stacking, XA_WINDOW, 32, + PropModeReplace, (unsigned char *)cl, stacking_order.count()); + delete [] cl; +} diff --git a/workspace.h b/workspace.h index 0c08047fa3..fb11c3282c 100644 --- a/workspace.h +++ b/workspace.h @@ -41,8 +41,10 @@ public: void clientHidden( Client* ); int currentDesktop() const; + void setCurrentDesktop( int new_desktop ); int numberOfDesktops() const; - + void setNumberOfDesktops( int n ); + QWidget* desktopWidget(); void grabKey(KeySym keysym, unsigned int mod); @@ -59,13 +61,13 @@ public: void showPopup( const QPoint&, Client* ); void setDesktopClient( Client* ); - void switchDesktop( int new_desktop ); void makeFullScreen( Client* ); protected: bool keyPress( XKeyEvent key ); bool keyRelease( XKeyEvent key ); + bool clientMessage( XClientMessageEvent msg ); private: void init(); @@ -87,12 +89,15 @@ private: void focusToNull(); Client* desktop_client; int current_desktop; + int number_of_desktops; Client* popup_client; QWidget* desktop_widget; //experimental void setDecoration( int deco ); + + void propagateClients( bool onlyStacking = FALSE); }; inline WId Workspace::rootWin() const