/****************************************************************************/ /* This module is based on fvwm, but has been siginificantly modified */ /* by TakaC Hasegawa (tac.hasegawa@gmail.com) */ /****************************************************************************/ /**************************************************************************** * This module is based on Twm, but has been siginificantly modified * by Rob Nation (nation@rocket.sanders.lockheed.com) ****************************************************************************/ /*****************************************************************************/ /** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ /** Salt Lake City, Utah **/ /** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ /** Cambridge, Massachusetts **/ /** **/ /** All Rights Reserved **/ /** **/ /** Permission to use, copy, modify, and distribute this software and **/ /** its documentation for any purpose and without fee is hereby **/ /** granted, provided that the above copyright notice appear in all **/ /** copies and that both that copyright notice and this permis- **/ /** sion notice appear in supporting documentation, and that the **/ /** names of Evans & Sutherland and M.I.T. not be used in advertising **/ /** in publicity pertaining to distribution of the software without **/ /** specific, written prior permission. **/ /** **/ /** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ /** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ /** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ /** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ /** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ /** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ /** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ /** OR PERFORMANCE OF THIS SOFTWARE. **/ /*****************************************************************************/ #include #include #include "mlvwm.h" #include "screen.h" #include "menus.h" #include "borders.h" #include "misc.h" #include #include #include char NoName[] = "Untitled"; extern int matchWildcards( char *, char * ); /* Used to parse command line of clients for specific desk requests. */ /* Todo: check for multiple desks. */ static XrmDatabase db; static XrmOptionDescRec table [] = { /* Want to accept "-workspace N" or -xrm "afterstep*desk:N" as options * to specify the desktop. I have to include dummy options that * are meaningless since Xrm seems to allow -w to match -workspace * if there would be no ambiguity. */ {"-workspace", "*desk", XrmoptionSepArg, (caddr_t) NULL}, {"-xrm", NULL, XrmoptionResArg, (caddr_t) NULL}, }; styles *lookupstyles( char *name, XClassHint *class ) { styles *nptr, *style=NULL; /* look for the name first */ for( nptr = Scr.style_list; nptr != NULL; nptr = nptr->next){ if( matchWildcards( nptr->name, name ) ) style = nptr; if( class ){ if( matchWildcards( nptr->name, class->res_name ) ) style = nptr; if( matchWildcards( nptr->name, class->res_class ) ) style = nptr; } } if( style && style->iconname && !(style->miniicon) ) style->miniicon = ReadIcon( style->iconname, NULL, False ); return style; } void create_resizebox( MlvwmWindow *tmp_win ) { unsigned long valuemask; XSetWindowAttributes attributes; valuemask = CWCursor | CWEventMask | CWBackPixel; attributes.event_mask = ButtonPressMask | ButtonReleaseMask | ExposureMask; attributes.background_pixel = WhitePixel( dpy, Scr.screen ); attributes.cursor = Scr.MlvwmCursors[RESIZE]; tmp_win->resize_b = XCreateWindow( dpy, tmp_win->frame, tmp_win->frame_w-2-SBAR_WH, tmp_win->frame_h-2-SBAR_WH, SBAR_WH+(Scr.flags&SYSTEM8?1:0), SBAR_WH+(Scr.flags&SYSTEM8?1:0), Scr.flags&SYSTEM8?0:1, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes ); XSaveContext( dpy, tmp_win->resize_b, MlvwmContext, (caddr_t)tmp_win ); } void create_scrollbar( MlvwmWindow *tmp_win ) { unsigned long valuemask; XSetWindowAttributes attributes; int title_height; int lp; title_height = tmp_win->flags & TITLE ? TITLE_HEIGHT : -1; valuemask = CWCursor | CWEventMask | CWBackPixel; attributes.event_mask = ButtonPressMask | ButtonReleaseMask | ExposureMask | EnterWindowMask | LeaveWindowMask; attributes.background_pixel = WhitePixel( dpy, Scr.screen ); if( tmp_win->flags&SBARV ){ attributes.cursor = Scr.MlvwmCursors[SBARV_CURSOR]; tmp_win->scroll_v[0] = XCreateWindow( dpy, tmp_win->frame, tmp_win->frame_w-2-SBAR_WH, title_height, SBAR_WH, tmp_win->attr.height, 1, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes ); tmp_win->scroll_v[1] = XCreateWindow( dpy, tmp_win->scroll_v[0], 0, 0, SBAR_WH, SBAR_WH, 0, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes ); tmp_win->scroll_v[2] = XCreateWindow( dpy, tmp_win->scroll_v[0], 0, 0, SBAR_WH, SBAR_WH, 0, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes ); tmp_win->scroll_v[3] = XCreateWindow( dpy, tmp_win->scroll_v[0], 0, 0, SBAR_WH, SBAR_WH, 0, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes ); XMapSubwindows( dpy, tmp_win->scroll_v[0] ); if( !(tmp_win->flags&SCROLL) ) XUnmapWindow( dpy, tmp_win->scroll_v[3] ); for( lp=0; lp<4; lp++ ) XSaveContext( dpy, tmp_win->scroll_v[lp], MlvwmContext, (caddr_t)tmp_win ); } if( tmp_win->flags&SBARH ){ attributes.cursor = Scr.MlvwmCursors[SBARH_CURSOR]; tmp_win->scroll_h[0] = XCreateWindow( dpy, tmp_win->frame, -1, tmp_win->frame_h-2-SBAR_WH, tmp_win->attr.width, SBAR_WH, 1, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes ); tmp_win->scroll_h[1] = XCreateWindow( dpy, tmp_win->scroll_h[0], 0, 0, SBAR_WH, SBAR_WH, 0, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes ); tmp_win->scroll_h[2] = XCreateWindow( dpy, tmp_win->scroll_h[0], 0, 0, SBAR_WH, SBAR_WH, 0, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes ); tmp_win->scroll_h[3] = XCreateWindow( dpy, tmp_win->scroll_h[0], 0, 0, SBAR_WH, SBAR_WH, 0, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes ); XMapSubwindows( dpy, tmp_win->scroll_h[0] ); if( !(tmp_win->flags&SCROLL) ) XUnmapWindow( dpy, tmp_win->scroll_h[3] ); for( lp=0; lp<4; lp++ ) XSaveContext(dpy,tmp_win->scroll_h[lp],MlvwmContext,(caddr_t)tmp_win); } } void create_titlebar( MlvwmWindow *tmp_win ) { unsigned long valuemask; XSetWindowAttributes attributes; valuemask = CWCursor | CWEventMask | CWBackPixel; attributes.event_mask = ButtonPressMask | ButtonReleaseMask | ExposureMask; attributes.background_pixel = WhitePixel( dpy, Scr.screen ); attributes.cursor = Scr.MlvwmCursors[TITLE_CURSOR]; tmp_win->title_w = XCreateWindow( dpy, tmp_win->frame, Scr.flags&SYSTEM8?2:0, 0, tmp_win->attr.width+SBAR_WH+1, TITLE_HEIGHT, 0, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes ); attributes.event_mask = ( ButtonPressMask|ButtonReleaseMask|ExposureMask | EnterWindowMask | LeaveWindowMask ); if( tmp_win->flags&CLOSER ){ attributes.cursor = Scr.MlvwmCursors[DESTROY]; tmp_win->close_b = XCreateWindow( dpy, tmp_win->title_w, Scr.flags&SYSTEM8?4:BOXSIZE+1, (TITLE_HEIGHT-BOXSIZE)/2, BOXSIZE, BOXSIZE, 0, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes ); XSaveContext( dpy, tmp_win->close_b, MlvwmContext, (caddr_t)tmp_win ); } if( tmp_win->flags&MINMAXR ){ attributes.cursor = Scr.MlvwmCursors[SELECT]; tmp_win->minmax_b = XCreateWindow( dpy, tmp_win->title_w, tmp_win->frame_w-BOXSIZE*2-1, (TITLE_HEIGHT-BOXSIZE)/2, BOXSIZE, BOXSIZE, 0, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes ); XSaveContext( dpy, tmp_win->minmax_b, MlvwmContext, (caddr_t)tmp_win ); } if( tmp_win->flags&SHADER ){ attributes.cursor = Scr.MlvwmCursors[SELECT]; tmp_win->shade_b = XCreateWindow( dpy, tmp_win->title_w, tmp_win->frame_w-BOXSIZE*2-1, (TITLE_HEIGHT-BOXSIZE)/2, BOXSIZE, BOXSIZE, 0, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes ); XSaveContext( dpy, tmp_win->shade_b, MlvwmContext, (caddr_t)tmp_win ); } XMapSubwindows( dpy, tmp_win->title_w ); XSaveContext( dpy, tmp_win->title_w, MlvwmContext, (caddr_t)tmp_win ); } void FetchWmProtocols (MlvwmWindow *tmp) { unsigned long flags = 0L; Atom *protocols = NULL, *ap; int i, n; Atom atype; int aformat; unsigned long bytes_remain,nitems; if(tmp == NULL) return; /* First, try the Xlib function to read the protocols. * This is what Twm uses. */ if (XGetWMProtocols (dpy, tmp->w, &protocols, &n)){ for (i = 0, ap = protocols; i < n; i++, ap++){ if (*ap == (Atom)_XA_WM_TAKE_FOCUS) flags |= DoesWmTakeFocus; if (*ap == (Atom)_XA_WM_DELETE_WINDOW) flags |= DoesWmDeleteWindow; } if (protocols) XFree ((char *) protocols); } else{ /* Next, read it the hard way. mosaic from Coreldraw needs to * be read in this way. */ if ((XGetWindowProperty(dpy, tmp->w, _XA_WM_PROTOCOLS, 0L, 10L, False, _XA_WM_PROTOCOLS, &atype, &aformat, &nitems, &bytes_remain, (unsigned char **)&protocols))==Success){ for (i = 0, ap = protocols; i < nitems; i++, ap++){ if (*ap == (Atom)_XA_WM_TAKE_FOCUS) flags |= DoesWmTakeFocus; if (*ap == (Atom)_XA_WM_DELETE_WINDOW) flags |= DoesWmDeleteWindow; } if (protocols) XFree ((char *) protocols); } } if( XGetWindowProperty(dpy, tmp->w, _XA_WM_STATE, 0L, 3L, False, _XA_WM_STATE, &atype, &aformat, &nitems, &bytes_remain, (unsigned char **)&protocols)==Success && protocols != NULL && *protocols==IconicState) tmp->flags |= STARTICONIC; tmp->flags |= flags; return; } void GrabKeys( MlvwmWindow *tmp_win ) { ShortCut *tmp; for (tmp = Scr.ShortCutRoot; tmp != NULL; tmp = tmp->next){ XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->frame, True, GrabModeAsync, GrabModeAsync); } return; } void GetWindowSizeHints( MlvwmWindow *mw ) { long supplied=0; if( !XGetWMNormalHints( dpy, mw->w,&(mw->hints), &supplied ) ) mw->hints.flags = 0; if (mw->hints.flags & PResizeInc){ if (mw->hints.width_inc == 0) mw->hints.width_inc = 1; if (mw->hints.height_inc == 0) mw->hints.height_inc = 1; } else{ mw->hints.width_inc = 1; mw->hints.height_inc = 1; } if(!(mw->hints.flags & PBaseSize)){ mw->hints.base_width = 0; mw->hints.base_height = 0; } if(!(mw->hints.flags & PMinSize)){ mw->hints.min_width = mw->hints.base_width; mw->hints.min_height = mw->hints.base_height; } if(!(mw->hints.flags & PMaxSize)){ mw->hints.max_width = MAX_WINDOW_WIDTH; mw->hints.max_height = MAX_WINDOW_HEIGHT; } if(mw->hints.max_width < mw->hints.min_width) mw->hints.max_width = MAX_WINDOW_WIDTH; if(mw->hints.max_height < mw->hints.min_height) mw->hints.max_height = MAX_WINDOW_HEIGHT; if(mw->hints.min_height <= 0) mw->hints.min_height = 1; if(mw->hints.min_width <= 0) mw->hints.min_width = 1; } void SmartPlacement( MlvwmWindow *t, int width, int height, int *x, int *y ) { int temp_h,temp_w; int test_x = 0,test_y = 0; int loc_ok = False, tw,tx,ty,th; MlvwmWindow *test_window; temp_h = height; temp_w = width; while( test_y+temp_hDesk==Scr.currentdesk && !(Scr.flags&STARTING))|| test_window->Desk==t->Desk) && !(test_window->flags&HIDED) && !(test_window->flags&TRANSIENT) ){ if( test_window!=t ){ tw=test_window->frame_w+2; th=test_window->frame_h+2; tx = test_window->frame_x; ty = test_window->frame_y; if( tx<=test_x+width && tx+tw>=test_x && ty<=test_y+height && ty+th>=test_y ){ loc_ok = False; test_x = tx + tw; } } } test_window = test_window->next; } test_x +=1; } test_y +=1; } if( loc_ok==False ){ if( Scr.ActiveWin ){ *x = Scr.ActiveWin->frame_x+TITLE_HEIGHT; *y = Scr.ActiveWin->frame_y+TITLE_HEIGHT; } } else{ *x = test_x; *y = test_y; } return; } MlvwmWindow *AddWindow( Window win ) { MlvwmWindow *tmp_win, *last; unsigned long valuemask; XSetWindowAttributes attributes; int title_height; XTextProperty text_prop; Atom atype; int aformat; int diff_x=0, diff_y=0; styles *tmp_style; #ifdef USE_LOCALE int num; char **list; #endif unsigned long nitems, bytes_remain; unsigned char *prop; XrmValue rm_value; int client_argc; char **client_argv = NULL, *str_type; Bool status; tmp_win = calloc( 1, sizeof( MlvwmWindow ) ); tmp_win->flags = NORMALWIN; if( Scr.flags&SYSTEM8 ) tmp_win->flags |= SHADER; tmp_win->size_w = Scr.MyDisplayWidth*90./100.; tmp_win->size_h = Scr.MyDisplayHeight*90./100.; tmp_win->miniicon = NULL; if( Scr.ActiveWin ) last = Scr.ActiveWin; else for ( last = (MlvwmWindow *)&Scr.MlvwmRoot; last->next != NULL; last = last->next); if( last->next ){ tmp_win->next = last->next; last->next->prev = tmp_win; } last->next = (struct MlvwmWindow *)tmp_win; tmp_win->prev = last; if( tmp_win==(MlvwmWindow *)0 ) return NULL; tmp_win->flags = 0; tmp_win->w = win; XGetWindowAttributes( dpy, tmp_win->w, &tmp_win->attr ); if( XGetWMName( dpy, tmp_win->w, &text_prop) != 0 ){ #ifdef USE_LOCALE if(text_prop.value) text_prop.nitems = strlen(text_prop.value); if(XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >= Success && num > 0 && *list) tmp_win->name = *list; else tmp_win->name = NoName; #else tmp_win->name = (char *)text_prop.value; #endif } else tmp_win->name = NoName; tmp_win->class = NoClass; XGetClassHint(dpy, tmp_win->w, &tmp_win->class); if (tmp_win->class.res_name == NULL) tmp_win->class.res_name = NoName; if (tmp_win->class.res_class == NULL) tmp_win->class.res_class = NoName; tmp_win->wmhints = XGetWMHints( dpy, tmp_win->w ); tmp_win->old_bw = tmp_win->attr.border_width; { int xws, yws, xbs, ybs; unsigned wws, hws, wbs, hbs; int boundingShaped, clipShaped; XShapeSelectInput (dpy, tmp_win->w, ShapeNotifyMask); XShapeQueryExtents (dpy, tmp_win->w, &boundingShaped, &xws, &yws, &wws, &hws, &clipShaped, &xbs, &ybs, &wbs, &hbs); tmp_win->wShaped = boundingShaped; } GetWindowSizeHints( tmp_win ); if( (tmp_style = lookupstyles( tmp_win->name, &tmp_win->class ))!=NULL ){ tmp_win->flags = tmp_style->flags; if( tmp_style->maxmizescale ){ tmp_win->size_w = Scr.MyDisplayWidth*(double)tmp_style->maxmizescale/100.; tmp_win->size_h = (Scr.MyDisplayHeight-MENUB_H)* (double)tmp_style->maxmizescale/100.; } else{ tmp_win->size_w = tmp_style->maxmizesize_w*tmp_win->hints.width_inc+ tmp_win->hints.base_width; tmp_win->size_h = tmp_style->maxmizesize_h*tmp_win->hints.height_inc+ tmp_win->hints.base_height; tmp_win->size_w += SBAR_WH+1+2; if( !(tmp_win->flags&SBARV) ) tmp_win->size_w-=(SBAR_WH+1); tmp_win->size_h += SBAR_WH+TITLE_HEIGHT+2+2; if( !(tmp_win->flags&SBARH) ) tmp_win->size_h-=(SBAR_WH+1); if( Scr.flags&SYSTEM8 ){ tmp_win->size_w += 12; tmp_win->size_h += 6; } } tmp_win->miniicon = tmp_style->miniicon; if( !tmp_win->miniicon ) if( (tmp_style = lookupstyles( "*", NULL ))!=NULL && tmp_style->miniicon ) tmp_win->miniicon = tmp_style->miniicon; } if(XGetTransientForHint(dpy, tmp_win->w, &tmp_win->transientfor)){ tmp_win->flags &= ~NORMALWIN; if( Scr.flags&SYSTEM8 ) tmp_win->flags &= ~SHADER; tmp_win->flags |= TRANSIENT; if( !(tmp_win->flags&NONTRANSIENTDECORATE) ) tmp_win->flags |= TITLE; } title_height = tmp_win->flags & TITLE ? TITLE_HEIGHT : -1; tmp_win->Desk = Scr.currentdesk; /* Find out if the client requested a specific desk on the command line. */ if ( XGetCommand( dpy, tmp_win->w, &client_argv, &client_argc ) ) { XrmParseCommand( &db, table, 2, "mlvwm", &client_argc, client_argv ); status = XrmGetResource( db, "mlvwm.desk", "Mlvwm.Desk", &str_type, &rm_value ); if ((status == True) && (rm_value.size != 0)) tmp_win->Desk = atoi(rm_value.addr); XrmDestroyDatabase (db); db = NULL; } if ((XGetWindowProperty(dpy, tmp_win->w, _XA_WM_DESKTOP, 0L, 1L, True, _XA_WM_DESKTOP, &atype, &aformat, &nitems, &bytes_remain, &prop))==Success){ if(prop != NULL){ tmp_win->Desk = *(unsigned long *)prop; XFree(prop); } } if( tmp_win->Desk<0 || tmp_win->Desk>=Scr.n_desktop ) tmp_win->Desk = 0; if( tmp_win->flags&(TITLE|SBARV|SBARH|RESIZER) ){ tmp_win->frame_w = tmp_win->attr.width+SBAR_WH+1+2; diff_x = 1; diff_y = title_height+1; if( !(tmp_win->flags&SBARV) ) tmp_win->frame_w-=(SBAR_WH+1); tmp_win->frame_h = tmp_win->attr.height+SBAR_WH+title_height+2+2; if( !(tmp_win->flags&SBARH) ) tmp_win->frame_h-=(SBAR_WH+1); if( Scr.flags&SYSTEM8 ){ diff_x += 6; tmp_win->frame_w += 12; tmp_win->frame_h += 6; } } else{ diff_x = (5+tmp_win->old_bw); diff_y = (5+tmp_win->old_bw); tmp_win->frame_w = tmp_win->attr.width+2+5*2; tmp_win->frame_h = tmp_win->attr.height+2+5*2; } if( !(tmp_win->flags & TRANSIENT) && !(tmp_win->hints.flags & USPosition) && !(tmp_win->hints.flags & PPosition) ) SmartPlacement( tmp_win, tmp_win->frame_w+2, tmp_win->frame_h+2, &(tmp_win->attr.x), &(tmp_win->attr.y) ); tmp_win->diff_x = tmp_win->attr.x; tmp_win->diff_y = tmp_win->attr.y; tmp_win->frame_x = tmp_win->attr.x + tmp_win->old_bw-1; tmp_win->frame_y = tmp_win->attr.y + tmp_win->old_bw-1; if( !(tmp_win->flags&TRANSIENT) ){ tmp_win->frame_x = tmp_win->frame_x+tmp_win->frame_w < Scr.MyDisplayWidth ? tmp_win->frame_x : Scr.MyDisplayWidth-tmp_win->frame_w-2; tmp_win->frame_x = tmp_win->frame_x<0 ? 0 : tmp_win->frame_x; tmp_win->frame_y = tmp_win->attr.y+tmp_win->frame_h < Scr.MyDisplayHeight ? tmp_win->frame_y : Scr.MyDisplayHeight-tmp_win->frame_h-2; } else{ tmp_win->frame_x -= diff_x; tmp_win->frame_y -= diff_y; } if( tmp_win->frame_yframe_y = MENUB_H; valuemask = CWCursor | CWEventMask | CWBackPixel; attributes.cursor = Scr.MlvwmCursors[TITLE_CURSOR]; attributes.background_pixel = WhitePixel( dpy, Scr.screen ); attributes.event_mask = (SubstructureRedirectMask | ButtonPressMask | ButtonReleaseMask |EnterWindowMask | ExposureMask | LeaveWindowMask ); tmp_win->frame = XCreateWindow( dpy, Scr.Root, tmp_win->frame_x, tmp_win->frame_y, tmp_win->frame_w, tmp_win->frame_h, 1, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes ); attributes.cursor = Scr.MlvwmCursors[DEFAULT]; attributes.background_pixel = WhitePixel( dpy, Scr.screen ); tmp_win->Parent = XCreateWindow( dpy, tmp_win->frame, -1, title_height, tmp_win->attr.width, tmp_win->attr.height, 1, CopyFromParent, InputOutput,CopyFromParent, valuemask,&attributes); if( tmp_win->flags&TITLE ) create_titlebar( tmp_win ); if( tmp_win->flags&RESIZER ) create_resizebox( tmp_win ); if( tmp_win->flags&SBARH || tmp_win->flags&SBARV ) create_scrollbar( tmp_win ); if( !(tmp_win->flags&( TITLE | SBARV | SBARH | RESIZER )) ) XMoveWindow( dpy, tmp_win->Parent, 5, 5 ); XSetWindowBorderWidth( dpy, tmp_win->w, 0 ); XSaveContext( dpy, tmp_win->frame, MlvwmContext, (caddr_t)tmp_win ); XSaveContext( dpy, tmp_win->Parent, MlvwmContext, (caddr_t)tmp_win ); XSaveContext( dpy, tmp_win->w, MlvwmContext, (caddr_t)tmp_win ); XAddToSaveSet( dpy, win ); XUnmapWindow( dpy, tmp_win->w ); XRaiseWindow( dpy, tmp_win->Parent ); if( tmp_win->flags&RESIZER ) XRaiseWindow( dpy, tmp_win->resize_b ); XReparentWindow( dpy, tmp_win->w, tmp_win->Parent, 0, 0 ); valuemask = (CWEventMask | CWDontPropagate ); attributes.event_mask = (StructureNotifyMask | PropertyChangeMask | VisibilityChangeMask | EnterWindowMask | LeaveWindowMask | ColormapChangeMask | FocusChangeMask); attributes.do_not_propagate_mask = ( ButtonPressMask | ButtonReleaseMask ); XChangeWindowAttributes( dpy, tmp_win->w, valuemask, &attributes ); SetUpFrame( tmp_win, tmp_win->frame_x, tmp_win->frame_y, tmp_win->frame_w, tmp_win->frame_h, True ); XMapSubwindows( dpy, tmp_win->Parent ); XMapWindow( dpy, tmp_win->Parent ); { Window JunkRoot, JunkChild; int JunkX, JunkY; unsigned int JunkWidth, JunkHeight, JunkBW, JunkDepth; int a, b; XGetGeometry(dpy, tmp_win->w, &JunkRoot, &JunkX, &JunkY, &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth); XTranslateCoordinates(dpy,tmp_win->frame,Scr.Root,JunkX,JunkY, &a,&b,&JunkChild); tmp_win->diff_x -= a; tmp_win->diff_y -= b; } FetchWmProtocols (tmp_win); if( !(Scr.flags&FOLLOWTOMOUSE) ){ XGrabButton(dpy, AnyButton, AnyModifier, tmp_win->frame,True, ButtonPressMask, GrabModeSync,GrabModeAsync,None, Scr.MlvwmCursors[SYS]); } tmp_win->win_w = tmp_win->frame_w; tmp_win->win_h = tmp_win->frame_h; GrabKeys( tmp_win ); return tmp_win; }