From b9466363b3a231ceb96ae757073f1b5efba5fc94 Mon Sep 17 00:00:00 2001 From: Henrik Kinnunen Date: Thu, 16 Oct 2008 22:38:42 +0200 Subject: Fixed so Extended Window Manager Hints actually work, needs more work though. --- ChangeLog | 9 ++- src/ClientHandler.hh | 3 +- src/Ewmh.cc | 118 +++++++++++++++++++---------- src/Ewmh.hh | 3 +- src/FbPager.cc | 208 ++++++++++++++++++++++++++++++--------------------- src/FbPager.hh | 23 +++--- src/FbTk/Makefile.in | 1 + src/Makefile.am | 4 +- src/Pager.hh | 8 ++ src/PropertyTools.cc | 71 ++++++++++++++++++ src/PropertyTools.hh | 38 ++++++++++ src/Workspace.cc | 48 +++++++----- src/Workspace.hh | 20 ++--- src/main.cc | 4 +- 14 files changed, 387 insertions(+), 171 deletions(-) create mode 100644 src/PropertyTools.cc create mode 100644 src/PropertyTools.hh diff --git a/ChangeLog b/ChangeLog index 14cacef..26e28e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,12 @@ * format ( year-month-day) +----- Version 0.1.6 +* 2008-10-16: + * Fixed so Extended Window Manager Hints actually work. ---- Version 0.1.5 * 2007-10-17: * Fixed gcc compile fix * Added _NET_DESKTOP_LAYOUT support - Which allows the WM to know the desktop layout displayed by + Which allows the WM to know the desktop layout displayed by the pager. ---- Version 0.1.4 * 2004-03-24: @@ -35,13 +38,13 @@ * Added -sr argument This will show the resources and value and exit fbpager main.cc, FbPager.hh/cc - * alot of new resources and updates, check README (Thanks Mathias Gumz) + * alot of new resources and updates, check README (Thanks Mathias Gumz) * 2004-02-27: * Fixed mouse gestures (Thanks Mathias Gumz) FbPager.hh/cc * Added fbpager.nextWorkspaceButton and fbpager.prevWorkspaceButton (Thanks Mathias Gumz) - Use these to define which button combination to move to next/prev + Use these to define which button combination to move to next/prev workspace FbPager.cc * Added fbpager.exitButton resource (Thanks Mathias Gumz) diff --git a/src/ClientHandler.hh b/src/ClientHandler.hh index 1ec128d..914fb34 100644 --- a/src/ClientHandler.hh +++ b/src/ClientHandler.hh @@ -1,6 +1,6 @@ // ClientHandler.hh for FbPager // Copyright (c) 2004 Henrik Kinnunen (fluxgen at users.sourceforge.net) -// +// // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation @@ -59,6 +59,7 @@ public: Orientation orientation, Corner starting_corner, unsigned int columns, unsigned int rows) = 0; + virtual bool propertyNotify( Pager &pager, XPropertyEvent &event) = 0; }; } // end namespace FbPager diff --git a/src/Ewmh.cc b/src/Ewmh.cc index 87e55bf..9f89f08 100644 --- a/src/Ewmh.cc +++ b/src/Ewmh.cc @@ -1,6 +1,6 @@ // Ewmh.cc for FbPager // Copyright (c) 2004 Henrik Kinnunen (fluxgen at users.sourceforge.net) -// +// // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation @@ -27,6 +27,7 @@ #include "FbTk/App.hh" #include "FbTk/FbWindow.hh" #include "FbRootWindow.hh" +#include "PropertyTools.hh" #include @@ -36,7 +37,41 @@ #include #include + using namespace std; +using namespace PropertyTools; + + +struct PropT { + PropT(unsigned char *data, unsigned int num):data(data), num(num) { } + ~PropT() { + if (data != 0) + XFree(data); + } + unsigned char *data; + unsigned int num; +}; + + +typedef std::auto_ptr PropTPtr; + +PropT *property(const FbTk::FbWindow &win, Atom atom, + Atom type, unsigned int num) { + Atom ret_type; + int fmt; + unsigned long nitems, bytes_after; + unsigned char *data = 0; + win.property(atom, + 0, num, + False, + type, + &ret_type, &fmt, + &nitems, + &bytes_after, + &data); + return new PropT(data, nitems); + +} namespace FbPager { @@ -56,7 +91,7 @@ public: wm_pid = XInternAtom(disp, "_NET_WM_PID", False); wm_type = XInternAtom(disp, "_NET_WM_WINDOW_TYPE", False); type_dock = XInternAtom(disp, "_NET_WM_WINDOW_TYPE_DOCK", False); - number_of_desktops = XInternAtom(disp, "_NET_NUMBER_OF_DESKTOPS", False); + number_of_desktops = XInternAtom(disp, "_NET_NUMBER_OF_DESKTOPS", False); current_desktop = XInternAtom(disp, "_NET_CURRENT_DESKTOP", False); clientlist = XInternAtom(disp, "_NET_CLIENT_LIST", False); moveresize_window = XInternAtom(disp, "_NET_MOVERESIZE_WINDOW", False); @@ -64,11 +99,11 @@ public: close_window = XInternAtom(disp, "_NET_CLOSE_WINDOW", False); desktop_layout = XInternAtom(disp, "_NET_DESKTOP_LAYOUT", False); } - Atom state_skip_pager, state_skip_taskbar, state_sticky, + Atom state_skip_pager, state_skip_taskbar, state_sticky, state_hidden, state_shaded, state_above, state_below; Atom wm_desktop, wm_state, wm_pid, wm_type; Atom type_dock; - Atom number_of_desktops, current_desktop; + Atom number_of_desktops, current_desktop; Atom clientlist; Atom moveresize_window; Atom active_window; @@ -106,11 +141,11 @@ void Ewmh::setDesktopLayout(FbTk::FbWindow &root, (unsigned char*)data, 4 ); } -void Ewmh::moveResize(FbTk::FbWindow &win) { +void Ewmh::moveResize(FbTk::FbWindow &win) { - // We can't do this yet, there is a bug in fluxbox 0.9.8 + // We can't do this yet, there is a bug in fluxbox 0.9.8 // and this makes it crash (it's fixed in cvs though) - /* + /* Display *disp = FbTk::App::instance()->display(); XEvent event; event.xclient.display = disp; @@ -144,9 +179,44 @@ void Ewmh::closeWindow(FbTk::FbWindow &win) { XSendEvent(disp, RootWindow(disp, DefaultScreen(disp)), False, SubstructureNotifyMask, &event); } +bool Ewmh::propertyNotify(Pager &pager, XPropertyEvent &event) try { + if (event.window != DefaultRootWindow(FbTk::App::instance()->display())) { + return false; + } + if (event.atom == m_data->current_desktop) { + pager.setCurrentWorkspace(getIntProperty(event.window, event.atom)); + } else if (event.atom == m_data->number_of_desktops) { + pager.updateWorkspaceCount(getIntProperty(event.window, event.atom)); + } else if (event.atom == m_data->active_window) { + pager.setFocusedWindow(getWinProperty(event.window, event.atom)); + } else if (event.atom == m_data->clientlist) { + vector windows; + getWinArrayProperty(DefaultRootWindow(FbTk::App::instance()->display()), event.atom, windows); + std::vector< pair > wins_workspaces; + for ( unsigned int win = 0; win < windows.size(); ++win ) { + wins_workspaces. + push_back( std::make_pair(windows[win], + getIntProperty(windows[win], + m_data->wm_desktop))); + } + pager.addWindows(wins_workspaces); + } else { + // did not handle it here + return false; + } + + return true; + +} catch ( const PropertyException& e ) { + cerr << "Ewmh Exception: " << e.what() << endl; + // we handle it + return true; +} + bool Ewmh::clientMessage(Pager &pager, XClientMessageEvent &event) { if (!m_support) - return false; + return false; + if (event.message_type == m_data->current_desktop) { pager.setCurrentWorkspace(event.data.l[0]); @@ -180,7 +250,7 @@ void Ewmh::changeWorkspace(int screen_num, int workspace) { } void Ewmh::setHints(FbTk::FbWindow &win, WindowHint &hint) { - + int data = getpid(); win.changeProperty(m_data->wm_pid, XA_CARDINAL, @@ -238,36 +308,6 @@ void Ewmh::setHints(FbTk::FbWindow &win, WindowHint &hint) { } -struct PropT { - PropT(unsigned char *data, unsigned int num):data(data), num(num) { } - ~PropT() { - if (data != 0) - XFree(data); - } - unsigned char *data; - unsigned int num; -}; - -typedef std::auto_ptr PropTPtr; - -PropT *property(const FbTk::FbWindow &win, Atom atom, - Atom type, unsigned int num) { - Atom ret_type; - int fmt; - unsigned long nitems, bytes_after; - unsigned char *data = 0; - win.property(atom, - 0, num, - False, - type, - &ret_type, &fmt, - &nitems, - &bytes_after, - &data); - return new PropT(data, nitems); - -} - void Ewmh::getHints(const FbTk::FbWindow &win, WindowHint &hint) const { PropTPtr p(property(win, m_data->wm_state, diff --git a/src/Ewmh.hh b/src/Ewmh.hh index 68c42b2..db1c17f 100644 --- a/src/Ewmh.hh +++ b/src/Ewmh.hh @@ -1,6 +1,6 @@ // Ewmh.hh for FbPager // Copyright (c) 2004 Henrik Kinnunen (fluxgen at users.sourceforge.net) -// +// // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation @@ -46,6 +46,7 @@ public: Orientation orientation, Corner starting_corner, unsigned int columns, unsigned int rows); + bool propertyNotify( Pager &pager, XPropertyEvent &event); private: bool m_support; std::auto_ptr m_data; diff --git a/src/FbPager.cc b/src/FbPager.cc index 3955200..d254f02 100644 --- a/src/FbPager.cc +++ b/src/FbPager.cc @@ -1,6 +1,6 @@ // FbPager.cc for FbPager // Copyright (c) 2003-2004 Henrik Kinnunen (fluxgen at users.sourceforge.net) -// +// // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation @@ -58,7 +58,7 @@ #include #define FB_istringstream istringstream #define FB_ostringstream ostringstream -#elif HAVE_STRSTREAM +#elif HAVE_STRSTREAM #include #define FB_istringstream istrstream #define FB_ostringstream ostrstream @@ -89,12 +89,12 @@ bool compareButtonQueues(std::string q1, std::string q2) { FbTk::StringUtil::removeFirstWhitespace(q2); FbTk::StringUtil::removeTrailingWhitespace(q1); FbTk::StringUtil::removeTrailingWhitespace(q2); - + return q1 == q2; } -// little helper to keep win visible in bigwin +// little helper to keep win visible in bigwin void respectConstraints(int& x, int& y, const FbTk::FbWindow& win, const FbTk::FbWindow& bigwin) { @@ -116,7 +116,7 @@ void respectConstraints(int& x, int& y, namespace FbPager { -FbPager::FbPager(int screen_num, bool withdraw, +FbPager::FbPager(int screen_num, bool withdraw, bool show_resources, int layer_flag, const char *resource_filename): @@ -161,14 +161,14 @@ FbPager::FbPager(int screen_num, bool withdraw, m_follow_scale(m_resmanager, "height", "fbpager.followScale", "FbPager.followScale"), - m_change_workspace_button(m_resmanager, "1", - "fbpager.changeWorkspaceButton", + m_change_workspace_button(m_resmanager, "1", + "fbpager.changeWorkspaceButton", "FbPager.ChangeWorkspaceButton"), - m_raise_window_button(m_resmanager, "2", - "fbpager.raiseWindowButton", + m_raise_window_button(m_resmanager, "2", + "fbpager.raiseWindowButton", "FbPager.RaiseWindowButton"), - m_lower_window_button(m_resmanager, "3", - "fbpager.lowerWindowButton", + m_lower_window_button(m_resmanager, "3", + "fbpager.lowerWindowButton", "FbPager.LowerWindowButton"), m_close_window_button(m_resmanager, "3 3 1", "fbpager.closeWindowButton", @@ -188,26 +188,26 @@ FbPager::FbPager(int screen_num, bool withdraw, m_drag_to_workspace_button(m_resmanager, 3, "fbpager.dragToWorkspaceButton", "FbPager.DragToWorkspaceButtton"), - m_align(m_resmanager, LEFT_TO_RIGHT, - "fbpager.align", + m_align(m_resmanager, LEFT_TO_RIGHT, + "fbpager.align", "FbPager.Align"), m_color_str(m_resmanager, "white", "fbpager.color", "FbPager.Color"), - m_window_color_str(m_resmanager, "white", - "fbpager.windowColor", + m_window_color_str(m_resmanager, "white", + "fbpager.windowColor", "FbPager.WindowColor"), m_focused_window_color_str(m_resmanager, "white", "fbpager.focusedWindowColor", "FbPager.FocusedWindowColor"), - m_window_bordercolor_str(m_resmanager, "black", - "fbpager.windowBorderColor", + m_window_bordercolor_str(m_resmanager, "black", + "fbpager.windowBorderColor", "FbPager.WindowBorderColor"), - m_background_color_str(m_resmanager, "darkgray", - "fbpager.backgroundColor", + m_background_color_str(m_resmanager, "darkgray", + "fbpager.backgroundColor", "FbPager.BackgroundColor"), - m_current_background_color_str(m_resmanager, "lightgray", - "fbpager.currentBackgroundColor", + m_current_background_color_str(m_resmanager, "lightgray", + "fbpager.currentBackgroundColor", "FbPager.CurrentBackgroundColor"), m_multiclick_time(m_resmanager, 250, "fbpager.multiClickTime", @@ -238,8 +238,8 @@ FbPager::FbPager(int screen_num, bool withdraw, FbTk::EventManager::instance()->add(*this, m_window); - // setup client window - m_window.setBackgroundColor(FbTk::Color((*m_color_str).c_str(), + // setup client window + m_window.setBackgroundColor(FbTk::Color((*m_color_str).c_str(), m_window.screenNumber())); m_window.setAlpha(*m_alpha); @@ -247,7 +247,7 @@ FbPager::FbPager(int screen_num, bool withdraw, XWMHints wmhints; if (!withdraw) { - + wmhints.initial_state = NormalState; } else // withdraw wmhints.initial_state = WithdrawnState; @@ -294,7 +294,7 @@ FbPager::FbPager(int screen_num, bool withdraw, } } - int extra_flags = 0; + int extra_flags = 0; // now setup extra flags if ( real_layer_flag != -1 ) { if (real_layer_flag == 2) { @@ -321,7 +321,7 @@ FbPager::FbPager(int screen_num, bool withdraw, ClientHandlerList::iterator it_end = m_clienthandlers.end(); int workspaces = 0; for (; it != it_end; ++it) { - workspaces = max((*it)->numberOfWorkspaces(m_window.screenNumber()), + workspaces = max((*it)->numberOfWorkspaces(m_window.screenNumber()), workspaces); } @@ -329,7 +329,7 @@ FbPager::FbPager(int screen_num, bool withdraw, // finaly show window show(); m_window.move(*m_start_x, *m_start_y); - + m_window.resize(m_window.width(), m_window.height()); m_last_button_event.time= 0; @@ -338,6 +338,13 @@ FbPager::FbPager(int screen_num, bool withdraw, // dump resources to stdout m_resmanager.dump(true); } + + Window root = DefaultRootWindow( FbTk::App::instance()->display() ); + XSelectInput( disp, root, + PropertyChangeMask | SubstructureNotifyMask ); + + FbTk::EventManager::instance()->add(*this, root); + } FbPager::~FbPager() { @@ -345,6 +352,7 @@ FbPager::~FbPager() { destroyList(m_workspaces); } + void FbPager::show() { m_window.show(); } @@ -355,7 +363,6 @@ void FbPager::hide() { void FbPager::handleEvent(XEvent &event) { // here we handle events that're not in FbTk::EventHandler interface - if (event.type == ClientMessage) clientMessageEvent(event.xclient); else if (event.type == ConfigureNotify) { @@ -369,7 +376,7 @@ void FbPager::handleEvent(XEvent &event) { m_window.updateGeometry(event.xconfigure.x, event.xconfigure.y, - event.xconfigure.width, + event.xconfigure.width, event.xconfigure.height); clearWindows(); // update transparency @@ -384,10 +391,10 @@ void FbPager::handleEvent(XEvent &event) { } void FbPager::buttonPressEvent(XButtonEvent &event) { - + if ( event.time - m_last_button_event.time > 1000 ) m_button_queue= ""; - + FB_ostringstream os; // double click @@ -406,7 +413,7 @@ void FbPager::buttonPressEvent(XButtonEvent &event) { if (event.button == *m_move_in_workspace_button || event.button == *m_drag_to_workspace_button ) { - + m_move_window.curr_window = 0; m_move_window.client = ClientWindow(0); @@ -422,10 +429,10 @@ void FbPager::buttonPressEvent(XButtonEvent &event) { // drag -> move it above all workspaces if (event.button == *m_drag_to_workspace_button) { - m_move_window.curr_window->reparent(m_window, - m_move_window.curr_window->x() + - m_move_window.curr_workspace->window().x(), - m_move_window.curr_window->y() + + m_move_window.curr_window->reparent(m_window, + m_move_window.curr_window->x() + + m_move_window.curr_workspace->window().x(), + m_move_window.curr_window->y() + m_move_window.curr_workspace->window().y()); } break; @@ -438,12 +445,12 @@ void FbPager::buttonPressEvent(XButtonEvent &event) { void FbPager::buttonReleaseEvent(XButtonEvent &event) { ClientWindow client(0); - if (m_move_window.curr_window != 0 && + if (m_move_window.curr_window != 0 && *m_move_in_workspace_button == event.button) { FbTk::FbWindow &win = *m_move_window.curr_window; int client_x = win.x(), client_y = win.y(); - scaleFromWindowToWindow(*(win.parent()), + scaleFromWindowToWindow(*(win.parent()), m_rootwin, client_x, client_y); @@ -456,14 +463,14 @@ void FbPager::buttonReleaseEvent(XButtonEvent &event) { if (m_move_window.curr_window != 0 && *m_drag_to_workspace_button == event.button) { - if (m_last_workspace_num >= 0 && + if (m_last_workspace_num >= 0 && m_last_workspace_num < m_workspaces.size()) { - + Workspace* workspace = m_workspaces[m_last_workspace_num]; // let someone else send it to the _new_ workspace if (workspace != m_move_window.curr_workspace) { - + ClientHandlerList::iterator it = m_clienthandlers.begin(); ClientHandlerList::iterator it_end = m_clienthandlers.end(); for (; it != it_end; ++it) { @@ -472,30 +479,30 @@ void FbPager::buttonReleaseEvent(XButtonEvent &event) { } // drop it to the last workspace, the mouse was over - m_move_window.curr_window->reparent(workspace->window(), - m_move_window.curr_window->x() - + m_move_window.curr_window->reparent(workspace->window(), + m_move_window.curr_window->x() - workspace->window().x(), - m_move_window.curr_window->y() - + m_move_window.curr_window->y() - workspace->window().y()); - + } else { m_move_window.curr_window->reparent(m_move_window.curr_workspace->window(), - m_grab_x, + m_grab_x, m_grab_y); } - + // move it to the right position FbTk::FbWindow &win = *m_move_window.curr_window; int client_x = win.x(), client_y = win.y(); - scaleFromWindowToWindow(*(win.parent()), + scaleFromWindowToWindow(*(win.parent()), m_rootwin, client_x, client_y); m_move_window.client.move(client_x, client_y); - // clean up + // clean up m_move_window.client = ClientWindow(0); m_move_window.curr_window = 0; m_move_window.curr_workspace = 0; @@ -520,13 +527,13 @@ void FbPager::buttonReleaseEvent(XButtonEvent &event) { } } } - + if (workspace != 0) sendChangeToWorkspace(workspace_it); } else if (compareButtonQueues(m_button_queue, *m_raise_window_button) && client.window() != 0) { - // raise, currently the same as focus + // raise, currently the same as focus for_each(m_clienthandlers.begin(), m_clienthandlers.end(), @@ -544,18 +551,18 @@ void FbPager::buttonReleaseEvent(XButtonEvent &event) { } else if (compareButtonQueues(m_button_queue, *m_exit_button)) { // exit FbTk::App::instance()->end(); - } else if (compareButtonQueues(m_button_queue, *m_next_workspace_button)) { + } else if (compareButtonQueues(m_button_queue, *m_next_workspace_button)) { // next workspace - sendChangeToWorkspace(m_curr_workspace < m_workspaces.size() - 1 ? + sendChangeToWorkspace(m_curr_workspace < m_workspaces.size() - 1 ? m_curr_workspace + 1 : 0); } else if (compareButtonQueues(m_button_queue, *m_prev_workspace_button)) { // prev workspace - sendChangeToWorkspace(m_curr_workspace > 0 ? m_curr_workspace - 1 : + sendChangeToWorkspace(m_curr_workspace > 0 ? m_curr_workspace - 1 : m_workspaces.size() - 1); } else { - // ok, we didn't find any queue that match + // ok, we didn't find any queue that match // so we return without clearing the current queue - return; + return; } m_button_queue.erase(); @@ -563,7 +570,7 @@ void FbPager::buttonReleaseEvent(XButtonEvent &event) { void FbPager::motionNotifyEvent(XMotionEvent &event) { - if (m_move_window.curr_window != 0 && + if (m_move_window.curr_window != 0 && m_move_window.curr_workspace != 0) { Workspace* workspace= 0; @@ -574,7 +581,7 @@ void FbPager::motionNotifyEvent(XMotionEvent &event) { // find out, on which workspace the motion started and // on which workspace we are now for(; w < m_workspaces.size(); ++w) { - + if (m_workspaces[w]->window() == event.window) workspace= m_workspaces[w]; @@ -586,12 +593,12 @@ void FbPager::motionNotifyEvent(XMotionEvent &event) { // m_window - coordinate - space x = m_move_window.curr_workspace->window().x() + event.x; y = m_move_window.curr_workspace->window().y() + event.y; - + // inside the new workspace? - if ( left <= x && x <= right && top <= y && y <= bottom ) + if ( left <= x && x <= right && top <= y && y <= bottom ) m_last_workspace_num= w; } - + int newx = event.x - m_grab_x; int newy = event.y - m_grab_y; @@ -605,18 +612,18 @@ void FbPager::motionNotifyEvent(XMotionEvent &event) { FbTk::FbWindow &win = *m_move_window.curr_window; int client_x = win.x(), client_y = win.y(); - scaleFromWindowToWindow(*(win.parent()), + scaleFromWindowToWindow(*(win.parent()), m_rootwin, client_x, client_y); m_move_window.client.move(client_x, client_y); } - + // drag between the workspaces } else if (m_last_button_event.button == *m_drag_to_workspace_button) { newx += m_move_window.curr_workspace->window().x(); newy += m_move_window.curr_workspace->window().y(); - + respectConstraints(newx, newy, *m_move_window.curr_window, m_window); m_move_window.curr_window->move(newx, newy); @@ -651,20 +658,47 @@ void FbPager::exposeEvent(XExposeEvent &event) { } void FbPager::clientMessageEvent(XClientMessageEvent &event) { + char* atom = XGetAtomName( FbTk::App::instance()->display(), + event.message_type ); + cout << "ClientMessage ATOM: " << atom << endl; + XFree( atom ); ClientHandlerList::iterator it = m_clienthandlers.begin(); ClientHandlerList::iterator it_end = m_clienthandlers.end(); for (; it != it_end; ++it) { - if ((*it)->clientMessage(*this, event)) - break; + (*it)->clientMessage(*this, event); } } void FbPager::propertyEvent(XPropertyEvent &event) { + ClientHandlerList::iterator it = m_clienthandlers.begin(); + ClientHandlerList::iterator it_end = m_clienthandlers.end(); + for (; it != it_end; ++it) { + (*it)->propertyNotify(*this, event); + } updateWindowHints(event.window); } +void FbPager::eraseAllWindows() { + for_each(m_workspaces.begin(), m_workspaces.end(), + mem_fun(&Workspace::removeAll)); + WindowList::iterator it = m_windows.begin(); + for (; it != m_windows.end(); ++it) { + FbTk::EventManager::instance()->remove(*it); + } + m_windows.clear(); +} + +void FbPager::addWindows(const WindowsAndWorkspaces& wins) { + // destroy all old windows + eraseAllWindows(); + + for (unsigned int w = 0; w < wins.size(); ++w) { + addWindow(wins[w].first, wins[w].second); + } +} + void FbPager::addWindow(Window win, unsigned int workspace_num) { if (workspace_num >= m_workspaces.size()) return; @@ -674,7 +708,7 @@ void FbPager::addWindow(Window win, unsigned int workspace_num) { m_workspaces[workspace_num]->add(win); // update window mode updateWindowHints(win); - + } void FbPager::moveToWorkspace(Window win, unsigned int w) { @@ -721,7 +755,7 @@ void FbPager::updateWorkspaceCount(unsigned int num) { width *= screenScale; } else if ( *m_follow_scale == "width" ) { height *= screenScale; - } + } // add some workspaces until we match number of workspaces FbTk::Color wincolor(m_window_color_str->c_str(), m_window.screenNumber()); FbTk::Color focusedcolor(m_focused_window_color_str->c_str(), m_window.screenNumber()); @@ -729,7 +763,7 @@ void FbPager::updateWorkspaceCount(unsigned int num) { FbTk::Color backgroundcol(m_background_color_str->c_str(), m_window.screenNumber()); while (m_workspaces.size() != num) { - Workspace *w = new Workspace(*this, m_window, + Workspace *w = new Workspace(*this, m_window, width, height, focusedcolor, wincolor, @@ -763,7 +797,7 @@ void setupWindow( FbTk::FbWindow &window, const std::string &border_color, unsigned int border_width ) { - window.setBackgroundColor(FbTk::Color(bg_color.c_str(), + window.setBackgroundColor(FbTk::Color(bg_color.c_str(), window.screenNumber())); window.setBorderColor(FbTk:: @@ -777,15 +811,15 @@ void setupWindow( FbTk::FbWindow &window, void FbPager::setCurrentWorkspace(unsigned int num) { if (num >= m_workspaces.size() || num == m_curr_workspace) - return; + return; - // set current workspaces background to "normal" background, + // set current workspaces background to "normal" background, FbTk::FbWindow &oldWindow = m_workspaces[m_curr_workspace]->window(); setupWindow(oldWindow, *m_background_color_str, *m_workspace_border_inactive_color, *m_workspace_border_inactive_width); - + // set next workspace background // update workspace background FbTk::FbWindow& newWindow = m_workspaces[num]->window(); @@ -793,14 +827,14 @@ void FbPager::setCurrentWorkspace(unsigned int num) { *m_current_background_color_str, *m_workspace_border_active_color, *m_workspace_border_width); - + newWindow.raise(); if (*m_workspace_border_inactive_width == 0) { oldWindow.move( oldWindow.x(), oldWindow.y() ); } - + m_curr_workspace = num; } @@ -816,7 +850,7 @@ void FbPager::alignWorkspaces() { const FbTk::FbWindow& workspace_win = m_workspaces[0]->window(); const unsigned int workspace_width = workspace_win.width(); const unsigned int workspace_height = workspace_win.height(); - + // Fix alignment of workspaces if (*m_align == LEFT_TO_RIGHT) diff_x = workspace_width + bevel; @@ -831,10 +865,10 @@ void FbPager::alignWorkspaces() { int workspace = 0; int max_x = 0; int max_y = 0; - for (; it != it_end; + for (; it != it_end; ++it, next_pos_y += diff_y, next_pos_x += diff_x, ++workspace) { - if (workspace >= *m_workspaces_per_row) { + if (workspace >= *m_workspaces_per_row) { workspace = 0; if (*m_align == LEFT_TO_RIGHT) { next_pos_x = bevel; @@ -862,17 +896,17 @@ void FbPager::alignWorkspaces() { sizehints.flags = PMinSize | PMaxSize; XSetWMProperties(FbTk::App::instance()->display(), m_window.window(), 0, 0, 0, 0, &sizehints, 0, 0); - + for_each(m_clienthandlers.begin(), m_clienthandlers.end(), RefBind(&ClientHandler::moveResize, m_window)); - + } void FbPager::sendChangeToWorkspace(unsigned int num) { assert(num < m_workspaces.size()); - + ClientHandlerList::iterator it = m_clienthandlers.begin(); ClientHandlerList::iterator it_end = m_clienthandlers.end(); for (; it != it_end; ++it) @@ -899,13 +933,13 @@ void FbPager::updateWindowHints(Window win) { } else continue; // normal window without sticky - } else if (!(hint.flags() & WindowHint::WHINT_STICKY) && + } else if (!(hint.flags() & WindowHint::WHINT_STICKY) && hint.workspace() != workspace || (hint.flags() & WindowHint::WHINT_SKIP_PAGER) || (hint.flags() & WindowHint::WHINT_TYPE_DOCK)) { // if win not sticky and if it's not suppose to be on this // workspace then remove it and try next workspace - m_workspaces[workspace]->remove(win); + m_workspaces[workspace]->remove(win); continue; // next workspace } @@ -916,12 +950,12 @@ void FbPager::updateWindowHints(Window win) { } else m_workspaces[workspace]->unshadeWindow(win); - if ((hint.flags() & WindowHint::WHINT_ICONIC) && + if ((hint.flags() & WindowHint::WHINT_ICONIC) && !(hint.flags() & WindowHint::WHINT_SHADED)) m_workspaces[workspace]->iconifyWindow(win); else if (!(hint.flags() & WindowHint::WHINT_SHADED)) m_workspaces[workspace]->deiconifyWindow(win); - + } // end for } @@ -948,8 +982,8 @@ void FbPager::load(const std::string &filename) { FbTk::Color bgcolor(m_background_color_str->c_str(), m_window.screenNumber()); for (size_t workspace = 0; workspace < m_workspaces.size(); ++workspace) { m_workspaces[workspace]->setAlpha(*m_alpha); - m_workspaces[workspace]->setWindowColor(*m_focused_window_color_str, - *m_window_color_str, + m_workspaces[workspace]->setWindowColor(*m_focused_window_color_str, + *m_window_color_str, *m_window_bordercolor_str); m_workspaces[workspace]->window().setBackgroundColor(bgcolor); } diff --git a/src/FbPager.hh b/src/FbPager.hh index 02fe1b6..429590c 100644 --- a/src/FbPager.hh +++ b/src/FbPager.hh @@ -1,6 +1,6 @@ // FbPager.hh for FbPager // Copyright (c) 2003-2007 Henrik Kinnunen (fluxgen at fluxbox org) -// +// // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation @@ -46,7 +46,7 @@ class ClientHandler; class FbPager:public FbTk::EventHandler, public Pager, private FbTk::NotCopyable { public: enum Alignment { LEFT_TO_RIGHT, TOP_TO_BOTTOM}; - FbPager(int screen_num, bool withdraw, + FbPager(int screen_num, bool withdraw, bool show_resources, int layer_flags, const char *resource_filename=0); @@ -61,8 +61,8 @@ public: */ //@{ void handleEvent(XEvent &event); - void buttonPressEvent(XButtonEvent &event); - void buttonReleaseEvent(XButtonEvent &event); + void buttonPressEvent(XButtonEvent &event); + void buttonReleaseEvent(XButtonEvent &event); void motionNotifyEvent(XMotionEvent &event); void exposeEvent(XExposeEvent &event); //@} @@ -83,6 +83,11 @@ public: return false; return true; } + + void eraseAllWindows(); + + void addWindows(const WindowsAndWorkspaces& windows); + private: void clientMessageEvent(XClientMessageEvent &event); void propertyEvent(XPropertyEvent &event); @@ -90,7 +95,7 @@ private: void alignWorkspaces(); - + void sendChangeToWorkspace(unsigned int num); void updateWindowHints(Window win); void load(const std::string &filename); @@ -99,13 +104,13 @@ private: FbTk::FbWindow m_window; typedef std::vector WorkspaceList; - typedef std::list ClientHandlerList; + typedef std::vector ClientHandlerList; typedef std::set WindowList; ClientHandlerList m_clienthandlers; WorkspaceList m_workspaces; WindowList m_windows; - + unsigned int m_curr_workspace; struct MoveWindow { @@ -135,7 +140,7 @@ private: FbTk::Resource m_prev_workspace_button; FbTk::Resource m_move_in_workspace_button; FbTk::Resource m_drag_to_workspace_button; - + FbTk::Resource m_align; FbTk::Resource m_color_str; FbTk::Resource m_window_color_str, m_focused_window_color_str; @@ -152,7 +157,7 @@ private: std::string m_button_queue; XButtonEvent m_last_button_event; int m_last_workspace_num; - + }; } // end namespace FbPager diff --git a/src/FbTk/Makefile.in b/src/FbTk/Makefile.in index 31a0ba1..67e5efd 100644 --- a/src/FbTk/Makefile.in +++ b/src/FbTk/Makefile.in @@ -81,6 +81,7 @@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ RC = @RC@ +SED = @SED@ STRIP = @STRIP@ VERSION = @VERSION@ X_CFLAGS = @X_CFLAGS@ diff --git a/src/Makefile.am b/src/Makefile.am index 1cb3131..b41ee5d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,6 +7,8 @@ fbpager_SOURCES= main.cc FbPager.hh FbPager.cc \ Workspace.cc Workspace.hh \ Ewmh.hh Ewmh.cc ClientHandler.hh \ ClientWindow.hh Pager.hh WindowHint.hh FbRootWindow.hh \ - ScaleWindowToWindow.hh Resources.hh RefBinder.hh + ScaleWindowToWindow.hh Resources.hh RefBinder.hh \ + PropertyTools.hh PropertyTools.cc + fbpager_CXXFLAGS=-IFbTk fbpager_LDADD=FbTk/libFbTk.a diff --git a/src/Pager.hh b/src/Pager.hh index 241dff0..d6faa87 100644 --- a/src/Pager.hh +++ b/src/Pager.hh @@ -1,6 +1,9 @@ #ifndef PAGER_HH #define PAGER_HH +#include +#include + namespace FbPager { /// @brief pager interface @@ -18,6 +21,11 @@ public: virtual void updateWorkspaceCount(unsigned int num) = 0; virtual void setCurrentWorkspace(unsigned int num) = 0; virtual bool haveWindow(Window win) = 0; + /// Window and workspace pair container + typedef std::vector< std::pair > WindowsAndWorkspaces; + + virtual void addWindows(const WindowsAndWorkspaces& windows) = 0; + }; } // end FbPager namespace diff --git a/src/PropertyTools.cc b/src/PropertyTools.cc new file mode 100644 index 0000000..9115278 --- /dev/null +++ b/src/PropertyTools.cc @@ -0,0 +1,71 @@ +#include "PropertyTools.hh" + +#include "FbTk/App.hh" + +#include + +namespace PropertyTools { + +std::string getAtomName(Atom atom) { + char* xstr = XGetAtomName(FbTk::App::instance()->display(), atom); + std::string name = xstr; + XFree(xstr); + return name; +} + + +unsigned int getIntProperty(Window win, Atom atom) throw (PropertyException){ + Atom ret_type = 0; + int fmt = 0; + unsigned long nitems = 0, bytes_after = 0; + long *data = 0; + if ( XGetWindowProperty(FbTk::App::instance()->display(), win, + atom, 0, 1, False, XA_CARDINAL, + &ret_type, &fmt, &nitems, + &bytes_after, (unsigned char**)&data) != Success) { + throw PropertyException(getAtomName(atom)); + } + + unsigned int val = (unsigned int)( *data ); + XFree(data); + return val; +} + +Window getWinProperty(Window win, Atom atom) throw (PropertyException){ + Atom ret_type = 0; + int fmt = 0; + unsigned long nitems = 0, bytes_after = 0; + long *data = 0; + if ( XGetWindowProperty(FbTk::App::instance()->display(), win, + atom, 0, 1, False, XA_WINDOW, + &ret_type, &fmt, &nitems, + &bytes_after, (unsigned char**)&data) != Success) { + throw PropertyException(getAtomName(atom)); + } + + Window val = (Window)( *data ); + XFree(data); + return val; +} + +void getWinArrayProperty(Window win, Atom atom, std::vector &cont) + throw (PropertyException) { + Atom ret_type = 0; + int fmt = 0; + unsigned long nitems = 0, bytes_after = 0; + long *data = 0; + if ( XGetWindowProperty(FbTk::App::instance()->display(), win, + atom, 0, 0xFFFFFF, False, XA_WINDOW, + &ret_type, &fmt, &nitems, + &bytes_after, (unsigned char**)&data) != Success) { + throw PropertyException(getAtomName(atom)); + } + for (unsigned long i = 0; i < nitems; ++i ) { + cont.push_back(((Window*)data)[i]); + } + + XFree(data); + +} + +} // PropertyTools diff --git a/src/PropertyTools.hh b/src/PropertyTools.hh new file mode 100644 index 0000000..9444531 --- /dev/null +++ b/src/PropertyTools.hh @@ -0,0 +1,38 @@ +#ifndef PROPERTY_TOOLS_H +#define PROPERTY_TOOLS_H + +#include +#include +#include +#include + +namespace PropertyTools { + +class PropertyException: public std::exception { +public: + PropertyException(const std::string &property) throw(): + m_property(property) { + } + + ~PropertyException() throw () { + } + + const char *what() const throw() { + return m_property.c_str(); + } + +private: + std::string m_property; +}; + +/// @return Atom name. +std::string getAtomName(Atom atom); + + +/// @return Integer value for property \c atom +unsigned int getIntProperty(Window win, Atom atom) throw (PropertyException); +Window getWinProperty(Window win, Atom atom) throw (PropertyException); +void getWinArrayProperty(Window win, Atom atom, std::vector &cont) throw (PropertyException); +} // PropertyTools + +#endif // PROPERTY_TOOL_H diff --git a/src/Workspace.cc b/src/Workspace.cc index 8c46b43..26ff1b0 100644 --- a/src/Workspace.cc +++ b/src/Workspace.cc @@ -1,6 +1,6 @@ // Workspace.cc for FbPager // Copyright (c) 2003-2004 Henrik Kinnunen (fluxgen at users.sourceforge.net) -// +// // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation @@ -41,7 +41,7 @@ namespace FbPager { Window Workspace::s_focused_window = 0; -Workspace::Workspace(FbTk::EventHandler &evh, +Workspace::Workspace(FbTk::EventHandler &evh, FbTk::FbWindow &parent, unsigned int width, unsigned int height, const FbTk::Color &focused_win_color, const FbTk::Color &wincolor, const FbTk::Color &border_color, @@ -60,7 +60,7 @@ Workspace::Workspace(FbTk::EventHandler &evh, m_window_bordercolor(border_color), m_focused_window(0), m_use_pixmap(use_pixmap), - m_window_border_width(window_border_width) { + m_window_border_width(window_border_width) { m_window.setBackgroundColor(background_color); FbTk::EventManager::instance()->add(evh, m_window); @@ -86,7 +86,7 @@ void Workspace::add(Window win) { fbwin = new FbTk::FbWindow(m_window, // parent 0, 0, // pos - 10, 10, // size + 10, 10, // size // event mask ExposureMask); // fbwin->setAlpha(m_window.alpha()); @@ -101,7 +101,7 @@ void Workspace::add(Window win) { // add window to list m_windowlist[win] = fbwin; - + // update pos and size updateGeometry(win); @@ -164,12 +164,12 @@ void Workspace::raiseWindow(Window win) { } void Workspace::setWindowColor(const std::string &focused, - const std::string &unfocused, + const std::string &unfocused, const std::string &bordercolor_str) { m_window_color = FbTk::Color(unfocused.c_str(), m_window.screenNumber()); m_focused_window_color = FbTk::Color(focused.c_str(), m_window.screenNumber()); m_window_bordercolor = FbTk::Color(bordercolor_str.c_str(), m_window.screenNumber()); - + WindowList::iterator it = m_windowlist.begin(); WindowList::iterator it_end = m_windowlist.end(); for (; it != it_end; ++it) { @@ -186,7 +186,7 @@ void Workspace::setAlpha(unsigned char alpha) { WindowList::iterator it_end = m_windowlist.end(); for (; it != it_end; ++it) { (*it).second->setAlpha(alpha); - } + } } void Workspace::clearWindows() { @@ -216,6 +216,16 @@ void Workspace::remove(Window win) { m_windowlist.erase(win); } + +void Workspace::removeAll() { + WindowList::iterator it = m_windowlist.begin(); + for (; it != m_windowlist.end(); ++it) { + FbTk::EventManager::instance()->remove(*(it->second)); + delete it->second; + } + m_windowlist.clear(); +} + ClientWindow Workspace::findClient(const FbTk::FbWindow &win) const { WindowList::const_iterator it = m_windowlist.begin(); WindowList::const_iterator it_end = m_windowlist.end(); @@ -230,8 +240,8 @@ FbTk::FbWindow *Workspace::find(Window win) { WindowList::iterator it = m_windowlist.begin(); WindowList::iterator it_end = m_windowlist.end(); for (; it != it_end; ++it) { - if ((*it).second->window() == win || - (*it).first == win) + if ((*it).second->window() == win || + (*it).first == win) return it->second; } return 0; @@ -241,8 +251,8 @@ const FbTk::FbWindow *Workspace::find(Window win) const { WindowList::const_iterator it = m_windowlist.begin(); WindowList::const_iterator it_end = m_windowlist.end(); for (; it != it_end; ++it) { - if ((*it).second->window() == win || - (*it).first == win) + if ((*it).second->window() == win || + (*it).first == win) return it->second; } return 0; @@ -251,7 +261,7 @@ const FbTk::FbWindow *Workspace::find(Window win) const { void Workspace::updateFocusedWindow() { if (s_focused_window == 0) return; - + FbTk::FbWindow *fbwin = find(s_focused_window); if (fbwin == m_focused_window) return; @@ -290,9 +300,9 @@ void Workspace::updateGeometry(Window win) { int x = 0, y = 0; Window child; - ClientWindow client(win); + ClientWindow client(win); FbRootWindow rootwin(m_window.screenNumber()); - rootwin.translateCoordinates(client, + rootwin.translateCoordinates(client, client.x(), client.y(), x, y, child); @@ -314,9 +324,9 @@ void Workspace::updateGeometry(Window win) { void Workspace::updateBackground(Window win, const FbTk::Color &bg_color) { FbTk::FbWindow* fbwin= find(win); - if (!fbwin ) + if (!fbwin ) return; - + if (m_use_pixmap) { XWMHints *hints = XGetWMHints(FbTk::App::instance()->display(), win); @@ -328,9 +338,9 @@ void Workspace::updateBackground(Window win, const FbTk::Color &bg_color) { } else fbwin->setBackgroundColor(bg_color); - + XFree(hints); - } + } else fbwin->setBackgroundColor(bg_color); } diff --git a/src/Workspace.hh b/src/Workspace.hh index 6a14fb5..942b555 100644 --- a/src/Workspace.hh +++ b/src/Workspace.hh @@ -1,6 +1,6 @@ // Workspace.hh for FbPager // Copyright (c) 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net) -// +// // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation @@ -45,12 +45,12 @@ class Workspace:private FbTk::NotCopyable { public: /// create a workspace with specified name, size, parent and eventhandler - Workspace(FbTk::EventHandler &evh, - FbTk::FbWindow &parent, unsigned int width, unsigned int height, + Workspace(FbTk::EventHandler &evh, + FbTk::FbWindow &parent, unsigned int width, unsigned int height, const FbTk::Color &focused_win_color, - const FbTk::Color &wincolor, + const FbTk::Color &wincolor, const FbTk::Color &border_color, - const FbTk::Color &background_color, + const FbTk::Color &background_color, const char *name = 0, const bool use_pixmap = true, const int window_border_width = 1); @@ -63,6 +63,8 @@ public: void resize(unsigned int width, unsigned int height); /// remove a window from workspace void remove(Window win); + /// remove all windows from this workspace + void removeAll(); void shadeWindow(Window win); void unshadeWindow(Window win); void iconifyWindow(Window win); @@ -88,9 +90,9 @@ public: const FbTk::FbWindow *find(Window win) const; /// @return workspace name const std::string &name() const { return m_name; } - /// @return the workspace's FbWindow + /// @return the workspace's FbWindow const FbTk::FbWindow &window() const { return m_window; } - /// @return the workspace's FbWindow + /// @return the workspace's FbWindow FbTk::FbWindow &window() { return m_window; } static void setFocusedWindow(Window win) { s_focused_window = win; } @@ -98,7 +100,7 @@ public: private: void updateBackground(Window win, const FbTk::Color& bg_color); - + std::string m_name; ///< name of this workspace FbTk::FbWindow m_window; ///< FbWindow of this workspace FbTk::EventHandler &m_eventhandler; @@ -113,7 +115,7 @@ private: bool m_use_pixmap; int m_window_border_width; - + }; }; // end namespace FbPager diff --git a/src/main.cc b/src/main.cc index 362c775..b441797 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,6 +1,6 @@ // main.cc for FbPager // Copyright (c) 2003-2004 Henrik Kinnunen (fluxgen at users.sourceforge.net) -// +// // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation @@ -98,7 +98,7 @@ int main(int argc, char **argv) { throw string("Display connection"); } - FbPager::FbPager fbpager(screen_num, withdraw, + FbPager::FbPager fbpager(screen_num, withdraw, show_resources, layer, resourcefile.c_str()); -- cgit v0.11.2