/[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.290 - (show annotations) (download)
Fri Oct 3 14:09:58 2003 UTC (20 years, 7 months ago) by benhur
Branch: MAIN
Changes since 1.289: +5 -19 lines
Set frame to autosaved frame in defaults

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

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