/[gnustep]/gnustep/core/gui/Source/NSWindow.m
ViewVC logotype

Contents of /gnustep/core/gui/Source/NSWindow.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.288 - (show annotations) (download)
Tue Sep 23 17:16:59 2003 UTC (20 years, 7 months ago) by alexm
Branch: MAIN
CVS Tags: gui-0_9_0
Changes since 1.287: +1 -1 lines
Only force a display of the content view if we're being ordered _to_ the screen.

1 /** <title>NSWindow</title>
2
3 <abstract>The window class</abstract>
4
5 Copyright (C) 1996 Free Software Foundation, Inc.
6
7 Author: Scott Christley <scottc@net-community.com>
8 Venkat Ajjanagadde <venkat@ocbi.com>
9 Date: 1996
10 Author: Felipe A. Rodriguez <far@ix.netcom.com>
11 Date: June 1998
12 Author: Richard Frith-Macdonald <richard@brainstorm.co.uk>
13 Date: December 1998
14
15 This file is part of the GNUstep GUI Library.
16
17 This library is free software; you can redistribute it and/or
18 modify it under the terms of the GNU Library General Public
19 License as published by the Free Software Foundation; either
20 version 2 of the License, or (at your option) any later version.
21
22 This library is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 Library General Public License for more details.
26
27 You should have received a copy of the GNU Library General Public
28 License along with this library; see the file COPYING.LIB.
29 If not, write to the Free Software Foundation,
30 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 */
32
33 #include "config.h"
34
35 #include <Foundation/NSDebug.h>
36 #include <Foundation/NSRunLoop.h>
37 #include <Foundation/NSScanner.h>
38 #include <Foundation/NSAutoreleasePool.h>
39 #include <Foundation/NSString.h>
40 #include <Foundation/NSCoder.h>
41 #include <Foundation/NSArray.h>
42 #include <Foundation/NSGeometry.h>
43 #include <Foundation/NSNotification.h>
44 #include <Foundation/NSValue.h>
45 #include <Foundation/NSException.h>
46 #include <Foundation/NSSet.h>
47 #include <Foundation/NSLock.h>
48 #include <Foundation/NSUserDefaults.h>
49
50 #include "AppKit/NSDocument.h"
51 #include "AppKit/NSWindow.h"
52 #include "AppKit/NSWindowController.h"
53 #include "AppKit/NSApplication.h"
54 #include "AppKit/NSButtonCell.h"
55 #include "AppKit/NSMenu.h"
56 #include "AppKit/NSImage.h"
57 #include "AppKit/NSTextFieldCell.h"
58 #include "AppKit/NSTextField.h"
59 #include "AppKit/NSFont.h"
60 #include "AppKit/NSColor.h"
61 #include "AppKit/NSScreen.h"
62 #include "AppKit/NSView.h"
63 #include "AppKit/NSCursor.h"
64 #include "AppKit/PSOperators.h"
65 #include "AppKit/NSDragging.h"
66 #include "AppKit/NSPasteboard.h"
67 #include "AppKit/NSHelpManager.h"
68 #include "AppKit/NSGraphics.h"
69 #include "AppKit/NSCachedImageRep.h"
70 #include "AppKit/NSToolbar.h"
71 #include "GNUstepGUI/GSTrackingRect.h"
72 #include "GNUstepGUI/GSDisplayServer.h"
73
74 BOOL GSViewAcceptsDrag(NSView *v, id<NSDraggingInfo> dragInfo);
75
76 @interface NSObject (DragInfoBackend)
77 - (void) dragImage: (NSImage*)anImage
78 at: (NSPoint)screenLocation
79 offset: (NSSize)initialOffset
80 event: (NSEvent*)event
81 pasteboard: (NSPasteboard*)pboard
82 source: (id)sourceObject
83 slideBack: (BOOL)slideFlag;
84 - (void) postDragEvent: (NSEvent*)event;
85 @end
86
87 /*
88 * Catagory for internal methods (for use only within the
89 * NSWindow class itsself)
90 */
91 @interface NSWindow (GNUstepPrivate)
92 - (void) _handleWindowNeedsDisplay: (id)bogus;
93 - (void) _lossOfKeyOrMainWindow;
94 @end
95
96 @implementation NSWindow (GNUstepPrivate)
97
98 /*
99 This method handles all normal displaying. It is set to be run on each
100 runloop iteration for each window that's on-screen. The performer is
101 added then the window is ordered in and re-added each time it is run.
102 If the window is ordered out, the performer is cancelled.
103
104 The reason why this performer is always added, as opposed to adding it
105 when display is needed and not re-adding it here, is that
106 -setNeedsDisplay* might be called from a method invoked by
107 -performSelector:target:argument:order:modes:, and if it is, the display
108 needs to happen in the same runloop iteration, before blocking for
109 events. If the performer were added in a call to another performer, it
110 wouldn't be called until the next runloop iteration, ie. after the runloop
111 has blocked and waited for events.
112 */
113 - (void) _handleWindowNeedsDisplay: (id)bogus
114 {
115 if (_f.is_autodisplay && _rFlags.needs_display)
116 {
117 [self displayIfNeeded];
118 }
119 [[NSRunLoop currentRunLoop]
120 performSelector: @selector(_handleWindowNeedsDisplay:)
121 target: self
122 argument: nil
123 order: 600000
124 modes: [NSArray arrayWithObjects:
125 NSDefaultRunLoopMode,
126 NSModalPanelRunLoopMode,
127 NSEventTrackingRunLoopMode, nil]];
128 }
129
130 /* We get here if we were ordered out or miniaturized. In this case if
131 we were the key or main window, go through the list of all windows
132 and try to find another window that can take our place as key
133 and/or main. Automatically ignore windows that cannot become
134 key/main and skip the main menu window (which is the only
135 non-obvious window that can become key) unless we have no choice
136 (i.e. all the candidate windows were ordered out.)
137
138 FIXME: It would really be better if we maintained a stack of the
139 most recent key/main windows and went through in order of most
140 recent to least recent. That's probably a lot of work, however.
141 */
142 - (void) _lossOfKeyOrMainWindow
143 {
144 NSArray *windowList = GSAllWindows();
145 unsigned pos = [windowList indexOfObjectIdenticalTo: self];
146 unsigned c = [windowList count];
147 unsigned i;
148 NSWindow *w;
149
150 if ([self isKeyWindow])
151 {
152 NSWindow *menu_window= [[NSApp mainMenu] window];
153 [self resignKeyWindow];
154 i = pos + 1;
155 if (i == c)
156 {
157 i = 0;
158 }
159 while (i != pos)
160 {
161 w = [windowList objectAtIndex: i];
162 if ([w isVisible] && [w canBecomeKeyWindow] && w != menu_window)
163 {
164 [w makeKeyWindow];
165 break;
166 }
167
168 i++;
169 if (i == c)
170 {
171 i = 0;
172 }
173 }
174 /*
175 * if we didn't find a possible key window - use the main menu window
176 */
177 if (i == pos)
178 {
179 if (menu_window != nil)
180 {
181 [GSServerForWindow(menu_window) setinputfocus:
182 [menu_window windowNumber]];
183 }
184 }
185 }
186 if ([self isMainWindow])
187 {
188 NSWindow *w = [NSApp keyWindow];
189
190 [self resignMainWindow];
191 if (w != nil && [w canBecomeMainWindow])
192 {
193 [w makeMainWindow];
194 }
195 else
196 {
197 i = pos + 1;
198 if (i == c)
199 {
200 i = 0;
201 }
202 while (i != pos)
203 {
204 w = [windowList objectAtIndex: i];
205 if ([w isVisible] && [w canBecomeMainWindow])
206 {
207 [w makeMainWindow];
208 break;
209 }
210
211 i++;
212 if (i == c)
213 {
214 i = 0;
215 }
216 }
217 }
218 }
219 }
220 @end
221
222
223
224
225 @interface NSMiniWindow : NSWindow
226 @end
227
228 @implementation NSMiniWindow
229
230 - (BOOL) canBecomeMainWindow
231 {
232 return NO;
233 }
234
235 - (BOOL) canBecomeKeyWindow
236 {
237 return NO;
238 }
239
240 - (void) _initDefaults
241 {
242 [super _initDefaults];
243 [self setExcludedFromWindowsMenu: YES];
244 [self setReleasedWhenClosed: NO];
245 _windowLevel = NSDockWindowLevel;
246 }
247
248 @end
249
250 @interface NSMiniWindowView : NSView
251 {
252 NSCell *imageCell;
253 NSTextFieldCell *titleCell;
254 }
255 - (void) setImage: (NSImage*)anImage;
256 - (void) setTitle: (NSString*)aString;
257 @end
258
259 static NSCell *tileCell = nil;
260
261 @implementation NSMiniWindowView
262
263 + (void) initialize
264 {
265 NSImage *tileImage = [NSImage imageNamed: @"common_Tile"];
266
267 tileCell = [[NSCell alloc] initImageCell: tileImage];
268 [tileCell setBordered: NO];
269 }
270
271 - (BOOL) acceptsFirstMouse: (NSEvent*)theEvent
272 {
273 return YES;
274 }
275
276 - (void) dealloc
277 {
278 TEST_RELEASE(imageCell);
279 TEST_RELEASE(titleCell);
280 [super dealloc];
281 }
282
283 - (void) drawRect: (NSRect)rect
284 {
285 [tileCell drawWithFrame: NSMakeRect(0,0,64,64) inView: self];
286 [imageCell drawWithFrame: NSMakeRect(8,8,48,48) inView: self];
287 [titleCell drawWithFrame: NSMakeRect(1,52,62,11) inView: self];
288 }
289
290 - (void) mouseDown: (NSEvent*)theEvent
291 {
292 if ([theEvent clickCount] >= 2)
293 {
294 NSWindow *w = [_window counterpart];
295 [w deminiaturize: self];
296 }
297 else
298 {
299 NSPoint lastLocation;
300 NSPoint location;
301 unsigned eventMask = NSLeftMouseDownMask | NSLeftMouseUpMask
302 | NSPeriodicMask | NSOtherMouseUpMask | NSRightMouseUpMask;
303 NSDate *theDistantFuture = [NSDate distantFuture];
304 BOOL done = NO;
305
306 lastLocation = [theEvent locationInWindow];
307 [NSEvent startPeriodicEventsAfterDelay: 0.02 withPeriod: 0.02];
308
309 while (!done)
310 {
311 theEvent = [NSApp nextEventMatchingMask: eventMask
312 untilDate: theDistantFuture
313 inMode: NSEventTrackingRunLoopMode
314 dequeue: YES];
315
316 switch ([theEvent type])
317 {
318 case NSRightMouseUp:
319 case NSOtherMouseUp:
320 case NSLeftMouseUp:
321 /* right mouse up or left mouse up means we're done */
322 done = YES;
323 break;
324 case NSPeriodic:
325 location = [_window mouseLocationOutsideOfEventStream];
326 if (NSEqualPoints(location, lastLocation) == NO)
327 {
328 NSPoint origin = [_window frame].origin;
329
330 origin.x += (location.x - lastLocation.x);
331 origin.y += (location.y - lastLocation.y);
332 [_window setFrameOrigin: origin];
333 }
334 break;
335
336 default:
337 break;
338 }
339 }
340 [NSEvent stopPeriodicEvents];
341 }
342 }
343
344 - (void) setImage: (NSImage*)anImage
345 {
346 if (imageCell == nil)
347 {
348 imageCell = [[NSCell alloc] initImageCell: anImage];
349 [imageCell setBordered: NO];
350 }
351 else
352 {
353 [imageCell setImage: anImage];
354 }
355 if ([self lockFocusIfCanDraw])
356 {
357 [self drawRect: [self bounds]];
358 [self unlockFocus];
359 [_window flushWindow];
360 }
361 }
362
363 - (void) setTitle: (NSString*)aString
364 {
365 if (titleCell == nil)
366 {
367 titleCell = [[NSTextFieldCell alloc] initTextCell: aString];
368 [titleCell setSelectable: NO];
369 [titleCell setEditable: NO];
370 [titleCell setBordered: NO];
371 [titleCell setAlignment: NSCenterTextAlignment];
372 [titleCell setDrawsBackground: YES];
373 [titleCell setBackgroundColor: [NSColor blackColor]];
374 [titleCell setTextColor: [NSColor whiteColor]];
375 [titleCell setFont: [NSFont systemFontOfSize: 8]];
376 }
377 else
378 {
379 [titleCell setStringValue: aString];
380 }
381 if ([self lockFocusIfCanDraw])
382 {
383 [self drawRect: [self bounds]];
384 [self unlockFocus];
385 [_window flushWindow];
386 }
387 }
388
389 @end
390
391
392
393 @interface GSWindowView : NSView
394 {
395 }
396 @end
397
398 @implementation GSWindowView
399
400 - (BOOL) isOpaque
401 {
402 return YES;
403 }
404
405 - (void) drawRect: (NSRect)rect
406 {
407 NSColor *c = [[self window] backgroundColor];
408
409 NSDebugLLog(@"NSView", @"-drawRect: %@ for %@ in window %p (%@)",
410 NSStringFromRect(rect), self, _window,
411 NSStringFromRect([_window frame]));
412 [c set];
413 NSRectFill(rect);
414 }
415
416 /*
417 * Special setFrame: implementation - a minimal autoresize mechanism
418 */
419 - (void) setFrame: (NSRect)frameRect
420 {
421 NSSize oldSize = _frame.size;
422 NSView *cv = [_window contentView];
423
424 _autoresizes_subviews = NO;
425 [super setFrame: frameRect];
426 // Safety Check.
427 [cv setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable)];
428 [cv resizeWithOldSuperviewSize: oldSize];
429 }
430
431 - (Class) classForCoder: (NSCoder*)aCoder
432 {
433 if ([self class] == [GSWindowView class])
434 return [super class];
435 return [self class];
436 }
437
438 @end
439
440 /*****************************************************************************
441 *
442 * NSWindow
443 *
444 *****************************************************************************/
445
446 /**
447 <unit>
448 <heading>NSWindow</heading>
449
450 <p> Instances of the NSWindow class handle on-screen windows, their
451 associated NSViews, and events generate by the user. An NSWindow's
452 size is defined by its frame rectangle, which encompasses its entire
453 structure, and its content rectangle, which includes only the
454 content.
455 </p>
456
457 <p> Every NSWindow has a content view, the NSView which forms the
458 root of the window's view hierarchy. This view can be set using the
459 <code>setContentView:</code> method, and accessed through the
460 <code>contentView</code> method. <code>setContentView:</code>
461 replaces the default content view created by NSWindow.
462 </p>
463
464 <p> Other views may be added to the window by using the content
465 view's <code>addSubview:</code> method. These subviews can also
466 have subviews added, forming a tree structure, the view hierarchy.
467 When an NSWindow must display itself, it causes this hierarchy to
468 draw itself. Leaf nodes in the view hierarchy are drawn last,
469 causing them to potentially obscure views further up in the
470 hierarchy.
471 </p>
472
473 <p> A delegate can be specified for an NSWindow, which will receive
474 notifications of events pertaining to the window. The delegate is
475 set using <code>setDelegate:</code>, and can be retrieved using
476 <code>delegate</code>. The delegate can restrain resizing by
477 implementing the <code>windowWillResize: toSize:</code> method, or
478 control the closing of the window by implementing
479 <code>windowShouldClose:</code>.
480 </p>
481
482 </unit>
483 */
484 @implementation NSWindow
485
486 typedef struct NSView_struct
487 {
488 @defs(NSView)
489 } *NSViewPtr;
490
491
492 /*
493 * Class variables
494 */
495 static SEL ccSel;
496 static SEL ctSel;
497 static IMP ccImp;
498 static IMP ctImp;
499 static Class responderClass;
500 static Class viewClass;
501 static NSMutableSet *autosaveNames;
502 static NSRecursiveLock *windowsLock;
503 static NSMapTable* windowmaps = NULL;
504 static NSNotificationCenter *nc = nil;
505
506
507 /*
508 * Class methods
509 */
510 + (void) initialize
511 {
512 if (self == [NSWindow class])
513 {
514 [self setVersion: 2];
515 ccSel = @selector(_checkCursorRectangles:forEvent:);
516 ctSel = @selector(_checkTrackingRectangles:forEvent:);
517 ccImp = [self instanceMethodForSelector: ccSel];
518 ctImp = [self instanceMethodForSelector: ctSel];
519 responderClass = [NSResponder class];
520 viewClass = [NSView class];
521 autosaveNames = [NSMutableSet new];
522 windowsLock = [NSRecursiveLock new];
523 nc = [NSNotificationCenter defaultCenter];
524 }
525 }
526
527 + (void) removeFrameUsingName: (NSString*)name
528 {
529 if (name != nil)
530 {
531 NSString *key;
532
533 key = [NSString stringWithFormat: @"NSWindow Frame %@", name];
534 [windowsLock lock];
535 [[NSUserDefaults standardUserDefaults] removeObjectForKey: key];
536 [windowsLock unlock];
537 }
538 }
539
540 + (NSRect) contentRectForFrameRect: (NSRect)aRect
541 styleMask: (unsigned int)aStyle
542 {
543 float t, b, l, r;
544
545 [GSCurrentServer() styleoffsets: &l : &r : &t : &b : aStyle];
546 aRect.size.width -= (l + r);
547 aRect.size.height -= (t + b);
548 aRect.origin.x += l;
549 aRect.origin.y += b;
550 return aRect;
551 }
552
553 + (NSRect) frameRectForContentRect: (NSRect)aRect
554 styleMask: (unsigned int)aStyle
555 {
556 float t, b, l, r;
557
558 [GSCurrentServer() styleoffsets: &l : &r : &t : &b : aStyle];
559 aRect.size.width += (l + r);
560 aRect.size.height += (t + b);
561 aRect.origin.x -= l;
562 aRect.origin.y -= b;
563 return aRect;
564 }
565
566 + (NSRect) minFrameWidthWithTitle: (NSString*)aTitle
567 styleMask: (unsigned int)aStyle
568 {
569 float t, b, l, r;
570 NSRect f = NSZeroRect;
571
572 [GSCurrentServer() styleoffsets: &l : &r : &t : &b : aStyle];
573 f.size.width = l + r;
574 f.size.height = t + b;
575 /*
576 * Assume that the width of the area needed for a button is equal to
577 * the height of the title bar.
578 */
579 if (aStyle & NSClosableWindowMask)
580 f.size.width += t;
581 if (aStyle & NSMiniaturizableWindowMask)
582 f.size.width += t;
583 /*
584 * FIXME - title width has to be better determined than this.
585 * need to get correct values from font.
586 */
587 f.size.width += [aTitle length] * 10;
588 return f;
589 }
590
591 /* default Screen and window depth */
592 + (NSWindowDepth) defaultDepthLimit
593 {
594 return [[NSScreen deepestScreen] depth];
595 }
596
597 + (void)menuChanged: (NSMenu*)aMenu
598 {
599 // FIXME: This method is for MS Windows only, does nothing
600 // on other window systems
601 }
602
603 /*
604 * Instance methods
605 */
606 - (id) init
607 {
608 int style;
609
610 style = NSTitledWindowMask | NSClosableWindowMask
611 | NSMiniaturizableWindowMask | NSResizableWindowMask;
612
613 return [self initWithContentRect: NSZeroRect
614 styleMask: style
615 backing: NSBackingStoreBuffered
616 defer: NO];
617 }
618
619 /*
620 It is important to make sure that the window is in a meaningful state after
621 this has been called, and that the backend window can be recreated later,
622 since one-shot windows may have their backend windows created and terminated
623 many times.
624 */
625 - (void) _terminateBackendWindow
626 {
627 NSGraphicsContext *context = GSCurrentContext();
628
629 /* Check for context also as it might have disappeared before us */
630 if (context && _gstate)
631 {
632 GSUndefineGState(context, _gstate);
633 _gstate = 0;
634 }
635
636 if (_windowNum)
637 {
638 [GSServerForWindow(self) termwindow: _windowNum];
639 NSMapRemove(windowmaps, (void*)_windowNum);
640 _windowNum = 0;
641 }
642 }
643
644 - (void) dealloc
645 {
646 [nc removeObserver: self];
647 [[NSRunLoop currentRunLoop]
648 cancelPerformSelector: @selector(_handleWindowNeedsDisplay:)
649 target: self
650 argument: nil];
651 [NSApp removeWindowsItem: self];
652
653 [windowsLock lock];
654 if (_autosaveName != nil)
655 {
656 [autosaveNames removeObject: _autosaveName];
657 _autosaveName = nil;
658 }
659 [windowsLock unlock];
660
661 if (_counterpart != 0 && (_styleMask & NSMiniWindowMask) == 0)
662 {
663 NSWindow *mini = [NSApp windowWithWindowNumber: _counterpart];
664
665 _counterpart = 0;
666 RELEASE(mini);
667 }
668 /* Clean references to this window - important if some of the views
669 are not deallocated now */
670 [_wv viewWillMoveToWindow: nil];
671 /* NB: releasing the window view does not necessarily result in the
672 deallocation of the window's views ! - some of them might be
673 retained for some other reason by the programmer or by other
674 parts of the code */
675 TEST_RELEASE(_wv);
676 TEST_RELEASE(_fieldEditor);
677 TEST_RELEASE(_backgroundColor);
678 TEST_RELEASE(_representedFilename);
679 TEST_RELEASE(_miniaturizedTitle);
680 TEST_RELEASE(_miniaturizedImage);
681 TEST_RELEASE(_windowTitle);
682 TEST_RELEASE(_rectsBeingDrawn);
683 TEST_RELEASE(_initialFirstResponder);
684 TEST_RELEASE(_defaultButtonCell);
685 TEST_RELEASE(_cachedImage);
686 TEST_RELEASE(_toolbar);
687 DESTROY(_lastView);
688 DESTROY(_lastDragView);
689 RELEASE(_screen);
690
691 /*
692 * FIXME This should not be necessary - the views should have removed
693 * their drag types, so we should already have been removed.
694 */
695 [GSServerForWindow(self) removeDragTypes: nil fromWindow: self];
696
697 [self _terminateBackendWindow];
698
699 if (_delegate != nil)
700 {
701 [nc removeObserver: _delegate name: nil object: self];
702 _delegate = nil;
703 }
704
705 [super dealloc];
706 }
707
708 - (void) _initBackendWindow: (NSRect)frame
709 {
710 int screenNumber;
711 NSCountedSet *dragTypes;
712 NSGraphicsContext *context = GSCurrentContext();
713 GSDisplayServer *srv = GSCurrentServer();
714
715 /* If we were deferred or one shot, our drag types may not have
716 been registered properly in the backend. Remove them then re-add
717 them when we create the window */
718 dragTypes = [srv dragTypesForWindow: self];
719 if (dragTypes)
720 {
721 // As this is the original entry, it will change soon.
722 // We use a copy to reregister the same types later on.
723 dragTypes = [dragTypes copy];
724
725 /* Now we need to remove all the drag types for this window. */
726 [srv removeDragTypes: nil fromWindow: self];
727 }
728
729 screenNumber = [_screen screenNumber];
730 _windowNum = [srv window: frame : _backingType : _styleMask : screenNumber];
731 [srv setwindowlevel: [self level] : _windowNum];
732 NSMapInsert (windowmaps, (void*)_windowNum, self);
733
734 // Set window in new _gstate
735 DPSgsave(context);
736 [srv windowdevice: _windowNum];
737 _gstate = GSDefineGState(context);
738 DPSgrestore(context);
739
740 frame = [NSWindow contentRectForFrameRect: frame styleMask: _styleMask];
741 if (NSIsEmptyRect([_wv frame]))
742 {
743 frame.origin = NSZeroPoint;
744 [_wv setFrame: frame];
745 }
746 [_wv setNeedsDisplay: YES];
747
748 /* Ok, now add the drag types back */
749 if (dragTypes)
750 {
751 id type;
752 NSMutableArray *dragTypesArray = [NSMutableArray array];
753 NSEnumerator *enumerator = [dragTypes objectEnumerator];
754
755 NSDebugLLog(@"NSWindow", @"Resetting drag types for window");
756 /* Now we need to restore the drag types. */
757
758 /* Put all the drag types to the dragTypesArray - counted
759 * with their multiplicity.
760 */
761 while ((type = [enumerator nextObject]) != nil)
762 {
763 int i, count = [dragTypes countForObject: type];
764
765 for (i = 0; i < count; i++)
766 {
767 [dragTypesArray addObject: type];
768 }
769 }
770
771 /* Now store the array. */
772 [srv addDragTypes: dragTypesArray toWindow: self];
773 // Free our local copy.
774 RELEASE(dragTypes);
775 }
776
777 /* Other stuff we need to do for deferred windows */
778 if (_windowTitle != nil)
779 [srv titlewindow: _windowTitle : _windowNum];
780 if (!NSEqualSizes(_minimumSize, NSZeroSize))
781 [self setMinSize: _minimumSize];
782 if (!NSEqualSizes(_maximumSize, NSZeroSize))
783 [self setMaxSize: _maximumSize];
784 if (!NSEqualSizes(_increments, NSZeroSize))
785 [self setResizeIncrements: _increments];
786
787 NSDebugLLog(@"NSWindow", @"Created NSWindow frame %@",
788 NSStringFromRect(_frame));
789 }
790
791 /*
792 * Initializing and getting a new NSWindow object
793 */
794 /**
795 <p> Initializes the receiver with a content rect of
796 <var>contentRect</var>, a style mask of <var>styleMask</var>, and a
797 backing store type of <var>backingType</var>.
798 </p>
799
800 <p> The style mask values are <code>NSTitledWindowMask</code>, for a
801 window with a title, <code>NSClosableWindowMask</code>, for a window
802 with a close widget, <code>NSMiniaturizableWindowMask</code>, for a
803 window with a miniaturize widget, and
804 <code>NSResizableWindowMask</code>, for a window with a resizing
805 widget. These mask values can be OR'd in any combination.
806 </p>
807
808 <p> Backing store values are <code>NSBackingStoreBuffered</code>,
809 <code>NSBackingStoreRetained</code> and
810 <code>NSBackingStoreNonretained</code>.
811 </p>
812 */
813 - (id) initWithContentRect: (NSRect)contentRect
814 styleMask: (unsigned int)aStyle
815 backing: (NSBackingStoreType)bufferingType
816 defer: (BOOL)flag
817 {
818 return [self initWithContentRect: contentRect
819 styleMask: aStyle
820 backing: bufferingType
821 defer: flag
822 screen: nil];
823 }
824
825 /**
826 <p> Initializes the receiver with a content rect of
827 <var>contentRect</var>, a style mask of <var>styleMask</var>, a
828 backing store type of <var>backingType</var> and a boolean
829 <var>flag</var>. <var>flag</var> specifies whether the window
830 should be created now (<code>NO</code>), or when it is displayed
831 (<code>YES</code>).
832 </p>
833
834 <p> The style mask values are <code>NSTitledWindowMask</code>, for a
835 window with a title, <code>NSClosableWindowMask</code>, for a window
836 with a close widget, <code>NSMiniaturizableWindowMask</code>, for a
837 window with a miniaturize widget, and
838 <code>NSResizableWindowMask</code>, for a window with a resizing
839 widget. These mask values can be OR'd in any combination.
840 </p>
841
842 <p> Backing store values are <code>NSBackingStoreBuffered</code>,
843 <code>NSBackingStoreRetained</code> and
844 <code>NSBackingStoreNonretained</code>.
845 </p>
846 */
847 - (id) initWithContentRect: (NSRect)contentRect
848 styleMask: (unsigned int)aStyle
849 backing: (NSBackingStoreType)bufferingType
850 defer: (BOOL)flag
851 screen: (NSScreen*)aScreen
852 {
853 NSRect cframe;
854
855 if (!NSApp)
856 NSLog(@"No application!\n");
857
858 NSDebugLLog(@"NSWindow", @"NSWindow start of init\n");
859 if (!windowmaps)
860 windowmaps = NSCreateMapTable(NSIntMapKeyCallBacks,
861 NSNonRetainedObjectMapValueCallBacks, 20);
862
863 /* Initialize attributes and flags */
864 [super init];
865 [self _initDefaults];
866
867 _backingType = bufferingType;
868 _styleMask = aStyle;
869 if (aScreen == nil)
870 aScreen = [NSScreen mainScreen];
871 ASSIGN(_screen, aScreen);
872 _depthLimit = [_screen depth];
873
874 _frame = [NSWindow frameRectForContentRect: contentRect styleMask: aStyle];
875 _minimumSize = NSMakeSize(_frame.size.width - contentRect.size.width + 1,
876 _frame.size.height - contentRect.size.height + 1);
877 _maximumSize = NSMakeSize (10e4, 10e4);
878
879 [self setNextResponder: NSApp];
880
881 _f.cursor_rects_enabled = YES;
882 _f.cursor_rects_valid = NO;
883
884 /* Create the window view */
885 cframe.origin = NSZeroPoint;
886 cframe.size = contentRect.size;
887 _wv = [[GSWindowView allocWithZone: [self zone]] initWithFrame: cframe];
888 [_wv viewWillMoveToWindow: self];
889
890 /* Create the content view */
891 cframe.origin = NSZeroPoint;
892 cframe.size = contentRect.size;
893 [self setContentView: AUTORELEASE([[NSView alloc] initWithFrame: cframe])];
894
895 /* rectBeingDrawn is variable used to optimize flushing the backing store.
896 It is set by NSGraphicsContext during a lockFocus to tell NSWindow what
897 part a view is drawing in, so NSWindow only has to flush that portion */
898 _rectsBeingDrawn = RETAIN([NSMutableArray arrayWithCapacity: 10]);
899
900 /* Create window (if not deferred) */
901 _windowNum = 0;
902 _gstate = 0;
903 if (flag == NO)
904 {
905 NSDebugLLog(@"NSWindow", @"Creating NSWindow\n");
906 [self _initBackendWindow: _frame];
907 }
908 else
909 NSDebugLLog(@"NSWindow", @"Defering NSWindow creation\n");
910
911 NSDebugLLog(@"NSWindow", @"NSWindow end of init\n");
912 return self;
913 }
914
915 /*
916 * Accessing the content view
917 */
918 - (id) contentView
919 {
920 return _contentView;
921 }
922
923 /**
924 Sets the window's content view to <var>aView</var>, replacing any
925 previous content view. */
926 - (void) setContentView: (NSView*)aView
927 {
928 if (aView == nil)
929 {
930 aView = AUTORELEASE([[NSView alloc] initWithFrame: _frame]);
931 }
932 if (_contentView != nil)
933 {
934 [_contentView removeFromSuperview];
935 }
936 _contentView = aView;
937 [_contentView setAutoresizingMask: (NSViewWidthSizable
938 | NSViewHeightSizable)];
939 [_wv addSubview: _contentView];
940 [_contentView resizeWithOldSuperviewSize: [_contentView frame].size];
941 [_contentView setFrameOrigin: [_wv bounds].origin];
942
943 NSAssert1 ([[_wv subviews] count] == 1,
944 @"window's view has %d subviews!", [[_wv subviews] count]);
945
946 [_contentView setNextResponder: self];
947 }
948
949 /*
950 * Window graphics
951 */
952 - (NSColor*) backgroundColor
953 {
954 return _backgroundColor;
955 }
956
957 - (NSString*) representedFilename
958 {
959 return _representedFilename;
960 }
961
962 - (void) setBackgroundColor: (NSColor*)color
963 {
964 ASSIGN(_backgroundColor, color);
965 }
966
967 - (void) setRepresentedFilename: (NSString*)aString
968 {
969 ASSIGN(_representedFilename, aString);
970 }
971
972 /** Sets the window's title to the string <var>aString</var>. */
973 - (void) setTitle: (NSString*)aString
974 {
975 if ([_windowTitle isEqual: aString] == NO)
976 {
977 ASSIGN(_windowTitle, aString);
978 [self setMiniwindowTitle: aString];
979 if (_windowNum > 0)
980 [GSServerForWindow(self) titlewindow: aString : _windowNum];
981 if (_f.menu_exclude == NO && _f.has_opened == YES)
982 {
983 [NSApp changeWindowsItem: self
984 title: aString
985 filename: NO];
986 }
987 }
988 }
989
990 - (void) setTitleWithRepresentedFilename: (NSString*)aString
991 {
992 [self setRepresentedFilename: aString];
993 aString = [NSString stringWithFormat:
994 @"%@ -- %@", [aString lastPathComponent],
995 [aString stringByDeletingLastPathComponent]];
996 if ([_windowTitle isEqual: aString] == NO)
997 {
998 ASSIGN(_windowTitle, aString);
999 [self setMiniwindowTitle: aString];
1000 if (_windowNum > 0)
1001 [GSServerForWindow(self) titlewindow: aString : _windowNum];
1002 if (_f.menu_exclude == NO && _f.has_opened == YES)
1003 {
1004 [NSApp changeWindowsItem: self
1005 title: aString
1006 filename: YES];
1007 }
1008 }
1009 }
1010
1011 - (unsigned int) styleMask
1012 {
1013 return _styleMask;
1014 }
1015
1016 /** Returns an NSString containing the text of the window's title. */
1017 - (NSString*) title
1018 {
1019 return _windowTitle;
1020 }
1021
1022 - (void) setHasShadow: (BOOL)hasShadow
1023 {
1024 // FIXME: Should be send to backend
1025 _f.has_shadow = hasShadow;
1026 }
1027
1028 - (BOOL) hasShadow
1029 {
1030 return _f.has_shadow;
1031 }
1032
1033 - (void) setAlphaValue: (float)windowAlpha
1034 {
1035 // FIXME
1036 _alphaValue = windowAlpha;
1037 }
1038
1039 - (float) alphaValue
1040 {
1041 return _alphaValue;
1042 }
1043
1044 - (void) setOpaque: (BOOL)isOpaque
1045 {
1046 // FIXME
1047 _f.is_opaque = isOpaque;
1048 }
1049
1050 - (BOOL) isOpaque
1051 {
1052 return _f.is_opaque;
1053 }
1054
1055 /*
1056 * Window device attributes
1057 */
1058 - (NSBackingStoreType) backingType
1059 {
1060 return _backingType;
1061 }
1062
1063 - (NSDictionary*) deviceDescription
1064 {
1065 return [[self screen] deviceDescription];
1066 }
1067
1068 - (int) gState
1069 {
1070 if (_gstate <= 0)
1071 NSDebugLLog(@"NSWindow", @"gState called on deferred window");
1072 return _gstate;
1073 }
1074
1075 - (BOOL) isOneShot
1076 {
1077 return _f.is_one_shot;
1078 }
1079
1080 - (void) setBackingType: (NSBackingStoreType)type
1081 {
1082 _backingType = type;
1083 }
1084
1085 - (void) setOneShot: (BOOL)flag
1086 {
1087 _f.is_one_shot = flag;
1088 }
1089
1090 - (int) windowNumber
1091 {
1092 if (_windowNum <= 0)
1093 NSDebugLLog(@"NSWindow", @"windowNumber called on deferred window");
1094 return _windowNum;
1095 }
1096
1097 /*
1098 * The miniwindow
1099 */
1100 - (NSImage*) miniwindowImage
1101 {
1102 return _miniaturizedImage;
1103 }
1104
1105 - (NSString*) miniwindowTitle
1106 {
1107 return _miniaturizedTitle;
1108 }
1109
1110 - (void) setMiniwindowImage: (NSImage*)image
1111 {
1112 ASSIGN(_miniaturizedImage, image);
1113 if (_counterpart != 0 && (_styleMask & NSMiniWindowMask) == 0)
1114 {
1115 NSMiniWindow *mini = [NSApp windowWithWindowNumber: _counterpart];
1116 id v = [mini contentView];
1117
1118 if ([v respondsToSelector: @selector(setImage:)])
1119 {
1120 [v setImage: [self miniwindowImage]];
1121 }
1122 }
1123 }
1124
1125 - (void) setMiniwindowTitle: (NSString*)title
1126 {
1127 ASSIGN(_miniaturizedTitle, title);
1128 if (_counterpart != 0 && (_styleMask & NSMiniWindowMask) == 0)
1129 {
1130 NSMiniWindow *mini = [NSApp windowWithWindowNumber: _counterpart];
1131 id v = [mini contentView];
1132
1133 if ([v respondsToSelector: @selector(setTitle:)])
1134 {
1135 [v setTitle: [self miniwindowTitle]];
1136 }
1137 }
1138 }
1139
1140 - (NSWindow*) counterpart
1141 {
1142 if (_counterpart == 0)
1143 return nil;
1144 return [NSApp windowWithWindowNumber: _counterpart];
1145 }
1146
1147 /*
1148 * The field editor
1149 */
1150 - (void) endEditingFor: (id)anObject
1151 {
1152 NSText *t = [self fieldEditor: NO
1153 forObject: anObject];
1154
1155 if (t && (_firstResponder == t))
1156 {
1157 [nc postNotificationName: NSTextDidEndEditingNotification
1158 object: t];
1159 [t setText: @""];
1160 [t setDelegate: nil];
1161 [t removeFromSuperview];
1162 _firstResponder = self;
1163 [_firstResponder becomeFirstResponder];
1164 }
1165 }
1166
1167 - (NSText*) fieldEditor: (BOOL)createFlag forObject: (id)anObject
1168 {
1169 /* ask delegate if it can provide a field editor */
1170 if ((_delegate != anObject)
1171 && [_delegate respondsToSelector:
1172 @selector(windowWillReturnFieldEditor:toObject:)])
1173 {
1174 NSText *editor;
1175
1176 editor = [_delegate windowWillReturnFieldEditor: self
1177 toObject: anObject];
1178
1179 if (editor != nil)
1180 {
1181 return editor;
1182 }
1183 }
1184 /*
1185 * Each window has a global text field editor, if it doesn't exist create it
1186 * if create flag is set
1187 */
1188 if (!_fieldEditor && createFlag)
1189 {
1190 _fieldEditor = [NSText new];
1191 [_fieldEditor setFieldEditor: YES];
1192 }
1193
1194 return _fieldEditor;
1195 }
1196
1197 /*
1198 * Window controller
1199 */
1200 - (void) setWindowController: (NSWindowController*)windowController
1201 {
1202 /* The window controller owns us, we only keep a weak reference to
1203 it */
1204 _windowController = windowController;
1205 }
1206
1207 - (id) windowController
1208 {
1209 return _windowController;
1210 }
1211
1212 /*
1213 * Window status and ordering
1214 */
1215 - (void) becomeKeyWindow
1216 {
1217 if (_f.is_key == NO)
1218 {
1219 _f.is_key = YES;
1220
1221 if ((!_firstResponder) || (_firstResponder == self))
1222 {
1223 if (_initialFirstResponder)
1224 {
1225 [self makeFirstResponder: _initialFirstResponder];
1226 }
1227 }
1228
1229 [_firstResponder becomeFirstResponder];
1230 if ((_firstResponder != self)
1231 && [_firstResponder respondsToSelector: @selector(becomeKeyWindow)])
1232 {
1233 [_firstResponder becomeKeyWindow];
1234 }
1235
1236 [GSServerForWindow(self) setinputstate: GSTitleBarKey : _windowNum];
1237 [GSServerForWindow(self) setinputfocus: _windowNum];
1238 [self resetCursorRects];
1239 [nc postNotificationName: NSWindowDidBecomeKeyNotification object: self];
1240 NSDebugLLog(@"NSWindow", @"%@ is now key window", [self title]);
1241 }
1242 }
1243
1244 - (void) becomeMainWindow
1245 {
1246 if (_f.is_main == NO)
1247 {
1248 _f.is_main = YES;
1249 if (_f.is_key == NO)
1250 {
1251 [GSServerForWindow(self) setinputstate: GSTitleBarMain : _windowNum];
1252 }
1253 [nc postNotificationName: NSWindowDidBecomeMainNotification object: self];
1254 NSDebugLLog(@"NSWindow", @"%@ is now main window", [self title]);
1255 }
1256 }
1257
1258 /** Returns YES if the receiver can be made key. If this method returns
1259 NO, the window will not be made key. This implementation returns YES
1260 if the window is resizable or has a title bar. You can override this
1261 method to change it's behavior */
1262 - (BOOL) canBecomeKeyWindow
1263 {
1264 if ((NSResizableWindowMask | NSTitledWindowMask) & _styleMask)
1265 return YES;
1266 else
1267 return NO;
1268 }
1269
1270 /** Returns YES if the receiver can be the main window. If this method
1271 returns NO, the window will not become the main window. This
1272 implementation returns YES if the window is resizable or has a
1273 title bar and is visible and is not an NSPanel. You can override
1274 this method to change it's behavior */
1275 - (BOOL) canBecomeMainWindow
1276 {
1277 if (!_f.visible)
1278 return NO;
1279 if ((NSResizableWindowMask | NSTitledWindowMask) & _styleMask)
1280 return YES;
1281 else
1282 return NO;
1283 }
1284
1285 - (BOOL) hidesOnDeactivate
1286 {
1287 return _f.hides_on_deactivate;
1288 }
1289
1290 - (void) setCanHide: (BOOL)flag
1291 {
1292 _f.can_hide = flag;
1293 }
1294
1295 - (BOOL) canHide
1296 {
1297 return _f.can_hide;
1298 }
1299
1300 - (BOOL) isKeyWindow
1301 {
1302 return _f.is_key;
1303 }
1304
1305 - (BOOL) isMainWindow
1306 {
1307 return _f.is_main;
1308 }
1309
1310 - (BOOL) isMiniaturized
1311 {
1312 return _f.is_miniaturized;
1313 }
1314
1315 - (BOOL) isVisible
1316 {
1317 return _f.visible;
1318 }
1319
1320 - (int) level
1321 {
1322 return _windowLevel;
1323 }
1324
1325 - (void) makeKeyAndOrderFront: (id)sender
1326 {
1327 [self orderFront: sender];
1328 [self makeKeyWindow];
1329 /*
1330 * OPENSTEP makes a window the main window when it makes it the key window.
1331 * So we do the same (though the documentation doesn't mention it).
1332 */
1333 [self makeMainWindow];
1334 }
1335
1336 - (void) makeKeyWindow
1337 {
1338 if (!_f.visible || _f.is_miniaturized || _f.is_key == YES)
1339 {
1340 return;
1341 }
1342 if (![self canBecomeKeyWindow])
1343 return;
1344 [[NSApp keyWindow] resignKeyWindow];
1345
1346 [self becomeKeyWindow];
1347 }
1348
1349 - (void) makeMainWindow
1350 {
1351 if (!_f.visible || _f.is_miniaturized || _f.is_main == YES)
1352 {
1353 return;
1354 }
1355 if (![self canBecomeMainWindow])
1356 return;
1357 [[NSApp mainWindow] resignMainWindow];
1358 [self becomeMainWindow];
1359 }
1360
1361 - (void) orderBack: (id)sender
1362 {
1363 [self orderWindow: NSWindowBelow relativeTo: 0];
1364 }
1365
1366 - (void) orderFront: (id)sender
1367 {
1368 if ([NSApp isActive] == YES)
1369 {
1370 [self orderWindow: NSWindowAbove relativeTo: 0];
1371 }
1372 }
1373
1374 - (void) orderFrontRegardless
1375 {
1376 [self orderWindow: NSWindowAbove relativeTo: 0];
1377 }
1378
1379 - (void) orderOut: (id)sender
1380 {
1381 [self orderWindow: NSWindowOut relativeTo: 0];
1382 }
1383
1384 - (void) orderWindow: (NSWindowOrderingMode)place relativeTo: (int)otherWin
1385 {
1386 GSDisplayServer *srv = GSServerForWindow(self);
1387 BOOL display = NO;
1388
1389 if (place == NSWindowOut)
1390 {
1391 _f.visible = NO;
1392 if (_rFlags.needs_display == YES)
1393 {
1394 /*
1395 * Don't keep trying to update the window while it is ordered out
1396 */
1397 [[NSRunLoop currentRunLoop]
1398 cancelPerformSelector: @selector(_handleWindowNeedsDisplay:)
1399 target: self
1400 argument: nil];
1401 }
1402 [self _lossOfKeyOrMainWindow];
1403 }
1404 else
1405 {
1406 /* Windows need to be constrained when displayed or resized - but only
1407 titled windows are constrained. Also, and this is the tricky part,
1408 don't constrain if we are merely unhidding the window or if it's
1409 already visible and is just being reordered. */
1410 if ((_styleMask & NSTitledWindowMask)
1411 && [NSApp isHidden] == NO
1412 && _f.visible == NO)
1413 {
1414 NSRect nframe = [self constrainFrameRect: _frame
1415 toScreen: [self screen]];
1416 if (_windowNum)
1417 [self setFrame: nframe display: NO];
1418 else
1419 _frame = nframe;
1420 }
1421 // create deferred window
1422 if (_windowNum == 0)
1423 {
1424 [self _initBackendWindow: _frame];
1425 display = YES;
1426 }
1427 }
1428
1429 // Draw content before backend window ordering
1430 if (display)
1431 [_contentView display];
1432 else if (place != NSWindowOut)
1433 [_contentView displayIfNeeded];
1434
1435 [srv orderwindow: place : otherWin : _windowNum];
1436 if (display)
1437 [self display];
1438
1439 if (place != NSWindowOut)
1440 {
1441 if (_rFlags.needs_display == YES)
1442 {
1443 /*
1444 * Once we are ordered back in, we will want to update the window
1445 * whenever there is anything to do.
1446 */
1447 [[NSRunLoop currentRunLoop]
1448 performSelector: @selector(_handleWindowNeedsDisplay:)
1449 target: self
1450 argument: nil
1451 order: 600000
1452 modes: [NSArray arrayWithObjects:
1453 NSDefaultRunLoopMode,
1454 NSModalPanelRunLoopMode,
1455 NSEventTrackingRunLoopMode, nil]];
1456 }
1457 if (_f.has_closed == YES)
1458 {
1459 _f.has_closed = NO; /* A closed window has re-opened */
1460 }
1461 if (_f.has_opened == NO)
1462 {
1463 _f.has_opened = YES;
1464 if (_f.menu_exclude == NO)
1465 {
1466 BOOL isFileName;
1467
1468 isFileName = [_windowTitle isEqual: _representedFilename];
1469
1470 [NSApp addWindowsItem: self
1471 title: _windowTitle
1472 filename: isFileName];
1473 }
1474 }
1475 if ([self isKeyWindow] == YES)
1476 {
1477 [srv setinputstate: GSTitleBarKey : _windowNum];
1478 [srv setinputfocus: _windowNum];
1479 }
1480 _f.visible = YES;
1481 }
1482 else if ([self isOneShot])
1483 {
1484 [self _terminateBackendWindow];
1485 }
1486 }
1487
1488 - (void) resignKeyWindow
1489 {
1490 if (_f.is_key == YES)
1491 {
1492 if ((_firstResponder != self)
1493 && [_firstResponder respondsToSelector: @selector(resignKeyWindow)])
1494 [_firstResponder resignKeyWindow];
1495
1496 _f.is_key = NO;
1497
1498 if (_f.is_main == YES)
1499 {
1500 [GSServerForWindow(self) setinputstate: GSTitleBarMain : _windowNum];
1501 }
1502 else
1503 {
1504 [GSServerForWindow(self) setinputstate: GSTitleBarNormal
1505 : _windowNum];
1506 }
1507 [self discardCursorRects];
1508
1509 [nc postNotificationName: NSWindowDidResignKeyNotification object: self];
1510 }
1511 }
1512
1513 - (void) resignMainWindow
1514 {
1515 if (_f.is_main == YES)
1516 {
1517 _f.is_main = NO;
1518 if (_f.is_key == YES)
1519 {
1520 [GSServerForWindow(self) setinputstate: GSTitleBarKey
1521 : _windowNum];
1522 }
1523 else
1524 {
1525 [GSServerForWindow(self) setinputstate: GSTitleBarNormal
1526 : _windowNum];
1527 }
1528 [nc postNotificationName: NSWindowDidResignMainNotification object: self];
1529 }
1530 }
1531
1532 - (void) setHidesOnDeactivate: (BOOL)flag
1533 {
1534 if (flag != _f.hides_on_deactivate)
1535 {
1536 _f.hides_on_deactivate = flag;
1537 }
1538 }
1539
1540 - (void) setLevel: (int)newLevel
1541 {
1542 if (_windowLevel != newLevel)
1543 {
1544 _windowLevel = newLevel;
1545 if (_windowNum > 0)
1546 {
1547 GSDisplayServer *srv = GSServerForWindow(self);
1548 [srv setwindowlevel: _windowLevel : _windowNum];
1549 }
1550 }
1551 }
1552
1553 /*
1554 * Moving and resizing the window
1555 */
1556 - (NSPoint) cascadeTopLeftFromPoint: (NSPoint)topLeftPoint
1557 {
1558 // FIXME: As we know nothing about the other window we can only guess
1559 topLeftPoint.x += 20;
1560 topLeftPoint.y += 20;
1561
1562 [self setFrameTopLeftPoint: topLeftPoint];
1563 return topLeftPoint;
1564 }
1565
1566 - (BOOL) showsResizeIndicator
1567 {
1568 // TODO
1569 NSLog(@"Method %s is not implemented for class %s",
1570 "showsResizeIndicator", "NSWindow");
1571 return YES;
1572 }
1573
1574 - (void) setShowsResizeIndicator: (BOOL)show
1575 {
1576 // TODO
1577 NSLog(@"Method %s is not implemented for class %s",
1578 "setShowsResizeIndicator:", "NSWindow");
1579 }
1580
1581 - (void) setFrame: (NSRect)frameRect
1582 display: (BOOL)displayFlag
1583 animate: (BOOL)animationFlag
1584 {
1585 // TODO
1586 [self setFrame: frameRect display: displayFlag];
1587 }
1588
1589 - (NSTimeInterval) animationResizeTime: (NSRect)newFrame
1590 {
1591 // TODO
1592 NSLog(@"Method %s is not implemented for class %s",
1593 "animationResizeTime:", "NSWindow");
1594 return 333;
1595 }
1596
1597 - (void) center
1598 {
1599 NSSize screenSize = [[self screen] frame].size;
1600 NSPoint origin = _frame.origin;
1601
1602 origin.x = (screenSize.width - _frame.size.width) / 2;
1603 origin.y = (screenSize.height - _frame.size.height) / 2;
1604
1605 [self setFrameOrigin: origin];
1606 }
1607
1608 /**
1609 * Given a proposed frame rectangle, return a modified version
1610 * which will fit inside the screen.
1611 */
1612 - (NSRect) constrainFrameRect: (NSRect)frameRect toScreen: (NSScreen*)screen
1613 {
1614 NSRect screenRect = [screen frame];
1615 float difference;
1616
1617 /* Move top edge of the window inside the screen */
1618 difference = NSMaxY (frameRect) - NSMaxY (screenRect);
1619
1620 if (difference > 0)
1621 {
1622 frameRect.origin.y -= difference;
1623 }
1624 else if (NSMaxY (frameRect) < NSMinY (screenRect))
1625 {
1626 float diff1 = NSMinY (frameRect) - NSMinY (screenRect);
1627 /* move bottom inside the screen, but keep top inside screen */
1628 frameRect.origin.y -= MAX(difference, diff1);
1629 difference = NSMaxY (frameRect) - NSMaxY (screenRect);
1630 }
1631
1632 /* If the window is resizable, resize it (if needed) so that the
1633 bottom edge is on the screen too */
1634 if (_styleMask & NSResizableWindowMask)
1635 {
1636 difference = screenRect.origin.y - frameRect.origin.y;
1637 if (difference > 0)
1638 {
1639 frameRect.size.height -= difference;
1640 frameRect.origin.y += difference;
1641 }
1642 /* Ensure that rewsizing doesn't makewindow smaller than minimum */
1643 difference = _minimumSize.height - frameRect.size.height;
1644 if (difference > 0)
1645 {
1646 frameRect.size.height += difference;
1647 frameRect.origin.y -= difference;
1648 }
1649 }
1650
1651 return frameRect;
1652 }
1653
1654 - (NSRect) frame
1655 {
1656 return _frame;
1657 }
1658
1659 - (NSSize) minSize
1660 {
1661 return _minimumSize;
1662 }
1663
1664 - (NSSize) maxSize
1665 {
1666 return _maximumSize;
1667 }
1668
1669 - (void) setContentSize: (NSSize)aSize
1670 {
1671 NSRect r = _frame;
1672
1673 r.size = aSize;
1674 r = [NSWindow frameRectForContentRect: r styleMask: _styleMask];
1675 r.origin = _frame.origin;
1676 [self setFrame: r display: YES];
1677 }
1678
1679 - (void) setFrame: (NSRect)frameRect display: (BOOL)flag
1680 {
1681 if (_maximumSize.width > 0 && frameRect.size.width > _maximumSize.width)
1682 {
1683 frameRect.size.width = _maximumSize.width;
1684 }
1685 if (_maximumSize.height > 0 && frameRect.size.height > _maximumSize.height)
1686 {
1687 frameRect.size.height = _maximumSize.height;
1688 }
1689 if (frameRect.size.width < _minimumSize.width)
1690 {
1691 frameRect.size.width = _minimumSize.width;
1692 }
1693 if (frameRect.size.height < _minimumSize.height)
1694 {
1695 frameRect.size.height = _minimumSize.height;
1696 }
1697
1698 if (NSEqualSizes(frameRect.size, _frame.size) == NO)
1699 {
1700 /* Windows need to be constrained when displayed or resized - but only
1701 titled windows are constrained */
1702 if (_styleMask & NSTitledWindowMask)
1703 {
1704 frameRect = [self constrainFrameRect: frameRect
1705 toScreen: [self screen]];
1706 }
1707
1708 if ([_delegate respondsToSelector: @selector(windowWillResize:toSize:)])
1709 {
1710 frameRect.size = [_delegate windowWillResize: self
1711 toSize: frameRect.size];
1712 }
1713 }
1714
1715 // If nothing changes, don't send it to the backend and don't redisplay
1716 if (NSEqualRects(_frame, frameRect))
1717 return;
1718
1719 if (NSEqualPoints(_frame.origin, frameRect.origin) == NO)
1720 [nc postNotificationName: NSWindowWillMoveNotification object: self];
1721
1722 /*
1723 * Now we can tell the graphics context to do the actual resizing.
1724 * We will recieve an event to tell us when the resize is done.
1725 */
1726 if (_windowNum)
1727 [GSServerForWindow(self) placewindow: frameRect : _windowNum];
1728 else
1729 {
1730 _frame = frameRect;
1731 frameRect = [NSWindow contentRectForFrameRect: frameRect
1732 styleMask: _styleMask];
1733 frameRect.origin = NSZeroPoint;
1734 [_wv setFrame: frameRect];
1735 }
1736
1737 if (flag)
1738 [self display];
1739 }
1740
1741 - (void) setFrameOrigin: (NSPoint)aPoint
1742 {
1743 NSRect r = _frame;
1744
1745 r.origin = aPoint;
1746 [self setFrame: r display: NO];
1747 }
1748
1749 - (void) setFrameTopLeftPoint: (NSPoint)aPoint
1750 {
1751 NSRect r = _frame;
1752
1753 r.origin = aPoint;
1754 r.origin.y -= _frame.size.height;
1755 [self setFrame: r display: NO];
1756 }
1757
1758 - (void) setMinSize: (NSSize)aSize
1759 {
1760 if (aSize.width < 1)
1761 aSize.width = 1;
1762 if (aSize.height < 1)
1763 aSize.height = 1;
1764 _minimumSize = aSize;
1765 if (_windowNum > 0)
1766 [GSServerForWindow(self) setminsize: aSize : _windowNum];
1767 }
1768
1769 - (void) setMaxSize: (NSSize)aSize
1770 {
1771 /*
1772 * Documented maximum size for macOS-X - do we need this restriction?
1773 */
1774 if (aSize.width > 10000)
1775 aSize.width = 10000;
1776 if (aSize.height > 10000)
1777 aSize.height = 10000;
1778 _maximumSize = aSize;
1779 if (_windowNum > 0)
1780 [GSServerForWindow(self) setmaxsize: aSize : _windowNum];
1781 }
1782
1783 - (NSSize) resizeIncrements
1784 {
1785 return _increments;
1786 }
1787
1788 - (void) setResizeIncrements: (NSSize)aSize
1789 {
1790 _increments = aSize;
1791 if (_windowNum > 0)
1792 [GSServerForWindow(self) setresizeincrements: aSize : _windowNum];
1793 }
1794
1795 - (NSSize) aspectRatio
1796 {
1797 // FIXME: This method is missing
1798 return NSMakeSize(1, 1);
1799 }
1800
1801 - (void) setAspectRatio: (NSSize)ratio
1802 {
1803 // FIXME: This method is missing
1804 }
1805
1806 /**
1807 * Convert from a point in the base coordinate system for the window
1808 * to a point in the screen coordinate system.
1809 */
1810 - (NSPoint) convertBaseToScreen: (NSPoint)aPoint
1811 {
1812 GSDisplayServer *srv = GSCurrentServer();
1813 NSPoint screenPoint;
1814 float t, b, l, r;
1815
1816 [srv styleoffsets: &l : &r : &t : &b : _styleMask];
1817 screenPoint.x = _frame.origin.x + aPoint.x + l;
1818 screenPoint.y = _frame.origin.y + aPoint.y + b;
1819
1820 return screenPoint;
1821 }
1822
1823 /**
1824 * Convert from a point in the screen coordinate system to a point in the
1825 * screen coordinate system of the receiver.
1826 */
1827 - (NSPoint) convertScreenToBase: (NSPoint)aPoint
1828 {
1829 GSDisplayServer *srv = GSCurrentServer();
1830 NSPoint basePoint;
1831 float t, b, l, r;
1832
1833 [srv styleoffsets: &l : &r : &t : &b : _styleMask];
1834 basePoint.x = aPoint.x - _frame.origin.x - l;
1835 basePoint.y = aPoint.y - _frame.origin.y - b;
1836
1837 return basePoint;
1838 }
1839
1840 /*
1841 * Managing the display
1842 */
1843 - (void) disableFlushWindow
1844 {
1845 _disableFlushWindow++;
1846 }
1847
1848 - (void) display
1849 {
1850 if (_gstate == 0 || _f.visible == NO)
1851 return;
1852
1853 _rFlags.needs_display = NO;
1854
1855 [_wv display];
1856 [self discardCachedImage];
1857 }
1858
1859 - (void) displayIfNeeded
1860 {
1861 if (_rFlags.needs_display)
1862 {
1863 [_wv displayIfNeeded];
1864 _rFlags.needs_display = NO;
1865 }
1866 }
1867
1868 - (void) update
1869 {
1870 [nc postNotificationName: NSWindowDidUpdateNotification object: self];
1871 }
1872
1873 - (void) flushWindowIfNeeded
1874 {
1875 if (_disableFlushWindow == 0 && _f.needs_flush == YES)
1876 {
1877 [self flushWindow];
1878 }
1879 }
1880
1881 /**
1882 * Flush all drawing in the windows buffer to the screen unless the window
1883 * is not buffered or flushing is not enabled.
1884 */
1885 - (void) flushWindow
1886 {
1887 int i;
1888
1889 /*
1890 * If flushWindow is called while flush is disabled
1891 * mark self as needing a flush, then return
1892 */
1893 if (_disableFlushWindow)
1894 {
1895 _f.needs_flush = YES;
1896 return;
1897 }
1898
1899 /*
1900 * Just flush graphics if backing is not buffered.
1901 * The documentation actually says that this is wrong ... the method
1902 * should do nothing when the backingType is NSBackingStoreNonretained
1903 */
1904 if (_backingType == NSBackingStoreNonretained)
1905 {
1906 NSGraphicsContext *context = GSCurrentContext();
1907
1908 [context flushGraphics];
1909 return;
1910 }
1911
1912 /* Check for special case of flushing while we are lock focused.
1913 For instance, when we are highlighting a button. */
1914 if (NSIsEmptyRect(_rectNeedingFlush))
1915 {
1916 if ([_rectsBeingDrawn count] == 0)
1917 {
1918 _f.needs_flush = NO;
1919 return;
1920 }
1921 }
1922
1923 /*
1924 * Accumulate the rectangles from all nested focus locks.
1925 */
1926 i = [_rectsBeingDrawn count];
1927 while (i-- > 0)
1928 {
1929 _rectNeedingFlush = NSUnionRect(_rectNeedingFlush,
1930 [[_rectsBeingDrawn objectAtIndex: i] rectValue]);
1931 }
1932
1933 if (_windowNum > 0)
1934 {
1935 [GSServerForWindow(self) flushwindowrect: _rectNeedingFlush
1936 : _windowNum];
1937 }
1938 _f.needs_flush = NO;
1939 _rectNeedingFlush = NSZeroRect;
1940 }
1941
1942 - (void) enableFlushWindow
1943 {
1944 if (_disableFlushWindow > 0)
1945 {
1946 _disableFlushWindow--;
1947 }
1948 }
1949
1950 - (BOOL) isAutodisplay
1951 {
1952 return _f.is_autodisplay;
1953 }
1954
1955 - (BOOL) isFlushWindowDisabled
1956 {
1957 return _disableFlushWindow == 0 ? NO : YES;
1958 }
1959
1960 - (void) setAutodisplay: (BOOL)flag
1961 {
1962 _f.is_autodisplay = flag;
1963 }
1964
1965 - (void) setViewsNeedDisplay: (BOOL)flag
1966 {
1967 if (_rFlags.needs_display != flag)
1968 {
1969 _rFlags.needs_display = flag;
1970 if (flag)
1971 {
1972 /* TODO: this call most likely shouldn't be here */
1973 [NSApp setWindowsNeedUpdate: YES];
1974 }
1975 }
1976 }
1977
1978 - (BOOL) viewsNeedDisplay
1979 {
1980 return _rFlags.needs_display;
1981 }
1982
1983 - (void) cacheImageInRect: (NSRect)aRect
1984 {
1985 NSView *cacheView;
1986 NSRect cacheRect;
1987
1988 aRect = NSIntegralRect (NSIntersectionRect (aRect, [_wv frame]));
1989 _cachedImageOrigin = aRect.origin;
1990 DESTROY(_cachedImage);
1991
1992 if (NSIsEmptyRect (aRect))
1993 {
1994 return;
1995 }
1996
1997 cacheRect.origin = NSZeroPoint;
1998 cacheRect.size = aRect.size;
1999 _cachedImage = [[NSCachedImageRep alloc] initWithWindow: nil
2000 rect: cacheRect];
2001 cacheView = [[_cachedImage window] contentView];
2002 [cacheView lockFocus];
2003 NSCopyBits (_gstate, aRect, NSZeroPoint);
2004 [cacheView unlockFocus];
2005 }
2006
2007 - (void) discardCachedImage
2008 {
2009 DESTROY(_cachedImage);
2010 }
2011
2012 - (void) restoreCachedImage
2013 {
2014 if (_cachedImage == nil)
2015 {
2016 return;
2017 }
2018 [_wv lockFocus];
2019 NSCopyBits ([[_cachedImage window] gState],
2020 [_cachedImage rect],
2021 _cachedImageOrigin);
2022 [_wv unlockFocus];
2023 }
2024
2025 - (void) useOptimizedDrawing: (BOOL)flag
2026 {
2027 _f.optimize_drawing = flag;
2028 }
2029
2030 - (BOOL) canStoreColor
2031 {
2032 if (NSNumberOfColorComponents(NSColorSpaceFromDepth(_depthLimit)) > 1)
2033 {
2034 return YES;
2035 }
2036 else
2037 {
2038 return NO;
2039 }
2040 }
2041
2042 /** Returns the screen the window is on. Unlike (apparently) OpenStep
2043 and MacOSX, GNUstep does not support windows being split across
2044 multiple screens */
2045 - (NSScreen *) deepestScreen
2046 {
2047 return [self screen];
2048 }
2049
2050 - (NSWindowDepth) depthLimit
2051 {
2052 return _depthLimit;
2053 }
2054
2055 - (BOOL) hasDynamicDepthLimit
2056 {
2057 return _f.dynamic_depth_limit;
2058 }
2059
2060 /** Returns the screen the window is on. */
2061 - (NSScreen *) screen
2062 {
2063 return _screen;
2064 }
2065
2066 - (void) setDepthLimit: (NSWindowDepth)limit
2067 {
2068 if (limit == 0)
2069 {
2070 limit = [isa defaultDepthLimit];
2071 }
2072
2073 _depthLimit = limit;
2074 }
2075
2076 - (void) setDynamicDepthLimit: (BOOL)flag
2077 {
2078 _f.dynamic_depth_limit = flag;
2079 }
2080
2081 /*
2082 * Cursor management
2083 */
2084 - (BOOL) areCursorRectsEnabled
2085 {
2086 return _f.cursor_rects_enabled;
2087 }
2088
2089 - (void) disableCursorRects
2090 {
2091 _f.cursor_rects_enabled = NO;
2092 }
2093
2094 static void
2095 discardCursorRectsForView(NSView *theView)
2096 {
2097 if (theView != nil)
2098 {
2099 if (((NSViewPtr)theView)->_rFlags.has_currects)
2100 {
2101 [theView discardCursorRects];
2102 }
2103
2104 if (((NSViewPtr)theView)->_rFlags.has_subviews)
2105 {
2106 NSArray *s = ((NSViewPtr)theView)->_sub_views;
2107 unsigned count = [s count];
2108
2109 if (count)
2110 {
2111 NSView *subs[count];
2112 unsigned i;
2113
2114 [s getObjects: subs];
2115 for (i = 0; i < count; i++)
2116 {
2117 discardCursorRectsForView(subs[i]);
2118 }
2119 }
2120 }
2121 }
2122 }
2123
2124 - (void) discardCursorRects
2125 {
2126 discardCursorRectsForView(_wv);
2127 }
2128
2129 - (void) enableCursorRects
2130 {
2131 _f.cursor_rects_enabled = YES;
2132 }
2133
2134 - (void) invalidateCursorRectsForView: (NSView*)aView
2135 {
2136 if (((NSViewPtr)aView)->_rFlags.valid_rects)
2137 {
2138 [((NSViewPtr)aView)->_cursor_rects
2139 makeObjectsPerformSelector: @selector(invalidate)];
2140 ((NSViewPtr)aView)->_rFlags.valid_rects = 0;
2141 _f.cursor_rects_valid = NO;
2142 }
2143 }
2144
2145 static void
2146 resetCursorRectsForView(NSView *theView)
2147 {
2148 if (theView != nil)
2149 {
2150 [theView resetCursorRects];
2151
2152 if (((NSViewPtr)theView)->_rFlags.has_subviews)
2153 {
2154 NSArray *s = ((NSViewPtr)theView)->_sub_views;
2155 unsigned count = [s count];
2156
2157 if (count)
2158 {
2159 NSView *subs[count];
2160 unsigned i;
2161
2162 [s getObjects: subs];
2163 for (i = 0; i < count; i++)
2164 {
2165 resetCursorRectsForView(subs[i]);
2166 }
2167 }
2168 }
2169 }
2170 }
2171
2172 - (void) resetCursorRects
2173 {
2174 [self discardCursorRects];
2175 resetCursorRectsForView(_wv);
2176 _f.cursor_rects_valid = YES;
2177 }
2178
2179 /*
2180 * Handling user actions and events
2181 */
2182 - (void) close
2183 {
2184 if (_f.has_closed == NO)
2185 {
2186 CREATE_AUTORELEASE_POOL(pool);
2187
2188 /* The NSWindowCloseNotification might result in us being
2189 deallocated. To make sure self stays valid as long as is
2190 necessary, we retain ourselves here and balance it with a
2191 release later (unless we're supposed to release ourselves when
2192 we close).
2193 */
2194 if (!_f.is_released_when_closed)
2195 {
2196 RETAIN(self);
2197 }
2198
2199 [nc postNotificationName: NSWindowWillCloseNotification object: self];
2200 _f.has_opened = NO;
2201 [[NSRunLoop currentRunLoop]
2202 cancelPerformSelector: @selector(_handleWindowNeedsDisplay:)
2203 target: self
2204 argument: nil];
2205 [NSApp removeWindowsItem: self];
2206 [self orderOut: self];
2207
2208 RELEASE(pool);
2209
2210 _f.has_closed = YES;
2211 RELEASE(self);
2212 }
2213 }
2214
2215 /* Private Method. Many X Window managers will just deminiaturize us without
2216 telling us to do it ourselves. Deal with it.
2217 */
2218 - (void) _didDeminiaturize: sender
2219 {
2220 _f.is_miniaturized = NO;
2221 [nc postNotificationName: NSWindowDidDeminiaturizeNotification object: self];
2222 }
2223
2224 /**
2225 Causes the window to deminiaturize. Normally you would not call this
2226 method directly. A window is automatically deminiaturized by the
2227 user via a mouse click event. */
2228 - (void) deminiaturize: sender
2229 {
2230 if (_counterpart != 0)
2231 {
2232 NSWindow *mini = GSWindowWithNumber(_counterpart);
2233
2234 [mini orderOut: self];
2235 }
2236 _f.is_miniaturized = NO;
2237 [self makeKeyAndOrderFront: self];
2238 [self _didDeminiaturize: sender];
2239 }
2240
2241 - (BOOL) isDocumentEdited
2242 {
2243 return _f.is_edited;
2244 }
2245
2246 - (BOOL) isReleasedWhenClosed
2247 {
2248 return _f.is_released_when_closed;
2249 }
2250
2251 /**
2252 Causes the window to miniaturize, that is the window is removed from
2253 the screen and it's counterpart (mini)window is displayed. */
2254 - (void) miniaturize: (id)sender
2255 {
2256 GSDisplayServer *srv = GSServerForWindow(self);
2257 [nc postNotificationName: NSWindowWillMiniaturizeNotification
2258 object: self];
2259
2260 _f.is_miniaturized = YES;
2261 /* Make sure we're not defered */
2262 if (_windowNum == 0)
2263 {
2264 [self _initBackendWindow: _frame];
2265 }
2266 /*
2267 * Ensure that we have a miniwindow counterpart.
2268 */
2269 if (_counterpart == 0 && [srv appOwnsMiniwindow])
2270 {
2271 NSWindow *mini;
2272 NSMiniWindowView *v;
2273
2274 mini = [[NSMiniWindow alloc] initWithContentRect: NSMakeRect(0,0,64,64)
2275 styleMask: NSMiniWindowMask
2276 backing: NSBackingStoreBuffered
2277 defer: NO];
2278 mini->_counterpart = [self windowNumber];
2279 _counterpart = [mini windowNumber];
2280 v = [[NSMiniWindowView alloc] initWithFrame: NSMakeRect(0,0,64,64)];
2281 [v setImage: [self miniwindowImage]];
2282 [v setTitle: [self miniwindowTitle]];
2283 [mini setContentView: v];
2284 RELEASE(v);
2285 }
2286 [self _lossOfKeyOrMainWindow];
2287 [srv miniwindow: _windowNum];
2288 _f.visible = NO;
2289
2290 /*
2291 * We must order the miniwindow in so that we will start sending
2292 * it -_handleWindowNeedsDisplay: messages to tell it to display
2293 * itsself when neccessary.
2294 */
2295 if (_counterpart != 0)
2296 {
2297 NSWindow *mini = GSWindowWithNumber(_counterpart);
2298
2299 [mini orderFront: self];
2300 }
2301 [nc postNotificationName: NSWindowDidMiniaturizeNotification
2302 object: self];
2303 }
2304
2305 - (void) performClose: (id)sender
2306 {
2307 /* Don't close if a modal session is running and we are not the
2308 modal window */
2309 if ([NSApp modalWindow] && self != [NSApp modalWindow])
2310 return;
2311
2312 /* self must have a close button in order to be closed */
2313 if (!(_styleMask & NSClosableWindowMask))
2314 {
2315 NSBeep();
2316 return;
2317 }
2318
2319 if (_windowController)
2320 {
2321 NSDocument *document = [_windowController document];
2322
2323 if (document && ![document shouldCloseWindowController: _windowController])
2324 {
2325 NSBeep();
2326 return;
2327 }
2328 }
2329 if ([_delegate respondsToSelector: @selector(windowShouldClose:)])
2330 {
2331 /*
2332 * if delegate responds to windowShouldClose query it to see if
2333 * it's ok to close the window
2334 */
2335 if (![_delegate windowShouldClose: self])
2336 {
2337 NSBeep();
2338 return;
2339 }
2340 }
2341 else
2342 {
2343 /*
2344 * else if self responds to windowShouldClose query
2345 * self to see if it's ok to close self
2346 */
2347 if ([self respondsToSelector: @selector(windowShouldClose:)])
2348 {
2349 if (![self windowShouldClose: self])
2350 {
2351 NSBeep();
2352 return;
2353 }
2354 }
2355 }
2356
2357 // FIXME: The button should be highlighted
2358 [self close];
2359 }
2360
2361 - (BOOL) performKeyEquivalent: (NSEvent*)theEvent
2362 {
2363 if (_contentView)
2364 return [_contentView performKeyEquivalent: theEvent];
2365 return NO;
2366 }
2367
2368 /**
2369 * Miniaturize the receiver ... as long as its style mask includes
2370 * NSMiniaturizableWindowMask (and as long as the receiver is not an
2371 * icon or mini window itsself). Calls -miniaturize: to do this.<br />
2372 * Beeps if the window can't be miniaturised.<br />
2373 * Should ideally provide visual feedback (highlighting the miniaturize
2374 * button as if it had been clicked) first ... but that's not yet implemented.
2375 */
2376 - (void) performMiniaturize: (id)sender
2377 {
2378 if ((!(_styleMask & NSMiniaturizableWindowMask))
2379 || (_styleMask & (NSIconWindowMask | NSMiniWindowMask)))
2380 {
2381 NSBeep();
2382 return;
2383 }
2384
2385 // FIXME: The button should be highlighted
2386 [self miniaturize: sender];
2387 }
2388
2389 - (int) resizeFlags
2390 {
2391 // FIXME: The implementation is missing
2392 return 0;
2393 }
2394
2395 - (void) setDocumentEdited: (BOOL)flag
2396 {
2397 if (_f.is_edited != flag)
2398 {
2399 _f.is_edited = flag;
2400 if (_f.menu_exclude == NO && _f.has_opened == YES)
2401 {
2402 [NSApp updateWindowsItem: self];
2403 }
2404 if (_windowNum)
2405 [GSServerForWindow(self) docedited: flag : _windowNum];
2406 }
2407 }
2408
2409 - (void) setReleasedWhenClosed: (BOOL)flag
2410 {
2411 _f.is_released_when_closed = flag;
2412 }
2413
2414 /*
2415 * Aiding event handling
2416 */
2417 - (BOOL) acceptsMouseMovedEvents
2418 {
2419 return _f.accepts_mouse_moved;
2420 }
2421
2422 - (NSEvent*) currentEvent
2423 {
2424 return [NSApp currentEvent];
2425 }
2426
2427 - (void) discardEventsMatchingMask: (unsigned int)mask
2428 beforeEvent: (NSEvent*)lastEvent
2429 {
2430 [NSApp discardEventsMatchingMask: mask beforeEvent: lastEvent];
2431 }
2432
2433 - (NSResponder*) firstResponder
2434 {
2435 return _firstResponder;
2436 }
2437
2438 - (BOOL) acceptsFirstResponder
2439 {
2440 return YES;
2441 }
2442
2443 - (BOOL) makeFirstResponder: (NSResponder*)aResponder
2444 {
2445 if (_firstResponder == aResponder)
2446 return YES;
2447
2448 if (![aResponder isKindOfClass: responderClass])
2449 return NO;
2450
2451 if (![aResponder acceptsFirstResponder])
2452 return NO;
2453
2454 /* So that the implementation of -resignFirstResponder in
2455 _firstResponder might ask for what will be the new first
2456 responder by calling our method _futureFirstResponder */
2457 _futureFirstResponder = aResponder;
2458
2459 /*
2460 * If there is a first responder tell it to resign.
2461 * Change only if it replies YES.
2462 */
2463 if ((_firstResponder) && (![_firstResponder resignFirstResponder]))
2464 return NO;
2465
2466 _firstResponder = aResponder;
2467 if (![_firstResponder becomeFirstResponder])
2468 {
2469 _firstResponder = self;
2470 [_firstResponder becomeFirstResponder];
2471 return NO;
2472 }
2473
2474 return YES;
2475 }
2476
2477 - (void) setInitialFirstResponder: (NSView*)aView
2478 {
2479 if ([aView isKindOfClass: viewClass])
2480 {
2481 ASSIGN(_initialFirstResponder, aView);
2482 }
2483 }
2484
2485 - (NSView*) initialFirstResponder
2486 {
2487 return _initialFirstResponder;
2488 }
2489
2490 - (void) keyDown: (NSEvent*)theEvent
2491 {
2492 NSString *characters = [theEvent characters];
2493 unichar character = 0;
2494
2495 if ([characters length] > 0)
2496 {
2497 character = [characters characterAtIndex: 0];
2498 }
2499
2500 // If this is a TAB or TAB+SHIFT event, move to the next key view
2501 if (character == NSTabCharacter)
2502 {
2503 if ([theEvent modifierFlags] & NSShiftKeyMask)
2504 [self selectPreviousKeyView: self];
2505 else
2506 [self selectNextKeyView: self];
2507 return;
2508 }
2509
2510 // If this is an ESC event, abort modal loop
2511 if (character == 0x001b)
2512 {
2513 if ([NSApp modalWindow] == self)
2514 {
2515 // NB: The following *never* returns.
2516 [NSApp abortModal];
2517 }
2518 return;
2519 }
2520
2521 if (character == NSEnterCharacter
2522 || character == NSFormFeedCharacter
2523 || character == NSCarriageReturnCharacter)
2524 {
2525 if (_defaultButtonCell && _f.default_button_cell_key_disabled == NO)
2526 {
2527 [_defaultButtonCell performClick: self];
2528 return;
2529 }
2530 }
2531
2532 // Discard null character events such as a Shift event after a tab key
2533 if ([characters length] == 0)
2534 return;
2535
2536 // Try to process the event as a key equivalent
2537 // without Command having being pressed
2538 {
2539 NSEvent *new_event
2540 = [NSEvent keyEventWithType: [theEvent type]
2541 location: NSZeroPoint
2542 modifierFlags: ([theEvent modifierFlags] | NSCommandKeyMask)
2543 timestamp: [theEvent timestamp]
2544 windowNumber: [theEvent windowNumber]
2545 context: [theEvent context]
2546 characters: characters
2547 charactersIgnoringModifiers: [theEvent
2548 charactersIgnoringModifiers]
2549 isARepeat: [theEvent isARepeat]
2550 keyCode: [theEvent keyCode]];
2551 if ([self performKeyEquivalent: new_event])
2552 return;
2553 }
2554
2555 // Otherwise, pass the event up
2556 [super keyDown: theEvent];
2557 }
2558
2559 /* Return mouse location in reciever's base coord system, ignores event
2560 * loop status */
2561 - (NSPoint) mouseLocationOutsideOfEventStream
2562 {
2563 int screen;
2564 NSPoint p;
2565
2566 screen = [_screen screenNumber];
2567 p = [GSServerForWindow(self) mouseLocationOnScreen: screen window: NULL];
2568 if (p.x != -1)
2569 p = [self convertScreenToBase: p];
2570 return p;
2571 }
2572
2573 - (NSEvent*) nextEventMatchingMask: (unsigned int)mask
2574 {
2575 return [NSApp nextEventMatchingMask: mask
2576 untilDate: nil
2577 inMode: NSEventTrackingRunLoopMode
2578 dequeue: YES];
2579 }
2580
2581 - (NSEvent*) nextEventMatchingMask: (unsigned int)mask
2582 untilDate: (NSDate*)expiration
2583 inMode: (NSString*)mode
2584 dequeue: (BOOL)deqFlag
2585 {
2586 return [NSApp nextEventMatchingMask: mask
2587 untilDate: expiration
2588 inMode: mode
2589 dequeue: deqFlag];
2590 }
2591
2592 - (void) postEvent: (NSEvent*)event atStart: (BOOL)flag
2593 {
2594 [NSApp postEvent: event atStart: flag];
2595 }
2596
2597 - (void) setAcceptsMouseMovedEvents: (BOOL)flag
2598 {
2599 _f.accepts_mouse_moved = flag;
2600 }
2601
2602 - (void) _checkTrackingRectangles: (NSView*)theView
2603 forEvent: (NSEvent*)theEvent
2604 {
2605 if (((NSViewPtr)theView)->_rFlags.has_trkrects)
2606 {
2607 NSArray *tr = ((NSViewPtr)theView)->_tracking_rects;
2608 unsigned count = [tr count];
2609
2610 /*
2611 * Loop through the tracking rectangles
2612 */
2613 if (count > 0)
2614 {
2615 GSTrackingRect *rects[count];
2616 NSPoint loc = [theEvent locationInWindow];
2617 unsigned i;
2618
2619 [tr getObjects: rects];
2620
2621 for (i = 0; i < count; ++i)
2622 {
2623 BOOL last;
2624 BOOL now;
2625 GSTrackingRect *r = rects[i];
2626
2627 /* Check mouse at last point */
2628 last = NSMouseInRect(_lastPoint, r->rectangle, NO);
2629 /* Check mouse at current point */
2630 now = NSMouseInRect(loc, r->rectangle, NO);
2631
2632 if ((!last) && (now)) // Mouse entered event
2633 {
2634 if (r->flags.checked == NO)
2635 {
2636 if ([r->owner respondsToSelector:
2637 @selector(mouseEntered:)])
2638 r->flags.ownerRespondsToMouseEntered = YES;
2639 if ([r->owner respondsToSelector:
2640 @selector(mouseExited:)])
2641 r->flags.ownerRespondsToMouseExited = YES;
2642 r->flags.checked = YES;
2643 }
2644 if (r->flags.ownerRespondsToMouseEntered)
2645 {
2646 NSEvent *e;
2647
2648 e = [NSEvent enterExitEventWithType: NSMouseEntered
2649 location: loc
2650 modifierFlags: [theEvent modifierFlags]
2651 timestamp: 0
2652 windowNumber: [theEvent windowNumber]
2653 context: NULL
2654 eventNumber: 0
2655 trackingNumber: r->tag
2656 userData: r->user_data];
2657 [r->owner mouseEntered: e];
2658 }
2659 }
2660
2661 if ((last) && (!now)) // Mouse exited event
2662 {
2663 if (r->flags.checked == NO)
2664 {
2665 if ([r->owner respondsToSelector:
2666 @selector(mouseEntered:)])
2667 r->flags.ownerRespondsToMouseEntered = YES;
2668 if ([r->owner respondsToSelector:
2669 @selector(mouseExited:)])
2670 r->flags.ownerRespondsToMouseExited = YES;
2671 r->flags.checked = YES;
2672 }
2673 if (r->flags.ownerRespondsToMouseExited)
2674 {
2675 NSEvent *e;
2676
2677 e = [NSEvent enterExitEventWithType: NSMouseExited
2678 location: loc
2679 modifierFlags: [theEvent modifierFlags]
2680 timestamp: 0
2681 windowNumber: [theEvent windowNumber]
2682 context: NULL
2683 eventNumber: 0
2684 trackingNumber: r->tag
2685 userData: r->user_data];
2686 [r->owner mouseExited: e];
2687 }
2688 }
2689 }
2690 }
2691 }
2692
2693 /*
2694 * Check tracking rectangles for the subviews
2695 */
2696 if (((NSViewPtr)theView)->_rFlags.has_subviews)
2697 {
2698 NSArray *sb = ((NSViewPtr)theView)->_sub_views;
2699 unsigned count = [sb count];
2700
2701 if (count > 0)
2702 {
2703 NSView *subs[count];
2704 unsigned i;
2705
2706 [sb getObjects: subs];
2707 for (i = 0; i < count; ++i)
2708 (*ctImp)(self, ctSel, subs[i], theEvent);
2709 }
2710 }
2711 }
2712
2713 - (void) _checkCursorRectangles: (NSView*)theView forEvent: (NSEvent*)theEvent
2714 {
2715 if (((NSViewPtr)theView)->_rFlags.valid_rects)
2716 {
2717 NSArray *tr = ((NSViewPtr)theView)->_cursor_rects;
2718 unsigned count = [tr count];
2719
2720 // Loop through cursor rectangles
2721 if (count > 0)
2722 {
2723 GSTrackingRect *rects[count];
2724 NSPoint loc = [theEvent locationInWindow];
2725 unsigned i;
2726
2727 [tr getObjects: rects];
2728
2729 for (i = 0; i < count; ++i)
2730 {
2731 GSTrackingRect *r = rects[i];
2732 BOOL last;
2733 BOOL now;
2734
2735 if ([r isValid] == NO)
2736 continue;
2737
2738 /*
2739 * Check for presence of point in rectangle.
2740 */
2741 last = NSMouseInRect(_lastPoint, r->rectangle, NO);
2742 now = NSMouseInRect(loc, r->rectangle, NO);
2743
2744 // Mouse entered
2745 if ((!last) && (now))
2746 {
2747 NSEvent *e;
2748
2749 e = [NSEvent enterExitEventWithType: NSCursorUpdate
2750 location: loc
2751 modifierFlags: [theEvent modifierFlags]
2752 timestamp: 0
2753 windowNumber: [theEvent windowNumber]
2754 context: [theEvent context]
2755 eventNumber: 0
2756 trackingNumber: (int)YES
2757 userData: (void*)r];
2758 [self postEvent: e atStart: YES];
2759 }
2760 // Mouse exited
2761 if ((last) && (!now))
2762 {
2763 NSEvent *e;
2764
2765 e = [NSEvent enterExitEventWithType: NSCursorUpdate
2766 location: loc
2767 modifierFlags: [theEvent modifierFlags]
2768 timestamp: 0
2769 windowNumber: [theEvent windowNumber]
2770 context: [theEvent context]
2771 eventNumber: 0
2772 trackingNumber: (int)NO
2773 userData: (void*)r];
2774 [self postEvent: e atStart: YES];
2775 }
2776 }
2777 }
2778 }
2779
2780 /*
2781 * Check cursor rectangles for the subviews
2782 */
2783 if (((NSViewPtr)theView)->_rFlags.has_subviews)
2784 {
2785 NSArray *sb = ((NSViewPtr)theView)->_sub_views;
2786 unsigned count = [sb count];
2787
2788 if (count > 0)
2789 {
2790 NSView *subs[count];
2791 unsigned i;
2792
2793 [sb getObjects: subs];
2794 for (i = 0; i < count; ++i)
2795 (*ccImp)(self, ccSel, subs[i], theEvent);
2796 }
2797 }
2798 }
2799
2800 - (void) _processResizeEvent
2801 {
2802 if (_windowNum && _gstate)
2803 {
2804 NSGraphicsContext *context = GSCurrentContext();
2805 DPSgsave(context);
2806 DPSsetgstate(context, _gstate);
2807 [GSServerForWindow(self) windowdevice: _windowNum];
2808 GSReplaceGState(context, _gstate);
2809 DPSgrestore(context);
2810 }
2811
2812 [self update];
2813 }
2814
2815 - (void) mouseDown: (NSEvent*)theEvent
2816 {
2817 // Quietly discard an unused mouse down.
2818 }
2819
2820 /** Handles mouse and other events sent to the receiver by NSApplication.
2821 Do not invoke this method directly.
2822 */
2823 - (void) sendEvent: (NSEvent*)theEvent
2824 {
2825 NSView *v;
2826 NSEventType type;
2827
2828 if (!_f.cursor_rects_valid)
2829 {
2830 [self resetCursorRects];
2831 }
2832
2833 type = [theEvent type];
2834 switch (type)
2835 {
2836 case NSLeftMouseDown:
2837 /*
2838 Code shared with [NSPanel -sendEvent:], remember to update both places.
2839 */
2840 {
2841 BOOL wasKey = _f.is_key;
2842
2843 if ([NSApp isActive] == NO && self != [NSApp iconWindow])
2844 {
2845 [NSApp activateIgnoringOtherApps: YES];
2846 }
2847 if (_f.has_closed == NO)
2848 {
2849 v = [_contentView hitTest: [theEvent locationInWindow]];
2850 if (_f.is_key == NO)
2851 {
2852 [self makeKeyAndOrderFront: self];
2853 }
2854 if (_firstResponder != v)
2855 {
2856 [self makeFirstResponder: v];
2857 }
2858 if (_lastView)
2859 {
2860 DESTROY(_lastView);
2861 }
2862 if (wasKey == YES || [v acceptsFirstMouse: theEvent] == YES)
2863 {
2864 if ([NSHelpManager isContextHelpModeActive])
2865 {
2866 [v helpRequested: theEvent];
2867 }
2868 else
2869 {
2870 ASSIGN(_lastView, v);
2871 [v mouseDown: theEvent];
2872 }
2873 }
2874 else
2875 {
2876 [self mouseDown: theEvent];
2877 }
2878 }
2879 _lastPoint = [theEvent locationInWindow];
2880 break;
2881 }
2882
2883 case NSLeftMouseUp:
2884 v = AUTORELEASE(RETAIN(_lastView));
2885 DESTROY(_lastView);
2886 if (v == nil)
2887 break;
2888 [v mouseUp: theEvent];
2889 _lastPoint = [theEvent locationInWindow];
2890 break;
2891
2892 case NSOtherMouseDown:
2893 v = [_contentView hitTest: [theEvent locationInWindow]];
2894 [v otherMouseDown: theEvent];
2895 _lastPoint = [theEvent locationInWindow];
2896 break;
2897
2898 case NSOtherMouseUp:
2899 v = [_contentView hitTest: [theEvent locationInWindow]];
2900 [v otherMouseUp: theEvent];
2901 _lastPoint = [theEvent locationInWindow];
2902 break;
2903
2904 case NSRightMouseDown:
2905 {
2906 v = [_contentView hitTest: [theEvent locationInWindow]];
2907 [v rightMouseDown: theEvent];
2908 _lastPoint = [theEvent locationInWindow];
2909 }
2910 break;
2911
2912 case NSRightMouseUp:
2913 v = [_contentView hitTest: [theEvent locationInWindow]];
2914 [v rightMouseUp: theEvent];
2915 _lastPoint = [theEvent locationInWindow];
2916 break;
2917
2918 case NSLeftMouseDragged:
2919 case NSOtherMouseDragged:
2920 case NSRightMouseDragged:
2921 case NSMouseMoved:
2922 switch (type)
2923 {
2924 case NSLeftMouseDragged:
2925 v = [_contentView hitTest: [theEvent locationInWindow]];
2926 [v mouseDragged: theEvent];
2927 break;
2928 case NSOtherMouseDragged:
2929 v = [_contentView hitTest: [theEvent locationInWindow]];
2930 [v otherMouseDragged: theEvent];
2931 break;
2932 case NSRightMouseDragged:
2933 v = [_contentView hitTest: [theEvent locationInWindow]];
2934 [v rightMouseDragged: theEvent];
2935 break;
2936 default:
2937 if (_f.accepts_mouse_moved)
2938 {
2939 /*
2940 * If the window is set to accept mouse movements, we need to
2941 * forward the mouse movement to the correct view.
2942 */
2943 v = [_contentView hitTest: [theEvent locationInWindow]];
2944 [v mouseMoved: theEvent];
2945 }
2946 break;
2947 }
2948
2949 /*
2950 * We need to go through all of the views, and if there is any with
2951 * a tracking rectangle then we need to determine if we should send
2952 * a NSMouseEntered or NSMouseExited event.
2953 */
2954 (*ctImp)(self, ctSel, _contentView, theEvent);
2955
2956 if (_f.is_key)
2957 {
2958 /*
2959 * We need to go through all of the views, and if there is any with
2960 * a cursor rectangle then we need to determine if we should send a
2961 * cursor update event.
2962 */
2963 if (_f.cursor_rects_enabled)
2964 (*ccImp)(self, ccSel, _contentView, theEvent);
2965 }
2966
2967 _lastPoint = [theEvent locationInWindow];
2968 break;
2969
2970 case NSMouseEntered:
2971 case NSMouseExited:
2972 break;
2973
2974 case NSKeyDown:
2975 [_firstResponder keyDown: theEvent];
2976 break;
2977
2978 case NSKeyUp:
2979 [_firstResponder keyUp: theEvent];
2980 break;
2981
2982 case NSFlagsChanged:
2983 [_firstResponder flagsChanged: theEvent];
2984 break;
2985
2986 case NSCursorUpdate:
2987 {
2988 GSTrackingRect *r =(GSTrackingRect*)[theEvent userData];
2989 NSCursor *c = (NSCursor*)[r owner];
2990
2991 if ([theEvent trackingNumber]) // It's a mouse entered
2992 {
2993 [c mouseEntered: theEvent];
2994 }
2995 else // it is a mouse exited
2996 {
2997 [c mouseExited: theEvent];
2998 }
2999 }
3000 break;
3001
3002 case NSScrollWheel:
3003 v = [_contentView hitTest: [theEvent locationInWindow]];
3004 [v scrollWheel: theEvent];
3005 break;
3006
3007 case NSAppKitDefined:
3008 {
3009 id dragInfo;
3010 int action;
3011 NSEvent *e;
3012 GSAppKitSubtype sub = [theEvent subtype];
3013
3014 switch (sub)
3015 {
3016 case GSAppKitWindowMoved:
3017 _frame.origin.x = (float)[theEvent data1];
3018 _frame.origin.y = (float)[theEvent data2];
3019 NSDebugLLog(@"Moving", @"Move event: %d %@",
3020 _windowNum, NSStringFromPoint(_frame.origin));
3021 if (_autosaveName != nil)
3022 {
3023 [self saveFrameUsingName: _autosaveName];
3024 }
3025 [nc postNotificationName: NSWindowDidMoveNotification
3026 object: self];
3027 break;
3028
3029 case GSAppKitWindowResized:
3030 _frame.size.width = (float)[theEvent data1];
3031 _frame.size.height = (float)[theEvent data2];
3032 /* Resize events always move the frame origin. The new origin
3033 is stored in the event location field */
3034 _frame.origin = [theEvent locationInWindow];
3035 if (_autosaveName != nil)
3036 {
3037 [self saveFrameUsingName: _autosaveName];
3038 }
3039 {
3040 NSRect rect = _frame;
3041
3042 rect = [NSWindow contentRectForFrameRect: rect
3043 styleMask: _styleMask];
3044 rect.origin = NSZeroPoint;
3045 [_wv setFrame: rect];
3046 [_wv setNeedsDisplay: YES];
3047 }
3048 [self _processResizeEvent];
3049 [nc postNotificationName: NSWindowDidResizeNotification
3050 object: self];
3051 break;
3052
3053 case GSAppKitWindowClose:
3054 [self performClose: NSApp];
3055 break;
3056
3057 case GSAppKitWindowMiniaturize:
3058 [self performMiniaturize: NSApp];
3059 break;
3060
3061 case GSAppKitWindowFocusIn:
3062 if (_f.is_miniaturized)
3063 {
3064 /* Window Manager just deminiaturized us */
3065 [self deminiaturize: self];
3066 //[self _didDeminiaturize: self];
3067 }
3068 if ([NSApp isHidden])
3069 {
3070 /* This often occurs when hidding an app, since a bunch
3071 of windows get hidden at once, and the WM is searching
3072 for a window to take focus after each one gets
3073 hidden. */
3074 NSDebugLLog(@"Focus", @"WM take focus while hiding");
3075 break;
3076 }
3077 if ([self canBecomeKeyWindow] == YES)
3078 {
3079 [self makeKeyWindow];
3080 [self makeMainWindow];
3081 [NSApp activateIgnoringOtherApps: YES];
3082 }
3083 if (self == [[NSApp mainMenu] window])
3084 {
3085 /* We should really find another window that can become
3086 key (if possible)
3087 */
3088 [self _lossOfKeyOrMainWindow];
3089 }
3090 break;
3091
3092 case GSAppKitWindowFocusOut:
3093 break;
3094
3095 case GSAppKitWindowLeave:
3096 /*
3097 * We need to go through all of the views, and if there
3098 * is any with a tracking rectangle then we need to
3099 * determine if we should send a NSMouseExited event. */
3100 (*ctImp)(self, ctSel, _contentView, theEvent);
3101
3102 if (_f.is_key)
3103 {
3104 /*
3105 * We need to go through all of the views, and if
3106 * there is any with a cursor rectangle then we need
3107 * to determine if we should send a cursor update
3108 * event. */
3109 if (_f.cursor_rects_enabled)
3110 (*ccImp)(self, ccSel, _contentView, theEvent);
3111 }
3112
3113 _lastPoint = NSMakePoint(-1, -1);
3114 break;
3115
3116 case GSAppKitWindowEnter:
3117 break;
3118
3119
3120 #define GSPerformDragSelector(view, sel, info, action) \
3121 if ([view window] == self) \
3122 { \
3123 id target; \
3124 \
3125 if (view == _contentView && _delegate != nil) \
3126 { \
3127 target = _delegate; \
3128 } \
3129 else \
3130 { \
3131 target= view; \
3132 } \
3133 \
3134 if ([target respondsToSelector: sel]) \
3135 { \
3136 action = (int)[target performSelector: sel \
3137 withObject: info]; \
3138 } \
3139 }
3140
3141 #define GSPerformVoidDragSelector(view, sel, info) \
3142 if ([view window] == self) \
3143 { \
3144 id target; \
3145 \
3146 if (view == _contentView && _delegate) \
3147 { \
3148 target = _delegate; \
3149 } \
3150 else \
3151 { \
3152 target= view; \
3153 } \
3154 \
3155 if ([target respondsToSelector: sel]) \
3156 { \
3157 [target performSelector: sel withObject: info]; \
3158 } \
3159 }
3160
3161 case GSAppKitDraggingEnter:
3162 case GSAppKitDraggingUpdate:
3163 {
3164 BOOL isEntry;
3165
3166 v = [_contentView hitTest: [theEvent locationInWindow]];
3167 if (v == nil)
3168 {
3169 v = _contentView;
3170 }
3171 dragInfo = [GSServerForWindow(self) dragInfo];
3172 if (_lastDragView == v)
3173 {
3174 isEntry = NO;
3175 }
3176 else
3177 {
3178 isEntry = YES;
3179 if (_lastDragView != nil && _f.accepts_drag)
3180 {
3181 NSDebugLLog(@"NSDragging", @"Dragging exit");
3182 GSPerformVoidDragSelector(_lastDragView,
3183 @selector(draggingExited:), dragInfo);
3184 }
3185 ASSIGN(_lastDragView, v);
3186 _f.accepts_drag = GSViewAcceptsDrag(v, dragInfo);
3187 action = NSDragOperationNone;
3188 }
3189 if (_f.accepts_drag)
3190 {
3191 if (isEntry == YES)
3192 {
3193 action = NSDragOperationNone;
3194 NSDebugLLog(@"NSDragging", @"Dragging entered");
3195 GSPerformDragSelector(v, @selector(draggingEntered:),
3196 dragInfo, action);
3197 }
3198 else
3199 {
3200 action = _lastDragOperationMask;
3201 NSDebugLLog(@"NSDragging", @"Dragging updated");
3202 GSPerformDragSelector(v, @selector(draggingUpdated:),
3203 dragInfo, action);
3204 }
3205 }
3206 else
3207 {
3208 action = NSDragOperationNone;
3209 }
3210
3211 e = [NSEvent otherEventWithType: NSAppKitDefined
3212 location: [theEvent locationInWindow]
3213 modifierFlags: 0
3214 timestamp: 0
3215 windowNumber: _windowNum
3216 context: GSCurrentContext()
3217 subtype: GSAppKitDraggingStatus
3218 data1: [theEvent data1]
3219 data2: action];
3220
3221 _lastDragOperationMask = action;
3222 [dragInfo postDragEvent: e];
3223 break;
3224 }
3225
3226 case GSAppKitDraggingStatus:
3227 NSDebugLLog(@"NSDragging",
3228 @"Internal: dropped GSAppKitDraggingStatus event");
3229 break;
3230
3231 case GSAppKitDraggingExit:
3232 NSDebugLLog(@"NSDragging", @"GSAppKitDraggingExit");
3233 dragInfo = [GSServerForWindow(self) dragInfo];
3234 if (_lastDragView && _f.accepts_drag)
3235 {
3236 NSDebugLLog(@"NSDragging", @"Dragging exit");
3237 GSPerformVoidDragSelector(_lastDragView,
3238 @selector(draggingExited:), dragInfo);
3239 }
3240 _lastDragOperationMask = NSDragOperationNone;
3241 DESTROY(_lastDragView);
3242 break;
3243
3244 case GSAppKitDraggingDrop:
3245 NSDebugLLog(@"NSDragging", @"GSAppKitDraggingDrop");
3246 dragInfo = [GSServerForWindow(self) dragInfo];
3247 if (_lastDragView && _f.accepts_drag)
3248 {
3249 action = NO;
3250 GSPerformDragSelector(_lastDragView,
3251 @selector(prepareForDragOperation:), dragInfo, action);
3252 if (action)
3253 {
3254 action = NO;
3255 GSPerformDragSelector(_lastDragView,
3256 @selector(performDragOperation:), dragInfo, action);
3257 }
3258 if (action)
3259 {
3260 GSPerformVoidDragSelector(_lastDragView,
3261 @selector(concludeDragOperation:), dragInfo);
3262 }
3263 }
3264 _lastDragOperationMask = NSDragOperationNone;
3265 DESTROY(_lastDragView);
3266 e = [NSEvent otherEventWithType: NSAppKitDefined
3267 location: [theEvent locationInWindow]
3268 modifierFlags: 0
3269 timestamp: 0
3270 windowNumber: _windowNum
3271 context: GSCurrentContext()
3272 subtype: GSAppKitDraggingFinished
3273 data1: [theEvent data1]
3274 data2: 0];
3275 [dragInfo postDragEvent: e];
3276 break;
3277
3278 case GSAppKitDraggingFinished:
3279 _lastDragOperationMask = NSDragOperationNone;
3280 DESTROY(_lastDragView);
3281 NSDebugLLog(@"NSDragging",
3282 @"Internal: dropped GSAppKitDraggingFinished event");
3283 break;
3284
3285 default:
3286 break;
3287 }
3288 }
3289 break;
3290
3291 case NSPeriodic:
3292 case NSSystemDefined:
3293 case NSApplicationDefined:
3294 break;
3295 }
3296 }
3297
3298 - (BOOL) tryToPerform: (SEL)anAction with: (id)anObject
3299 {
3300 if ([super tryToPerform: anAction with: anObject])
3301 return YES;
3302 else if (_delegate && [_delegate respondsToSelector: anAction])
3303 {
3304 [_delegate performSelector: anAction withObject: anObject];
3305 return YES;
3306 }
3307 else
3308 return NO;
3309 }
3310
3311 - (BOOL) worksWhenModal
3312 {
3313 return NO;
3314 }
3315
3316 - (void) selectKeyViewFollowingView: (NSView*)aView
3317 {
3318 NSView *theView = nil;
3319
3320 if ([aView isKindOfClass: viewClass])
3321 theView = [aView nextValidKeyView];
3322 if (theView)
3323 {
3324 [self makeFirstResponder: theView];
3325 if ([theView respondsToSelector:@selector(selectText:)])
3326 {
3327 _selectionDirection = NSSelectingNext;
3328 [(id)theView selectText: self];
3329 _selectionDirection = NSDirectSelection;
3330 }
3331 }
3332 }
3333
3334 - (void) selectKeyViewPrecedingView: (NSView*)aView
3335 {
3336 NSView *theView = nil;
3337
3338 if ([aView isKindOfClass: viewClass])
3339 theView = [aView previousValidKeyView];
3340 if (theView)
3341 {
3342 [self makeFirstResponder: theView];
3343 if ([theView respondsToSelector:@selector(selectText:)])
3344 {
3345 _selectionDirection = NSSelectingPrevious;
3346 [(id)theView selectText: self];
3347 _selectionDirection = NSDirectSelection;
3348 }
3349 }
3350 }
3351
3352 - (void) selectNextKeyView: (id)sender
3353 {
3354 NSView *theView = nil;
3355
3356 if ([_firstResponder isKindOfClass: viewClass])
3357 theView = [_firstResponder nextValidKeyView];
3358
3359 if ((theView == nil) && (_initialFirstResponder))
3360 {
3361 if ([_initialFirstResponder acceptsFirstResponder])
3362 theView = _initialFirstResponder;
3363 else
3364 theView = [_initialFirstResponder nextValidKeyView];
3365 }
3366
3367 if (theView)
3368 {
3369 [self makeFirstResponder: theView];
3370 if ([theView respondsToSelector:@selector(selectText:)])
3371 {
3372 _selectionDirection = NSSelectingNext;
3373 [(id)theView selectText: self];
3374 _selectionDirection = NSDirectSelection;
3375 }
3376 }
3377 }
3378
3379 - (void) selectPreviousKeyView: (id)sender
3380 {
3381 NSView *theView = nil;
3382
3383 if ([_firstResponder isKindOfClass: viewClass])
3384 theView = [_firstResponder previousValidKeyView];
3385
3386 if ((theView == nil) && (_initialFirstResponder))
3387 {
3388 if ([_initialFirstResponder acceptsFirstResponder])
3389 theView = _initialFirstResponder;
3390 else
3391 theView = [_initialFirstResponder previousValidKeyView];
3392 }
3393
3394 if (theView)
3395 {
3396 [self makeFirstResponder: theView];
3397 if ([theView respondsToSelector:@selector(selectText:)])
3398 {
3399 _selectionDirection = NSSelectingPrevious;
3400 [(id)theView selectText: self];
3401 _selectionDirection = NSDirectSelection;
3402 }
3403 }
3404 }
3405
3406 // This is invoked by selectText: of some views (eg matrixes),
3407 // to know whether they have received it from the window, and
3408 // if so, in which direction is the selection moving (so that they know
3409 // if they should select the last or the first editable cell).
3410 - (NSSelectionDirection) keyViewSelectionDirection
3411 {
3412 return _selectionDirection;
3413 }
3414
3415 /*
3416 * Dragging
3417 */
3418 - (void) dragImage: (NSImage*)anImage
3419 at: (NSPoint)baseLocation
3420 offset: (NSSize)initialOffset
3421 event: (NSEvent*)event
3422 pasteboard: (NSPasteboard*)pboard
3423 source: (id)sourceObject
3424 slideBack: (BOOL)slideFlag
3425 {
3426 id dragView = [GSServerForWindow(self) dragInfo];
3427
3428 [NSApp preventWindowOrdering];
3429 [dragView dragImage: anImage
3430 at: [self convertBaseToScreen: baseLocation]
3431 offset: initialOffset
3432 event: event
3433 pasteboard: pboard
3434 source: sourceObject
3435 slideBack: slideFlag];
3436 }
3437
3438 - (void) registerForDraggedTypes: (NSArray*)newTypes
3439 {
3440 [_wv registerForDraggedTypes: newTypes];
3441 }
3442
3443 - (void) unregisterDraggedTypes
3444 {
3445 [_wv unregisterDraggedTypes];
3446 }
3447
3448 /*
3449 * Services and windows menu support
3450 */
3451 - (BOOL) isExcludedFromWindowsMenu
3452 {
3453 return _f.menu_exclude;
3454 }
3455
3456 - (void) setExcludedFromWindowsMenu: (BOOL)flag
3457 {
3458 if (_f.menu_exclude != flag)
3459 {
3460 _f.menu_exclude = flag;
3461 if (_f.has_opened == YES)
3462 {
3463 if (_f.menu_exclude == NO)
3464 {
3465 BOOL isFileName;
3466
3467 isFileName = [_windowTitle isEqual: _representedFilename];
3468
3469 [NSApp addWindowsItem: self
3470 title: _windowTitle
3471 filename: isFileName];
3472 }
3473 else
3474 {
3475 [NSApp removeWindowsItem: self];
3476 }
3477 }
3478 }
3479 }
3480
3481 - (id) validRequestorForSendType: (NSString*)sendType
3482 returnType: (NSString*)returnType
3483 {
3484 id result = nil;
3485
3486 // FIXME: We should not forward this method if the delegate is a NSResponder
3487 if (_delegate && [_delegate respondsToSelector: _cmd])
3488 result = [_delegate validRequestorForSendType: sendType
3489 returnType: returnType];
3490
3491 if (result == nil)
3492 result = [NSApp validRequestorForSendType: sendType
3493 returnType: returnType];
3494 return result;
3495 }
3496
3497 /*
3498 * Saving and restoring the frame
3499 */
3500 - (NSString*) frameAutosaveName
3501 {
3502 return _autosaveName;
3503 }
3504
3505 - (void) saveFrameUsingName: (NSString*)name
3506 {
3507 NSUserDefaults *defs;
3508 NSString *key;
3509 id obj;
3510
3511 [windowsLock lock];
3512 defs = [NSUserDefaults standardUserDefaults];
3513 obj = [self stringWithSavedFrame];
3514 key = [NSString stringWithFormat: @"NSWindow Frame %@", name];
3515 [defs setObject: obj forKey: key];
3516 [windowsLock unlock];
3517 }
3518
3519 - (BOOL) setFrameAutosaveName: (NSString*)name
3520 {
3521 NSString *nameToRemove = nil;
3522
3523 if ([name isEqual: _autosaveName])
3524 {
3525 return YES; /* That's our name already. */
3526 }
3527
3528 [windowsLock lock];
3529 if ([autosaveNames member: name] != nil)
3530 {
3531 [windowsLock unlock];
3532 return NO; /* Name in use elsewhere. */
3533 }
3534 if (_autosaveName != nil)
3535 {
3536 if (name == nil || [name isEqual: @""] == YES)
3537 {
3538 nameToRemove = RETAIN(_autosaveName);
3539 }
3540 [autosaveNames removeObject: _autosaveName];
3541 _autosaveName = nil;
3542 }
3543 if (name != nil && [name isEqual: @""] == NO)
3544 {
3545 name = [name copy];
3546 [autosaveNames addObject: name];
3547 _autosaveName = name;
3548 RELEASE(name);
3549 }
3550 else if (nameToRemove != nil)
3551 {
3552 NSUserDefaults *defs;
3553 NSString *key;
3554
3555 /*
3556 * Autosave name cleared - remove from defaults database.
3557 */
3558 defs = [NSUserDefaults standardUserDefaults];
3559 key = [NSString stringWithFormat: @"NSWindow Frame %@", nameToRemove];
3560 [defs removeObjectForKey: key];
3561 RELEASE(nameToRemove);
3562 }
3563 [windowsLock unlock];
3564 return YES;
3565 }
3566
3567 - (void) setFrameFromString: (NSString*)string
3568 {
3569 NSScanner *scanner = [NSScanner scannerWithString: string];
3570 NSRect nRect;
3571 NSRect sRect;
3572 NSRect fRect;
3573 int value;
3574
3575 /*
3576 * Scan in the window frame (flipped coordinate system).
3577 */
3578 if ([scanner scanInt: &value] == NO)
3579 {
3580 NSLog(@"Bad window frame format - x-coord missing");
3581 return;
3582 }
3583 fRect.origin.x = value;
3584
3585 if ([scanner scanInt: &value] == NO)
3586 {
3587 NSLog(@"Bad window frame format - y-coord missing");
3588 return;
3589 }
3590 fRect.origin.y = value;
3591
3592 if ([scanner scanInt: &value] == NO)
3593 {
3594 NSLog(@"Bad window frame format - width missing");
3595 return;
3596 }
3597 fRect.size.width = value;
3598
3599 if ([scanner scanInt: &value] == NO)
3600 {
3601 NSLog(@"Bad window frame format - height missing");
3602 return;
3603 }
3604 fRect.size.height = value;
3605
3606 /*
3607 * Scan in the frame for the area the window was placed in in screen.
3608 */
3609 if ([scanner scanInt: &value] == NO)
3610 {
3611 NSLog(@"Bad screen frame format - x-coord missing");
3612 return;
3613 }
3614 sRect.origin.x = value;
3615
3616 if ([scanner scanInt: &value] == NO)
3617 {
3618 NSLog(@"Bad screen frame format - y-coord missing");
3619 return;
3620 }
3621 sRect.origin.y = value;
3622
3623 if ([scanner scanInt: &value] == NO)
3624 {
3625 NSLog(@"Bad screen frame format - width missing");
3626 return;
3627 }
3628 sRect.size.width = value;
3629
3630 if ([scanner scanInt: &value] == NO)
3631 {
3632 NSLog(@"Bad screen frame format - height missing");
3633 return;
3634 }
3635 sRect.size.height = value;
3636
3637 /*
3638 * The screen rectangle gives the area of the screen in which
3639 * the window could be placed (ie a rectangle excluding the dock).
3640 */
3641 nRect = [[self screen] visibleFrame];
3642
3643 /*
3644 * If the new screen drawable area has moved relative to the one in
3645 * which the window was saved, adjust the window position accordingly.
3646 */
3647 if (NSEqualPoints(nRect.origin, sRect.origin) == NO)
3648 {
3649 fRect.origin.x += nRect.origin.x - sRect.origin.x;
3650 fRect.origin.y += nRect.origin.y - sRect.origin.y;
3651 }
3652
3653 /*
3654 * If the stored screen area is not the same as that currently
3655 * available, we adjust the window frame (position) to try to
3656 * make layout sensible.
3657 */
3658 if (nRect.size.width != sRect.size.width)
3659 {
3660 fRect.origin.x = nRect.origin.x + (fRect.origin.x - nRect.origin.x)
3661 * (nRect.size.width / sRect.size.width);
3662 }
3663 if (nRect.size.height != sRect.size.height)
3664 {
3665 fRect.origin.y = nRect.origin.y + (fRect.origin.y - nRect.origin.y)
3666 * (nRect.size.height / sRect.size.height);
3667 }
3668
3669 /*
3670 * Set frame.
3671 */
3672 [self setFrame: fRect display: (_f.visible) ? YES : NO];
3673 }
3674
3675 - (BOOL) setFrameUsingName: (NSString*)name
3676 {
3677 NSUserDefaults *defs;
3678 id obj;
3679 NSString *key;
3680
3681 [windowsLock lock];
3682 defs = [NSUserDefaults standardUserDefaults];
3683 key = [NSString stringWithFormat: @"NSWindow Frame %@", name];
3684 obj = [defs objectForKey: key];
3685 [windowsLock unlock];
3686 if (obj == nil)
3687 return NO;
3688 [self setFrameFromString: obj];
3689 return YES;
3690 }
3691
3692 - (BOOL) setFrameUsingName: (NSString *)name
3693 force: (BOOL)force
3694 {
3695 // FIXME
3696 return [self setFrameUsingName: name];
3697 }
3698
3699 - (NSString *) stringWithSavedFrame
3700 {
3701 NSRect fRect;
3702 NSRect sRect;
3703
3704 fRect = _frame;
3705
3706 /*
3707 * The screen rectangle should gives the area of the screen in which
3708 * the window could be placed (ie a rectangle excluding the dock).
3709 */
3710 sRect = [[self screen] visibleFrame];
3711
3712 return [NSString stringWithFormat: @"%d %d %d %d %d %d % d %d ",
3713 (int)fRect.origin.x, (int)fRect.origin.y,
3714 (int)fRect.size.width, (int)fRect.size.height,
3715 (int)sRect.origin.x, (int)sRect.origin.y,
3716 (int)sRect.size.width, (int)sRect.size.height];
3717 }
3718
3719 /*
3720 * Printing and postscript
3721 */
3722 - (NSData *) dataWithEPSInsideRect: (NSRect)rect
3723 {
3724 return [_contentView dataWithEPSInsideRect:
3725 [_contentView convertRect: rect fromView: nil]];
3726 }
3727
3728 - (NSData *)dataWithPDFInsideRect:(NSRect)aRect
3729 {
3730 return [_contentView dataWithPDFInsideRect:
3731 [_contentView convertRect: aRect fromView: nil]];
3732 }
3733
3734 - (void) fax: (id)sender
3735 {
3736 [_contentView fax: sender];
3737 }
3738
3739 - (void) print: (id)sender
3740 {
3741 [_contentView print: sender];
3742 }
3743
3744 /*
3745 * Zooming
3746 */
3747
3748 - (BOOL) isZoomed
3749 {
3750 // FIXME: Method is missing
3751 return NO;
3752 }
3753
3754 - (void) performZoom: (id)sender
3755 {
3756 // FIXME: We should check for the style and highlight the button
3757 [self zoom: sender];
3758 }
3759
3760 #define DIST 3
3761
3762 - (void) zoom: (id)sender
3763 {
3764 NSRect maxRect = [[self screen] visibleFrame];
3765
3766 if ([_delegate respondsToSelector: @selector(windowWillUseStandardFrame:defaultFrame:)])
3767 {
3768 maxRect = [_delegate windowWillUseStandardFrame: self defaultFrame: maxRect];
3769 }
3770 else if ([self respondsToSelector: @selector(windowWillUseStandardFrame:defaultFrame:)])
3771 {
3772 maxRect = [self windowWillUseStandardFrame: self defaultFrame: maxRect];
3773 }
3774
3775 maxRect = [self constrainFrameRect: maxRect toScreen: [self screen]];
3776
3777 // Compare the new frame with the current one
3778 if ((abs(NSMaxX(maxRect) - NSMaxX(_frame)) < DIST) &&
3779 (abs(NSMaxY(maxRect) - NSMaxY(_frame)) < DIST) &&
3780 (abs(NSMinX(maxRect) - NSMinX(_frame)) < DIST) &&
3781 (abs(NSMinY(maxRect) - NSMinY(_frame)) < DIST))
3782 {
3783 // Already in zoomed mode, reset user frame, if stored
3784 if (_autosaveName != nil)
3785 {
3786 [self setFrameUsingName: _autosaveName];
3787 }
3788 return;
3789 }
3790
3791 if ([_delegate respondsToSelector: @selector(windowShouldZoom:toFrame:)])
3792 {
3793 if (![_delegate windowShouldZoom: self toFrame: maxRect])
3794 return;
3795 }
3796 else if ([self respondsToSelector: @selector(windowShouldZoom:toFrame:)])
3797 {
3798 if (![self windowShouldZoom: self toFrame: maxRect])
3799 return;
3800 }
3801
3802 if (_autosaveName != nil)
3803 {
3804 [self saveFrameUsingName: _autosaveName];
3805 }
3806
3807 [self setFrame: maxRect display: YES];
3808 }
3809
3810
3811 /*
3812 * Default botton
3813 */
3814
3815 - (NSButtonCell *) defaultButtonCell
3816 {
3817 return _defaultButtonCell;
3818 }
3819
3820 - (void) setDefaultButtonCell: (NSButtonCell *)aCell
3821 {
3822 ASSIGN(_defaultButtonCell, aCell);
3823 _f.default_button_cell_key_disabled = NO;
3824
3825 [aCell setKeyEquivalent: @"\r"];
3826 [aCell setKeyEquivalentModifierMask: 0];
3827 }
3828
3829 - (void) disableKeyEquivalentForDefaultButtonCell
3830 {
3831 _f.default_button_cell_key_disabled = YES;
3832 }
3833
3834 - (void) enableKeyEquivalentForDefaultButtonCell
3835 {
3836 _f.default_button_cell_key_disabled = NO;
3837 }
3838
3839 /*
3840 * Assigning a delegate
3841 */
3842 - (id) delegate
3843 {
3844 return _delegate;
3845 }
3846
3847 - (void) setDelegate: (id)anObject
3848 {
3849 if (_delegate)
3850 {
3851 [nc removeObserver: _delegate name: nil object: self];
3852 }
3853 _delegate = anObject;
3854
3855 #define SET_DELEGATE_NOTIFICATION(notif_name) \
3856 if ([_delegate respondsToSelector: @selector(window##notif_name:)]) \
3857 [nc addObserver: _delegate \
3858 selector: @selector(window##notif_name:) \
3859 name: NSWindow##notif_name##Notification object: self]
3860
3861 SET_DELEGATE_NOTIFICATION(DidBecomeKey);
3862 SET_DELEGATE_NOTIFICATION(DidBecomeMain);
3863 SET_DELEGATE_NOTIFICATION(DidChangeScreen);
3864 SET_DELEGATE_NOTIFICATION(DidDeminiaturize);
3865 SET_DELEGATE_NOTIFICATION(DidExpose);
3866 SET_DELEGATE_NOTIFICATION(DidMiniaturize);
3867 SET_DELEGATE_NOTIFICATION(DidMove);
3868 SET_DELEGATE_NOTIFICATION(DidResignKey);
3869 SET_DELEGATE_NOTIFICATION(DidResignMain);
3870 SET_DELEGATE_NOTIFICATION(DidResize);
3871 SET_DELEGATE_NOTIFICATION(DidUpdate);
3872 SET_DELEGATE_NOTIFICATION(WillClose);
3873 SET_DELEGATE_NOTIFICATION(WillMiniaturize);
3874 SET_DELEGATE_NOTIFICATION(WillMove);
3875 }
3876
3877 /*
3878 * NSCoding protocol
3879 */
3880 - (void) encodeWithCoder: (NSCoder*)aCoder
3881 {
3882 BOOL flag;
3883
3884 [super encodeWithCoder: aCoder];
3885
3886 [aCoder encodeRect: [[self contentView] frame]];
3887 [aCoder encodeValueOfObjCType: @encode(unsigned) at: &_styleMask];
3888 [aCoder encodeValueOfObjCType: @encode(NSBackingStoreType) at: &_backingType];
3889
3890 [aCoder encodePoint: NSMakePoint(NSMinX([self frame]), NSMaxY([self frame]))];
3891 [aCoder encodeObject: _contentView];
3892 [aCoder encodeObject: _backgroundColor];
3893 [aCoder encodeObject: _representedFilename];
3894 [aCoder encodeObject: _miniaturizedTitle];
3895 [aCoder encodeObject: _windowTitle];
3896
3897 [aCoder encodeSize: _minimumSize];
3898 [aCoder encodeSize: _maximumSize];
3899
3900 [aCoder encodeValueOfObjCType: @encode(int) at: &_windowLevel];
3901
3902 flag = _f.menu_exclude;
3903 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
3904 flag = _f.is_one_shot;
3905 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
3906 flag = _f.is_autodisplay;
3907 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
3908 flag = _f.optimize_drawing;
3909 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
3910 flag = _f.dynamic_depth_limit;
3911 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
3912 flag = _f.cursor_rects_enabled;
3913 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
3914 flag = _f.is_released_when_closed;
3915 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
3916 flag = _f.hides_on_deactivate;
3917 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
3918 flag = _f.accepts_mouse_moved;
3919 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
3920
3921 [aCoder encodeObject: _miniaturizedImage];
3922 [aCoder encodeConditionalObject: _initialFirstResponder];
3923 }
3924
3925 - (id) initWithCoder: (NSCoder*)aDecoder
3926 {
3927 id oldself = self;
3928 BOOL flag;
3929
3930 if ((self = [super initWithCoder: aDecoder]) == oldself)
3931 {
3932 NSSize aSize;
3933 NSRect aRect;
3934 NSPoint p;
3935 unsigned aStyle;
3936 NSBackingStoreType aBacking;
3937 int anInt;
3938 id obj;
3939
3940 aRect = [aDecoder decodeRect];
3941 [aDecoder decodeValueOfObjCType: @encode(unsigned)
3942 at: &aStyle];
3943 [aDecoder decodeValueOfObjCType: @encode(NSBackingStoreType)
3944 at: &aBacking];
3945
3946 self = [self initWithContentRect: aRect
3947 styleMask: aStyle
3948 backing: aBacking
3949 defer: NO
3950 screen: nil];
3951
3952 p = [aDecoder decodePoint];
3953 obj = [aDecoder decodeObject];
3954 [self setContentView: obj];
3955 obj = [aDecoder decodeObject];
3956 [self setBackgroundColor: obj];
3957 obj = [aDecoder decodeObject];
3958 [self setRepresentedFilename: obj];
3959 obj = [aDecoder decodeObject];
3960 [self setMiniwindowTitle: obj];
3961 obj = [aDecoder decodeObject];
3962 [self setTitle: obj];
3963
3964 aSize = [aDecoder decodeSize];
3965 [self setMinSize: aSize];
3966 aSize = [aDecoder decodeSize];
3967 [self setMaxSize: aSize];
3968
3969 [aDecoder decodeValueOfObjCType: @encode(int)
3970 at: &anInt];
3971 [self setLevel: anInt];
3972
3973 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
3974 [self setExcludedFromWindowsMenu: flag];
3975 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
3976 [self setOneShot: flag];
3977 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
3978 [self setAutodisplay: flag];
3979 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
3980 [self useOptimizedDrawing: flag];
3981 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
3982 [self setDynamicDepthLimit: flag];
3983 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
3984 if (flag)
3985 [self enableCursorRects];
3986 else
3987 [self disableCursorRects];
3988 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
3989 [self setReleasedWhenClosed: flag];
3990 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
3991 [self setHidesOnDeactivate: flag];
3992 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
3993 [self setAcceptsMouseMovedEvents: flag];
3994
3995 [aDecoder decodeValueOfObjCType: @encode(id)
3996 at: &_miniaturizedImage];
3997 [aDecoder decodeValueOfObjCType: @encode(id)
3998 at: &_initialFirstResponder];
3999
4000 [self setFrameTopLeftPoint: p];
4001 }
4002
4003 return self;
4004 }
4005
4006 - (NSArray *) drawers
4007 {
4008 // TODO
4009 NSLog(@"Method %s is not implemented for class %s",
4010 "drawers", "NSWindow");
4011 return nil;
4012 }
4013
4014 - (void) setToolbar: (NSToolbar*)toolbar
4015 {
4016 ASSIGN(_toolbar, toolbar);
4017 // FIXME The toolbar needs to know about the window!
4018 }
4019
4020 - (NSToolbar *) toolbar
4021 {
4022 return _toolbar;
4023 }
4024
4025 - (void) toggleToolbarShown: (id)sender
4026 {
4027 [_toolbar setVisible: [_toolbar isVisible]];
4028 }
4029
4030 - (void) runToolbarCustomizationPalette: (id)sender
4031 {
4032 [_toolbar runCustomizationPalette: sender];
4033 }
4034
4035 - (id) initWithWindowRef: (void *)windowRef
4036 {
4037 // TODO
4038 NSLog(@"Method %s is not implemented for class %s",
4039 "initWithWindowRef:", "NSWindow");
4040 return nil;
4041 }
4042
4043 - (void *)windowRef
4044 {
4045 // TODO
4046 NSLog(@"Method %s is not implemented for class %s",
4047 "windowRef", "NSWindow");
4048 return (void *) 0;
4049 }
4050
4051 - (void *) windowHandle
4052 {
4053 // Should only be defined on MS Windows
4054 return (void *)_windowNum;
4055 }
4056
4057 @end
4058
4059 /*
4060 * GNUstep backend methods
4061 */
4062 @implementation NSWindow (GNUstepBackend)
4063
4064 /*
4065 * Mouse capture/release
4066 */
4067 - (void) _captureMouse: sender
4068 {
4069 [GSCurrentServer() capturemouse: _windowNum];
4070 }
4071
4072 - (void) _releaseMouse: sender
4073 {
4074 [GSCurrentServer() releasemouse];
4075 }
4076
4077 - (void) setContentViewSize: (NSSize)aSize
4078 {
4079 NSRect r;
4080
4081 r.origin = NSZeroPoint;
4082 r.size = aSize;
4083 if (_contentView)
4084 {
4085 [_contentView setFrame: r];
4086 }
4087 }
4088
4089 - (void) _setVisible: (BOOL)flag
4090 {
4091 _f.visible = flag;
4092 }
4093
4094 - (void) performDeminiaturize: sender
4095 {
4096 [self deminiaturize: sender];
4097 }
4098
4099 /*
4100 * Allow subclasses to init without the backend
4101 * class attempting to create an actual window
4102 */
4103 - (void) _initDefaults
4104 {
4105 _firstResponder = self;
4106 _initialFirstResponder = nil;
4107 _selectionDirection = NSDirectSelection;
4108 _delegate = nil;
4109 _windowNum = 0;
4110 _gstate = 0;
4111 _backgroundColor = RETAIN([NSColor windowBackgroundColor]);
4112 _representedFilename = @"Window";
4113 _miniaturizedTitle = @"Window";
4114 _miniaturizedImage = RETAIN([NSApp applicationIconImage]);
4115 _windowTitle = @"Window";
4116 _lastPoint = NSZeroPoint;
4117 _windowLevel = NSNormalWindowLevel;
4118
4119 _depthLimit = NSDefaultDepth;
4120 _disableFlushWindow = 0;
4121 _alphaValue = 0.0;
4122
4123 _f.is_one_shot = NO;
4124 _f.is_autodisplay = YES;
4125 _f.optimize_drawing = NO;
4126 _f.dynamic_depth_limit = YES;
4127 _f.cursor_rects_enabled = NO;
4128 _f.visible = NO;
4129 _f.is_key = NO;
4130 _f.is_main = NO;
4131 _f.is_edited = NO;
4132 _f.is_released_when_closed = YES;
4133 _f.is_miniaturized = NO;
4134 _f.menu_exclude = NO;
4135 _f.hides_on_deactivate = NO;
4136 _f.accepts_mouse_moved = NO;
4137 _f.has_opened = NO;
4138 _f.has_closed = NO;
4139 _f.can_hide = YES;
4140 _f.has_shadow = NO;
4141 _f.is_opaque = YES;
4142
4143 _rFlags.needs_display = YES;
4144 }
4145
4146 @end
4147
4148 @implementation NSWindow (GNUstepTextView)
4149 - (id) _futureFirstResponder
4150 {
4151 return _futureFirstResponder;
4152 }
4153 @end
4154
4155 BOOL GSViewAcceptsDrag(NSView *v, id<NSDraggingInfo> dragInfo)
4156 {
4157 NSPasteboard *pb = [dragInfo draggingPasteboard];
4158 if ([pb availableTypeFromArray: GSGetDragTypes(v)])
4159 return YES;
4160 return NO;
4161 }
4162
4163 void NSCountWindows(int *count)
4164 {
4165 *count = (int)NSCountMapTable(windowmaps);
4166 }
4167
4168 void NSWindowList(int size, int list[])
4169 {
4170 NSMapEnumerator me = NSEnumerateMapTable(windowmaps);
4171 int num;
4172 id win;
4173 int i = 0;
4174
4175 while (i < size && NSNextMapEnumeratorPair(&me, (void*)&num, (void*)&win))
4176 {
4177 list[i++] = num;
4178 }
4179 /* FIXME - the list produced should be in window stacking order */
4180 }
4181
4182 NSArray* GSAllWindows(void)
4183 {
4184 if (windowmaps)
4185 return NSAllMapTableValues(windowmaps);
4186 return nil;
4187 }
4188
4189 NSWindow* GSWindowWithNumber(int num)
4190 {
4191 return (NSWindow*)NSMapGet(windowmaps, (void*)num);
4192 }

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26