/////////////////////////////////////////////
// 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;
}
syntax highlighted by Code2HTML, v. 0.9.1