///////////////////////////////////////////// // NovaWM - Nova Window Manager for X11 // ///////////////////////////////////////////// // By: Tim Walters // ///////////////////////////////////////////// // Copyright (C) 2001-2002 Tim Walters // ///////////////////////////////////////////// //////////////////////////////////////////////////////////////// //This code is released under the terms of the GNU GPL. Refer // //to the license file included with this source code. // //////////////////////////////////////////////////////////////// #include "novawm.h" WinMgr::WinMgr () { focusWindow = 0; cDesktop = 1; } WinMgr::~WinMgr () { } Novawm_Window::Novawm_Window () { window = 0; titlebar = 0; kill = 0; stretch = 0; hide = 0; // tChild = 0; // title = "Unnamed"; ignoreTransient = false; nTChildren = 0; desktop = winmgr.cDesktop; hasTitlebar = true; isTransient = false; size_hints = 0; isSticky = false; #ifdef _WIN_GNOME_SUPPORT layer = WIN_LAYER_NORMAL; #else layer = 0; #endif isShaded = false; } Novawm_Window::~Novawm_Window () { } void WinMgr::NewWindow (Window x11_window) { #ifdef DEBUG printf ("DEBUG: NewWindow()\n"); #endif XWindowAttributes win_attrib; XSetWindowAttributes set_attrib; long dummy; char *name; // = (char *) malloc(1027); unsigned long udummy; Atom adummy; int idummy; MotifHints *motif_hints = NULL; Window tranWin = None; XGetWindowAttributes (display, x11_window, &win_attrib); XGrabServer (display); if (win_attrib.override_redirect == true) { #ifdef DEBUG printf ("DEBUG: override_redirect == true\n"); #endif XUnmapWindow (display, x11_window); AddUnmapIgnore (x11_window); //unmapignore++; XUngrabServer (display); return; } Novawm_Window *win = new Novawm_Window; /* XTextProperty *tprop; if(!XGetWMName(display,x11_window,tprop)) { #ifdef DEBUG printf("DEBUG: XGetWMName returned bad status\n"); #endif win->title = "Unknown"; } if(!tprop->value||tprop->nitems <= 0) win->title = "Unknown"; if(tprop->value) win->title = (char *)tprop->value; */ XFetchName (display, x11_window, &name); printf("New Window Name: %s\n", name); if (!name) win->title = "Unknown"; else win->title = name; win->hasTitlebar = true; win->x = win_attrib.x; win->y = win_attrib.y; win->width = win_attrib.width; win->height = win_attrib.height; win->colorMap = win_attrib.colormap; win->size_hints = XAllocSizeHints (); XGetWMNormalHints (display, x11_window, win->size_hints, &dummy); if(win->size_hints->flags & PPosition) { win->x = win->size_hints->x; win->y = win->size_hints->y; } if ((win->y < 20) || (win->y < NOVABAR_HEIGHT)) win->y = NOVABAR_HEIGHT + 20; if (win_attrib.border_width > 0) { win->width += win_attrib.border_width * 2; win->height += win_attrib.border_width * 2; } win->orig_x = win->x; //win_attrib.x; win->orig_y = win->y; //win_attrib.y; win->orig_width = win->width; //win_attrib.width; win->orig_height = win->height; //win_attrib.height; win->bWidth = win_attrib.border_width; win->nTChildren = 0; win->window = x11_window; if (win->width > XDisplayWidth (display, screen)) win->width = XDisplayWidth (display, screen); if (win->height > XDisplayHeight (display, screen)) win->height = XDisplayHeight (display, screen); if (!(win->size_hints->flags & PMaxSize)) { #ifdef DEBUG printf ("DEBUG: Bad SizeHints: MIN %dx%d | MAX %dx%d\n", win->size_hints->min_width, win->size_hints->min_height, win->size_hints->max_width, win->size_hints->max_height); #endif //So set the maximum to the display geometry win->size_hints->max_width = XDisplayWidth (display, screen) + 100; win->size_hints->max_height = XDisplayHeight (display, screen) + 100; #ifdef DEBUG printf ("DEBUG: New SizeHints: MIN %dx%d | MAX %dx%d\n", win->size_hints->min_width, win->size_hints->min_height, win->size_hints->max_width, win->size_hints->max_height); #endif } if (!(win->size_hints->flags & PMinSize)) { #ifdef DEBUG printf ("DEBUG: Bad (MIN)SizeHints(%s): MIN %dx%d | MAX %dx%d\n", win->title, win->size_hints->min_width, win->size_hints->min_height, win->size_hints->max_width, win->size_hints->max_height); #endif win->size_hints->min_width = 10; win->size_hints->min_height = 10; #ifdef DEBUG printf ("DEBUG: New SizeHints: MIN %dx%d | MAX %dx%d\n", win->size_hints->min_width, win->size_hints->min_height, win->size_hints->max_width, win->size_hints->max_height); #endif } XGetTransientForHint (display, win->window, &tranWin); if (tranWin) win->isTransient = true; else win->isTransient = false; Novawm_Window *parent = winmgr.WindowSearch (tranWin); if (parent) { parent->nTChildren++; // if (parent->nTChildren == 1) // parent->tChild = new Window; parent->tChild.push_back(x11_window); //parent->tChild[parent->nTChildren - 1] = x11_window; } XGetWindowProperty (display, win->window, motifAtom, 0L, 20L, false, motifAtom, &adummy, &idummy, &udummy, &udummy, (unsigned char **) &motif_hints); if (motif_hints) { if ((motif_hints->flags & (1l << 1)) && (!(motif_hints->decorations & (1l << 0)))) { if ((motif_hints->decorations & (1l << 3)) == 0) win->hasTitlebar = false; else win->hasTitlebar = true; } } XFree (motif_hints); set_attrib.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask; set_attrib.event_mask = ExposureMask | ButtonPressMask | ButtonReleaseMask | PropertyChangeMask | SubstructureRedirectMask | FocusChangeMask | SubstructureNotifyMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask; set_attrib.background_pixel = mainPixel; set_attrib.override_redirect = false; //true; if (win->hasTitlebar == true) { win->titlebar = XCreateWindow (display, root, win->x, win->y - 20, win->width, win->height + 20, 0, DefaultDepth (display, screen), CopyFromParent, DefaultVisual (display, screen), CWBackPixel | CWEventMask | CWOverrideRedirect | CWDontPropagate, &set_attrib); //Create the Kill/Close Button Window win->kill = XCreateWindow (display, win->titlebar, win->width - 19, 3, 16, 16, 0, DefaultDepth (display, screen), CopyFromParent, DefaultVisual (display, screen), CWEventMask | CWDontPropagate, &set_attrib); //Create the Stretch/Maximize Button Window win->stretch = XCreateWindow (display, win->titlebar, win->width - 37, 3, 16, 16, 0, DefaultDepth (display, screen), CopyFromParent, DefaultVisual (display, screen), CWBackPixel | CWEventMask | CWDontPropagate, &set_attrib); //Create the Hide/Minimize Button Window win->hide = XCreateWindow (display, win->titlebar, win->width - 56, 3, 16, 16, 0, DefaultDepth (display, screen), CopyFromParent, DefaultVisual (display, screen), CWBackPixel | CWEventMask | CWDontPropagate, &set_attrib); } XChangeWindowAttributes (display, win->window, CWDontPropagate, &set_attrib); XSelectInput (display, win->window, PropertyChangeMask | FocusChangeMask); XAddToSaveSet (display, win->window); if (win->hasTitlebar == true) XReparentWindow (display, win->window, win->titlebar, 0, 20); if (focusType == 1) { if (win->hasTitlebar == true) XGrabButton (display, Button1, AnyModifier, win->titlebar, 1, ButtonPressMask, GrabModeSync, GrabModeAsync, None, None); } novawm_window_List.push_back (win); if (win->hasTitlebar == true) XMapRaised (display, win->titlebar); XMapWindow (display, win->window); if (win->hasTitlebar == true) { XSetWindowBackgroundPixmap (display, win->kill, killPixmap); XClearWindow (display, win->kill); XSetWindowBackgroundPixmap (display, win->stretch, stretchPixmap); XClearWindow (display, win->stretch); XSetWindowBackgroundPixmap (display, win->hide, hidePixmap); XClearWindow (display, win->hide); //Map the button windows XMapWindow (display, win->kill); XMapWindow (display, win->stretch); XMapWindow (display, win->hide); } SetFocus (win); if (win->hasTitlebar == true) XRaiseWindow (display, novawm.NovaBar); Redraw (win); win->Get_Net_States (); nClients++; #ifdef _WIN_GNOME_SUPPORT _WIN_CLIENT_LIST_UpdateList (); #endif XSync (display, true); //false); XUngrabServer (display); #ifdef DEBUG printf ("DEBUG: NewWindow() -- ORIG_GEOM %dx%dx%dx%d | GEOM %dx%dx%dx%d\n", win->orig_x, win->orig_y, win->orig_width, win->orig_height, win->x, win->y, win->width, win->height); #endif SendToDesktop (win, winmgr.cDesktop); #ifdef _WIN_GNOME_SUPPORT //Get Layer unsigned char *cLayer = 0; XGetWindowProperty (display, win->window, winProtocols_Layer, 0L, 20L, false, XA_CARDINAL, &adummy, &idummy, &udummy, &udummy, (unsigned char **) &cLayer); if (!cLayer) { win->layer = WIN_LAYER_NORMAL; } else { win->layer = atoi ((const char *) cLayer); } #endif if(win->x < 0) //TEMPORARY: FORCE WINDOWS TO BE MAPPED FOR THE FIRST TIME ON THE SCREEN win->x = win->orig_x = 0; if(win->y < 0) win->y = win->orig_y = 0; } //Should be a member of WinMgr but I'm in a hurry and I like this way better void Novawm_Window::Shade () { //FIXME: Could be cleaner? if (isShaded == true) { winmgr.SetSize (this, width, height); //XResizeWindow(display,titlebar,width,height+20); isShaded = false; } else { XResizeWindow (display, titlebar, width, 20); isShaded = true; } } Novawm_Window * WinMgr::WindowSearch (Window x11_window) { #ifdef DEBUG //printf ("DEBUG: WindowSearch(%x)\n", x11_window); #endif if (!x11_window || x11_window == root || x11_window == rootMenu.menuWindow () || x11_window == windowMenu.menuWindow ()) return 0; for (list < Novawm_Window * >::const_iterator i = novawm_window_List.begin (); i != novawm_window_List.end (); ++i) { if (((*i)->window == x11_window) || ((*i)->titlebar == x11_window) || ((*i)->kill == x11_window) || ((*i)->stretch == x11_window) || ((*i)->hide == x11_window)) return *i; } return 0; } void WinMgr::Redraw (Novawm_Window * novawm_window) { if (!novawm_window) return; if (novawm_window->title == NULL) { printf ("BAD TITLE!\n"); novawm_window->title = "Unknown"; } //XClearWindow (display, novawm_window->titlebar); XDrawString (display, novawm_window->titlebar, novawm_gc, 4, 14, novawm_window->title, strlen (novawm_window->title)); //Draw Raised Border for the titlebar and buttons //Titlebar (White lines) XDrawLine (display, novawm_window->titlebar, novawm_gc, 0, 0, 0, 20); XDrawLine (display, novawm_window->titlebar, novawm_gc, 0, 0, novawm_window->width, 0); if (events.downWindow != novawm_window->kill) { //Kill Button (White lines) XDrawLine (display, novawm_window->kill, novawm_gc, 0, 0, 0, 16); XDrawLine (display, novawm_window->kill, novawm_gc, 0, 0, 16, 0); } if (events.downWindow != novawm_window->stretch) { //Stretch Button (White lines) XDrawLine (display, novawm_window->stretch, novawm_gc, 0, 0, 0, 16); XDrawLine (display, novawm_window->stretch, novawm_gc, 0, 0, 16, 0); } if (events.downWindow != novawm_window->hide) { //Hide Button (White lines) XDrawLine (display, novawm_window->hide, novawm_gc, 0, 0, 0, 16); XDrawLine (display, novawm_window->hide, novawm_gc, 0, 0, 16, 0); } XSetForeground (display, novawm_gc, BlackPixel (display, screen)); if (focusWindow == novawm_window) XDrawString (display, novawm_window->titlebar, novawm_gc, 3, 13, novawm_window->title, strlen (novawm_window->title)); //Titlebar (black lines) XDrawLine (display, novawm_window->titlebar, novawm_gc, 1, 19, novawm_window->width, 19); XDrawLine (display, novawm_window->titlebar, novawm_gc, novawm_window->width - 1, 1, novawm_window->width - 1, 20); if (events.downWindow != novawm_window->kill) { //Kill Button (Black lines) XDrawLine (display, novawm_window->kill, novawm_gc, 15, 1, 15, 16); XDrawLine (display, novawm_window->kill, novawm_gc, 0, 15, 16, 15); } if (events.downWindow != novawm_window->stretch) { //Stretch Button (Black lines) XDrawLine (display, novawm_window->stretch, novawm_gc, 15, 1, 15, 16); XDrawLine (display, novawm_window->stretch, novawm_gc, 0, 15, 16, 15); } if (events.downWindow != novawm_window->hide) { //Hide Button (Black lines) XDrawLine (display, novawm_window->hide, novawm_gc, 15, 1, 15, 16); XDrawLine (display, novawm_window->hide, novawm_gc, 0, 15, 16, 15); } XSetForeground (display, novawm_gc, WhitePixel (display, screen)); } void WinMgr::Move (Novawm_Window * novawm_window) { #ifdef DEBUG printf ("DEBUG: Move()\n"); #endif XEvent event; XConfigureEvent configEvent; Window wdummy; int x, y, winx, winy; unsigned int mdummy; int idummy; //XGrabPointer (display, novawm_window->titlebar, false, // ButtonReleaseMask | PointerMotionMask, GrabModeAsync, // GrabModeAsync, None, MoveCursor, CurrentTime); //XGrabServer (display); XDefineCursor (display, novawm_window->titlebar, MoveCursor); XQueryPointer (display, novawm_window->titlebar, &wdummy, &wdummy, &x, &y, &winx, &winy, &mdummy); configEvent.type = ConfigureNotify; configEvent.event = novawm_window->window; configEvent.window = novawm_window->window; configEvent.width = novawm_window->width; configEvent.height = novawm_window->height; // - novawm_window->bWidth; configEvent.border_width = novawm_window->bWidth; configEvent.above = Below; configEvent.override_redirect = false; while (1) { XMaskEvent (display, ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask, &event); switch (event.type) { case Expose: Redraw (WindowSearch (event.xexpose.window)); if ((event.xexpose.window == novawm.NovaBar) || (event.xexpose.window == novawm.nbClock) || (event.xexpose.window == novawm.nbCurWin) || (event.xexpose.window == novawm.nbListButton) || (event.xexpose.window == novawm.nbWinList) || (event.xexpose.window == novawm.nbWLstScrllBar) || (event.xexpose.window == novawm.nbWLstItemWin) || (event.xexpose.window == novawm.nbWLstScrllUp) || (event.xexpose.window == novawm.nbWLstScrllDwn) || (event.xexpose.window == novawm.nbButton)) novawm.DrawBar (); break; case MotionNotify: XQueryPointer (display, novawm_window->titlebar, &wdummy, &wdummy, &x, &y, &idummy, &idummy, &mdummy); XMoveWindow (display, novawm_window->titlebar, //x - winx, y - winy); event.xmotion.x_root - winx, //event.xmotion.x, event.xmotion.y_root - winy); //event.xmotion.y); novawm_window->x = event.xmotion.x_root - winx; //event.xmotion.x; novawm_window->y = event.xmotion.y_root - winy + 20; //event.xmotion.y+20; break; case ButtonRelease: // novawm_window->x = x; // novawm_window->y = y; //XUngrabServer (display); // XUngrabPointer (display, CurrentTime); XDefineCursor (display, novawm_window->titlebar, Arrow); //Add 20 for the titlebar //(Incase the window needs its EXACT position) configEvent.x = novawm_window->x; configEvent.y = novawm_window->y; //+20; XSendEvent (display, novawm_window->window, false, StructureNotifyMask, (XEvent *) & configEvent); //Update the Window Redraw (novawm_window); return; break; } } } //Added to always check size hints before resizing void WinMgr::SetSize (Novawm_Window * novawm_window, int wWidth, int wHeight) { XConfigureEvent configEvent; XWindowAttributes win_attr; if (wWidth > novawm_window->size_hints->max_width) wWidth = novawm_window->size_hints->max_width; if (wWidth < novawm_window->size_hints->min_width) wWidth = novawm_window->size_hints->max_width; if (wHeight > novawm_window->size_hints->max_height) wHeight = novawm_window->size_hints->max_height; if (wHeight < novawm_window->size_hints->min_height) wHeight = novawm_window->size_hints->max_height; XGetWindowAttributes (display, novawm_window->window, &win_attr); configEvent.border_width = win_attr.border_width; novawm_window->width = wWidth; novawm_window->height = wHeight; configEvent.type = ConfigureNotify; configEvent.event = novawm_window->window; configEvent.window = novawm_window->window; configEvent.x = novawm_window->x; configEvent.y = novawm_window->y; configEvent.width = novawm_window->width; configEvent.height = novawm_window->height; configEvent.above = Below; configEvent.override_redirect = false; XResizeWindow (display, novawm_window->titlebar, wWidth, wHeight + 20); XResizeWindow (display, novawm_window->window, wWidth - (win_attr.border_width * 2), wHeight - (win_attr.border_width * 2)); //Move the titlebar buttons XMoveWindow (display, novawm_window->kill, novawm_window->width - 19, 3); XMoveWindow (display, novawm_window->stretch, novawm_window->width - 37, 3); XMoveWindow (display, novawm_window->hide, novawm_window->width - 56, 3); XSendEvent (display, novawm_window->window, false, StructureNotifyMask, (XEvent *) & configEvent); } void WinMgr::Stretch (Novawm_Window * novawm_window) { #ifdef DEBUG printf ("DEBUG: Stretch()\n"); #endif //Check if it is already stretched if ((novawm_window->width != novawm_window->orig_width) && (novawm_window->height != novawm_window->orig_height)) { if (novawm_window->hasTitlebar != true) //Has no titlebar { novawm_window->width = novawm_window->orig_width; novawm_window->height = novawm_window->orig_height; XMoveWindow (display, novawm_window->window, novawm_window->orig_x, novawm_window->orig_y); SetSize (novawm_window, novawm_window->orig_width, novawm_window->orig_height); return; } else //Has a titlebar { if ((novawm_window->width > novawm_window->size_hints->max_width) || (novawm_window->height > novawm_window->size_hints->max_height)) { novawm_window->width = novawm_window->size_hints->max_width; novawm_window->height = novawm_window->size_hints->max_height; } novawm_window->x = novawm_window->orig_x; novawm_window->y = novawm_window->orig_y; novawm_window->width = novawm_window->orig_width; novawm_window->height = novawm_window->orig_height; SetSize (novawm_window, novawm_window->orig_width, novawm_window->orig_height); XMoveWindow (display, novawm_window->titlebar, novawm_window->x, novawm_window->y); return; } } //Stretch to fullscreen else { if (novawm_window->hasTitlebar != true) //Has no titlebar { //This probably wouldn't be possible in this version return; } else { novawm_window->orig_x = novawm_window->x; novawm_window->orig_y = novawm_window->y; novawm_window->x = 0; novawm_window->y = NOVABAR_HEIGHT; novawm_window->width = XDisplayWidth (display, screen); novawm_window->height = XDisplayHeight (display, screen) - NOVABAR_HEIGHT; if ((novawm_window->width > novawm_window->size_hints->max_width) || (novawm_window->height > novawm_window->size_hints->max_height)) { #ifdef DEBUG printf ("DEBUG: Going fullscreen\n"); #endif novawm_window->width = novawm_window->size_hints->max_width; novawm_window->height = novawm_window->size_hints->max_height; } XMoveWindow (display, novawm_window->titlebar, 0, NOVABAR_HEIGHT); SetSize (novawm_window, XDisplayWidth (display, screen), XDisplayHeight (display, screen) - NOVABAR_HEIGHT - 20); //Leave room for the NovaBar and titlebar return; } } } void WinMgr::Raise (Novawm_Window * novawm_window) { #ifdef DEBUG printf ("DEBUG: Raise()\n"); #endif if (!novawm_window) { #ifdef DEBUG printf("DEBUG: Can't raise bad window.\n"); #endif return; } //Check the desktop #ifdef _WIN_GNOME_SUPPORT if (novawm_window->layer == WIN_LAYER_NORMAL) { #endif if (novawm_window->desktop != cDesktop) SetDesktop (novawm_window->desktop); //Goto that desktop #ifdef _WIN_GNOME_SUPPORT } #endif novawm_window->SetState (NormalState); if (novawm_window->hasTitlebar != true) { XMapRaised (display, novawm_window->window); #ifdef DEBUG printf("DEBUG: Raising window without titlebar(%s)\n", novawm_window->title); #endif } else { XMapRaised (display, novawm_window->titlebar); XMapRaised (display, novawm_window->window); } if (novawm_window->ignoreTransient != true) { if (novawm_window->nTChildren > 0) { for (int i = 0; i < novawm_window->nTChildren; i++) { //Raise any windows transient to this one Raise (WindowSearch (novawm_window->tChild[i])); } } } } void WinMgr::SetFocus (Novawm_Window * novawm_window) { #ifdef DEBUG printf ("DEBUG: SetFocus()\n"); #endif Raise (novawm_window); focusWindow = novawm_window; //Redraw all titlebars for (list < Novawm_Window * >::const_iterator i = winmgr.novawm_window_List.begin (); i != winmgr.novawm_window_List.end (); ++i) { XClearWindow (display, (*i)->titlebar); Redraw ((*i)); } if (!novawm_window) return; XSetInputFocus (display, novawm_window->window, RevertToNone, CurrentTime); novawm.DrawBar (); } void WinMgr::Hide (Novawm_Window * novawm_window) { #ifdef DEBUG printf ("DEBUG: Hide()\n"); #endif if (!novawm_window) return; if (novawm_window->hasTitlebar != true) XUnmapWindow (display, novawm_window->window); else XUnmapWindow (display, novawm_window->titlebar); novawm_window->SetState (WithdrawnState); if (novawm_window->nTChildren > 0) { for (int i = 0; i < novawm_window->nTChildren; i++) { //Hide any windows transient to this one Hide (WindowSearch (novawm_window->tChild[i])); } } //if(focusWindow == novawm_window && novawm_window->prev) //SetFocus(novawm_window->prev); SetFocus (0); if (novawm_window->hasTitlebar == true) AddUnmapIgnore (novawm_window->titlebar); //unmapignore++; else AddUnmapIgnore (novawm_window->window); } void WinMgr::Resize (Novawm_Window * novawm_window) { #ifdef DEBUG printf ("DEBUG: Resize()\n"); #endif if (!novawm_window) return; XEvent event; Window wdummy; XWindowAttributes win_attrib; int x, y, winx, winy; unsigned int mdummy; int idummy; XGrabPointer (display, novawm_window->titlebar, false, ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, None, ResizeCursor, CurrentTime); // XGrabServer (display); XQueryPointer (display, novawm_window->titlebar, &wdummy, &wdummy, &x, &y, &winx, &winy, &mdummy); /*configEvent.type = ConfigureNotify; * configEvent.event = novawm_window->window; * configEvent.window = novawm_window->window; * configEvent.width = novawm_window->width; * configEvent.height = novawm_window->height; * configEvent.border_width = 0; * configEvent.above = Below; * configEvent.override_redirect = false; */ XGetWindowAttributes (display, novawm_window->window, &win_attrib); //I added this because of problems with the wrong values //Update size values /*novawm_window->width = win_attrib.width; * novawm_window->height = win_attrib.height; * novawm_window->orig_width = win_attrib.width; * novawm_window->orig_height = win_attrib.height; */ XWarpPointer (display, None, root, 0, 0, 0, 0, novawm_window->x + novawm_window->width + 2, novawm_window->y + novawm_window->height + 2); while (1) { XMaskEvent (display, ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask, &event); switch (event.type) { case Expose: Redraw (WindowSearch (event.xexpose.window)); break; case MotionNotify: XQueryPointer (display, root, &wdummy, &wdummy, &idummy, &idummy, &x, &y, &mdummy); //Can't make it smaller than the titlebar (Doing so will also cause some apps to quit) if (y - novawm_window->y - 2 <= 21 + win_attrib.border_width) break; if ((x - novawm_window->x - 2 > novawm_window->size_hints->max_width) || (x - novawm_window->x - 2 < novawm_window->size_hints->min_width) || (y - novawm_window->y - 2 > novawm_window->size_hints->max_height) || (y - novawm_window->y - 2 < novawm_window->size_hints->min_height)) { #ifdef DEBUG /* printf ("DEBUG: Resize to %dx%d, Max GEOM is %dx%d Min GEOM is % dx % d \ n ", x - novawm_window->x - 2, y - novawm_window->y - 2, novawm_window->size_hints->max_width, novawm_window->size_hints->max_height, novawm_window->size_hints->max_width, novawm_window->size_hints->min_height); */#endif break; } SetSize (novawm_window, x - novawm_window->x - 2, y - novawm_window->y - 2); novawm_window->orig_width = novawm_window->width; //x - novawm_window->x - 2; novawm_window->orig_height = novawm_window->height; break; case ButtonRelease: XUngrabPointer (display, CurrentTime); XSync (display, true); //false); Redraw (novawm_window); return; break; } } } void WinMgr::Kill (Novawm_Window * novawm_window) { #ifdef DEBUG printf ("DEBUG: Kill()\n"); #endif Atom *pCheck = 0; XEvent deleteEvent; int nProtocols; if (!novawm_window) return; deleteEvent.type = ClientMessage; deleteEvent.xclient.window = novawm_window->window; deleteEvent.xclient.message_type = protocolAtom; deleteEvent.xclient.format = 32; deleteEvent.xclient.data.l[0] = deleteAtom; deleteEvent.xclient.data.l[1] = CurrentTime; int deleted = 0; //Hide (novawm_window); if (!novawm_window->window) { XDestroyWindow (display, novawm_window->titlebar); novawm_window->Destroy (); } XGetWMProtocols (display, novawm_window->window, &pCheck, &nProtocols); if (pCheck) { for (int i = 0; i < nProtocols; i++) { if (pCheck[i] == deleteAtom) { deleted = 1; XSendEvent (display, novawm_window->window, false, NoEventMask, &deleteEvent); //AddUnmapIgnore(novawm_window->window); //unmapignore++; break; } } if (pCheck) XFree (pCheck); } if (deleted != 1) //The Window doesn't support the Delete Protocol { XKillClient (display, novawm_window->window); //Safe? //unmapignore++; } } void WinMgr::Create_ListMenu (int menu_x, int menu_y) { listMenu.Clear (); //Clear the menu if (novawm_window_List.size () == 0) //There are no windows to manage { listMenu.AddItem ("No windows to manage!"); return; } nListWindow = 0; for (list < Novawm_Window * >::const_iterator i = winmgr.novawm_window_List.begin (); i != winmgr.novawm_window_List.end (); ++i) { if ((*i)->isTransient != true) { listMenu.AddItem ((*i)->title); nListWindow++; } } listMenu.Create (menu_x, menu_y); } void WinMgr::listMenu_Click (int item) { if (item > nListWindow && item < 0) return; int n = 0; // for (Novawm_Window * cWindow = topWindow; // cWindow || i >= nListWindow; cWindow = cWindow->next) for (list < Novawm_Window * >::const_iterator i = winmgr.novawm_window_List.begin (); i != winmgr.novawm_window_List.end (); ++i) { if ((*i)->isTransient != true) { if (n == item) { SetFocus ((*i)); break; } n++; } } //Clear list nListWindow = 0; } void Novawm_Window::Destroy () { #ifdef DEBUG printf ("DEBUG: Novawm_Window::Destroy()\n"); #endif XGrabServer (display); if (focusType == 1) XUngrabButton (display, AnyButton, AnyModifier, titlebar); XReparentWindow (display, window, root, x, y); XRemoveFromSaveSet (display, window); if (hasTitlebar == true) XDestroyWindow (display, titlebar); XSync (display, false); XUngrabServer (display); winmgr.novawm_window_List.remove (this); winmgr.SetFocus (0); delete this; #ifdef _WIN_GNOME_SUPPORT winmgr._WIN_CLIENT_LIST_UpdateList (); #endif } int Novawm_Window::GetState () { #ifdef DEBUG printf ("DEBUG: GetState()\n"); #endif Atom gState; int format; unsigned long dummy; long *data; int get_state = WithdrawnState; XGetWindowProperty (display, window, stateAtom, 0L, 2L, false, stateAtom, &gState, &format, &dummy, &dummy, (unsigned char **) &data); if (data) get_state = *data; XFree (data); return get_state; } void Novawm_Window::SetState (int set_state) { #ifdef DEBUG printf ("DEBUG: SetState(%d)\n", set_state); #endif CARD32 data[2]; state = set_state; data[0] = set_state; data[1] = None; XChangeProperty (display, window, stateAtom, stateAtom, 32, PropModeReplace, (unsigned char *) data, 2); } void Novawm_Window::Get_Net_States () { unsigned char StateList[10]; if (!StateList) { printf ("NovaWM ERROR: Failed to allocate memory for retrieving _NET_WM_STATEs\n"); return; } Atom dAtom; unsigned long nStates = 0; int format; unsigned long dummy; XGetWindowProperty (display, window, netStateAtom, XA_CARDINAL, 32, false, netStateAtom, &dAtom, &format, &nStates, &dummy, (unsigned char **) &StateList); for (int i = 0; i < nStates; i++) { if ((Atom) StateList[i] == netStateStickyAtom) { isSticky = true; } if ((Atom) StateList[i] == netStateSkipBarAtom) skipBar = true; } } void WinMgr::SetDesktop (int desktop) { #ifdef DEBUG printf ("DEBUG: SetDesktop(%d)\n", desktop); #endif if ((desktop > maxDesktops) || (desktop < 0)) { #ifdef DEBUG printf ("DEBUG: Attempt to goto desktop outside of allowed desktops.\n"); #endif return; //Bad Desktop } if (desktop + 1 > nDesktops) AddDesktop (); cDesktop = desktop; // for (Novawm_Window * window = topWindow; // (window) ; window = window->next) for (list < Novawm_Window * >::const_iterator i = winmgr.novawm_window_List.begin (); i != winmgr.novawm_window_List.end (); ++i) { if (((*i)->desktop != cDesktop) && ((*i)->state == NormalState)) { //Don't Hide() the window or it won't show up when we return to its desktop #ifdef _WIN_GNOME_SUPPORT if ((*i)->layer == WIN_LAYER_NORMAL) { #endif if ((*i)->isSticky == false) { if ((*i)->hasTitlebar == true) XUnmapWindow (display, (*i)->titlebar); else XUnmapWindow (display, (*i)->window); } #ifdef _WIN_GNOME_SUPPORT } #endif //Don't let the window change its state! (fixes desktop bugs!! :) ) if ((*i)->hasTitlebar == true) AddUnmapIgnore ((*i)->titlebar); //unmapignore++; else AddUnmapIgnore ((*i)->window); } if (((*i)->desktop == cDesktop) && ((*i)->state == NormalState)) { //Don't Raise() the window because if it's already hidden it shouldn't be mapped Raise ((*i)); } } //Make sure the NovaBar is on top (For apps like Nautilus) XRaiseWindow (display, novawm.NovaBar); #ifdef _WIN_GNOME_SUPPORT //Set the current desktop CARD32 currentWorkspace = (CARD32) winmgr.cDesktop; XChangeProperty (display, root, winProtocols_Workspace, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) ¤tWorkspace, 1); #endif } //There may be a more code in AddDesktop() in some other version int WinMgr::AddDesktop () { #ifdef DEBUG printf ("DEBUG: AddDesktop()\n"); #endif nDesktops++; #ifdef _WIN_GNOME_SUPPORT //Set the number of desktops CARD32 desktopNum = (CARD32) winmgr.nDesktops; XChangeProperty (display, root, winProtocols_WorkspaceCount, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &desktopNum, 1); #endif return 1; } void WinMgr::RemoveDesktop () { #ifdef DEBUG printf ("DEBUG: RemoveDesktop()\n"); #endif nDesktops--; } void WinMgr::SendToDesktop (Novawm_Window * window, int desktop) { #ifdef DEBUG printf ("DEBUG: SendToDesktop(%d)\n", desktop); #endif if ((desktop > maxDesktops) || (desktop < 0)) { #ifdef DEBUG printf ("DEBUG: Attempt to send a window to a illegal desktop\n"); #endif return; } if (desktop + 1 > nDesktops) AddDesktop (); window->desktop = desktop; if ((cDesktop != desktop) && (window->state == NormalState)) { if (window->hasTitlebar == true) XUnmapWindow (display, window->titlebar); else XUnmapWindow (display, window->window); //Don't let the window change its state! AddUnmapIgnore (window->titlebar); //window); } CARD32 desktopNum = (CARD32) desktop; XChangeProperty (display, window->window, netDesktopAtom, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &desktopNum, 1); #ifdef _WIN_GNOME_SUPPORT XChangeProperty (display, window->window, winProtocols_WorkspaceCount, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &desktopNum, 1); #endif } #ifdef _WIN_GNOME_SUPPORT void WinMgr::_WIN_CLIENT_LIST_UpdateList () { #ifdef DEBUG printf ("DEBUG: Updating _WIN_CLIENT_LIST\n"); #endif Window *wIDList = (Window *) malloc (sizeof (Window) * nClients); if (!wIDList) { printf ("NovaWM ERROR: Failed to allocate memory for the _WIN_CLIENT_LIST for some reason.\n"); return; } int n = 0; int listClients = 0; // for (Novawm_Window * currentWindow = topWindow; currentWindow; // currentWindow = currentWindow->next) for (list < Novawm_Window * >::const_iterator i = winmgr.novawm_window_List.begin (); i != winmgr.novawm_window_List.end (); ++i) { if ((*i)->layer == WIN_LAYER_NORMAL) { wIDList[n] = (*i)->window; listClients++; } n++; } XChangeProperty (display, root, winProtocols_ClientList, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) wIDList, nClients); if (wIDList) free (wIDList); } #endif void WinMgr::AddUnmapIgnore (Window ignoreWindow) { #ifdef DEBUG printf ("DEBUG: AddUnmapIgnore(%x)\n", ignoreWindow); #endif ignoreUnmapList.push_back (ignoreWindow); } void WinMgr::RemoveUnmapIgnore (Window ignoreWindow) { #ifdef DEBUG printf ("DEBUG: RemoveUnmapIgnore(%x)\n", ignoreWindow); #endif ignoreUnmapList.remove (ignoreWindow); } int WinMgr::Find_UnmapIgnore (Window ignoreWindow) { #ifdef DEBUG printf ("DEBUG: Find_UnmapIgnore(%x)\n", ignoreWindow); #endif for (list < Window >::const_iterator i = ignoreUnmapList.begin (); i != ignoreUnmapList.end (); ++i) { if ((*i) == ignoreWindow) { #ifdef DEBUG printf ("DEBUG: Found %x\n", i); #endif return 1; } } return -1; }