diff options
| author | Manolo Gouy <Manolo> | 2011-09-29 16:04:24 +0000 |
|---|---|---|
| committer | Manolo Gouy <Manolo> | 2011-09-29 16:04:24 +0000 |
| commit | d9cda5c3aa48da9ef3238d993b34cde7047175d8 (patch) | |
| tree | 751d1c5daa9c837444e53a2ed955dcfb2c6c302f /src/Fl_cocoa.mm | |
| parent | bc1b17056a44af5890cb2b5ec56cf9fbb72ccea4 (diff) | |
Fix STR#2695 & 2697: correct computation of work areas with multiple screens.
This introduces 3 new functions
static void Fl::screen_work_area(X,Y,W,H)
static void Fl::screen_work_area(X,Y,W,H,mx,my)
static void Fl::screen_work_area(X,Y,W,H,screen_no)
that compute screen work areas and are used by FLTK to position menu windows.
The Fl::x(),y(),w(),h() functions are made consistent across platforms: they return
the origin/size of the work area of the main screen (as far as possible, see below).
On the Mac OS platform, all screen functions reflect changes in screen number and
positions without requiring the application to restart.
On the X11 platform, I did not find an API to compute the main screen work area
in all conditions. What's used does compute the correct work area when there's
a single screen, but not when there are several, because it returns an area that
encompasses all screens. The implemented workaround is that Fl::x(),y(),w(),h()
and Fl::screen_work_area(X,Y,W,H,0) return the exact work area when there's
a single screen, and return the full screen area when there are several.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@9084 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/Fl_cocoa.mm')
| -rw-r--r-- | src/Fl_cocoa.mm | 118 |
1 files changed, 67 insertions, 51 deletions
diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm index c15730d45..801c848c2 100644 --- a/src/Fl_cocoa.mm +++ b/src/Fl_cocoa.mm @@ -109,6 +109,7 @@ int fl_mac_os_version = 0; // the version number of the running Mac OS X (e.g., // forward declarations of variables in this file static int got_events = 0; static Fl_Window* resize_from_system; +static int main_screen_height; // height of menubar-containing screen used to convert between Cocoa and FLTK global screen coordinates #if CONSOLIDATE_MOTION static Fl_Window* send_motion; @@ -675,6 +676,7 @@ double fl_mac_flush_and_wait(double time_to_wait, char in_idle) { return retval; } + // updates Fl::e_x, Fl::e_y, Fl::e_x_root, and Fl::e_y_root static void update_e_xy_and_e_xy_root(NSWindow *nsw) { @@ -684,7 +686,7 @@ static void update_e_xy_and_e_xy_root(NSWindow *nsw) Fl::e_y = int([[nsw contentView] frame].size.height - pt.y); pt = [NSEvent mouseLocation]; Fl::e_x_root = int(pt.x); - Fl::e_y_root = int([[nsw screen] frame].size.height - pt.y); + Fl::e_y_root = int(main_screen_height - pt.y); } /* @@ -902,16 +904,6 @@ void fl_open_callback(void (*cb)(const char *)) { } -/* - * initialize the Mac toolboxes, dock status, and set the default menubar - */ - -extern "C" { - extern OSErr CPSEnableForegroundOperation(ProcessSerialNumber *psn, UInt32 _arg2, - UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -} - - @interface FLDelegate : NSObject #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 <NSWindowDelegate, NSApplicationDelegate> @@ -929,6 +921,7 @@ extern "C" { - (void)anywindowwillclosenotif:(NSNotification *)notif; - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender; - (void)applicationDidBecomeActive:(NSNotification *)notify; +- (void)applicationDidChangeScreenParameters:(NSNotification *)aNotification; - (void)applicationWillResignActive:(NSNotification *)notify; - (void)applicationWillHide:(NSNotification *)notify; - (void)applicationWillUnhide:(NSNotification *)notify; @@ -946,7 +939,7 @@ extern "C" { pt.y = [[nsw contentView] frame].size.height; pt2 = [nsw convertBaseToScreen:pt]; update_e_xy_and_e_xy_root(nsw); - window->position((int)pt2.x, (int)([[nsw screen] frame].size.height - pt2.y)); + window->position((int)pt2.x, (int)(main_screen_height - pt2.y)); if ([nsw containsGLsubwindow] ) { [nsw display];// redraw window after moving if it contains OpenGL subwindows } @@ -965,7 +958,7 @@ extern "C" { resize_from_system = window; update_e_xy_and_e_xy_root(nsw); window->resize((int)pt2.x, - (int)([[nsw screen] frame].size.height - pt2.y), + (int)(main_screen_height - pt2.y), (int)r.size.width, (int)r.size.height); fl_unlock_function(); @@ -1092,6 +1085,21 @@ extern "C" { } fl_unlock_function(); } +- (void)applicationDidChangeScreenParameters:(NSNotification *)unused +{ // react to changes in screen numbers and positions + main_screen_height = [[[NSScreen screens] objectAtIndex:0] frame].size.height; + Fl_X::mac_screen_init(); + // FLTK windows have already been notified they were moved, + // but they had the old main_screen_height, so they must be notified again. + NSArray *windows = [NSApp windows]; + int count = [windows count]; + for (int i = 0; i < count; i++) { + NSWindow *win = [windows objectAtIndex:i]; + if ([win isKindOfClass:[FLWindow class]]) { + [[NSNotificationCenter defaultCenter] postNotificationName:NSWindowDidMoveNotification object:win]; + } + } +} - (void)applicationWillResignActive:(NSNotification *)notify { fl_lock_function(); @@ -1213,7 +1221,10 @@ extern "C" { } @end -static FLDelegate *mydelegate; +extern "C" { + OSErr CPSEnableForegroundOperation(ProcessSerialNumber *psn, UInt32 _arg2, + UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); +} void fl_open_display() { static char beenHereDoneThat = 0; @@ -1224,8 +1235,7 @@ void fl_open_display() { if (need_new_nsapp) [NSApplication sharedApplication]; NSAutoreleasePool *localPool; localPool = [[NSAutoreleasePool alloc] init]; // never released - mydelegate = [[FLDelegate alloc] init]; - [NSApp setDelegate:mydelegate]; + [NSApp setDelegate:[[FLDelegate alloc] init]]; if (need_new_nsapp) [NSApp finishLaunching]; // empty the event queue but keep system events for drag&drop of files at launch @@ -1266,17 +1276,12 @@ void fl_open_display() { // both TransformProcessType and CPSEnableForegroundOperation, the following // conditional code compiled on 10.2 will still work on newer releases... OSErr err; -#if __LP64__ - err = TransformProcessType(&cur_psn, kProcessTransformToForegroundApplication); -#else - -#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 if (TransformProcessType != NULL) { err = TransformProcessType(&cur_psn, kProcessTransformToForegroundApplication); } else -#endif // MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 err = CPSEnableForegroundOperation(&cur_psn, 0x03, 0x3C, 0x2C, 0x1103); -#endif // __LP64__ if (err == noErr) { SetFrontProcess( &cur_psn ); } @@ -1285,10 +1290,11 @@ void fl_open_display() { if (![NSApp servicesMenu]) createAppleMenu(); fl_system_menu = [NSApp mainMenu]; - [[NSNotificationCenter defaultCenter] addObserver:mydelegate + [[NSNotificationCenter defaultCenter] addObserver:[NSApp delegate] selector:@selector(anywindowwillclosenotif:) name:NSWindowWillCloseNotification object:nil]; + [[NSNotificationCenter defaultCenter] postNotificationName:NSApplicationDidChangeScreenParametersNotification object:NSApp]; } } @@ -1319,38 +1325,46 @@ static void get_window_frame_sizes(int &bx, int &by, int &bt) { } /* - * smallest x ccordinate in screen space + * smallest x coordinate in screen space of work area of menubar-containing display */ int Fl::x() { - return int([[NSScreen mainScreen] visibleFrame].origin.x); + return int([[[NSScreen screens] objectAtIndex:0] visibleFrame].origin.x); } /* - * smallest y coordinate in screen space + * smallest y coordinate in screen space of work area of menubar-containing display */ int Fl::y() { - NSRect all = [[NSScreen mainScreen] frame]; - NSRect visible = [[NSScreen mainScreen] visibleFrame]; - return int(all.size.height - (visible.origin.y + visible.size.height)); + NSRect visible = [[[NSScreen screens] objectAtIndex:0] visibleFrame]; + return int(main_screen_height - (visible.origin.y + visible.size.height)); } /* - * screen width + * width of work area of menubar-containing display */ int Fl::w() { - return int([[NSScreen mainScreen] visibleFrame].size.width); + return int([[[NSScreen screens] objectAtIndex:0] visibleFrame].size.width); } /* - * screen height + * height of work area of menubar-containing display */ int Fl::h() { - return int([[NSScreen mainScreen] visibleFrame].size.height); + return int([[[NSScreen screens] objectAtIndex:0] visibleFrame].size.height); } +// computes the work area of the nth screen (screen #0 has the menubar) +void Fl_X::screen_work_area(int &X, int &Y, int &W, int &H, int n) +{ + NSRect r = [[[NSScreen screens] objectAtIndex:n] visibleFrame]; + X = int(r.origin.x); + Y = main_screen_height - int(r.origin.y + r.size.height); + W = int(r.size.width); + H = int(r.size.height); +} /* * get the current mouse pointer world coordinates @@ -1360,7 +1374,7 @@ void Fl::get_mouse(int &x, int &y) fl_open_display(); NSPoint pt = [NSEvent mouseLocation]; x = int(pt.x); - y = int([[NSScreen mainScreen] frame].size.height - pt.y); + y = int(main_screen_height - pt.y); } @@ -1438,7 +1452,7 @@ int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) NSArray *a = [NSScreen screens]; int count = (int)[a count]; NSRect r; int i; for( i = 0; i < count; i++) { r = [[a objectAtIndex:i] frame]; - cy = int(r.size.height - cy); + r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use FLTK's multiscreen coordinates if ( cx >= r.origin.x && cx <= r.origin.x + r.size.width && cy >= r.origin.y && cy <= r.origin.y + r.size.height) break; @@ -1449,8 +1463,9 @@ int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) if (!gd) { for( i = 0; i < count; i++) { r = [[a objectAtIndex:i] frame]; + r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use FLTK's multiscreen coordinates if ( X >= r.origin.x && X <= r.origin.x + r.size.width - && r.size.height - Y >= r.origin.y && r.size.height - Y <= r.origin.y + r.size.height) + && Y >= r.origin.y && Y <= r.origin.y + r.size.height) break; } if (i < count) gd = [a objectAtIndex:i]; @@ -1459,8 +1474,9 @@ int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) if (!gd) { for( i = 0; i < count; i++) { r = [[a objectAtIndex:i] frame]; + r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use FLTK's multiscreen coordinates if ( R >= r.origin.x && R <= r.origin.x + r.size.width - && r.size.height - Y >= r.origin.y && r.size.height - Y <= r.origin.y + r.size.height) + && Y >= r.origin.y && Y <= r.origin.y + r.size.height) break; } if (i < count) gd = [a objectAtIndex:i]; @@ -1469,8 +1485,9 @@ int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) if (!gd) { for( i = 0; i < count; i++) { r = [[a objectAtIndex:i] frame]; + r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use FLTK's multiscreen coordinates if ( X >= r.origin.x && X <= r.origin.x + r.size.width - && Y-H >= r.origin.y && Y-H <= r.origin.y + r.size.height) + && Y+H >= r.origin.y && Y+H <= r.origin.y + r.size.height) break; } if (i < count) gd = [a objectAtIndex:i]; @@ -1479,8 +1496,9 @@ int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) if (!gd) { for( i = 0; i < count; i++) { r = [[a objectAtIndex:i] frame]; + r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use FLTK's multiscreen coordinates if ( R >= r.origin.x && R <= r.origin.x + r.size.width - && Y-H >= r.origin.y && Y-H <= r.origin.y + r.size.height) + && Y+H >= r.origin.y && Y+H <= r.origin.y + r.size.height) break; } if (i < count) gd = [a objectAtIndex:i]; @@ -1490,11 +1508,11 @@ int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) if (!gd) gd = [a objectAtIndex:0]; if (gd) { r = [gd visibleFrame]; - int sh = int([gd frame].size.height); + r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use FLTK's multiscreen coordinates if ( R > r.origin.x + r.size.width ) X -= int(R - (r.origin.x + r.size.width)); - if ( B > sh - r.origin.y ) Y -= int(B - (sh - r.origin.y)); + if ( B > r.size.height + r.origin.y ) Y -= int(B - (r.size.height + r.origin.y)); if ( X < r.origin.x ) X = int(r.origin.x); - if ( Y < sh - (r.origin.y + r.size.height) ) Y = int(sh - (r.origin.y + r.size.height)); + if ( Y < r.origin.y ) Y = int(r.origin.y); } // Return the client area's top left corner in (X,Y) @@ -2024,7 +2042,7 @@ void Fl_X::make(Fl_Window* w) hp += 2*by+bt; } if (!(w->flags() & Fl_Window::FORCE_POSITION)) { - // use the Carbon functions below for default window positioning + // default window positioning on the main screen w->x(xyPos+Fl::x()); w->y(xyPos+Fl::y()); xyPos += 25; @@ -2054,10 +2072,9 @@ void Fl_X::make(Fl_Window* w) x->xidNext = 0; x->gc = 0; - NSRect srect = [[NSScreen mainScreen] frame]; NSRect crect; crect.origin.x = w->x(); - crect.origin.y = srect.size.height - (w->y() + w->h()); + crect.origin.y = main_screen_height - (w->y() + w->h()); crect.size.width=w->w(); crect.size.height=w->h(); FLWindow *cw = [[FLWindow alloc] initWithFl_W:w @@ -2105,7 +2122,7 @@ 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); - [cw setDelegate:mydelegate]; + [cw setDelegate:[NSApp delegate]]; if (fl_show_iconic) { fl_show_iconic = 0; [cw miniaturize:nil]; @@ -2118,8 +2135,7 @@ void Fl_X::make(Fl_Window* w) w->h(int(crect.size.height)); crect = [cw frame]; w->x(int(crect.origin.x)); - srect = [[cw screen] frame]; - w->y(int(srect.size.height - (crect.origin.y + w->h()))); + w->y(int(main_screen_height - (crect.origin.y + w->h()))); int old_event = Fl::e_number; w->handle(Fl::e_number = FL_SHOW); @@ -2235,14 +2251,14 @@ void Fl_Window::resize(int X,int Y,int W,int H) { else get_window_frame_sizes(bx, by, bt); NSRect dim; dim.origin.x = X; - dim.origin.y = [[(NSWindow*)i->xid screen] frame].size.height - (Y + H); + dim.origin.y = main_screen_height - (Y + H); dim.size.width = W; dim.size.height = H + bt; [(NSWindow*)i->xid setFrame:dim display:YES]; } else { NSPoint pt; pt.x = X; - pt.y = [[(NSWindow*)i->xid screen] frame].size.height - (Y + h()); + pt.y = main_screen_height - (Y + h()); [(NSWindow*)i->xid setFrameOrigin:pt]; } } |
