// Window.cc for Fluxbox Window Manager // Copyright (c) 2001 - 2002 Henrik Kinnunen (fluxgen@linuxmail.org) // // Window.cc for Blackbox - an X11 Window manager // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.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: Window.cc,v 1.26 2002/02/11 11:07:33 fluxgen Exp $ //use GNU extensions #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif // _GNU_SOURCE #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H #include "i18n.hh" #include "fluxbox.hh" #include "Icon.hh" #include "Screen.hh" #include "Toolbar.hh" #include "Window.hh" #include "Windowmenu.hh" #include "StringUtil.hh" #ifdef SLIT # include "Slit.hh" #endif // SLIT #include #include #ifdef STDC_HEADERS # include #endif // STDC_HEADERS #ifdef DEBUG # ifdef HAVE_STDIO_H # include # endif // HAVE_STDIO_H #endif // DEBUG #include using namespace std; FluxboxWindow::FluxboxWindow(Window w, BScreen *s): image_ctrl(0), moving(false), resizing(false), shaded(false), maximized(false), visible(false), iconic(false), transient(false), focused(false), stuck(false), modal(false), send_focus_message(false), managed(false), screen(0), timer(0), display(0), lastButtonPressTime(0), windowmenu(0), tab(0) { #ifdef DEBUG fprintf(stderr, I18n::instance()-> getMessage( #ifdef NLS WindowSet, WindowCreating, #else // !NLS 0, 0, #endif // NLS "FluxboxWindow::FluxboxWindow(): creating 0x%lx\n"), w); #endif // DEBUG Fluxbox *fluxbox = Fluxbox::instance(); display = fluxbox->getXDisplay(); BaseDisplay::GrabGuard gg(*fluxbox); blackbox_attrib.workspace = workspace_number = window_number = -1; blackbox_attrib.flags = blackbox_attrib.attrib = blackbox_attrib.stack = 0l; blackbox_attrib.premax_x = blackbox_attrib.premax_y = 0; blackbox_attrib.premax_w = blackbox_attrib.premax_h = 0; //use tab as default decorations.tab = true; client.window = w; frame.window = frame.plate = frame.title = frame.handle = None; frame.right_grip = frame.left_grip = None; frame.utitle = frame.ftitle = frame.uhandle = frame.fhandle = None; frame.ulabel = frame.flabel = frame.ubutton = frame.fbutton = None; frame.pbutton = frame.ugrip = frame.fgrip = None; //get decorations vector dir = fluxbox->getTitlebarLeft(); for (char c=0; c<2; c++) { for (unsigned int i=0; igetTitlebarRight(); } decorations.menu = true; //override menu option decorations.titlebar = decorations.border = decorations.handle = true; functions.resize = functions.move = functions.iconify = functions.maximize = true; functions.close = decorations.close = false; client.wm_hint_flags = client.normal_hint_flags = 0; client.transient_for = client.transient = 0; client.title = 0; client.title_len = 0; client.icon_title = 0; client.mwm_hint = (MwmHints *) 0; client.blackbox_hint = 0; fluxbox->grab(); if (! validateClient()) return; // fetch client size and placement XWindowAttributes wattrib; if ((! XGetWindowAttributes(display, client.window, &wattrib)) || (! wattrib.screen) || wattrib.override_redirect) { return; } if (s) screen = s; else screen = fluxbox->searchScreen(RootWindowOfScreen(wattrib.screen)); if (!screen) return; image_ctrl = screen->getImageControl(); client.x = wattrib.x; client.y = wattrib.y; client.width = wattrib.width; client.height = wattrib.height; client.old_bw = wattrib.border_width; timer = new BTimer(fluxbox, this); timer->setTimeout(fluxbox->getAutoRaiseDelay()); timer->fireOnce(true); getBlackboxHints(); if (! client.blackbox_hint) getMWMHints(); // get size, aspect, minimum/maximum size and other hints set by the // client getWMProtocols(); getWMHints(); getWMNormalHints(); #ifdef SLIT if (client.initial_state == WithdrawnState) { screen->getSlit()->addClient(client.window); return; } #endif // SLIT managed = true; //mark for usage fluxbox->saveWindowSearch(client.window, this); // determine if this is a transient window Window win; if (XGetTransientForHint(display, client.window, &win)) { if (win && (win != client.window)) { FluxboxWindow *tr; if ((tr = fluxbox->searchWindow(win))) { while (tr->client.transient) tr = tr->client.transient; client.transient_for = tr; tr->client.transient = this; stuck = client.transient_for->stuck; transient = true; } else if (win == client.window_group) { if ((tr = fluxbox->searchGroup(win, this))) { while (tr->client.transient) tr = tr->client.transient; client.transient_for = tr; tr->client.transient = this; stuck = client.transient_for->stuck; transient = true; } } } if (win == screen->getRootWindow()) modal = true; } // adjust the window decorations based on transience and window sizes if (transient) { decorations.maximize = decorations.handle = decorations.border = functions.maximize = false; } if ((client.normal_hint_flags & PMinSize) && (client.normal_hint_flags & PMaxSize) && client.max_width <= client.min_width && client.max_height <= client.min_height) { decorations.maximize = decorations.handle = functions.resize = functions.maximize = false; decorations.tab = false; //no tab for this window } upsize(); bool place_window = true; if (fluxbox->isStartup() || transient || client.normal_hint_flags & (PPosition|USPosition)) { setGravityOffsets(); if (! fluxbox->isStartup()) { // is going to be used when position if (decorations.tab) { // window is cleanly fixed int real_x = frame.x; int real_y = frame.y; if (screen->getTabPlacement() == Tab::PTOP) real_y -= screen->getTabHeight(); else if (screen->getTabPlacement() == Tab::PLEFT) { if (screen->isTabRotateVertical()) real_x -= screen->getTabHeight(); else real_x -= screen->getTabWidth(); } if (real_x >= 0 && real_y + frame.y_border >= 0 && real_x <= (signed) screen->getWidth() && real_y <= (signed) screen->getHeight()) place_window = false; } else if (frame.x >= 0 && // non tab (signed) (frame.y + frame.y_border) >= 0 && frame.x <= (signed) screen->getWidth() && frame.y <= (signed) screen->getHeight()) place_window = false; } else place_window = false; /* if ((fluxbox->isStartup()) || (frame.x >= 0 && (signed) (frame.y + frame.y_border) >= 0 && frame.x <= (signed) screen->getWidth() && frame.y <= (signed) screen->getHeight())) place_window = false; */ } frame.window = createToplevelWindow(frame.x, frame.y, frame.width, frame.height, screen->getBorderWidth()); //create frame window fluxbox->saveWindowSearch(frame.window, this); //save frame window frame.plate = createChildWindow(frame.window); //Create plate window fluxbox->saveWindowSearch(frame.plate, this); //save plate window frame.title = createChildWindow(frame.window); //create titlebar win if (decorations.titlebar) { //have titlebar decorations? fluxbox->saveWindowSearch(frame.title, this); //save titlebar win frame.label = createChildWindow(frame.title); //create label win in titlebar fluxbox->saveWindowSearch(frame.label, this); //save label win } if (decorations.handle) { //have handle decorations ? frame.handle = createChildWindow(frame.window); //create handle win fluxbox->saveWindowSearch(frame.handle, this); //save handle win frame.left_grip = // create left handle createChildWindow(frame.handle, fluxbox->getLowerLeftAngleCursor()); fluxbox->saveWindowSearch(frame.left_grip, this); //save left handle frame.right_grip = // create right handle createChildWindow(frame.handle, fluxbox->getLowerRightAngleCursor()); fluxbox->saveWindowSearch(frame.right_grip, this); //save right handle } associateClientWindow(); XGrabButton(display, Button1, AnyModifier, frame.plate, True, ButtonPressMask, GrabModeSync, GrabModeSync, None, None); XUngrabButton(display, Button1, Mod1Mask|Mod2Mask|Mod3Mask, frame.plate); XGrabButton(display, Button1, Mod1Mask, frame.window, True, ButtonReleaseMask | ButtonMotionMask, GrabModeAsync, GrabModeAsync, None, fluxbox->getMoveCursor()); //----grab with "all" modifiers grabButton(display, Button1, frame.window, fluxbox->getMoveCursor()); XGrabButton(display, Button2, Mod1Mask, frame.window, True, ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None); XGrabButton(display, Button3, Mod1Mask, frame.window, True, ButtonReleaseMask | ButtonMotionMask, GrabModeAsync, GrabModeAsync, None, fluxbox->getLowerRightAngleCursor()); //---grab with "all" modifiers grabButton(display, Button3, frame.window, fluxbox->getLowerRightAngleCursor()); positionWindows(); //use tab? delayed this so that tabs wont "flicker" when creating windows if (decorations.tab && fluxbox->useTabs()) tab = new Tab(this, 0, 0); decorate(); XRaiseWindow(display, frame.plate); XMapSubwindows(display, frame.plate); if (decorations.titlebar) XMapSubwindows(display, frame.title); XMapSubwindows(display, frame.window); if (decorations.menu) windowmenu = new Windowmenu(this); if (workspace_number < 0 || workspace_number >= screen->getCount()) screen->getCurrentWorkspace()->addWindow(this, place_window); else screen->getWorkspace(workspace_number)->addWindow(this, place_window); configure(frame.x, frame.y, frame.width, frame.height); if (shaded) { shaded = false; shade(); } if (maximized && functions.maximize) { int m = maximized; maximized = false; maximize(m); } setFocusFlag(false); #ifdef GNOME updateGnomeAtoms(); #endif #ifdef DEBUG fprintf(stderr, "%s(%d): FluxboxWindow(this=%p)\n", __FILE__, __LINE__, this); #endif } FluxboxWindow::~FluxboxWindow(void) { #ifdef GNOME XDeleteProperty (display, client.window, screen->getBaseDisplay()->getGnomeWorkspaceAtom()); #endif Fluxbox *fluxbox = Fluxbox::instance(); if (moving || resizing) { screen->hideGeometry(); XUngrabPointer(display, CurrentTime); } if (workspace_number != -1 && window_number != -1) screen->getWorkspace(workspace_number)->removeWindow(this); else if (iconic) screen->removeIcon(this); if (timer) { if (timer->isTiming()) timer->stop(); delete timer; } if (windowmenu) delete windowmenu; if (client.title) delete [] client.title; if (client.icon_title) delete [] client.icon_title; if (tab) delete tab; tab = 0; if (client.mwm_hint) XFree(client.mwm_hint); if (client.blackbox_hint) XFree(client.blackbox_hint); //TODO: Move this to Workspace::removeWindow if (client.transient_for) fluxbox->setFocusedWindow(client.transient_for); if (client.window_group) fluxbox->removeGroupSearch(client.window_group); if (transient && client.transient_for) client.transient_for->client.transient = client.transient; if (client.transient) client.transient->client.transient_for = client.transient_for; while ( !buttonlist.empty()) { //destroy all buttons on titlebar fluxbox->removeWindowSearch(buttonlist.back().win); XDestroyWindow(display, buttonlist.back().win); buttonlist.pop_back(); } if (frame.title) { if (frame.ftitle) image_ctrl->removeImage(frame.ftitle); if (frame.utitle) image_ctrl->removeImage(frame.utitle); if (frame.flabel) image_ctrl->removeImage(frame.flabel); if( frame.ulabel) image_ctrl->removeImage(frame.ulabel); fluxbox->removeWindowSearch(frame.label); fluxbox->removeWindowSearch(frame.title); XDestroyWindow(display, frame.label); XDestroyWindow(display, frame.title); } if (frame.handle) { if (frame.fhandle) image_ctrl->removeImage(frame.fhandle); if (frame.uhandle) image_ctrl->removeImage(frame.uhandle); if (frame.fgrip) image_ctrl->removeImage(frame.fgrip); if (frame.ugrip) image_ctrl->removeImage(frame.ugrip); fluxbox->removeWindowSearch(frame.right_grip); fluxbox->removeWindowSearch(frame.left_grip); fluxbox->removeWindowSearch(frame.handle); XDestroyWindow(display, frame.right_grip); XDestroyWindow(display, frame.left_grip); XDestroyWindow(display, frame.handle); } if (frame.fbutton) image_ctrl->removeImage(frame.fbutton); if (frame.ubutton) image_ctrl->removeImage(frame.ubutton); if (frame.pbutton) image_ctrl->removeImage(frame.pbutton); if (frame.plate) { //NOTE fluxbox->removeWindowSearch(frame.plate); XDestroyWindow(display, frame.plate); } if (frame.window) { fluxbox->removeWindowSearch(frame.window); XDestroyWindow(display, frame.window); } if (managed) { fluxbox->removeWindowSearch(client.window); screen->removeNetizen(client.window); } #ifdef DEBUG cerr<<__FILE__<<"("<<__LINE__<<"): ~FluxboxWindow(this="< getMessage( #ifdef NLS WindowSet, WindowXGetWindowAttributesFail, #else // !NLS 0, 0, #endif // NLS "FluxboxWindow::FluxboxWindow(): XGetWindowAttributes " "failed\n") ); break; case CANTFINDSCREEN: fprintf(stderr, I18n::instance()-> getMessage( #ifdef NLS WindowSet, WindowCannotFindScreen, #else // !NLS 0, 0, #endif // NLS "FluxboxWindow::FluxboxWindow(): can't find screen\n" " for root window")); break; }; #endif // DEBUG } Window FluxboxWindow::createToplevelWindow( int x, int y, unsigned int width, unsigned int height, unsigned int borderwidth) { XSetWindowAttributes attrib_create; unsigned long create_mask = CWBackPixmap | CWBorderPixel | CWColormap | CWOverrideRedirect | CWEventMask; attrib_create.background_pixmap = None; attrib_create.colormap = screen->getColormap(); attrib_create.override_redirect = True; attrib_create.event_mask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | EnterWindowMask; return (XCreateWindow(display, screen->getRootWindow(), x, y, width, height, borderwidth, screen->getDepth(), InputOutput, screen->getVisual(), create_mask, &attrib_create)); } Window FluxboxWindow::createChildWindow(Window parent, Cursor cursor) { XSetWindowAttributes attrib_create; unsigned long create_mask = CWBackPixmap | CWBorderPixel | CWEventMask; attrib_create.background_pixmap = None; attrib_create.event_mask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | ExposureMask | EnterWindowMask | LeaveWindowMask; if (cursor) { create_mask |= CWCursor; attrib_create.cursor = cursor; } return (XCreateWindow(display, parent, 0, 0, 1, 1, 0, screen->getDepth(), InputOutput, screen->getVisual(), create_mask, &attrib_create)); } void FluxboxWindow::associateClientWindow(void) { XSetWindowBorderWidth(display, client.window, 0); getWMName(); getWMIconName(); XChangeSaveSet(display, client.window, SetModeInsert); XSetWindowAttributes attrib_set; XSelectInput(display, frame.plate, NoEventMask); XReparentWindow(display, client.window, frame.plate, 0, 0); XSelectInput(display, frame.plate, SubstructureRedirectMask); XFlush(display); attrib_set.event_mask = PropertyChangeMask | StructureNotifyMask | FocusChangeMask; attrib_set.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask; XChangeWindowAttributes(display, client.window, CWEventMask|CWDontPropagate, &attrib_set); #ifdef SHAPE if (Fluxbox::instance()->hasShapeExtensions()) { XShapeSelectInput(display, client.window, ShapeNotifyMask); int foo; unsigned int ufoo; XShapeQueryExtents(display, client.window, &frame.shaped, &foo, &foo, &ufoo, &ufoo, &foo, &foo, &foo, &ufoo, &ufoo); if (frame.shaped) { XShapeCombineShape(display, frame.window, ShapeBounding, frame.mwm_border_w, frame.y_border + frame.mwm_border_w, client.window, ShapeBounding, ShapeSet); int num = 1; XRectangle xrect[2]; xrect[0].x = xrect[0].y = 0; xrect[0].width = frame.width; xrect[0].height = frame.y_border; if (decorations.handle) { xrect[1].x = 0; xrect[1].y = frame.y_handle; xrect[1].width = frame.width; xrect[1].height = frame.handle_h + screen->getBorderWidth(); num++; } XShapeCombineRectangles(display, frame.window, ShapeBounding, 0, 0, xrect, num, ShapeUnion, Unsorted); } } #endif // SHAPE //create the buttons if (decorations.iconify) createButton(Fluxbox::MINIMIZE, FluxboxWindow::iconifyPressed_cb, FluxboxWindow::iconifyButton_cb, FluxboxWindow::iconifyDraw_cb); if (decorations.maximize) createButton(Fluxbox::MAXIMIZE, FluxboxWindow::maximizePressed_cb, FluxboxWindow::maximizeButton_cb, FluxboxWindow::maximizeDraw_cb); if (decorations.close) createButton(Fluxbox::CLOSE, FluxboxWindow::closePressed_cb, FluxboxWindow::closeButton_cb, FluxboxWindow::closeDraw_cb); if (decorations.sticky) createButton(Fluxbox::STICK, FluxboxWindow::stickyPressed_cb, FluxboxWindow::stickyButton_cb, FluxboxWindow::stickyDraw_cb); if (decorations.menu)//TODO createButton(Fluxbox::MENU, 0, 0, 0); if (decorations.shade) createButton(Fluxbox::SHADE, 0, FluxboxWindow::shadeButton_cb, FluxboxWindow::shadeDraw_cb); if (frame.ubutton) { for (unsigned int i=0; idecorate(); Pixmap tmp = frame.fbutton; BTexture *texture = &(screen->getWindowStyle()->b_focus); if (texture->getTexture() == (BImage::FLAT | BImage::SOLID)) { frame.fbutton = None; frame.fbutton_pixel = texture->getColor()->getPixel(); } else frame.fbutton = image_ctrl->renderImage(frame.button_w, frame.button_h, texture); if (tmp) image_ctrl->removeImage(tmp); tmp = frame.ubutton; texture = &(screen->getWindowStyle()->b_unfocus); if (texture->getTexture() == (BImage::FLAT | BImage::SOLID)) { frame.ubutton = None; frame.ubutton_pixel = texture->getColor()->getPixel(); } else frame.ubutton = image_ctrl->renderImage(frame.button_w, frame.button_h, texture); if (tmp) image_ctrl->removeImage(tmp); tmp = frame.pbutton; texture = &(screen->getWindowStyle()->b_pressed); if (texture->getTexture() == (BImage::FLAT | BImage::SOLID)) { frame.pbutton = None; frame.pbutton_pixel = texture->getColor()->getPixel(); } else frame.pbutton = image_ctrl->renderImage(frame.button_w, frame.button_h, texture); if (tmp) image_ctrl->removeImage(tmp); if (decorations.titlebar) { tmp = frame.ftitle; texture = &(screen->getWindowStyle()->t_focus); if (texture->getTexture() == (BImage::FLAT | BImage::SOLID)) { frame.ftitle = None; frame.ftitle_pixel = texture->getColor()->getPixel(); } else frame.ftitle = image_ctrl->renderImage(frame.width, frame.title_h, texture); if (tmp) image_ctrl->removeImage(tmp); tmp = frame.utitle; texture = &(screen->getWindowStyle()->t_unfocus); if (texture->getTexture() == (BImage::FLAT | BImage::SOLID)) { frame.utitle = None; frame.utitle_pixel = texture->getColor()->getPixel(); } else frame.utitle = image_ctrl->renderImage(frame.width, frame.title_h, texture); if (tmp) image_ctrl->removeImage(tmp); XSetWindowBorder(display, frame.title, screen->getBorderColor()->getPixel()); decorateLabel(); } if (decorations.border) { frame.fborder_pixel = screen->getWindowStyle()->f_focus.getPixel(); frame.uborder_pixel = screen->getWindowStyle()->f_unfocus.getPixel(); } if (decorations.handle) { tmp = frame.fhandle; texture = &(screen->getWindowStyle()->h_focus); if (texture->getTexture() == (BImage::FLAT | BImage::SOLID)) { frame.fhandle = None; frame.fhandle_pixel = texture->getColor()->getPixel(); } else frame.fhandle = image_ctrl->renderImage(frame.width, frame.handle_h, texture); if (tmp) image_ctrl->removeImage(tmp); tmp = frame.uhandle; texture = &(screen->getWindowStyle()->h_unfocus); if (texture->getTexture() == (BImage::FLAT | BImage::SOLID)) { frame.uhandle = None; frame.uhandle_pixel = texture->getColor()->getPixel(); } else frame.uhandle = image_ctrl->renderImage(frame.width, frame.handle_h, texture); if (tmp) image_ctrl->removeImage(tmp); tmp = frame.fgrip; texture = &(screen->getWindowStyle()->g_focus); if (texture->getTexture() == (BImage::FLAT | BImage::SOLID)) { frame.fgrip = None; frame.fgrip_pixel = texture->getColor()->getPixel(); } else frame.fgrip = image_ctrl->renderImage(frame.grip_w, frame.grip_h, texture); if (tmp) image_ctrl->removeImage(tmp); tmp = frame.ugrip; texture = &(screen->getWindowStyle()->g_unfocus); if (texture->getTexture() == (BImage::FLAT | BImage::SOLID)) { frame.ugrip = None; frame.ugrip_pixel = texture->getColor()->getPixel(); } else frame.ugrip = image_ctrl->renderImage(frame.grip_w, frame.grip_h, texture); if (tmp) image_ctrl->removeImage(tmp); XSetWindowBorder(display, frame.handle, screen->getBorderColor()->getPixel()); XSetWindowBorder(display, frame.left_grip, screen->getBorderColor()->getPixel()); XSetWindowBorder(display, frame.right_grip, screen->getBorderColor()->getPixel()); } XSetWindowBorder(display, frame.window, screen->getBorderColor()->getPixel()); } void FluxboxWindow::decorateLabel(void) { Pixmap tmp = frame.flabel; BTexture *texture = &(screen->getWindowStyle()->l_focus); if (texture->getTexture() == (BImage::FLAT | BImage::SOLID)) { frame.flabel = None; frame.flabel_pixel = texture->getColor()->getPixel(); } else frame.flabel = image_ctrl->renderImage(frame.label_w, frame.label_h, texture); if (tmp) image_ctrl->removeImage(tmp); tmp = frame.ulabel; texture = &(screen->getWindowStyle()->l_unfocus); if (texture->getTexture() == (BImage::FLAT | BImage::SOLID)) { frame.ulabel = None; frame.ulabel_pixel = texture->getColor()->getPixel(); } else frame.ulabel = image_ctrl->renderImage(frame.label_w, frame.label_h, texture); if (tmp) image_ctrl->removeImage(tmp); } void FluxboxWindow::createButton(int type, ButtonEventProc pressed, ButtonEventProc released, ButtonDrawProc draw) { Button b; b.win = createChildWindow(frame.title); Fluxbox::instance()->saveWindowSearch(b.win, this); b.type = type; b.used = true; b.draw = draw; b.pressed = pressed; b.released = released; buttonlist.push_back(b); } #ifdef GNOME void FluxboxWindow::updateGnomeAtoms() { int val = workspace_number; XChangeProperty(display, client.window, screen->getBaseDisplay()->getGnomeWorkspaceAtom(), XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&val, 1); long state = getGnomeWindowState(); XChangeProperty(display, client.window, screen->getBaseDisplay()->getGnomeStateAtom(), XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&state, 1); #ifdef DEBUG cerr<<__FILE__<<"("<<__LINE__<<"): 0x"<getBaseDisplay()->getGnomeStateAtom()<