// WinClient.cc for Fluxbox - an X11 Window manager // 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 // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. // $Id: WinClient.cc,v 1.2 2003/04/14 12:08:21 fluxgen Exp $ #include "WinClient.hh" #include "Window.hh" #include "fluxbox.hh" #include "Screen.hh" #include "i18n.hh" #include <iostream> #include <algorithm> #include <iterator> using namespace std; WinClient::WinClient(Window win, FluxboxWindow &fbwin):FbTk::FbWindow(win), transient_for(0), window_group(0), x(0), y(0), old_bw(0), min_width(1), min_height(1), max_width(1), max_height(1), width_inc(1), height_inc(1), min_aspect_x(1), min_aspect_y(1), max_aspect_x(1), max_aspect_y(1), base_width(1), base_height(1), win_gravity(0), initial_state(0), normal_hint_flags(0), wm_hint_flags(0), mwm_hint(0), blackbox_hint(0), m_win(&fbwin), m_title(""), m_icon_title(""), m_diesig(*this) { } WinClient::~WinClient() { #ifdef DEBUG cerr<<__FILE__<<"(~"<<__FUNCTION__<<")[this="<<this<<"]"<<endl; #endif // DEBUG m_diesig.notify(); Fluxbox *fluxbox = Fluxbox::instance(); if (transient_for != 0) { if (transientFor() == m_win) { transient_for = 0; } fluxbox->setFocusedWindow(transient_for); if (transient_for != 0) { FluxboxWindow::ClientList::iterator client_it = transientFor()->clientList().begin(); FluxboxWindow::ClientList::iterator client_it_end = transientFor()->clientList().end(); for (; client_it != client_it_end; ++client_it) { (*client_it)->transientList().remove(m_win); } transient_for->setInputFocus(); transient_for = 0; } } while (!transients.empty()) { FluxboxWindow::ClientList::iterator it = transients.back()->clientList().begin(); FluxboxWindow::ClientList::iterator it_end = transients.back()->clientList().end(); for (; it != it_end; ++it) { if ((*it)->transientFor() == m_win) (*it)->transient_for = 0; } transients.pop_back(); } if (window_group != 0) { fluxbox->removeGroupSearch(window_group); window_group = 0; } if (mwm_hint != 0) XFree(mwm_hint); if (blackbox_hint != 0) XFree(blackbox_hint); if (window()) fluxbox->removeWindowSearch(window()); if (m_win != 0) m_win->removeClient(*this); m_win = 0; } void WinClient::updateRect(int x, int y, unsigned int width, unsigned int height) { Display *disp = FbTk::App::instance()->display(); XEvent event; event.type = ConfigureNotify; event.xconfigure.display = disp; event.xconfigure.event = window(); event.xconfigure.window = window(); event.xconfigure.x = x; event.xconfigure.y = y; event.xconfigure.width = width; event.xconfigure.height = height; //!! TODO event.xconfigure.border_width = 1;//client.old_bw; //!! TODO event.xconfigure.above = None; //m_frame.window().window(); event.xconfigure.override_redirect = false; XSendEvent(disp, window(), False, StructureNotifyMask, &event); } void WinClient::sendFocus() { Display *disp = FbTk::App::instance()->display(); // setup focus msg XEvent ce; ce.xclient.type = ClientMessage; ce.xclient.message_type = FbAtoms::instance()->getWMProtocolsAtom(); ce.xclient.display = disp; ce.xclient.window = window(); ce.xclient.format = 32; ce.xclient.data.l[0] = FbAtoms::instance()->getWMTakeFocusAtom(); ce.xclient.data.l[1] = Fluxbox::instance()->getLastTime(); ce.xclient.data.l[2] = 0l; ce.xclient.data.l[3] = 0l; ce.xclient.data.l[4] = 0l; // send focus msg XSendEvent(disp, window(), false, NoEventMask, &ce); } void WinClient::sendClose() { Display *disp = FbTk::App::instance()->display(); // fill in XClientMessage structure for delete message XEvent ce; ce.xclient.type = ClientMessage; ce.xclient.message_type = FbAtoms::instance()->getWMProtocolsAtom(); ce.xclient.display = disp; ce.xclient.window = window(); ce.xclient.format = 32; ce.xclient.data.l[0] = FbAtoms::instance()->getWMDeleteAtom(); ce.xclient.data.l[1] = CurrentTime; ce.xclient.data.l[2] = 0l; ce.xclient.data.l[3] = 0l; ce.xclient.data.l[4] = 0l; // send event delete message to client window XSendEvent(disp, window(), false, NoEventMask, &ce); } void WinClient::reparent(Window win, int x, int y) { XReparentWindow(FbTk::App::instance()->display(), window(), win, x, y); } bool WinClient::getAttrib(XWindowAttributes &attr) const { return XGetWindowAttributes(FbTk::App::instance()->display(), window(), &attr); } bool WinClient::getWMName(XTextProperty &textprop) const { return XGetWMName(FbTk::App::instance()->display(), window(), &textprop); } bool WinClient::getWMIconName(XTextProperty &textprop) const { return XGetWMName(FbTk::App::instance()->display(), window(), &textprop); } void WinClient::updateTransientInfo() { if (m_win == 0) return; // remove us from parent if (transientFor() != 0) { //!! TODO // since we don't know which client in transientFor() // that we're transient for then we just remove us // from every client in transientFor() clientlist FluxboxWindow::ClientList::iterator client_it = transientFor()->clientList().begin(); FluxboxWindow::ClientList::iterator client_it_end = transientFor()->clientList().end(); for (; client_it != client_it_end; ++client_it) { (*client_it)->transientList().remove(m_win); } } transient_for = 0; Display *disp = FbTk::App::instance()->display(); // determine if this is a transient window Window win; if (!XGetTransientForHint(disp, window(), &win)) return; // we can't be transient to ourself if (win == window()) return; if (win != 0 && m_win->getScreen().getRootWindow() == win) { m_win->modal = true; return; } transient_for = Fluxbox::instance()->searchWindow(win); if (transient_for != 0 && window_group != None && win == window_group) { transient_for = Fluxbox::instance()->searchGroup(win, m_win); } // make sure we don't have deadlock loop in transient chain for (FluxboxWindow *w = m_win; w != 0; w = w->m_client->transient_for) { if (w == w->m_client->transient_for) { w->m_client->transient_for = 0; break; } } if (transientFor() != 0) { // we need to add ourself to the right client in // the transientFor() window so we search client WinClient *client = transientFor()->findClient(win); assert(client != 0); client->transientList().push_back(m_win); // make sure we only have on instance of this client->transientList().unique(); if (transientFor()->isStuck()) m_win->stick(); } } void WinClient::updateTitle() { XTextProperty text_prop; char **list = 0; int num = 0; I18n *i18n = I18n::instance(); if (getWMName(text_prop)) { if (text_prop.value && text_prop.nitems > 0) { if (text_prop.encoding != XA_STRING) { text_prop.nitems = strlen((char *) text_prop.value); if (XmbTextPropertyToTextList(FbTk::App::instance()->display(), &text_prop, &list, &num) == Success && num > 0 && *list) { m_title = static_cast<char *>(*list); XFreeStringList(list); } else m_title = (char *)text_prop.value; } else m_title = (char *)text_prop.value; XFree((char *) text_prop.value); } else { // ok, we don't have a name, set default name m_title = i18n->getMessage( FBNLS::WindowSet, FBNLS::WindowUnnamed, "Unnamed"); } } else { m_title = i18n->getMessage( FBNLS::WindowSet, FBNLS::WindowUnnamed, "Unnamed"); } } void WinClient::updateIconTitle() { XTextProperty text_prop; char **list = 0; int num = 0; if (getWMIconName(text_prop)) { if (text_prop.value && text_prop.nitems > 0) { if (text_prop.encoding != XA_STRING) { text_prop.nitems = strlen((char *) text_prop.value); if (XmbTextPropertyToTextList(FbTk::App::instance()->display(), &text_prop, &list, &num) == Success && num > 0 && *list) { m_icon_title = (char *)*list; XFreeStringList(list); } else m_icon_title = (char *)text_prop.value; } else m_icon_title = (char *)text_prop.value; XFree((char *) text_prop.value); } else m_icon_title = title(); } else m_icon_title = title(); }