From d9cda5c3aa48da9ef3238d993b34cde7047175d8 Mon Sep 17 00:00:00 2001 From: Manolo Gouy Date: Thu, 29 Sep 2011 16:04:24 +0000 Subject: 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 --- FL/Fl.H | 18 ++++++-- FL/mac.H | 2 + src/Fl_Menu.cxx | 12 ++---- src/Fl_cocoa.mm | 118 +++++++++++++++++++++++++++++----------------------- src/Fl_x.cxx | 15 ++++--- src/screen_xywh.cxx | 100 +++++++++++++++++++++++++++++++++----------- 6 files changed, 171 insertions(+), 94 deletions(-) diff --git a/FL/Fl.H b/FL/Fl.H index 634545fb6..ed6b7c56b 100644 --- a/FL/Fl.H +++ b/FL/Fl.H @@ -757,13 +757,13 @@ public: fl global screen functions declared in @{ */ // screen size: - /** Returns the origin of the current screen work area, where 0 indicates the left side of the screen. */ + /** Returns the leftmost x coordinate of the main screen work area. */ static int x(); // platform dependent - /** Returns the origin of the current screen work area, where 0 indicates the top edge of the screen. */ + /** Returns the topmost y coordinate of the main screen work area. */ static int y(); // platform dependent - /** Returns the width of the screen work area in pixels. */ + /** Returns the width in pixels of the main screen work area. */ static int w(); // platform dependent - /** Returns the height of the screen work area in pixels. */ + /** Returns the height in pixels of the main screen work area. */ static int h(); // platform dependent // multi-head support: @@ -780,6 +780,16 @@ public: static void screen_xywh(int &X, int &Y, int &W, int &H, int n); static void screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my, int mw, int mh); static void screen_dpi(float &h, float &v, int n=0); + static void screen_work_area(int &X, int &Y, int &W, int &H, int mx, int my); + static void screen_work_area(int &X, int &Y, int &W, int &H, int n); + /** + Gets the bounding box of the work area of the screen that contains the mouse pointer. + \param[out] X,Y,W,H the work area bounding box + \see void screen_work_area(int &x, int &y, int &w, int &h, int mx, int my) + */ + static void screen_work_area(int &X, int &Y, int &W, int &H) { + screen_work_area(X, Y, W, H, e_x_root, e_y_root); + } /** @} */ diff --git a/FL/mac.H b/FL/mac.H index 573ebe936..c53824ea7 100644 --- a/FL/mac.H +++ b/FL/mac.H @@ -125,6 +125,8 @@ public: static CGContextRef nwse_cursor_image(void); static CGContextRef none_cursor_image(void); static void *get_carbon_function(const char *name); + static void screen_work_area(int &X, int &Y, int &W, int &H, int n); // compute work area of a given screen + static void mac_screen_init(void); // recompute screen number and dimensions private: static void relink(Fl_Window*, Fl_Window*); bool subwindow; diff --git a/src/Fl_Menu.cxx b/src/Fl_Menu.cxx index 1162c0238..224645b95 100644 --- a/src/Fl_Menu.cxx +++ b/src/Fl_Menu.cxx @@ -276,13 +276,7 @@ menuwindow::menuwindow(const Fl_Menu_Item* m, int X, int Y, int Wp, int Hp, int scr_x, scr_y, scr_w, scr_h; int tx = X, ty = Y; - Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h); -#ifdef __APPLE__ - scr_x = Fl::x(); - scr_w = Fl::w(); -#endif - scr_y = Fl::y(); - scr_h = Fl::h(); + Fl::screen_work_area(scr_x, scr_y, scr_w, scr_h); if (!right_edge || right_edge > scr_x+scr_w) right_edge = scr_x+scr_w; end(); @@ -417,8 +411,8 @@ void menuwindow::autoscroll(int n) { int scr_y, scr_h; int Y = y()+Fl::box_dx(box())+2+n*itemheight; - scr_y = Fl::y(); - scr_h = Fl::h(); + int xx, ww; + Fl::screen_work_area(xx, scr_y, ww, scr_h); if (Y <= scr_y) Y = scr_y-Y+10; else { Y = Y+itemheight-scr_h-scr_y; 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 @@ -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]; } } diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx index fe98cd1d9..bc528aa34 100644 --- a/src/Fl_x.cxx +++ b/src/Fl_x.cxx @@ -655,16 +655,21 @@ static void fl_init_workarea() { int format; unsigned *xywh; - if (XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen), + /* If there are several screens, the _NET_WORKAREA property + does not give the work area of the main screen, but that of all screens together. + Therefore, we use this property only when there is a single screen, + and fall back to the main screen full area when there are several screens. + */ + if (Fl::screen_count() > 1 || XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen), _NET_WORKAREA, 0, 4 * sizeof(unsigned), False, XA_CARDINAL, &actual, &format, &count, &remaining, (unsigned char **)&xywh) || !xywh || !xywh[2] || !xywh[3]) { - fl_workarea_xywh[0] = 0; - fl_workarea_xywh[1] = 0; - fl_workarea_xywh[2] = DisplayWidth(fl_display, fl_screen); - fl_workarea_xywh[3] = DisplayHeight(fl_display, fl_screen); + Fl::screen_xywh(fl_workarea_xywh[0], + fl_workarea_xywh[1], + fl_workarea_xywh[2], + fl_workarea_xywh[3], 0); } else { diff --git a/src/screen_xywh.cxx b/src/screen_xywh.cxx index 9ceb8630e..878b9bf9a 100644 --- a/src/screen_xywh.cxx +++ b/src/screen_xywh.cxx @@ -47,6 +47,7 @@ typedef BOOL (WINAPI* fl_gmi_func)(HMONITOR, LPMONITORINFO); static fl_gmi_func fl_gmi = NULL; // used to get a proc pointer for GetMonitorInfoA static RECT screens[16]; +static RECT work_area[16]; static float dpi[16][2]; static BOOL CALLBACK screen_cb(HMONITOR mon, HDC, LPRECT r, LPARAM) { @@ -60,8 +61,11 @@ static BOOL CALLBACK screen_cb(HMONITOR mon, HDC, LPRECT r, LPARAM) { if (fl_gmi(mon, &mi)) { screens[num_screens] = mi.rcMonitor; // If we also want to record the work area, we would also store mi.rcWork at this point -// work_area[num_screens] = mi.rcWork; - + work_area[num_screens] = mi.rcWork; +/*fl_alert("screen %d %d,%d,%d,%d work %d,%d,%d,%d",num_screens, + screens[num_screens].left,screens[num_screens].right,screens[num_screens].top,screens[num_screens].bottom, + work_area[num_screens].left,work_area[num_screens].right,work_area[num_screens].top,work_area[num_screens].bottom); +*/ // find the pixel size if (mi.cbSize == sizeof(mi)) { HDC screen = CreateDC(mi.szDevice, NULL, NULL, NULL); @@ -107,6 +111,7 @@ static void screen_init() { screens[0].left = 0; screens[0].right = GetSystemMetrics(SM_CXSCREEN); screens[0].bottom = GetSystemMetrics(SM_CYSCREEN); + work_area[0] = screens[0]; } #elif defined(__APPLE__) static XRectangle screens[16]; @@ -124,12 +129,23 @@ static void screen_init() { screens[i].y = int(r.origin.y); screens[i].width = int(r.size.width); screens[i].height = int(r.size.height); - CGSize s = CGDisplayScreenSize(displays[i]); - dpi_h[i] = screens[i].width / (s.width/25.4); - dpi_v[i] = screens[i].height / (s.height/25.4); +//fprintf(stderr,"screen %d %dx%dx%dx%d\n",i,screens[i].x,screens[i].y,screens[i].width,screens[i].height); + if (CGDisplayScreenSize != NULL) { + CGSize s = CGDisplayScreenSize(displays[i]); // from 10.3 + dpi_h[i] = screens[i].width / (s.width/25.4); + dpi_v[i] = screens[i].height / (s.height/25.4); + } + else { + dpi_h[i] = dpi_v[i] = 75.; + } } num_screens = count; } + +void Fl_X::mac_screen_init() { + screen_init(); + } + #elif HAVE_XINERAMA # include @@ -183,19 +199,11 @@ int Fl::screen_count() { return num_screens ? num_screens : 1; } -/** - Gets the bounding box of a screen - that contains the specified screen position \p mx, \p my - \param[out] X,Y,W,H the corresponding screen bounding box - \param[in] mx, my the absolute screen position -*/ -void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my) { +static int find_screen_with_point(int mx, int my) { int screen = 0; - int i; - if (num_screens < 0) screen_init(); - - for (i = 0; i < num_screens; i ++) { + + for (int i = 0; i < num_screens; i ++) { int sx, sy, sw, sh; Fl::screen_xywh(sx, sy, sw, sh, i); if ((mx >= sx) && (mx < (sx+sw)) && (my >= sy) && (my < (sy+sh))) { @@ -203,12 +211,62 @@ void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my) { break; } } + return screen; +} + +/** + Gets the bounding box of a screen + that contains the specified screen position \p mx, \p my + \param[out] X,Y,W,H the corresponding screen bounding box + \param[in] mx, my the absolute screen position +*/ +void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my) { + screen_xywh(X, Y, W, H, find_screen_with_point(mx, my)); +} - screen_xywh(X, Y, W, H, screen); + +/** + Gets the bounding box of the work area of a screen + that contains the specified screen position \p mx, \p my + \param[out] X,Y,W,H the work area bounding box + \param[in] mx, my the absolute screen position + */ +void Fl::screen_work_area(int &X, int &Y, int &W, int &H, int mx, int my) { + screen_work_area(X, Y, W, H, find_screen_with_point(mx, my)); +} + +/** + Gets the bounding box of the work area of the given screen. + \param[out] X,Y,W,H the work area bounding box + \param[in] n the screen number (0 to Fl::screen_count() - 1) + \see void screen_xywh(int &x, int &y, int &w, int &h, int mx, int my) +*/ +void Fl::screen_work_area(int &X, int &Y, int &W, int &H, int n) { + if (num_screens < 0) screen_init(); + if (n < 0 || n >= num_screens) n = 0; +#ifdef WIN32 + X = work_area[n].left; + Y = work_area[n].top; + W = work_area[n].right - X; + H = work_area[n].bottom - Y; +#elif defined(__APPLE__) + Fl_X::screen_work_area(X, Y, W, H, n); +#else + if (n == 0) { // for the main screen, these return the work area + X = Fl::x(); + Y = Fl::y(); + W = Fl::w(); + H = Fl::h(); + } + else { // for other screens, work area is full screen, + screen_xywh(X, Y, W, H, n); + } +#endif } /** Gets the screen bounding rect for the given screen. + Under MSWindows, Mac OS X, and the Gnome desktop, screen #0 contains the menubar/taskbar \param[out] X,Y,W,H the corresponding screen bounding box \param[in] n the screen number (0 to Fl::screen_count() - 1) \see void screen_xywh(int &x, int &y, int &w, int &h, int mx, int my) @@ -233,18 +291,10 @@ void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int n) { H = GetSystemMetrics(SM_CYSCREEN); } #elif defined(__APPLE__) - if (num_screens > 0) { X = screens[n].x; Y = screens[n].y; W = screens[n].width; H = screens[n].height; - } else { - /* Fallback if something is broken... */ - X = Fl::x(); - Y = Fl::y(); - W = Fl::w(); - H = Fl::h(); - } #else #if HAVE_XINERAMA if (num_screens > 0 && screens) { -- cgit v1.2.3