From: <co...@us...> - 2003-08-19 02:36:14
|
Update of /cvsroot/interfacewm/interfacewm In directory sc8-pr-cvs1:/tmp/cvs-serv4460 Modified Files: IWMWindowManager.h IWMWindowManager.m Added Files: IWMWindowManager+Event.m IWMWindowManager+Notification.m Log Message: prepare for reorg --- NEW FILE: IWMWindowManager+Event.m --- /* * $Id: IWMWindowManager+Event.m,v 1.1 2003/08/19 02:36:11 copal Exp $ * * This file is part of Interface WM. * * Copyright (C) 2002, Ian Mondragon * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "IWMWindowManager.h" #include "InterfaceWM.h" #include "IWMWindow.h" #include "IWMClient.h" #include "IWMScreen.h" #include "IWMDebug.h" #include "IWMCoreUtilities.h" @implementation IWMWindowManager (EventMethods) - (BOOL)grabPointerAndServer { IWMScreen *screen = [self currentScreen]; if (XGrabPointer(GlobalDisplay, [screen rootXWindow], False, IWM_EVENT_MASK_MOUSE, GrabModeAsync, GrabModeAsync, None, [screen normalCursor], CurrentTime) == GrabSuccess) { XGrabServer(GlobalDisplay); return YES; } return NO; } - (void)ungrabPointerAndServer { XUngrabServer(GlobalDisplay); XUngrabPointer(GlobalDisplay, CurrentTime); } - (void)cacheEventTime:(XEvent *)event { Time NewTimestamp = CurrentTime; IWMTRACE; switch (event->type) { case KeyPress: case KeyRelease: NewTimestamp = event->xkey.time; break; case ButtonPress: GlobalLastButtonClick = event->xbutton.time; // cache button clicks GlobalLastButtonClickWindow = event->xbutton.window; // cache clicked window NewTimestamp = event->xbutton.time; break; case ButtonRelease: NewTimestamp = event->xbutton.time; break; case MotionNotify: NewTimestamp = event->xmotion.time; break; case EnterNotify: case LeaveNotify: NewTimestamp = event->xcrossing.time; break; case PropertyNotify: NewTimestamp = event->xproperty.time; break; case SelectionClear: NewTimestamp = event->xselectionclear.time; break; case SelectionRequest: NewTimestamp = event->xselectionrequest.time; break; case SelectionNotify: NewTimestamp = event->xselection.time; break; default: return (void)0x0; } if ((NewTimestamp > GlobalTimestamp) || ((GlobalTimestamp - NewTimestamp) > 30000)) { GlobalTimestamp = NewTimestamp; } } - (void)handleEvent:(XEvent *)event { switch (event->type) { case ButtonPress: [self handleButtonEvent:&event->xbutton]; break; case KeyPress: [self handleKeyEvent:&event->xkey]; break; case ConfigureRequest: [self handleConfigureRequest:&event->xconfigurerequest]; break; case MapRequest: [self handleMapRequest:&event->xmaprequest]; break; case UnmapNotify: [self handleUnmapEvent:&event->xunmap]; break; case DestroyNotify: [self handleDestroyEvent:&event->xdestroywindow]; break; case ClientMessage: [self cacheEventTime:event]; [self handleClientMessage:&event->xclient]; break; case ColormapNotify: [self handleColormapChange:&event->xcolormap]; break; case PropertyNotify: [self handlePropertyChange:&event->xproperty]; break; case EnterNotify: [self handleEnterEvent:&event->xcrossing]; break; case Expose: [self handleExposeEvent:&event->xexpose]; break; #if 0 case ReparentNotify: [self handleReparentEvent:&event->xreparent]; break; #endif #ifdef SHAPE default: if (_flags.shape && event->type == shapeEvent) { [self handleShapeChange:(XShapeEvent *)&event]; } #endif } return (void)0x0; } - (void)handleKeyEvent:(XKeyEvent *)event { IWMClient *client = nil; if (!(client = [self clientWithWindow:event->window isParent:YES])) { } /*XXX no key events yet */ } - (void)handleButtonEvent:(XButtonEvent *)event { Atom type = [self typeForWindow:event->window]; IWMClient *client = [self clientWithWindow:event->window isParent:NO]; int double_click = NO; IWMTRACE; IWMDebug(@"[IWMWindowManager] -> handleButtonEvent: 0x%x", event->window); IWMDebug(@"Window type: %s\n", XGetAtomName(GlobalDisplay,type)); // set double_click flag if time between clicks doesn't exceed limit & both // clicks took place in the same window if (((event->time - GlobalLastButtonClick) < 250) && (event->window == GlobalLastButtonClickWindow)) { fprintf(stderr, "---> DOUBLE CLICK\n"); double_click = YES; } fprintf(stderr, "-> Last click: %i\n", (int)GlobalLastButtonClick); fprintf(stderr, "-> This click: %i\n", (int)event->time); // now we can update GlobalLastButtonClick & GlobalLastButtonClickWindow // with the current event data [self cacheEventTime:event]; GlobalLastButtonClickWindow = event->window; if (client) { [self setHeadClient:client]; } // root window if (type == atoms.iwm_window_type_root_window) { switch (event->button) { case Button1: [self runCommand:mouseButtons.one]; break; case Button2: //[self runCommand:mouseButtons.two]; [self cycleClients]; break; case Button3: [self runCommand:mouseButtons.three]; break; } return (void)0x0; } // client window else if (type == atoms.iwm_window_type_client_window) { switch (event->button) { case Button1: [client raise]; [self setHeadClient:client]; break; case Button2: break; case Button3: break; } return (void)0x0; } else if (type == atoms.iwm_window_type_titlebar) { // shade client if titlebar was double-clicked if (double_click) { [client shade]; } else { [client raise]; [client move]; [self setHeadClient:client]; } } else if (type == atoms.iwm_window_type_resizebar) { [client resize:NO]; } else if (type == atoms.iwm_window_type_left_grip || type == atoms.iwm_window_type_right_grip) { [client resize:YES]; } else if (type == atoms.iwm_window_type_close_button) { IWMDebug(@"close button pushed..."); [self removeClient:client]; } else if (type == atoms.iwm_window_type_minimize_button) { [client minimize]; } else if (type == atoms.iwm_window_type_maximize_button) { [client maximize]; } else if (type == atoms.iwm_window_type_icon) { // XXX - not accounted for yet } else if (type == atoms.iwm_window_type_unknown) { // XXX - should never get here NSLog(@"-> IWM_WINDOW_TYPE_UNKNKOWN"); } return (void)0x0; } - (void)handleClientMessage:(XClientMessageEvent *)event { IWMClient *client = nil; Atom action = event->data.l[0]; // // CBV: those two are unused // Atom property_1 = event->data.l[1]; // Atom property_2 = event->data.l[2]; IWMTRACE; client = [self clientWithWindow:event->window isParent:NO]; if (client) { // WM_PROTOCOLS if (event->message_type == atoms.wm_protocols) { // WM_DELETE_WINDOW: close window if (action == atoms.wm_delete_window) { NSLog(@"*** WM_DELETE_WINDOW message..."); [self removeClient:client]; } // WM_TAKE_FOCUS: re-assign keyboard focus (Xlib Vol. 1, pg. 421) else if (action == atoms.wm_take_focus) { [[client window] takeFocus]; } // WM_SAVE_YOURSELF else if (action == atoms.wm_save_yourself) { // XXX currently unimplemented } } // WM_CHANGE_STATE else if (event->message_type == atoms.wm_change_state) { if (IconicState == action) { //[client minimize]; } if (NormalState == action) { //[client unminimize]; } } // _NET_CLOSE_WINDOW: close a client else if (event->message_type == atoms.net_close_window) { NSLog(@"*** _NET_CLOSE_WINDOW message..."); [self removeClient:client]; } // _NET_MOVERESIZE_WINDOW: prefered over ConfigureRequest else if (event->message_type == atoms.net_moveresize_window) { int gravity, x, y, width, height; gravity = event->data.l[0]; // XXX not used right now x = event->data.l[1]; y = event->data.l[2]; width = event->data.l[3]; height = event->data.l[4]; [client resizeToWidth:width height:height x:x y:y]; } // _NET_WM_DESKTOP: change desktop client is on else if (event->message_type == atoms.net_wm_desktop) { int screen; screen = event->data.l[0]; [client moveToScreenNumber:screen]; } // _NET_CURRENT_DESKTOP: change the virtual desktop being shown else if (event->message_type == atoms.net_current_desktop) { int screen; screen = event->data.l[0]; // XXX currently unimplemented } // _NET_SHOWING_DESKTOP: toggle view of desktop without clients else if (event->message_type == atoms.net_showing_desktop) { // XXX currently unimplemented } // _NET_DESKTOP_VIEWPORT: large desktops are not part of IWM else if (event->message_type == atoms.net_desktop_viewport) { // XXX ignored in IWM XXX // } // _NET_DESKTOP_GEOMETRY: desktop geometry changes are not part of IWM else if (event->message_type == atoms.net_desktop_geometry) { // XXX ignored in IWM XXX // } // _NET_NUMBER_OF_DESKTOPS: change number of desktops else if (event->message_type == atoms.net_number_of_desktops) { int number; number = event->data.l[0]; // XXX currently unimplemented } // _NET_ACTIVE_WINDOW: set a client to active (focused) else if (event->message_type == atoms.net_active_window) { [client focus]; } // _NET_WM_STATE: change state of a client (1 or 2 states at a time) // // according to the EWMH spec, the first element in the event->data.l // is one of the following: // // _NET_WM_STATE_REMOVE, _NET_WM_STATE_ADD, or _NET_WM_STATE_TOGGLE // // these are supposed to be (respectively) 0, 1 and 2. the other two // allowable elements are the _NET_WM_STATE properties to be modified. else if (event->message_type == atoms.net_wm_state) { int i; // CBV: modification is unused // Atom modification = event->data.l[0]; Atom property; for (i = 0; i < 2; i++) { property = event->data.l[++i]; if (NULL != property) { #if 0 if (property == atoms.net_wm_state_modal) { _WM_STATE_MOD(desc->state.modal, modification); } else if (property == atoms.net_wm_state_sticky) { _WM_STATE_MOD(desc->state.sticky, modification); } else if (property == atoms.net_wm_state_maximized_vert) { _WM_STATE_MOD(desc->state.maximized_vert, modification); } else if (property == atoms.net_wm_state_maximized_horz) { _WM_STATE_MOD(desc->state.maximized_horz, modification); } else if (property == atoms.net_wm_state_shaded) { _WM_STATE_MOD(desc->state.shaded, modification); } else if (property == atoms.net_wm_state_skip_taskbar) { _WM_STATE_MOD(desc->state.skip_taskbar, modification); } else if (property == atoms.net_wm_state_skip_pager) { _WM_STATE_MOD(desc->state.skip_pager, modification); } else if (property == atoms.net_wm_state_hidden) { _WM_STATE_MOD(desc->state.hidden, modification); } else if (property == atoms.net_wm_state_fullscreen) { _WM_STATE_MOD(desc->state.fullscreen, modification); } else if (property == atoms.net_wm_state_above) { _WM_STATE_MOD(desc->state.above, modification); } else if (property == atoms.net_wm_state_below) { _WM_STATE_MOD(desc->state.below, modification); } #endif } } // rebuild the window state hints array [[client window] updateWindowState]; } } } - (void)handleColormapChange:(XColormapEvent *)event { IWMClient *client = nil; IWMTRACE; client = [self clientWithWindow:event->window isParent:NO]; if (client && event->new) { [client setColormap:event->colormap]; XInstallColormap(GlobalDisplay, event->colormap); } } /* * XXX - ConfigureRequests suck. _NET_MOVERESIZE_WINDOW is prefered. */ - (void)handleConfigureRequest:(XConfigureRequestEvent *)event { IWMClient *client = nil; XWindowChanges changes; IWMTRACE; if (!(client = [self clientWithWindow:event->window isParent:NO])) { client = [self headClient]; } if (client) { [client ungravitate]; if (event->value_mask & CWX) { [client setX:event->x]; } if (event->value_mask & CWY) { [client setY:event->y]; } if (event->value_mask & CWWidth) { [client setWidth:event->width]; } if (event->value_mask & CWHeight) { [client setHeight:event->height]; } [client gravitate]; changes.x = [client x]; changes.y = [client y]; changes.width = [client width]; changes.height = [client height]; changes.border_width = [client borderWidth]; changes.sibling = event->above; changes.stack_mode = event->detail; XConfigureWindow(GlobalDisplay, [[client parent] xWindow], event->value_mask, &changes); [client configure]; } changes.x = (client ? 0 : event->x); changes.y = (client ? [client titlebarHeight] : event->y); changes.width = event->width; changes.height = event->height; changes.sibling = event->above; changes.stack_mode = event->detail; XConfigureWindow(GlobalDisplay, event->window, event->value_mask, &changes); } - (void)handleEnterEvent:(XCrossingEvent *)event { IWMClient *client = nil; IWMTRACE; if ((client = [self clientWithWindow:event->window isParent:NO])) { XGrabButton(GlobalDisplay, AnyButton, Mod1Mask, [[client parent] xWindow], False, IWM_EVENT_MASK_BUTTON, GrabModeAsync, GrabModeAsync, None, None); // normal focus if (focusType == IWM_FOCUS_MOUSE || !(focusType == IWM_FOCUS_CLICK)) { [client focus]; } // sloppy focus: keep stacking order, but allow input into window else if (focusType == IWM_FOCUS_SLOPPY) { [[client window] takeFocus]; } } } /* * XXX - b0rken */ - (void)handleExposeEvent:(XExposeEvent *)event { IWMClient *client = nil; IWMTRACE; client = [self clientWithWindow:event->window isParent:YES]; if (client && event->count == 0) { [client redraw]; } } - (void)handleMapRequest:(XMapRequestEvent *)event { IWMClient *client = nil; IWMTRACE; if ((client = [self clientWithWindow:event->window isParent:NO])) { [self setHeadClient:client]; } else { client = [[IWMClient alloc] initWithWindow:event->window onScreen:_currentScreen]; [self addClient:client]; } } - (void)handlePropertyChange:(XPropertyEvent *)event { IWMClient *client = nil; IWMTRACE; client = [self clientWithWindow:event->window isParent:NO]; if (client) { switch (event->atom){ //case atoms.net_wm_name: case XA_WM_NAME: [[client parent] clear]; [client redraw]; break; case XA_WM_TRANSIENT_FOR: [client setTransient:[[client window] transient]]; break; case XA_WM_NORMAL_HINTS: [client setSizeHints:[[client window] wmNormalHints]]; break; case XA_WM_HINTS: //new_hints = XGetWMHints([screen display], // [[client window]xWindow]); break; //case _GNUSTEP_WM_ATTR: //break; default: break; } } } - (void)handleDestroyEvent:(XDestroyWindowEvent *)event { IWMClient *client = nil; IWMTRACE; if ((client = [self clientWithWindow:event->window isParent:NO])) { NSLog(@"*** destroy event..."); [self removeClient:client]; } XSync(GlobalDisplay, False); } - (void)handleUnmapEvent:(XUnmapEvent *)event { IWMClient *client = nil; IWMTRACE; if (event) { if ((client = [self clientWithWindow:event->window isParent:NO])) { if ([client ignoreUnmap]) { [client decrementIgnoreUnmap]; } //XXX - is this right? else if ([[client window] xWindow] == event->window) { NSLog(@"*** unmap event..."); [self removeClient:client]; } } } } #ifdef SHAPE - (void)handleShapeChange:(XShapeEvent *)event { } #endif @end --- NEW FILE: IWMWindowManager+Notification.m --- /* * $Id: IWMWindowManager+Notification.m,v 1.1 2003/08/19 02:36:11 copal Exp $ * * This file is part of Interface WM. * * Copyright (C) 2002, Ian Mondragon * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "IWMWindowManager.h" #include "IWMNotifications.h" #include "IWMDebug.h" #include <Foundation/NSNotification.h> @implementation IWMWindowManager (NotificationMethods) - (void)registerObservedNotifications { NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; // change name [center addObserver:self selector:@selector(changeClientName:) name:IWMClientChangeNameNotification object:nil]; // focus [center addObserver:self selector:@selector(focusClient:) name:IWMClientFocusNotification object:nil]; [center addObserver:self selector:@selector(unfocusClient:) name:IWMClientUnfocusNotification object:nil]; // resize [center addObserver:self selector:@selector(resizeClient:) name:IWMClientResizeNotification object:nil]; // move [center addObserver:self selector:@selector(moveClient:) name:IWMClientMoveNotification object:nil]; // move & resize [center addObserver:self selector:@selector(moveResizeClient:) name:IWMClientMoveResizeNotification object:nil]; // change screen [center addObserver:self selector:@selector(changeClientScreen:) name:IWMClientChangeScreenNotification object:nil]; [center addObserver:self selector:@selector(didChangeClientScreen:) name:IWMClientDidChangeScreenNotification object:nil]; // close [center addObserver:self selector:@selector(closeClient:) name:IWMClientCloseNotification object:nil]; [center addObserver:self selector:@selector(didCloseClient:) name:IWMClientDidCloseNotification object:nil]; // minimize [center addObserver:self selector:@selector(minimizeClient:) name:IWMClientMinimizeNotification object:nil]; [center addObserver:self selector:@selector(didMinimizeClient:) name:IWMClientDidMinimizeNotification object:nil]; [center addObserver:self selector:@selector(unminimizeClient:) name:IWMClientUnminimizeNotification object:nil]; [center addObserver:self selector:@selector(didUnminimizeClient:) name:IWMClientDidUnminimizeNotification object:nil]; // maximize [center addObserver:self selector:@selector(maximizeClient:) name:IWMClientMaximizeNotification object:nil]; [center addObserver:self selector:@selector(didMaximizeClient:) name:IWMClientDidMaximizeNotification object:nil]; [center addObserver:self selector:@selector(unmaximizeClient:) name:IWMClientUnmaximizeNotification object:nil]; [center addObserver:self selector:@selector(didUnmaximizeClient:) name:IWMClientDidUnmaximizeNotification object:nil]; // hide [center addObserver:self selector:@selector(hideClient:) name:IWMClientHideNotification object:nil]; [center addObserver:self selector:@selector(didHideClient:) name:IWMClientDidHideNotification object:nil]; [center addObserver:self selector:@selector(unhideClient:) name:IWMClientUnhideNotification object:nil]; [center addObserver:self selector:@selector(didUnhideClient:) name:IWMClientDidUnhideNotification object:nil]; // shade [center addObserver:self selector:@selector(shadeClient:) name:IWMClientShadeNotification object:nil]; [center addObserver:self selector:@selector(didShadeClient:) name:IWMClientDidShadeNotification object:nil]; [center addObserver:self selector:@selector(unshadeClient:) name:IWMClientUnshadeNotification object:nil]; [center addObserver:self selector:@selector(didUnshadeClient:) name:IWMClientDidUnshadeNotification object:nil]; return (void)0x0; } - (IWMClient *)obtainClientFromInfo:(NSDictionary *)info { IWMClient *client = nil; id obj = nil; // check for direct reference to client object if ((obj = [info objectForKey:@"client"])) { return client = obj; } // check for reference to client id else if ((obj = [info objectForKey:@"client_id"])) { client = [self clientWithID:[obj intValue]]; } // check for reference to a client's window else if ((obj = [info objectForKey:@"client_window"])) { client = [self clientWithWindow:[obj intValue] isParent:NO]; } // check for reference to a client's parent window else if ((obj = [info objectForKey:@"client_parent_window"])) { client = [self clientWithWindow:[obj intValue] isParent:YES]; } return client; } - changeClientName:(NSNotification *)notification { IWMDebug(@"changeClientName: %@", [notification userInfo]); return self; } - focusClient:(NSNotification *)notification { IWMDebug(@"focusClient: %@", [notification userInfo]); return self; } - unfocusClient:(NSNotification *)notification { IWMDebug(@"unfocusCilent: %@", [notification userInfo]); return self; } - resizeClient:(NSNotification *)notification { IWMDebug(@"resizeClient: %@", [notification userInfo]); return self; } - moveClient:(NSNotification *)notification { IWMDebug(@"moveClient: %@", [notification userInfo]); return self; } - moveResizeClient:(NSNotification *)notification { IWMDebug(@"moveResizeClient: %@", [notification userInfo]); return self; } - changeClientScreen:(NSNotification *)notification { IWMDebug(@"changeClientScreen: %@", [notification userInfo]); return self; } - didChangeClientScreen:(NSNotification *)notification { IWMDebug(@"didChangeClientScreen: %@", [notification userInfo]); return self; } - closeClient:(NSNotification *)notification { IWMDebug(@"closeClient: %@", [notification userInfo]); return self; } - didCloseClient:(NSNotification *)notification { IWMDebug(@"didCloseClient: %@", [notification userInfo]); return self; } - minimizeClient:(NSNotification *)notification { IWMDebug(@"minimizeClient: %@", [notification userInfo]); return self; } - didMinimizeClient:(NSNotification *)notification { IWMDebug(@"didMinimizeClient: %@", [notification userInfo]); return self; } - unminimizeClient:(NSNotification *)notification { IWMDebug(@"unminimizeClient: %@", [notification userInfo]); return self; } - didUnminimizeClient:(NSNotification *)notification { IWMDebug(@"didUnminimizeClient: %@", [notification userInfo]); return self; } - maximizeClient:(NSNotification *)notification { IWMDebug(@"maximizeClient : %@", [notification userInfo]); return self; } - didMaximizeClient:(NSNotification *)notification { IWMDebug(@"didMaximizeClient : %@", [notification userInfo]); return self; } - unmaximizeClient:(NSNotification *)notification { IWMDebug(@"unmaximizeClient : %@", [notification userInfo]); return self; } - didUnmaximizeClient:(NSNotification *)notification { IWMDebug(@"didUnmaximizeClient : %@", [notification userInfo]); return self; } - hideClient:(NSNotification *)notification { IWMDebug(@"hideClient : %@", [notification userInfo]); return self; } - didHideClient:(NSNotification *)notification { IWMDebug(@"didHideClient : %@", [notification userInfo]); return self; } - unhideClient:(NSNotification *)notification { IWMDebug(@"unhideClient : %@", [notification userInfo]); return self; } - didUnhideClient:(NSNotification *)notification { IWMDebug(@"didUnhideClient : %@", [notification userInfo]); return self; } - shadeClient:(NSNotification *)notification { IWMDebug(@"shadeClient : %@", [notification userInfo]); return self; } - didShadeClient:(NSNotification *)notification { IWMDebug(@"didShadeClient : %@", [notification userInfo]); return self; } - unshadeClient:(NSNotification *)notification { IWMDebug(@"unshadeClient : %@", [notification userInfo]); return self; } - didUnshadeClient:(NSNotification *)notification { IWMDebug(@"didUnshadeClient : %@", [notification userInfo]); return self; } @end Index: IWMWindowManager.h =================================================================== RCS file: /cvsroot/interfacewm/interfacewm/IWMWindowManager.h,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** IWMWindowManager.h 22 Apr 2003 17:39:42 -0000 1.12 --- IWMWindowManager.h 19 Aug 2003 02:36:11 -0000 1.13 *************** *** 35,45 **** @class NSString, NSMutableArray, NSMutableDictionary, NSNotification; - /*==========================================================================* - NOTIFICATIONS - *==========================================================================*/ - - extern NSString *IWMNotification_Debug; - extern NSString *IWMNotification_Quit; - @interface IWMWindowManager : NSObject { --- 35,38 ---- *************** *** 84,95 **** IWMWindowManager *GlobalIWM; Display *GlobalDisplay; ! Time Timestamp; ! ! /*==========================================================================* ! NOTIFICATION METHODS ! *==========================================================================*/ ! ! - (void)debug:(NSNotification *)notification; ! - (void)quit:(NSNotification *)notification; /*==========================================================================* --- 77,83 ---- IWMWindowManager *GlobalIWM; Display *GlobalDisplay; ! Time GlobalTimestamp; ! Time GlobalLastButtonClick; ! Window GlobalLastButtonClickWindow; /*==========================================================================* *************** *** 125,134 **** /*! - * @method initializeAsNotificationObserver - * @abstract Prepares notifications that InterfaceWM will respond to - */ - - (void)initializeAsNotificationObserver; - - /*! * @method scanWindows * @abstract Scans for any previously mapped windows & remaps them into IWM --- 113,116 ---- *************** *** 219,247 **** /*==========================================================================* - EVENT HANDLING - *==========================================================================*/ - - - (void)cacheEventTime:(XEvent *)event; - - (BOOL)grabPointerAndServer; - - (void)ungrabPointerAndServer; - - - (void)handleKeyEvent:(XKeyEvent *)event; - - (void)handleButtonEvent:(XButtonEvent *)event; - - (void)handleClientMessage:(XClientMessageEvent *)event; - - (void)handleColormapChange:(XColormapEvent *)event; - - (void)handleConfigureRequest:(XConfigureRequestEvent *)event; - - (void)handleEnterEvent:(XCrossingEvent *)event; - - (void)handleExposeEvent:(XExposeEvent *)event; - - (void)handleMapRequest:(XMapRequestEvent *)event; - - (void)handlePropertyChange:(XPropertyEvent *)event; - //- (void)handleReparentEvent:(XReparentEvent *)event; - - (void)handleDestroyEvent:(XDestroyWindowEvent *)event; - - (void)handleUnmapEvent:(XUnmapEvent *)event; - - #ifdef SHAPE - - (void)handleShapeChange:(XShapeEvent *)event; - #endif - - /*==========================================================================* SET METHODS *==========================================================================*/ --- 201,204 ---- *************** *** 287,290 **** --- 244,250 ---- #endif /* SHAPE */ + - (IWMClient *)clientWithID:(int)anID; + - (IWMClient *)clientWithWindow:(Window)window isParent:(BOOL)isParent; + - (void)resetSignalHandlers; *************** *** 299,302 **** --- 259,342 ---- int handle_xerror(Display *display, XErrorEvent *event); int XIO_Handler(Display *dpy); + + @end + + /*==========================================================================* + EventMethods + *==========================================================================*/ + + @interface IWMWindowManager (EventMethods) + + - (BOOL)grabPointerAndServer; + - (void)ungrabPointerAndServer; + + - (void)cacheEventTime:(XEvent *)event; + + /*! + * @method handleEvent: + * @description Determines the type of XEvent and passes control to the + * appropriate method for processing. + * @param event An XEvent + */ + - (void)handleEvent:(XEvent *)event; + + - (void)handleKeyEvent:(XKeyEvent *)event; + - (void)handleButtonEvent:(XButtonEvent *)event; + - (void)handleClientMessage:(XClientMessageEvent *)event; + - (void)handleColormapChange:(XColormapEvent *)event; + - (void)handleConfigureRequest:(XConfigureRequestEvent *)event; + - (void)handleEnterEvent:(XCrossingEvent *)event; + - (void)handleExposeEvent:(XExposeEvent *)event; + - (void)handleMapRequest:(XMapRequestEvent *)event; + - (void)handlePropertyChange:(XPropertyEvent *)event; + //- (void)handleReparentEvent:(XReparentEvent *)event; + - (void)handleDestroyEvent:(XDestroyWindowEvent *)event; + - (void)handleUnmapEvent:(XUnmapEvent *)event; + + #ifdef SHAPE + - (void)handleShapeChange:(XShapeEvent *)event; + #endif + + @end + + @interface IWMWindowManager (NotificationMethods) + + - (void)registerObservedNotifications; + - (IWMClient *)obtainClientFromInfo:(NSDictionary *)info; + + - changeClientName:(NSNotification *)notification; + + - focusClient:(NSNotification *)notification; + - unfocusClient:(NSNotification *)notification; + + - resizeClient:(NSNotification *)notification; + - moveClient:(NSNotification *)notification; + - moveResizeClient:(NSNotification *)notification; + + - changeClientScreen:(NSNotification *)notification; + - didChangeClientScreen:(NSNotification *)notification; + + - closeClient:(NSNotification *)notification; + - didCloseClient:(NSNotification *)notification; + + - minimizeClient:(NSNotification *)notification; + - didMinimizeClient:(NSNotification *)notification; + - unminimizeClient:(NSNotification *)notification; + - didUnminimizeClient:(NSNotification *)notification; + + - maximizeClient:(NSNotification *)notification; + - didMaximizeClient:(NSNotification *)notification; + - unmaximizeClient:(NSNotification *)notification; + - didUnmaximizeClient:(NSNotification *)notification; + + - hideClient:(NSNotification *)notification; + - didHideClient:(NSNotification *)notification; + - unhideClient:(NSNotification *)notification; + - didUnhideClient:(NSNotification *)notification; + + - shadeClient:(NSNotification *)notification; + - didShadeClient:(NSNotification *)notification; + - unshadeClient:(NSNotification *)notification; + - didUnshadeClient:(NSNotification *)notification; @end Index: IWMWindowManager.m =================================================================== RCS file: /cvsroot/interfacewm/interfacewm/IWMWindowManager.m,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** IWMWindowManager.m 5 Jun 2003 00:32:47 -0000 1.15 --- IWMWindowManager.m 19 Aug 2003 02:36:11 -0000 1.16 *************** *** 50,73 **** #include "IWMDebug.h" - /*==========================================================================* - PrivateMethods - *==========================================================================*/ - - - @interface IWMWindowManager (IWMPrivateMethods) - - - (IWMClient *)_clientWithID:(int)anID; - - (IWMClient *)_clientWithWindow:(Window)window isParent:(BOOL)parent; - - @end - - - /*==========================================================================* - NOTIFICATIONS - *==========================================================================*/ - - NSString *IWMNotification_Debug = @"_IWMNotification_Debug__"; - NSString *IWMNotification_Quit = @"_IWMNotification_Quit__"; - @implementation IWMWindowManager --- 50,53 ---- *************** *** 85,102 **** /*==========================================================================* - NOTIFICATION METHODS - *==========================================================================*/ - - - (void)debug:(NSNotification *)notification - { - NSLog(@"IWMNotification: debug"); - } - - - (void)quit:(NSNotification *)notification - { - NSLog(@"IWMNotification: quit"); - } - - /*==========================================================================* DESIGNATED INITIALIZER *==========================================================================*/ --- 65,68 ---- *************** *** 145,149 **** [self applyOverridesToWindowManager]; [self applyOverridesToTheme:nil]; ! [self initializeAsNotificationObserver]; // CBV: check whether there are already mapped windows --- 111,115 ---- [self applyOverridesToWindowManager]; [self applyOverridesToTheme:nil]; ! [self registerObservedNotifications]; // CBV: check whether there are already mapped windows *************** *** 402,417 **** } - - (void)initializeAsNotificationObserver - { - NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; - - #ifdef DEBUG - NSLog(@"Registering as NSNotification observer..."); - #endif - - [center addObserver:self selector:@selector(debug:) - name:IWMNotification_Debug object:nil]; - } - /* * clients may have already been mapped before IWM was started; these need to --- 368,371 ---- *************** *** 487,495 **** - - (IWMClient *)clientWithID:(int)anID - { - return [self _clientWithID:anID]; - } - - (Atom)typeForWindow:(Window)window { --- 441,444 ---- *************** *** 501,507 **** pid_t pid; ! #ifdef DEBUG ! NSLog(@"[IWMWindowManager] -> runCommand: %@", command); ! #endif pid = fork(); --- 450,454 ---- pid_t pid; ! IWMDebug(@"[IWMWindowManager] -> runCommand: %@", command); pid = fork(); *************** *** 523,591 **** - (void)run { ! XEvent ev; IWMTRACE; ! for (;;) { ! XNextEvent(GlobalDisplay, &ev); ! ! switch (ev.type) ! { ! case ButtonPress: ! [self handleButtonEvent:&ev.xbutton]; ! break; ! ! case KeyPress: ! [self handleKeyEvent:&ev.xkey]; ! break; ! ! case ConfigureRequest: ! [self handleConfigureRequest:&ev.xconfigurerequest]; ! break; ! ! case MapRequest: ! [self handleMapRequest:&ev.xmaprequest]; ! break; ! ! case UnmapNotify: ! [self handleUnmapEvent:&ev.xunmap]; ! break; ! ! case DestroyNotify: ! [self handleDestroyEvent:&ev.xdestroywindow]; ! break; ! ! case ClientMessage: ! [self handleClientMessage:&ev.xclient]; ! break; ! ! case ColormapNotify: ! [self handleColormapChange:&ev.xcolormap]; ! break; ! ! case PropertyNotify: ! [self handlePropertyChange:&ev.xproperty]; ! break; ! ! case EnterNotify: ! [self handleEnterEvent:&ev.xcrossing]; ! break; ! ! case Expose: ! [self handleExposeEvent:&ev.xexpose]; ! break; ! #if 0 ! case ReparentNotify: ! [self handleReparentEvent:&ev.xreparent]; ! break; ! #endif ! #ifdef SHAPE ! default: ! if (_flags.shape && ev.type == shapeEvent) ! { ! [self handleShapeChange:(XShapeEvent *)&ev]; ! } ! #endif ! } } } --- 470,481 ---- - (void)run { ! XEvent event; IWMTRACE; ! for (;;) ! { ! XNextEvent(GlobalDisplay, &event); ! [self handleEvent:&event]; } } *************** *** 970,1588 **** /*==========================================================================* - EVENT HANDLING - *==========================================================================*/ - - - (void)cacheEventTime:(XEvent *)event - { - Time NewTimestamp = CurrentTime; - - IWMTRACE; - - switch(event->type) { - case KeyPress: - case KeyRelease: - NewTimestamp = event->xkey.time; - break; - - case ButtonPress: - case ButtonRelease: - NewTimestamp = event->xbutton.time; - break; - - case MotionNotify: - NewTimestamp = event->xmotion.time; - break; - - case EnterNotify: - case LeaveNotify: - NewTimestamp = event->xcrossing.time; - break; - - case PropertyNotify: - NewTimestamp = event->xproperty.time; - break; - - case SelectionClear: - NewTimestamp = event->xselectionclear.time; - break; - - case SelectionRequest: - NewTimestamp = event->xselectionrequest.time; - break; - - case SelectionNotify: - NewTimestamp = event->xselection.time; - break; - - default: - return (void)0x0; - } - - if ((NewTimestamp > Timestamp) || ((Timestamp - NewTimestamp) > 30000)) - { - Timestamp = NewTimestamp; - } - } - - - (BOOL)grabPointerAndServer - { - IWMScreen *screen = [self currentScreen]; - - if (XGrabPointer(GlobalDisplay, [screen rootXWindow], False, - IWM_EVENT_MASK_MOUSE, GrabModeAsync, GrabModeAsync, None, - [screen normalCursor], CurrentTime) == GrabSuccess) - { - XGrabServer(GlobalDisplay); - - return YES; - } - - return NO; - } - - - (void)ungrabPointerAndServer - { - XUngrabServer(GlobalDisplay); - XUngrabPointer(GlobalDisplay, CurrentTime); - } - - - (void)handleKeyEvent:(XKeyEvent *)event - { - IWMClient *client = nil; - - if (!(client = [self _clientWithWindow:event->window isParent:YES])) - { - } - - /*XXX no key events yet */ - } - - - (void)handleButtonEvent:(XButtonEvent *)event - { - Atom type = [self typeForWindow:event->window]; - IWMClient *client = [self _clientWithWindow:event->window isParent:NO]; - - IWMTRACE; - - IWMDebug(@"[IWMWindowManager] -> handleButtonEvent: 0x%x", event->window); - IWMDebug(@"Window type: %s\n", XGetAtomName(GlobalDisplay,type)); - - if (client) - [self setHeadClient:client]; - - // root window - if (type == atoms.iwm_window_type_root_window) - { - switch (event->button) - { - case Button1: - [self runCommand:mouseButtons.one]; - break; - case Button2: - //[self runCommand:mouseButtons.two]; - [self cycleClients]; - break; - case Button3: - [self runCommand:mouseButtons.three]; - break; - } - - return (void)0x0; - } - - // client window - else if (type == atoms.iwm_window_type_client_window) - { - switch (event->button) - { - case Button1: - [client raise]; - [self setHeadClient:client]; - break; - case Button2: - break; - case Button3: - break; - } - - return (void)0x0; - } - - else if (type == atoms.iwm_window_type_titlebar) - { - [client raise]; - [client move]; - [self setHeadClient:client]; - } - - else if (type == atoms.iwm_window_type_resizebar) - { - [client resize:NO]; - } - - else if (type == atoms.iwm_window_type_left_grip || - type == atoms.iwm_window_type_right_grip) - { - [client resize:YES]; - } - - else if (type == atoms.iwm_window_type_close_button) - { - IWMDebug(@"close button pushed..."); - [self removeClient:client]; - } - - else if (type == atoms.iwm_window_type_minimize_button) - { - [client minimize]; - } - - else if (type == atoms.iwm_window_type_maximize_button) - { - [client maximize]; - } - - else if (type == atoms.iwm_window_type_icon) - { - // XXX - not accounted for yet - } - - else if (type == atoms.iwm_window_type_unknown) - { - // XXX - should never get here - NSLog(@"-> IWM_WINDOW_TYPE_UNKNKOWN"); - } - - return (void)0x0; - } - - - (void)handleClientMessage:(XClientMessageEvent *)event - { - IWMClient *client = nil; - Atom action = event->data.l[0]; - // - // CBV: those two are unused - // Atom property_1 = event->data.l[1]; - // Atom property_2 = event->data.l[2]; - - IWMTRACE; - - client = [self _clientWithWindow:event->window isParent:NO]; - - if (client) - { - // WM_PROTOCOLS - if (event->message_type == atoms.wm_protocols) - { - // WM_DELETE_WINDOW: close window - if (action == atoms.wm_delete_window) - { - NSLog(@"*** WM_DELETE_WINDOW message..."); - [self removeClient:client]; - } - - // WM_TAKE_FOCUS: re-assign keyboard focus (Xlib Vol. 1, pg. 421) - else if (action == atoms.wm_take_focus) - { - [[client window] takeFocus]; - } - - // WM_SAVE_YOURSELF - else if (action == atoms.wm_save_yourself) - { - // XXX currently unimplemented - } - } - - // WM_CHANGE_STATE - else if (event->message_type == atoms.wm_change_state) - { - if (IconicState == action) - { - //[client minimize]; - } - if (NormalState == action) - { - //[client unminimize]; - } - } - - // _NET_CLOSE_WINDOW: close a client - else if (event->message_type == atoms.net_close_window) - { - NSLog(@"*** _NET_CLOSE_WINDOW message..."); - [self removeClient:client]; - } - - // _NET_MOVERESIZE_WINDOW: prefered over ConfigureRequest - else if (event->message_type == atoms.net_moveresize_window) - { - int gravity, x, y, width, height; - - gravity = event->data.l[0]; // XXX not used right now - x = event->data.l[1]; - y = event->data.l[2]; - width = event->data.l[3]; - height = event->data.l[4]; - - [client resizeToWidth:width height:height x:x y:y]; - } - - // _NET_WM_DESKTOP: change desktop client is on - else if (event->message_type == atoms.net_wm_desktop) - { - int screen; - - screen = event->data.l[0]; - - [client moveToScreenNumber:screen]; - } - - // _NET_CURRENT_DESKTOP: change the virtual desktop being shown - else if (event->message_type == atoms.net_current_desktop) - { - int screen; - - screen = event->data.l[0]; - - // XXX currently unimplemented - } - - // _NET_SHOWING_DESKTOP: toggle view of desktop without clients - else if (event->message_type == atoms.net_showing_desktop) - { - // XXX currently unimplemented - } - - // _NET_DESKTOP_VIEWPORT: large desktops are not part of IWM - else if (event->message_type == atoms.net_desktop_viewport) - { - // XXX ignored in IWM XXX // - } - - // _NET_DESKTOP_GEOMETRY: desktop geometry changes are not part of IWM - else if (event->message_type == atoms.net_desktop_geometry) - { - // XXX ignored in IWM XXX // - } - - // _NET_NUMBER_OF_DESKTOPS: change number of desktops - else if (event->message_type == atoms.net_number_of_desktops) - { - int number; - - number = event->data.l[0]; - - // XXX currently unimplemented - } - - // _NET_ACTIVE_WINDOW: set a client to active (focused) - else if (event->message_type == atoms.net_active_window) - { - [client focus]; - } - - // _NET_WM_STATE: change state of a client (1 or 2 states at a time) - // - // according to the EWMH spec, the first element in the event->data.l - // is one of the following: - // - // _NET_WM_STATE_REMOVE, _NET_WM_STATE_ADD, or _NET_WM_STATE_TOGGLE - // - // these are supposed to be (respectively) 0, 1 and 2. the other two - // allowable elements are the _NET_WM_STATE properties to be modified. - else if (event->message_type == atoms.net_wm_state) - { - int i; - // CBV: modification is unused - // Atom modification = event->data.l[0]; - Atom property; - - for (i = 0; i < 2; i++) - { - property = event->data.l[++i]; - - if (0 != property) - { - #if 0 - if (property == atoms.net_wm_state_modal) - { - _WM_STATE_MOD(desc->state.modal, modification); - } - else if (property == atoms.net_wm_state_sticky) - { - _WM_STATE_MOD(desc->state.sticky, modification); - } - else if (property == atoms.net_wm_state_maximized_vert) - { - _WM_STATE_MOD(desc->state.maximized_vert, modification); - } - else if (property == atoms.net_wm_state_maximized_horz) - { - _WM_STATE_MOD(desc->state.maximized_horz, modification); - } - else if (property == atoms.net_wm_state_shaded) - { - _WM_STATE_MOD(desc->state.shaded, modification); - } - else if (property == atoms.net_wm_state_skip_taskbar) - { - _WM_STATE_MOD(desc->state.skip_taskbar, modification); - } - else if (property == atoms.net_wm_state_skip_pager) - { - _WM_STATE_MOD(desc->state.skip_pager, modification); - } - else if (property == atoms.net_wm_state_hidden) - { - _WM_STATE_MOD(desc->state.hidden, modification); - } - else if (property == atoms.net_wm_state_fullscreen) - { - _WM_STATE_MOD(desc->state.fullscreen, modification); - } - else if (property == atoms.net_wm_state_above) - { - _WM_STATE_MOD(desc->state.above, modification); - } - else if (property == atoms.net_wm_state_below) - { - _WM_STATE_MOD(desc->state.below, modification); - } - #endif - } - } - - // rebuild the window state hints array - [[client window] updateWindowState]; - } - } - } - - - (void)handleColormapChange:(XColormapEvent *)event - { - IWMClient *client = nil; - - IWMTRACE; - - client = [self _clientWithWindow:event->window isParent:NO]; - - if (client && event->new) - { - [client setColormap:event->colormap]; - XInstallColormap(GlobalDisplay, event->colormap); - } - } - - /* - * XXX - ConfigureRequests suck. _NET_MOVERESIZE_WINDOW is prefered. - */ - - (void)handleConfigureRequest:(XConfigureRequestEvent *)event - { - IWMClient *client = nil; - XWindowChanges changes; - - IWMTRACE; - - if (!(client = [self _clientWithWindow:event->window isParent:NO])) - { - client = [self headClient]; - } - - if (client) - { - [client ungravitate]; - - if (event->value_mask & CWX) - { - [client setX:event->x]; - } - if (event->value_mask & CWY) - { - [client setY:event->y]; - } - if (event->value_mask & CWWidth) - { - [client setWidth:event->width]; - } - if (event->value_mask & CWHeight) - { - [client setHeight:event->height]; - } - - [client gravitate]; - - changes.x = [client x]; - changes.y = [client y]; - changes.width = [client width]; - changes.height = [client height]; - changes.border_width = [client borderWidth]; - changes.sibling = event->above; - changes.stack_mode = event->detail; - - XConfigureWindow(GlobalDisplay, [[client parent] xWindow], - event->value_mask, &changes); - - [client configure]; - } - - changes.x = (client ? 0 : event->x); - changes.y = (client ? [client titlebarHeight] : event->y); - changes.width = event->width; - changes.height = event->height; - changes.sibling = event->above; - changes.stack_mode = event->detail; - - XConfigureWindow(GlobalDisplay, event->window, event->value_mask, &changes); - } - - - (void)handleEnterEvent:(XCrossingEvent *)event - { - IWMClient *client = nil; - - IWMTRACE; - - if ((client = [self _clientWithWindow:event->window isParent:NO])) - { - XGrabButton(GlobalDisplay, AnyButton, Mod1Mask, - [[client parent] xWindow], - False, IWM_EVENT_MASK_BUTTON, GrabModeAsync, GrabModeAsync, - None, None); - - // normal focus - if (focusType == IWM_FOCUS_MOUSE || !(focusType == IWM_FOCUS_CLICK)) - { - [client focus]; - } - - // sloppy focus: keep stacking order, but allow input into window - else if (focusType == IWM_FOCUS_SLOPPY) - { - [[client window] takeFocus]; - } - } - } - - /* - * XXX - b0rken - */ - - (void)handleExposeEvent:(XExposeEvent *)event - { - IWMClient *client = nil; - - IWMTRACE; - - client = [self _clientWithWindow:event->window isParent:YES]; - - if (client && event->count == 0) - { - [client redraw]; - } - } - - - (void)handleMapRequest:(XMapRequestEvent *)event - { - IWMClient *client = nil; - - IWMTRACE; - - if ((client = [self _clientWithWindow:event->window isParent:NO])) - { - [self setHeadClient:client]; - } - else - { - client = [[IWMClient alloc] initWithWindow:event->window - onScreen:_currentScreen]; - [self addClient:client]; - } - } - - - (void)handlePropertyChange:(XPropertyEvent *)event - { - IWMClient *client = nil; - - IWMTRACE; - - client = [self _clientWithWindow:event->window isParent:NO]; - - if (client) - { - switch (event->atom){ - //case atoms.net_wm_name: - case XA_WM_NAME: - [[client parent] clear]; - [client redraw]; - break; - - case XA_WM_TRANSIENT_FOR: - [client setTransient:[[client window] transient]]; - break; - - case XA_WM_NORMAL_HINTS: - [client setSizeHints:[[client window] wmNormalHints]]; - break; - - case XA_WM_HINTS: - //new_hints = XGetWMHints([screen display], - // [[client window]xWindow]); - break; - - //case _GNUSTEP_WM_ATTR: - //break; - - default: - break; - } - } - } - - - (void)handleDestroyEvent:(XDestroyWindowEvent *)event - { - IWMClient *client = nil; - - IWMTRACE; - - if ((client = [self _clientWithWindow:event->window isParent:NO])) - { - NSLog(@"*** destroy event..."); - [self removeClient:client]; - } - - XSync(GlobalDisplay, False); - } - - - (void)handleUnmapEvent:(XUnmapEvent *)event - { - IWMClient *client = nil; - - IWMTRACE; - - if (event) - { - if ((client = [self _clientWithWindow:event->window isParent:NO])) - { - if ([client ignoreUnmap]) - { - [client decrementIgnoreUnmap]; - } - //XXX - is this right? - else if ([[client window] xWindow] == event->window) - { - NSLog(@"*** unmap event..."); - [self removeClient:client]; - } - } - } - } - - #ifdef SHAPE - - (void)handleShapeChange:(XShapeEvent *)event - { - } - - #endif - - /*==========================================================================* SET METHODS *==========================================================================*/ --- 860,863 ---- *************** *** 1764,1767 **** --- 1039,1085 ---- #endif /* SHAPE */ + - (IWMClient *)clientWithID:(int)anID + { + if (anID) + { + IWMClient *client = nil; + int count, i; + + count = [clientArray count]; + for (i = 0; i < count; i++) + { + client = [clientArray objectAtIndex:i]; + if (anID == [client clientID]) + { + return client; + } + } + } + + return nil; + } + + - (IWMClient *)clientWithWindow:(Window)window isParent:(BOOL)parent + { + int i, count = [clientArray count]; + + if (count) + { + IWMClient *client = nil; + + for (i = 0; i < count; i++) + { + client = [clientArray objectAtIndex:i]; + if (client && [client containsXWindow:window isParent:parent]) + { + return client; + } + } + } + + return nil; + } + + - (void) resetSignalHandlers { *************** *** 1858,1862 **** // ! client = [GlobalIWM _clientWithWindow:event->resourceid isParent:NO]; if ( (event->error_... [truncated message content] |