diff --git a/ede-panel/Panel.cpp b/ede-panel/Panel.cpp index 675f9af..9ee9c98 100644 --- a/ede-panel/Panel.cpp +++ b/ede-panel/Panel.cpp @@ -357,10 +357,7 @@ void Panel::do_layout(void) { } void Panel::show(void) { - if(shown()) { - Fl_Window::show(); - return; - } + if(shown()) return; /* * hush known FLTK bug with XGetImage; a lot of errors will be print when menu icons goes @@ -375,10 +372,15 @@ void Panel::show(void) { void Panel::hide(void) { Fl::remove_handler(x_events); + netwm_window_remove_strut(fl_xid(this)); + + E_DEBUG("Panel::hide()\n"); /* strange; this is not called when panel goes out :S */ mgr.clear(); save_config(); + + Fl_Window::hide(); } void Panel::update_size_and_pos(bool create_xid, bool update_strut) { diff --git a/ede-panel/applets/system-tray/Tray.cpp b/ede-panel/applets/system-tray/Tray.cpp index 35ac8d3..5baae4a 100644 --- a/ede-panel/applets/system-tray/Tray.cpp +++ b/ede-panel/applets/system-tray/Tray.cpp @@ -44,6 +44,7 @@ static int handle_xevent(int e) { } } else if(fl_xevent->type == DestroyNotify) { XDestroyWindowEvent xev = fl_xevent->xdestroywindow; + E_DEBUG(E_STRLOC ": Unock request for %i\n", fl_xevent->xclient.data.l[2]); curr_tray->unembed_window(xev.window); return false; } else if(fl_xevent->type == ConfigureNotify) { @@ -67,6 +68,7 @@ static int validate_drawable(Display *d, Window xid) { } Tray::Tray() : Fl_Group(0, 0, 1, 25), opcode(0) { + //color(FL_RED); box(FL_FLAT_BOX); register_notification_area(); } @@ -87,6 +89,7 @@ void Tray::distribute_children(void) { Y = y(); for(int i = 0; i < children(); i++) { child(i)->position(X, Y); + E_DEBUG(E_STRLOC ": child %i at %i %i\n", i, child(i)->x(), child(i)->y()); X += child(i)->w() + TRAY_ICONS_SPACE; } } diff --git a/ede-panel/applets/taskbar/TaskButton.cpp b/ede-panel/applets/taskbar/TaskButton.cpp index 831a06e..65aaf10 100644 --- a/ede-panel/applets/taskbar/TaskButton.cpp +++ b/ede-panel/applets/taskbar/TaskButton.cpp @@ -47,12 +47,10 @@ EDELIB_NS_USING(netwm_window_set_active) EDELIB_NS_USING(netwm_window_get_title) EDELIB_NS_USING(netwm_window_get_icon) EDELIB_NS_USING(netwm_window_set_state) -EDELIB_NS_USING(wm_window_ede_restore) -EDELIB_NS_USING(wm_window_get_state) -EDELIB_NS_USING(wm_window_set_state) -EDELIB_NS_USING(WM_WINDOW_STATE_ICONIC) EDELIB_NS_USING(NETWM_STATE_ACTION_TOGGLE) +EDELIB_NS_USING(NETWM_STATE_ACTION_ADD) EDELIB_NS_USING(NETWM_STATE_MAXIMIZED) +EDELIB_NS_USING(NETWM_STATE_HIDDEN) static Fl_Pixmap image_window(window_xpm); @@ -83,25 +81,22 @@ static void close_cb(Fl_Widget*, void *b) { static void restore_cb(Fl_Widget*, void *b) { TaskButton *bb = (TaskButton*)b; - wm_window_ede_restore(bb->get_window_xid()); - netwm_window_set_active(bb->get_window_xid()); + netwm_window_set_active(bb->get_window_xid(), 1); redraw_whole_panel(bb); } static void minimize_cb(Fl_Widget*, void *b) { TaskButton *bb = (TaskButton*)b; - if(wm_window_get_state(bb->get_window_xid()) != WM_WINDOW_STATE_ICONIC) - wm_window_set_state(bb->get_window_xid(), WM_WINDOW_STATE_ICONIC); - + netwm_window_set_state(bb->get_window_xid(), NETWM_STATE_HIDDEN, NETWM_STATE_ACTION_ADD); redraw_whole_panel(bb); } static void maximize_cb(Fl_Widget*, void *b) { TaskButton *bb = (TaskButton*)b; - netwm_window_set_active(bb->get_window_xid()); + netwm_window_set_active(bb->get_window_xid(), 1); netwm_window_set_state(bb->get_window_xid(), NETWM_STATE_MAXIMIZED, NETWM_STATE_ACTION_TOGGLE); redraw_whole_panel(bb); diff --git a/ede-panel/applets/taskbar/Taskbar.cpp b/ede-panel/applets/taskbar/Taskbar.cpp index 1ec30fe..f34547f 100644 --- a/ede-panel/applets/taskbar/Taskbar.cpp +++ b/ede-panel/applets/taskbar/Taskbar.cpp @@ -22,14 +22,15 @@ #include #include #include +#include #include "TaskButton.h" #include "Taskbar.h" -#include "Panel.h" #define DEFAULT_CHILD_W 175 #define DEFAULT_SPACING 5 +EDELIB_NS_USING(list) EDELIB_NS_USING(netwm_callback_add) EDELIB_NS_USING(netwm_callback_remove) EDELIB_NS_USING(netwm_window_get_all_mapped) @@ -37,6 +38,7 @@ EDELIB_NS_USING(netwm_window_is_manageable) EDELIB_NS_USING(netwm_window_get_workspace) EDELIB_NS_USING(netwm_window_get_active) EDELIB_NS_USING(netwm_window_set_active) +EDELIB_NS_USING(netwm_window_set_state) EDELIB_NS_USING(netwm_workspace_get_current) EDELIB_NS_USING(wm_window_set_state) EDELIB_NS_USING(wm_window_get_state) @@ -46,6 +48,11 @@ EDELIB_NS_USING(NETWM_CHANGED_WINDOW_LIST) EDELIB_NS_USING(NETWM_CHANGED_WINDOW_NAME) EDELIB_NS_USING(NETWM_CHANGED_WINDOW_ICON) EDELIB_NS_USING(WM_WINDOW_STATE_ICONIC) +EDELIB_NS_USING(NETWM_STATE_ACTION_TOGGLE) +EDELIB_NS_USING(NETWM_STATE_HIDDEN) + +typedef list WindowList; +typedef list::iterator WindowListIt; static void button_cb(TaskButton *b, void *t) { Taskbar *tt = (Taskbar*)t; @@ -59,9 +66,16 @@ static void button_cb(TaskButton *b, void *t) { static void net_event_cb(int action, Window xid, void *data) { E_RETURN_IF_FAIL(data != NULL); + /* this is a message, so property is not changed and netwm_window_get_active() must be called */ + if(action == NETWM_CHANGED_ACTIVE_WINDOW) { + Taskbar *tt = (Taskbar*)data; + tt->update_active_button(); + return; + } + if(action == NETWM_CHANGED_CURRENT_WORKSPACE || action == NETWM_CHANGED_WINDOW_LIST) { Taskbar *tt = (Taskbar*)data; - tt->create_task_buttons(); + tt->update_task_buttons(); return; } @@ -71,13 +85,6 @@ static void net_event_cb(int action, Window xid, void *data) { return; } - /* this is a message, so property is not changed and netwm_window_get_active() must be called */ - if(action == NETWM_CHANGED_ACTIVE_WINDOW) { - Taskbar *tt = (Taskbar*)data; - tt->update_active_button(); - return; - } - if(action == NETWM_CHANGED_WINDOW_ICON) { Taskbar *tt = (Taskbar*)data; tt->update_child_icon(xid); @@ -85,11 +92,10 @@ static void net_event_cb(int action, Window xid, void *data) { } } -Taskbar::Taskbar() : Fl_Group(0, 0, 40, 25), curr_active(NULL), prev_active(NULL), panel(NULL) { +Taskbar::Taskbar() : Fl_Group(0, 0, 40, 25), curr_active(NULL), prev_active(NULL) { end(); - panel = EDE_PANEL_GET_PANEL_OBJECT(this); - create_task_buttons(); + update_task_buttons(); netwm_callback_add(net_event_cb, this); } @@ -97,64 +103,92 @@ Taskbar::~Taskbar() { netwm_callback_remove(net_event_cb); } -void Taskbar::create_task_buttons(void) { - /* erase all current elements */ - if(children()) - clear(); +void Taskbar::update_task_buttons(void) { + Window *wins; + int nwins = netwm_window_get_all_mapped(&wins); - /* also current/prev storage */ - curr_active = prev_active = NULL; + if(nwins < 1) { + if(children() > 0) clear(); + return; + } - /* redraw it, in case no windows exists in this workspace */ - panel_redraw(); + TaskButton *b; + int curr_workspace = netwm_workspace_get_current(); + bool need_full_redraw = false; - Window *wins, transient_prop_win; - int nwins = netwm_window_get_all_mapped(&wins); + /* + * first remove windows not available in list received by wm + * + * TODO: FLTK 1.3.x got new function remove(int index) which will make + * faster removal, comparing to remove(Fl_Widget*) + */ + for(int i = 0, found; i < children(); i++) { + found = 0; + b = (TaskButton*)child(i); - if(nwins > 0) { - TaskButton *b; - int curr_workspace = netwm_workspace_get_current(); + for(int j = 0; j < nwins; j++) { + if(b->get_window_xid() == wins[j]) { + found = 1; + break; + } + } - for(int i = 0; i < nwins; i++) { - transient_prop_win = None; + if(!found) { + remove(b); + /* Fl_Group does not call delete on remove() */ + delete b; + need_full_redraw = true; + } + } - if(!netwm_window_is_manageable(wins[i])) - continue; + /* now see which one needs to create */ + for(int i = 0, found; i < nwins; i++) { + found = 0; - /* - * see if it has WM_TRANSIENT_FOR hint set; transient_prop_win would point to parent window, but - * parent should not be root window for this screen - */ - if(XGetTransientForHint(fl_display, wins[i], &transient_prop_win) - && (transient_prop_win != None) - && (transient_prop_win != RootWindow(fl_display, fl_screen))) - { - continue; - } + for(int j = 0; j < children(); j++) { + b = (TaskButton*)child(j); - /* - * show window per workspace - * TODO: allow showing all windows in each workspace - */ - if(curr_workspace == netwm_window_get_workspace(wins[i])) { - b = new TaskButton(0, 0, DEFAULT_CHILD_W, 25); - b->set_window_xid(wins[i]); - b->update_title_from_xid(); - b->update_image_from_xid(); - - /* catch the name changes */ - XSelectInput(fl_display, wins[i], PropertyChangeMask | StructureNotifyMask); - - b->callback((Fl_Callback*)button_cb, this); - add(b); + if(b->get_window_xid() == wins[i]) { + found = 1; + break; } } - XFree(wins); + if(found || !netwm_window_is_manageable(wins[i])) + continue; + + Window transient_prop_win = None; + + /* + * see if it has WM_TRANSIENT_FOR hint set; transient_prop_win would point to parent window, but + * parent should not be root window for this screen + */ + if(XGetTransientForHint(fl_display, wins[i], &transient_prop_win) + && (transient_prop_win != None) + && (transient_prop_win != RootWindow(fl_display, fl_screen))) + { + continue; + } + + /* TODO: allow showing all windows in each workspace */ + if(curr_workspace == netwm_window_get_workspace(wins[i])) { + b = new TaskButton(0, 0, DEFAULT_CHILD_W, 25); + b->set_window_xid(wins[i]); + b->update_title_from_xid(); + b->update_image_from_xid(); + + /* catch the name changes */ + XSelectInput(fl_display, wins[i], PropertyChangeMask | StructureNotifyMask); + b->callback((Fl_Callback*)button_cb, this); + add(b); + } } + XFree(wins); layout_children(); - update_active_button(); + update_active_button(!need_full_redraw); + + if(need_full_redraw) panel_redraw(); } void Taskbar::resize(int X, int Y, int W, int H) { @@ -193,7 +227,7 @@ void Taskbar::layout_children(void) { } } -void Taskbar::update_active_button(int xid) { +void Taskbar::update_active_button(bool do_redraw, int xid) { if(!children()) return; @@ -212,7 +246,7 @@ void Taskbar::update_active_button(int xid) { o->box(FL_UP_BOX); } - redraw(); + if(do_redraw) redraw(); } void Taskbar::activate_window(TaskButton *b) { @@ -239,7 +273,7 @@ void Taskbar::activate_window(TaskButton *b) { } /* active or restore minimized */ - netwm_window_set_active(xid); + netwm_window_set_active(xid, 1); update_active_button(xid); /* TODO: use stack for this (case when this can't handle: minimize three window, out of four on the workspace) */ @@ -277,8 +311,7 @@ void Taskbar::update_child_icon(Window xid) { } void Taskbar::panel_redraw(void) { - E_RETURN_IF_FAIL(panel != NULL); - panel->redraw(); + parent()->redraw(); } EDE_PANEL_APPLET_EXPORT ( diff --git a/ede-panel/applets/taskbar/Taskbar.h b/ede-panel/applets/taskbar/Taskbar.h index 830748b..6d557f0 100644 --- a/ede-panel/applets/taskbar/Taskbar.h +++ b/ede-panel/applets/taskbar/Taskbar.h @@ -25,23 +25,20 @@ #include "Applet.h" class TaskButton; -class Panel; class Taskbar : public Fl_Group { public: TaskButton *curr_active, *prev_active; - Panel *panel; - public: Taskbar(); ~Taskbar(); - void create_task_buttons(void); + void update_task_buttons(void); void resize(int X, int Y, int W, int H); void layout_children(void); - void update_active_button(int xid = -1); + void update_active_button(bool do_redraw = true, int xid = -1); void activate_window(TaskButton *b); void update_child_title(Window xid); void update_child_icon(Window xid); diff --git a/ede-panel/ede-panel.cpp b/ede-panel/ede-panel.cpp index 446e1a8..00baaa6 100644 --- a/ede-panel/ede-panel.cpp +++ b/ede-panel/ede-panel.cpp @@ -31,28 +31,22 @@ #include "Panel.h" #include "AppletManager.h" -static bool running; +static Panel *panel; static void exit_signal(int signum) { - running = false; + if(panel) panel->hide(); } int main(int argc, char **argv) { EDE_APPLICATION("ede-panel"); + panel = NULL; signal(SIGTERM, exit_signal); signal(SIGKILL, exit_signal); signal(SIGINT, exit_signal); - Panel *panel = new Panel(); + panel = new Panel(); panel->load_applets(); panel->show(); - running = true; - - while(running) - Fl::wait(); - - /* so Panel::hide() can be called */ - panel->hide(); - return 0; + return Fl::run(); }