summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Fl.cxx23
-rw-r--r--src/Fl_Gl_Window.cxx12
-rw-r--r--src/Fl_cocoa.mm511
3 files changed, 234 insertions, 312 deletions
diff --git a/src/Fl.cxx b/src/Fl.cxx
index e800d79e7..a08b095ec 100644
--- a/src/Fl.cxx
+++ b/src/Fl.cxx
@@ -681,20 +681,13 @@ Fl_X* Fl_X::first;
Fl_Window* fl_find(Window xid) {
Fl_X *window;
for (Fl_X **pp = &Fl_X::first; (window = *pp); pp = &window->next)
-#if defined(WIN32) || defined(USE_X11)
- if (window->xid == xid)
-#elif defined(__APPLE_QUARTZ__)
- if (window->xid == xid && !window->w->window())
-#else
-# error unsupported platform
-#endif // __APPLE__
- {
+ if (window->xid == xid) {
if (window != Fl_X::first && !Fl::modal()) {
- // make this window be first to speed up searches
- // this is not done if modal is true to avoid messing up modal stack
- *pp = window->next;
- window->next = Fl_X::first;
- Fl_X::first = window;
+ // make this window be first to speed up searches
+ // this is not done if modal is true to avoid messing up modal stack
+ *pp = window->next;
+ window->next = Fl_X::first;
+ Fl_X::first = window;
}
return window->w;
}
@@ -1505,7 +1498,6 @@ void Fl_Window::hide() {
for (; *pp != ip; pp = &(*pp)->next) if (!*pp) return;
*pp = ip->next;
#ifdef __APPLE__
- ip->unlink();
// MacOS X manages a single pointer per application. Make sure that hiding
// a toplevel window will not leave us with some random pointer shape, or
// worst case, an invisible pointer
@@ -1556,7 +1548,7 @@ void Fl_Window::hide() {
}
#elif defined(__APPLE_QUARTZ__)
Fl_X::q_release_context(ip);
- if ( ip->xid == fl_window && !parent() )
+ if ( ip->xid == fl_window )
fl_window = 0;
#endif
@@ -1584,6 +1576,7 @@ void Fl_Window::hide() {
if (count) delete[] doit;
#elif defined(__APPLE_QUARTZ__)
ip->destroy();
+ delete ip->subRect;
#else
# error unsupported platform
#endif
diff --git a/src/Fl_Gl_Window.cxx b/src/Fl_Gl_Window.cxx
index 7e97e3297..f23b8e2ab 100644
--- a/src/Fl_Gl_Window.cxx
+++ b/src/Fl_Gl_Window.cxx
@@ -180,16 +180,8 @@ void Fl_Gl_Window::make_current() {
// correct parent window size to work with...
GLint xywh[4];
- if (window()) {
- int xoff,yoff;
- const Fl_Window *win = top_window_offset(xoff, yoff); // STR #2944 [2]
- xywh[0] = xoff;
- xywh[1] = win->h() - yoff - h();
- } else {
- xywh[0] = 0;
- xywh[1] = 0;
- }
-
+ xywh[0] = 0;
+ xywh[1] = 0;
xywh[2] = w();
xywh[3] = h();
diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm
index ff693c57e..2674899d4 100644
--- a/src/Fl_cocoa.mm
+++ b/src/Fl_cocoa.mm
@@ -88,7 +88,6 @@ extern int fl_send_system_handlers(void *e);
// converting cr lf converter function
static void convert_crlf(char * string, size_t len);
static void createAppleMenu(void);
-static Fl_Region MacRegionMinusRect(Fl_Region r, int x,int y,int w,int h);
static void cocoaMouseHandler(NSEvent *theEvent);
static int calc_mac_os_version();
static void clipboard_check(void);
@@ -96,6 +95,7 @@ static NSString *calc_utf8_format(void);
static void im_update(void);
static unsigned make_current_counts = 0; // if > 0, then Fl_Window::make_current() can be called only once
static Fl_X *fl_x_to_redraw = NULL; // set by Fl_X::flush() to the Fl_X object of the window to be redrawn
+static NSBitmapImageRep* rect_to_NSBitmapImageRep(Fl_Window *win, int x, int y, int w, int h);
Fl_Display_Device *Fl_Display_Device::_display = new Fl_Display_Device(new Fl_Quartz_Graphics_Driver); // the platform display
@@ -649,19 +649,11 @@ void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data)
@interface FLWindow : NSWindow {
Fl_Window *w;
- BOOL containsGLsubwindow;
}
- (FLWindow*)initWithFl_W:(Fl_Window *)flw
contentRect:(NSRect)rect
styleMask:(NSUInteger)windowStyle;
- (Fl_Window *)getFl_Window;
-/* These two functions allow to check if a window contains OpenGL-subwindows.
- This is useful only for Mac OS < 10.7 to repair a problem apparent with the "cube" test program:
- if the cube window is moved around rapidly (with OS < 10.7), the GL pixels leak away from where they should be.
- The repair is performed by [FLWindowDelegate windowDidMove:], only if OS < 10.7.
- */
-- (BOOL)containsGLsubwindow;
-- (void)containsGLsubwindow:(BOOL)contains;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
- (NSPoint)convertBaseToScreen:(NSPoint)aPoint;
#endif
@@ -691,7 +683,6 @@ void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data)
self = [super initWithContentRect:rect styleMask:windowStyle backing:NSBackingStoreBuffered defer:NO];
if (self) {
w = flw;
- containsGLsubwindow = NO;
if (fl_mac_os_version >= 100700) {
// replaces [self setRestorable:NO] that may trigger a compiler warning
typedef void (*setIMP)(id, SEL, BOOL);
@@ -705,22 +696,13 @@ void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data)
{
return w;
}
-- (BOOL)containsGLsubwindow
-{
- return containsGLsubwindow;
-}
-- (void)containsGLsubwindow:(BOOL)contains
-{
- containsGLsubwindow = contains;
-}
- (BOOL)canBecomeKeyWindow
{
if (Fl::modal_ && (Fl::modal_ != w))
return NO; // prevent the caption to be redrawn as active on click
// when another modal window is currently the key win
-
- return !(w->tooltip_window() || w->menu_window());
+ return !(w->tooltip_window() || w->menu_window() || w->parent());
}
- (BOOL)canBecomeMainWindow
@@ -729,7 +711,7 @@ void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data)
return NO; // prevent the caption to be redrawn as active on click
// when another modal window is currently the key win
- return !(w->tooltip_window() || w->menu_window());
+ return !(w->tooltip_window() || w->menu_window() || w->parent());
}
@end
@@ -1107,12 +1089,52 @@ static FLTextView *fltextview_instance = nil;
- (void)windowDidResignKey:(NSNotification *)notif;
- (void)windowDidBecomeKey:(NSNotification *)notif;
- (void)windowDidBecomeMain:(NSNotification *)notif;
+- (void)windowWillMiniaturize:(NSNotification *)notif;
- (void)windowDidDeminiaturize:(NSNotification *)notif;
- (void)windowDidMiniaturize:(NSNotification *)notif;
- (BOOL)windowShouldClose:(id)fl;
- (void)anyWindowWillClose:(NSNotification *)notif;
@end
+/* recursively set Cocoa's position and size of subwindows from their FLTK coords
+ */
+static void position_subwindows(Fl_Window *parent, BOOL is_a_move)
+{
+ FLWindow *xid = fl_xid(parent);
+ NSArray *children = [xid childWindows]; // 10.2
+ NSEnumerator *enumerator = [children objectEnumerator];
+ id child;
+ NSRect pframe = [xid frame];
+ while ((child = [enumerator nextObject]) != nil) {
+ NSRect rchild;
+ Fl_Window *sub = [child getFl_Window];
+ rchild.origin = NSMakePoint(pframe.origin.x + sub->x(), pframe.origin.y + parent->h() - (sub->h() + sub->y()));
+ rchild.size = NSMakeSize(sub->w(), sub->h());
+ [child setFrame:rchild display:YES];
+ position_subwindows(sub, is_a_move);
+ if (is_a_move && fl_mac_os_version < 100700) { // after move, redraw parent and children of GL windows
+ if (parent->as_gl_window()) [child display];
+ if (sub->as_gl_window()) [xid display];
+ }
+ }
+}
+
+/* make subwindows re-appear after appl unhide or window deminiaturize
+ (not necessary with 10.5 and above)
+ */
+static void orderfront_subwindows(FLWindow *xid)
+{
+ NSArray *children = [xid childWindows]; // 10.2
+ NSEnumerator *enumerator = [children objectEnumerator];
+ id child;
+ while ((child = [enumerator nextObject]) != nil) { // this undo-redo seems necessary under 10.3
+ [xid removeChildWindow:child];
+ [xid addChildWindow:child ordered:NSWindowAbove];
+ [child orderWindow:NSWindowAbove relativeTo:[xid windowNumber]];
+ orderfront_subwindows(child);
+ }
+}
+
@interface FLWindowDelegateBefore10_6 : FLWindowDelegate
- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)client;
@end
@@ -1123,12 +1145,35 @@ static FLTextView *fltextview_instance = nil;
}
@end
+@interface FLWindowDelegateBefore10_5 : FLWindowDelegateBefore10_6
+-(void)windowDidDeminiaturize:(NSNotification *)notif;
+-(void)windowWillMiniaturize:(NSNotification *)notif;
+@end
+@implementation FLWindowDelegateBefore10_5
+-(void)windowDidDeminiaturize:(NSNotification *)notif
+{
+ [super windowDidDeminiaturize:notif];
+ fl_lock_function();
+ orderfront_subwindows([notif object]);
+ fl_unlock_function();
+}
+-(void)windowWillMiniaturize:(NSNotification *)notif
+{
+ [super windowWillMiniaturize:notif];
+ NSArray *children = [(NSWindow*)[notif object] childWindows]; // 10.2
+ NSEnumerator *enumerator = [children objectEnumerator];
+ id child;
+ while ((child = [enumerator nextObject]) != nil) [child orderOut:self];
+}
+@end
+
static FLWindowDelegate *flwindowdelegate_instance = nil;
@implementation FLWindowDelegate
+ (void)initialize
{
if (self == [FLWindowDelegate self]) {
- if (fl_mac_os_version < 100600) flwindowdelegate_instance = [FLWindowDelegateBefore10_6 alloc];
+ if (fl_mac_os_version < 100500) flwindowdelegate_instance = [FLWindowDelegateBefore10_5 alloc];
+ else if (fl_mac_os_version < 100600) flwindowdelegate_instance = [FLWindowDelegateBefore10_6 alloc];
else flwindowdelegate_instance = [FLWindowDelegate alloc];
flwindowdelegate_instance = [flwindowdelegate_instance init];
}
@@ -1141,16 +1186,14 @@ static FLWindowDelegate *flwindowdelegate_instance = nil;
fl_lock_function();
FLWindow *nsw = (FLWindow*)[notif object];
Fl_Window *window = [nsw getFl_Window];
- NSPoint pt, pt2;
- pt.x = 0;
- pt.y = [[nsw contentView] frame].size.height;
- pt2 = [nsw convertBaseToScreen:pt];
- update_e_xy_and_e_xy_root(nsw);
- resize_from_system = window;
- window->position((int)pt2.x, (int)(main_screen_height - pt2.y));
- if ([nsw containsGLsubwindow] && fl_mac_os_version < 100700) {
- [nsw display];// with OS < 10.7, redraw window after moving if it contains OpenGL subwindows
- }
+ if (!window->parent()) {
+ NSPoint pt2;
+ pt2 = [nsw convertBaseToScreen:NSMakePoint(0, [[nsw contentView] frame].size.height)];
+ update_e_xy_and_e_xy_root(nsw);
+ resize_from_system = NULL;
+ window->position((int)pt2.x, (int)(main_screen_height - pt2.y));
+ position_subwindows(window, YES);
+ }
fl_unlock_function();
}
- (void)windowDidResize:(NSNotification *)notif
@@ -1158,17 +1201,16 @@ static FLWindowDelegate *flwindowdelegate_instance = nil;
fl_lock_function();
FLWindow *nsw = (FLWindow*)[notif object];
Fl_Window *window = [nsw getFl_Window];
- NSRect r = [[nsw contentView] frame];
- NSPoint pt, pt2;
- pt.x = 0;
- pt.y = [[nsw contentView] frame].size.height;
- pt2 = [nsw convertBaseToScreen:pt];
- resize_from_system = window;
- update_e_xy_and_e_xy_root(nsw);
- window->resize((int)pt2.x,
- (int)(main_screen_height - pt2.y),
- (int)r.size.width,
- (int)r.size.height);
+ NSRect r; NSPoint pt2;
+ if (!window->parent()) {
+ r = [[nsw contentView] frame];
+ pt2 = [nsw convertBaseToScreen:NSMakePoint(0, [[nsw contentView] frame].size.height)];
+ pt2.y = main_screen_height - pt2.y;
+ resize_from_system = window;
+ update_e_xy_and_e_xy_root(nsw);
+ window->resize((int)pt2.x, (int)pt2.y, (int)r.size.width, (int)r.size.height);
+ position_subwindows(window, NO);
+ }
fl_unlock_function();
}
- (void)windowDidResignKey:(NSNotification *)notif
@@ -1195,7 +1237,7 @@ static FLWindowDelegate *flwindowdelegate_instance = nil;
[nsw setLevel:NSStatusWindowLevel];
fixup_window_levels();
}
- if ( w->border() || (!w->modal() && !w->tooltip_window()) ) Fl::handle( FL_FOCUS, w);
+ Fl::handle( FL_FOCUS, w);
fl_unlock_function();
}
- (void)windowDidBecomeMain:(NSNotification *)notif
@@ -1216,6 +1258,22 @@ static FLWindowDelegate *flwindowdelegate_instance = nil;
update_e_xy_and_e_xy_root(nsw);
fl_unlock_function();
}
+- (void)windowWillMiniaturize:(NSNotification *)notif
+{
+ // subwindows are not captured in system-built miniature window image
+ fl_lock_function();
+ FLWindow *nsw = (FLWindow*)[notif object];
+ if ([nsw childWindows]) {
+ // capture the window and its subwindows and use as miniature window image
+ Fl_Window *window = [nsw getFl_Window];
+ NSBitmapImageRep *bitmap = rect_to_NSBitmapImageRep(window, 0, 0, window->w(), window->h());
+ NSImage *img = [[[NSImage alloc] initWithSize:NSMakeSize([bitmap pixelsWide], [bitmap pixelsHigh])] autorelease];
+ [img addRepresentation:bitmap];
+ [bitmap release];
+ [nsw setMiniwindowImage:img];
+ }
+ fl_unlock_function();
+}
- (void)windowDidMiniaturize:(NSNotification *)notif
{
fl_lock_function();
@@ -1417,6 +1475,22 @@ static FLWindowDelegate *flwindowdelegate_instance = nil;
}
@end
+@interface FLAppDelegateBefore10_5 : FLAppDelegate
+- (void)applicationDidUnhide:(NSNotification *)notify;
+@end
+@implementation FLAppDelegateBefore10_5
+- (void)applicationDidUnhide:(NSNotification *)notify
+{ // before 10.5, subwindows are lost when application is unhidden
+ fl_lock_function();
+ for (Fl_X *x = Fl_X::first; x; x = x->next) {
+ if (![x->xid parentWindow]) {
+ orderfront_subwindows(x->xid);
+ }
+ }
+ fl_unlock_function();
+}
+@end
+
/*
* Install an open documents event handler...
*/
@@ -1484,7 +1558,8 @@ void fl_open_display() {
if (need_new_nsapp) [NSApplication sharedApplication];
NSAutoreleasePool *localPool;
localPool = [[NSAutoreleasePool alloc] init]; // never released
- [(NSApplication*)NSApp setDelegate:[[FLAppDelegate alloc] init]];
+ FLAppDelegate *delegate = (fl_mac_os_version < 100500 ? [FLAppDelegateBefore10_5 alloc] : [FLAppDelegate alloc]);
+ [(NSApplication*)NSApp setDelegate:[delegate init]];
if (need_new_nsapp) [NSApp finishLaunching];
// empty the event queue but keep system events for drag&drop of files at launch
@@ -1531,8 +1606,8 @@ void fl_open_display() {
/* support of Mac OS 10.2 or earlier used this undocumented call instead
err = CPSEnableForegroundOperation(&cur_psn, 0x03, 0x3C, 0x2C, 0x1103);
*/
- [NSApp activateIgnoringOtherApps:YES];
}
+ [NSApp activateIgnoringOtherApps:YES];
}
if (![NSApp servicesMenu]) createAppleMenu();
main_screen_height = [[[NSScreen screens] objectAtIndex:0] frame].size.height;
@@ -1702,18 +1777,6 @@ static void handleUpdateEvent( Fl_Window *window )
i->region = 0;
}
- for ( Fl_X *cx = i->xidChildren; cx; cx = cx->xidNext ) {
- if ( cx->region ) {
- XDestroyRegion(cx->region);
- cx->region = 0;
- }
- cx->w->clear_damage(FL_DAMAGE_ALL);
- CGContextRef gc = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
- CGContextSaveGState(gc); // save original context
- cx->flush();
- CGContextRestoreGState(gc); // restore original context
- cx->w->clear_damage();
- }
window->clear_damage(FL_DAMAGE_ALL);
i->flush();
window->clear_damage();
@@ -1741,6 +1804,8 @@ int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by)
W = w->w()+dx;
H = w->h()+dy;
+ if (w->parent()) return 0;
+
// Proceed to positioning the window fully inside the screen, if possible
// let's get a little elaborate here. Mac OS X puts a lot of stuff on the desk
@@ -2167,7 +2232,6 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
prevMods = mods;
}
mods_to_e_state( mods );
- while (window->parent()) window = window->window();
if (sendEvent) Fl::handle(sendEvent,window);
fl_unlock_function();
}
@@ -2535,54 +2599,34 @@ void Fl_X::flush()
fl_x_to_redraw = NULL;
}
-//bool Fl_X::make_shaped = false;
+
+static void set_subwindow_frame(Fl_Window *w) { // maps a subwindow at its correct position/size
+ FLWindow *xid = fl_xid(w);
+ Fl_Window *parent = w->window();
+ FLWindow *pxid = fl_xid(parent);
+ if (!pxid) return;
+ NSRect rp = [pxid frame];
+ // subwindow coordinates are in screen units from bottom just like all windows
+ rp.origin = NSMakePoint(rp.origin.x + w->x(), rp.origin.y + parent->h() - w->y() - w->h());
+ rp.size = NSMakeSize(w->w(), w->h());
+ [xid setFrame:rp display:YES];
+ [pxid addChildWindow:xid ordered:NSWindowAbove]; // needs OS X 10.2
+ [xid orderWindow:NSWindowAbove relativeTo:[pxid windowNumber]]; // necessary under 10.3
+}
/*
* go ahead, create that (sub)window
*/
void Fl_X::make(Fl_Window* w)
{
- if ( w->parent() ) { // create a subwindow
- Fl_Group::current(0);
- // our subwindow needs this structure to know about its clipping.
- Fl_X* x = new Fl_X;
- x->subwindow = true;
- x->other_xid = 0;
- x->region = 0;
- x->subRegion = 0;
- x->cursor = NULL;
- x->gc = 0; // stay 0 for Quickdraw; fill with CGContext for Quartz
- w->set_visible();
- Fl_Window *win = w->window();
- Fl_X *xo = Fl_X::i(win);
- if (xo) {
- x->xidNext = xo->xidChildren;
- x->xidChildren = 0L;
- xo->xidChildren = x;
- x->xid = win->i->xid;
- x->w = w; w->i = x;
- x->wait_for_expose = 0;
- {
- Fl_X *z = xo->next; // we don't want a subwindow in Fl_X::first
- xo->next = x;
- x->next = z;
- }
- int old_event = Fl::e_number;
- w->handle(Fl::e_number = FL_SHOW);
- Fl::e_number = old_event;
- w->redraw(); // force draw to happen
- }
- if (w->as_gl_window()) { // if creating a sub-GL-window
- while (win->window()) win = win->window();
- [Fl_X::i(win)->xid containsGLsubwindow:YES];
- }
- fl_show_iconic = 0;
- }
- else { // create a desktop window
Fl_Group::current(0);
fl_open_display();
NSInteger winlevel = NSNormalWindowLevel;
NSUInteger winstyle;
+ if (w->parent()) {
+ w->border(0);
+ fl_show_iconic = 0;
+ }
if (w->border()) winstyle = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask;
else winstyle = NSBorderlessWindowMask;
int xp = w->x();
@@ -2599,7 +2643,7 @@ void Fl_X::make(Fl_Window* w)
int minw = o->w(); if (minw > 100) minw = 100;
int minh = o->h(); if (minh > 100) minh = 100;
w->size_range(w->w() - o->w() + minw, w->h() - o->h() + minh, 0, 0);
- if (w->border()) winstyle |= NSResizableWindowMask;
+ if (w->border()) winstyle |= NSResizableWindowMask;
} else {
w->size_range(w->w(), w->h(), w->w(), w->h());
}
@@ -2611,11 +2655,9 @@ void Fl_X::make(Fl_Window* w)
if (w->modal()||w->tooltip_window()) {
winlevel = modal_window_level();
}
- //winstyle = NSBorderlessWindowMask;
- }
+ }
if (w->modal()) {
winstyle &= ~NSMiniaturizableWindowMask;
- // winstyle &= ~(NSResizableWindowMask | NSMiniaturizableWindowMask);
winlevel = modal_window_level();
}
else if (w->non_modal()) {
@@ -2634,21 +2676,12 @@ void Fl_X::make(Fl_Window* w)
xp -= bx;
yp -= by+bt;
}
-
- if (w->non_modal() && Fl_X::first /*&& !fl_disable_transient_for*/) {
- // find some other window to be "transient for":
- Fl_Window* w = Fl_X::first->w;
- while (w->parent()) w = w->window(); // todo: this code does not make any sense! (w!=w??)
- }
-
+
Fl_X* x = new Fl_X;
- x->subwindow = false;
x->other_xid = 0; // room for doublebuffering image map. On OS X this is only used by overlay windows
x->region = 0;
- x->subRegion = 0;
+ x->subRect = 0;
x->cursor = NULL;
- x->xidChildren = 0;
- x->xidNext = 0;
x->gc = 0;
NSRect crect;
@@ -2682,7 +2715,7 @@ void Fl_X::make(Fl_Window* w)
winstyle = NSBorderlessWindowMask;
winlevel = NSStatusWindowLevel;
}
- crect.origin.x = w->x();
+ crect.origin.x = w->x(); // correct origin set later for subwindows
crect.origin.y = main_screen_height - (w->y() + w->h());
crect.size.width=w->w();
crect.size.height=w->h();
@@ -2690,7 +2723,7 @@ void Fl_X::make(Fl_Window* w)
contentRect:crect
styleMask:winstyle];
[cw setFrameOrigin:crect.origin];
- [cw setHasShadow:YES];
+ if (!w->parent()) [cw setHasShadow:YES];
[cw setAcceptsMouseMovedEvents:YES];
if (w->shape_data_) {
[cw setOpaque:NO]; // shaped windows must be non opaque
@@ -2699,8 +2732,17 @@ void Fl_X::make(Fl_Window* w)
x->xid = cw;
x->w = w; w->i = x;
x->wait_for_expose = 1;
- x->next = Fl_X::first;
- Fl_X::first = x;
+ if (!w->parent()) {
+ x->next = Fl_X::first;
+ Fl_X::first = x;
+ } else if (Fl_X::first) {
+ x->next = Fl_X::first->next;
+ Fl_X::first->next = x;
+ }
+ else {
+ x->next = NULL;
+ Fl_X::first = x;
+ }
FLView *myview = [[FLViewThisOS alloc] init];
[cw setContentView:myview];
[myview release];
@@ -2722,11 +2764,7 @@ void Fl_X::make(Fl_Window* w)
}
// Install DnD handlers
[myview registerForDraggedTypes:[NSArray arrayWithObjects:utf8_format, NSFilenamesPboardType, nil]];
- if ( ! Fl_X::first->next ) {
- // if this is the first window, we need to bring the application to the front
- [NSApp activateIgnoringOtherApps:YES];
- }
-
+
if (w->size_range_set) w->size_range_();
if ( w->border() || (!w->modal() && !w->tooltip_window()) ) {
@@ -2737,28 +2775,36 @@ void Fl_X::make(Fl_Window* w)
w->set_visible();
if ( w->border() || (!w->modal() && !w->tooltip_window()) ) Fl::handle(FL_FOCUS, w);
- Fl::first_window(w);
+ if (!w->parent()) Fl::first_window(w);
[cw setDelegate:[FLWindowDelegate singleInstance]];
if (fl_show_iconic) {
fl_show_iconic = 0;
[cw miniaturize:nil];
+ } else if (w->parent()) {
+ set_subwindow_frame(w);
} else {
[cw makeKeyAndOrderFront:nil];
}
- crect = [[cw contentView] frame];
- w->w(int(crect.size.width));
- w->h(int(crect.size.height));
- crect = [cw frame];
- w->x(int(crect.origin.x));
- w->y(int(main_screen_height - (crect.origin.y + w->h())));
+ if (w->parent()) {
+ [cw setIgnoresMouseEvents:YES]; // needs OS X 10.2
+ // next 2 statements so a subwindow doesn't leak out of its parent window
+ [cw setOpaque:NO];
+ [cw setBackgroundColor:[NSColor clearColor]]; // transparent background color
+ } else {
+ crect = [[cw contentView] frame];
+ w->w(int(crect.size.width));
+ w->h(int(crect.size.height));
+ crect = [cw frame];
+ w->x(int(crect.origin.x));
+ w->y(int(main_screen_height - (crect.origin.y + w->h())));
+ }
int old_event = Fl::e_number;
w->handle(Fl::e_number = FL_SHOW);
Fl::e_number = old_event;
// if (w->modal()) { Fl::modal_ = w; fl_fix_focus(); }
- }
}
@@ -2853,7 +2899,7 @@ void Fl_Window::resize(int X,int Y,int W,int H) {
resize_from_system = 0;
return;
}
- if ( (resize_from_system!=this) && (!parent()) && shown()) {
+ if ( (resize_from_system!=this) && shown()) {
if (is_a_resize) {
if (resizable()) {
if (W<minw) minw = W; // user request for resize takes priority
@@ -2864,20 +2910,29 @@ void Fl_Window::resize(int X,int Y,int W,int H) {
} else {
size_range(W, H, W, H);
}
- int bx, by, bt;
- if ( ! this->border() ) bt = 0;
- else get_window_frame_sizes(bx, by, bt);
- NSRect dim;
- dim.origin.x = X;
- dim.origin.y = main_screen_height - (Y + H);
- dim.size.width = W;
- dim.size.height = H + bt;
- [i->xid setFrame:dim display:YES]; // calls windowDidResize
+ Fl_Group::resize(X,Y,W,H);
+ // make sure that subwindows of this window don't leak out of their parent window
+ NSArray *children = [fl_xid(this) childWindows]; // 10.2
+ NSEnumerator *enumerator = [children objectEnumerator];
+ id child;
+ while ((child = [enumerator nextObject]) != nil) {
+ [[(FLWindow*)child contentView] setNeedsDisplay:YES];
+ Fl_Window *childw = [child getFl_Window];
+ CGRect prect = CGRectMake(0, 0, w(), h());
+ CGRect srect = CGRectMake(childw->x(), childw->y(), childw->w(), childw->h());
+ CGRect **active = &(Fl_X::i(childw)->subRect);
+ delete *active;
+ *active = NULL;
+ if (!CGRectContainsRect(prect, srect)) { // if subwindow extends outside its parent window
+ CGRect clip = CGRectIntersection(prect, srect);
+ clip = CGRectOffset(clip, -childw->x(), -childw->y());
+ clip = fl_cgrectmake_cocoa(clip.origin.x, clip.origin.y, clip.size.width, clip.size.height);
+ *active = new CGRect(clip);
+ }
+ }
+
} else {
- NSPoint pt;
- pt.x = X;
- pt.y = main_screen_height - (Y + h());
- [i->xid setFrameOrigin:pt]; // calls windowDidMove
+ x(X); y(Y);
}
return;
}
@@ -2927,28 +2982,10 @@ void Fl_Window::make_current()
fl_window = i->xid;
current_ = this;
- int xp = 0, yp = 0;
- Fl_Window *win = this;
- while ( win ) {
- if ( !win->window() )
- break;
- xp += win->x();
- yp += win->y();
- win = (Fl_Window*)win->window();
- }
- NSGraphicsContext *nsgc = through_drawRect ? [NSGraphicsContext currentContext] :
+ NSGraphicsContext *nsgc = through_drawRect ? [NSGraphicsContext currentContext] :
[NSGraphicsContext graphicsContextWithWindow:fl_window];
i->gc = (CGContextRef)[nsgc graphicsPort];
fl_gc = i->gc;
- Fl_Region fl_window_region = XRectangleRegion(0,0,w(),h());
- if ( ! this->window() ) {
- for ( Fl_X *cx = i->xidChildren; cx; cx = cx->xidNext ) { // clip-out all sub-windows
- Fl_Window *cw = cx->w;
- Fl_Region from = fl_window_region;
- fl_window_region = MacRegionMinusRect(from, cw->x(), cw->y(), cw->w(), cw->h() );
- XDestroyRegion(from);
- }
- }
// antialiasing must be deactivated because it applies to rectangles too
// and escapes even clipping!!!
@@ -2957,16 +2994,11 @@ void Fl_Window::make_current()
CGFloat hgt = [[fl_window contentView] frame].size.height;
CGContextTranslateCTM(fl_gc, 0.5, hgt-0.5f);
CGContextScaleCTM(fl_gc, 1.0f, -1.0f); // now 0,0 is top-left point of the window
- win = this;
- while(win && win->window()) { // translate to subwindow origin if this is a subwindow context
- CGContextTranslateCTM(fl_gc, win->x(), win->y());
- win = win->window();
- }
- //apply window's clip
- CGContextClipToRects(fl_gc, fl_window_region->rects, fl_window_region->count );
- XDestroyRegion(fl_window_region);
-// this is the context with origin at top left of (sub)window clipped out of its subwindows if any
- CGContextSaveGState(fl_gc);
+ // for subwindows, limit drawing to inside of parent window
+ if (i->subRect) CGContextClipToRect(fl_gc, *(i->subRect));
+
+// this is the context with origin at top left of (sub)window
+ CGContextSaveGState(fl_gc);
#if defined(FLTK_USE_CAIRO)
if (Fl::cairo_autolink_context()) Fl::cairo_make_current(this); // capture gc changes automatically to update the cairo context adequately
#endif
@@ -3296,60 +3328,19 @@ int Fl::clipboard_contains(const char *type) {
return found != nil;
}
-int Fl_X::unlink(Fl_X *start) {
- if (start) {
- Fl_X *pc = start;
- while (pc) {
- if (pc->xidNext == this) {
- pc->xidNext = xidNext;
- return 1;
- }
- if (pc->xidChildren) {
- if (pc->xidChildren == this) {
- pc->xidChildren = xidNext;
- return 1;
- }
- if (unlink(pc->xidChildren))
- return 1;
- }
- pc = pc->xidNext;
- }
- } else {
- for ( Fl_X *pc = Fl_X::first; pc; pc = pc->next ) {
- if (unlink(pc))
- return 1;
- }
- }
- return 0;
-}
-
-void Fl_X::relink(Fl_Window *w, Fl_Window *wp) {
- Fl_X *x = Fl_X::i(w);
- Fl_X *p = Fl_X::i(wp);
- if (!x || !p) return;
- // first, check if 'x' is already registered as a child of 'p'
- for (Fl_X *i = p->xidChildren; i; i=i->xidNext) {
- if (i == x) return;
- }
- // now add 'x' as the first child of 'p'
- x->xidNext = p->xidChildren;
- p->xidChildren = x;
-}
-
void Fl_X::destroy() {
- // subwindows share their xid with their parent window, so should not close it
- if (!subwindow && w && !w->parent() && xid) {
+ if (xid) {
[xid close];
}
}
void Fl_X::map() {
- if (w && xid) {
- [xid orderFront:nil];
+ if (w && xid && ![xid parentWindow]) { // 10.2
+ // after a subwindow has been unmapped, it has lost its parent window and its frame may be wrong
+ set_subwindow_frame(w);
}
//+ link to window list
if (w && w->parent()) {
- Fl_X::relink(w, w->window() );
w->redraw();
}
if (cursor) {
@@ -3359,58 +3350,10 @@ void Fl_X::map() {
}
void Fl_X::unmap() {
- if (w && !w->parent() && xid) {
+ if (w && xid) {
+ if (w->parent()) [[xid parentWindow] removeChildWindow:xid]; // necessary with at least 10.5
[xid orderOut:nil];
}
- if (w && Fl_X::i(w))
- Fl_X::i(w)->unlink();
-}
-
-
-// removes x,y,w,h rectangle from region r and returns result as a new Fl_Region
-static Fl_Region MacRegionMinusRect(Fl_Region r, int x,int y,int w,int h)
-{
- Fl_Region outr = (Fl_Region)malloc(sizeof(*outr));
- outr->rects = (CGRect*)malloc(4 * r->count * sizeof(CGRect));
- outr->count = 0;
- CGRect rect = fl_cgrectmake_cocoa(x, y, w, h);
- for( int i = 0; i < r->count; i++) {
- CGRect A = r->rects[i];
- CGRect test = CGRectIntersection(A, rect);
- if (CGRectIsEmpty(test)) {
- outr->rects[(outr->count)++] = A;
- }
- else {
- const CGFloat verylarge = 100000.;
- CGRect side = CGRectMake(0,0,rect.origin.x,verylarge);// W side
- test = CGRectIntersection(A, side);
- if ( ! CGRectIsEmpty(test)) {
- outr->rects[(outr->count)++] = test;
- }
- side = CGRectMake(0,rect.origin.y + rect.size.height,verylarge,verylarge);// N side
- test = CGRectIntersection(A, side);
- if ( ! CGRectIsEmpty(test)) {
- outr->rects[(outr->count)++] = test;
- }
- side = CGRectMake(rect.origin.x + rect.size.width, 0, verylarge, verylarge);// E side
- test = CGRectIntersection(A, side);
- if ( ! CGRectIsEmpty(test)) {
- outr->rects[(outr->count)++] = test;
- }
- side = CGRectMake(0, 0, verylarge, rect.origin.y);// S side
- test = CGRectIntersection(A, side);
- if ( ! CGRectIsEmpty(test)) {
- outr->rects[(outr->count)++] = test;
- }
- }
- }
- if (outr->count == 0) {
- free(outr->rects);
- free(outr);
- outr = XRectangleRegion(0,0,0,0);
- }
- else outr->rects = (CGRect*)realloc(outr->rects, outr->count * sizeof(CGRect));
- return outr;
}
// intersects current and x,y,w,h rectangle and returns result as a new Fl_Region
@@ -3454,8 +3397,7 @@ static NSImage *CGBitmapContextToNSImage(CGContextRef c)
else
#endif
{
- unsigned char *pdata = (unsigned char *)CGBitmapContextGetData(c);
- NSBitmapImageRep *imagerep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&pdata
+ NSBitmapImageRep *imagerep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:CGBitmapContextGetWidth(c)
pixelsHigh:CGBitmapContextGetHeight(c)
bitsPerSample:8
@@ -3465,7 +3407,9 @@ static NSImage *CGBitmapContextToNSImage(CGContextRef c)
colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:CGBitmapContextGetBytesPerRow(c)
bitsPerPixel:CGBitmapContextGetBitsPerPixel(c)];
- image = [[NSImage alloc] initWithData: [imagerep TIFFRepresentation]];
+ memcpy([imagerep bitmapData], CGBitmapContextGetData(c), [imagerep bytesPerRow] * [imagerep pixelsHigh]);
+ image = [[NSImage alloc] initWithSize:NSMakeSize([imagerep pixelsWide], [imagerep pixelsHigh])];
+ [image addRepresentation:imagerep];
[imagerep release];
}
return [image autorelease];
@@ -3598,6 +3542,7 @@ int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
int w, h, ww, wh;
Fl_Window *win = Fl::first_window();
if(!win) return;
+ if (win->parent()) win = win->top_window();
if( printer.start_job(1) ) return;
if( printer.start_page() ) return;
fl_lock_function();
@@ -3878,11 +3823,6 @@ static CGImageRef GL_rect_to_CGImage(Fl_Window *win, int x, int y, int w, int h)
// win is really a Fl_Gl_Window*
{
CGRect rect;
- while (win->window()) {
- x += win->x();
- y += win->y();
- win = win->window();
- }
NSRect r = [fl_xid(win) frame];
rect = CGRectMake(r.origin.x + x, r.origin.y + win->h() - (y + h), w, h); // rect is target rect in window coordinates
// convert r to global display coordinates
@@ -3904,7 +3844,7 @@ static void imgProviderReleaseData (void *info, const void *data, size_t size)
}
-CGImageRef GL_rect_to_CGImage_10_5(Fl_Window *win, int x, int y, int w, int h)
+static CGImageRef GL_rect_to_CGImage_10_5(Fl_Window *win, int x, int y, int w, int h)
// captures a rectangle from a GL window and returns it as a CGImageRef
// used with Mac OS X 10.5 and before
// win is really a Fl_Gl_Window*
@@ -3971,11 +3911,6 @@ static NSBitmapImageRep* rect_to_NSBitmapImageRep(Fl_Window *win, int x, int y,
if (win->as_gl_window() && y >= 0) {
bitmap = GL_rect_to_nsbitmap(win, x, y, w, h);
} else {
- while (win->window()) {
- x += win->x();
- y += win->y();
- win = win->window();
- }
NSView *winview = nil;
if ( through_drawRect && Fl_Window::current() == win ) {
CGFloat epsilon = 0;
@@ -3994,10 +3929,12 @@ static NSBitmapImageRep* rect_to_NSBitmapImageRep(Fl_Window *win, int x, int y,
if (!bitmap) return nil;
}
- // it's necessary to capture also GL subwindows
- for (Fl_X *flx = Fl_X::i(win)->xidChildren; flx; flx = flx->xidNext) {
- Fl_Window *sub = flx->w;
- if (!sub->as_gl_window() ) continue;
+ // capture also subwindows
+ NSArray *children = [fl_xid(win) childWindows]; // 10.2
+ NSEnumerator *enumerator = [children objectEnumerator];
+ id child;
+ while ((child = [enumerator nextObject]) != nil) {
+ Fl_Window *sub = [(FLWindow*)child getFl_Window];
CGRect rsub = CGRectMake(sub->x(), win->h() -(sub->y()+sub->h()), sub->w(), sub->h());
CGRect clip = CGRectMake(x, win->h()-(y+h), w, h);
clip = CGRectIntersection(rsub, clip);
@@ -4014,8 +3951,8 @@ static NSBitmapImageRep* rect_to_NSBitmapImageRep(Fl_Window *win, int x, int y,
unsigned char *Fl_X::bitmap_from_window_rect(Fl_Window *win, int x, int y, int w, int h, int *bytesPerPixel)
/* Returns a capture of a rectangle of a mapped window as a pre-multiplied RGBA array of bytes.
Alpha values are always 1 (except for the angles of a window title bar)
- so pre-multiplication can be ignored.
- *bytesPerPixel is always set to the value 4 upon return.
+ so pre-multiplication can be ignored.
+ *bytesPerPixel is set to the value 3 or 4 upon return.
delete[] the returned pointer after use
*/
{