STR#3437 : Support display of windows in tabbed form as in MacOS 10.12 Sierra

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12596 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Manolo Gouy 2017-12-18 15:19:15 +00:00
parent f24ee501b9
commit d361de4d0d
8 changed files with 366 additions and 40 deletions

12
CHANGES
View File

@ -18,6 +18,18 @@ Changes in FLTK 1.4.0 Released: ??? ?? 2017
New Features and Extensions
- (add new items here)
- MacOS platform: Added support for rescaling the GUI of any app at run-time
using the command/+/-/0/ keystrokes.
- MSWindows platform: Added optional support for rescaling the GUI of any app
at run-time using the ctrl/+/-/0/ keystrokes. This requires to build the
FLTK library with -DFLTK_HIDPI_SUPPORT (for now). This option also makes
app detect the desktop scaling factor and automatically scale their GUI
accordingly. This effectively renders WIN32 FLTK apps "per-monitor DPI-aware"
whereas they were "DPI-unaware" with FLTK 1.3.4.
- FLTK apps on the MacOS platform contain automatically a Window menu, which,
under MacOS ≥ 10.12, allows to group/ungroup windows in tabbed form. The new
Fl_Sys_Menu_Bar::window_menu_style() function allows to specify various
styles for the Window menu, even not to create it.
- New function: int fl_open_ext(const char* fname, int binary, int oflags, ...)
to control the opening of files in binary/text mode in a cross-platform way.
- New Fl_SVG_Image class: gives support of scalable vector graphics images

View File

@ -24,33 +24,48 @@
class Fl_Sys_Menu_Bar_Driver;
/**
A class to create, modify and delete menus that appear on Mac OS X in the menu bar at the top of the screen.
A class to create and modify menus that appear on Mac OS X in the menu bar at the top of the screen.
To use this class, just replace Fl_Menu_Bar by Fl_Sys_Menu_Bar, and, on the Mac platform,
a system menu at the top of the screen will be available. This menu will match an array
of Fl_Menu_Item's exactly as in all other FLTK menus.
On other than Mac OS X platforms, Fl_Sys_Menu_Bar is a synonym of class Fl_Menu_Bar.
\n To use this class, just replace Fl_Menu_Bar by Fl_Sys_Menu_Bar, and, on the Mac platform,
a system menu at the top of the screen will be available. This menu will match an array
of Fl_Menu_Item's exactly as with standard FLTK menus.
On the MacOS platform, the system menu bar of any FLTK app begins with the Application
menu which the FLTK library automatically constructs. Functions
Fl_Mac_App_Menu::custom_application_menu_items() and fl_mac_set_about() can be used to further customize
the Application menu. The FLTK library also automatically constructs and handles a Window menu which can be
further customized (or even removed) calling
Fl_Sys_Menu_Bar::window_menu_style(window_menu_style_enum style).
Other member functions of this class allow the app to generate the rest of the system menu bar.
It is recommended to localize the system menu bar using the standard Mac OS X localization procedure
(see \ref osissues_localize).
Changes to the menu state are immediately visible in the menubar when they are made
using member functions of the Fl_Sys_Menu_Bar class. Other changes (e.g., by a call to
Fl_Menu_Item::set()) should be followed by a call to update() to be
visible in the menubar across all platforms.
A few FLTK features are not supported by the Mac System menu:
A few FLTK menu features are not supported by the Mac System menu:
\li no symbolic labels
\li no embossed labels
\li no font sizes
You can configure a callback for the 'About' menu item to invoke your own code with Fl_Sys_Menu_Bar::about().
*/
*/
class FL_EXPORT Fl_Sys_Menu_Bar : public Fl_Menu_Bar {
protected:
virtual void draw();
public:
/** Possible styles of the Window menu in the system menu bar */
typedef enum {
no_window_menu = 0, ///< No Window menu in the system menu bar
tabbing_mode_none, ///< No tabbed windows, but the system menu bar contains a Window menu
tabbing_mode_automatic, ///< Windows are created by themselves but can be tabbed later
tabbing_mode_preferred ///< Windows are tabbed when created
} window_menu_style_enum;
Fl_Sys_Menu_Bar(int x,int y,int w,int h,const char *l=0);
virtual ~Fl_Sys_Menu_Bar();
static Fl_Sys_Menu_Bar_Driver *driver();
/** Return the system menu's array of Fl_Menu_Item's
/** Return the system menu's array of Fl_Menu_Item's
*/
const Fl_Menu_Item *menu() const {return Fl_Menu_::menu();}
void menu(const Fl_Menu_Item *m);
@ -81,6 +96,10 @@ public:
void shortcut (int i, int s);
void setonly (Fl_Menu_Item *item);
static void about(Fl_Callback *cb, void *data);
static window_menu_style_enum window_menu_style();
static void window_menu_style(window_menu_style_enum style);
static void create_window_menu();
};
extern Fl_Sys_Menu_Bar *fl_sys_menu_bar;

View File

@ -19,11 +19,15 @@
#ifndef Fl_Sys_Menu_Bar_Driver_H
#define Fl_Sys_Menu_Bar_Driver_H
#if !defined(FL_DOXYGEN)
#include <FL/Fl_Sys_Menu_Bar.H>
class Fl_Sys_Menu_Bar_Driver {
friend class Fl_Sys_Menu_Bar;
public:
static Fl_Sys_Menu_Bar::window_menu_style_enum window_menu_style_;
static Fl_Sys_Menu_Bar_Driver *driver_; // to be assigned with a unique object of this class or of a derived class
Fl_Sys_Menu_Bar *bar;
Fl_Sys_Menu_Bar_Driver();
virtual ~Fl_Sys_Menu_Bar_Driver();
@ -45,10 +49,12 @@ public:
virtual void remove(int index) { bar->Fl_Menu_Bar::remove(index); }
virtual void replace(int index, const char *name) { bar->Fl_Menu_Bar::replace(index, name); }
virtual void mode(int i, int fl) { bar->Fl_Menu_Bar::mode(i, fl); }
static Fl_Sys_Menu_Bar_Driver *driver_; // to be assigned with a unique object of this class or of a derived class
virtual void create_window_menu() {}
static Fl_Sys_Menu_Bar::window_menu_style_enum window_menu_style() { return window_menu_style_; }
static void window_menu_style(Fl_Sys_Menu_Bar::window_menu_style_enum style) { window_menu_style_ = style; }
};
#endif // !defined(FL_DOXYGEN)
#endif // Fl_Sys_Menu_Bar_Driver_H

View File

@ -21,9 +21,30 @@
#include <FL/Fl_Sys_Menu_Bar_Driver.H>
#include <FL/x.H>
#include "drivers/Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H"
#include "flstring.h"
#include <stdio.h>
#include <ctype.h>
#include <stdarg.h>
#import <Cocoa/Cocoa.h> // keep this after include of Fl_Sys_Menu_Bar_Driver.H because of check() conflict
Fl_Sys_Menu_Bar_Driver* Fl_MacOS_Sys_Menu_Bar_Driver::driver() {
typedef const Fl_Menu_Item *pFl_Menu_Item;
static Fl_Menu_Bar *custom_menu;
static NSString *localized_Window = nil;
static char *remove_ampersand(const char *s);
extern void (*fl_lock_function)();
extern void (*fl_unlock_function)();
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
static void previous_tab_cb(Fl_Widget *, void *data);
static void next_tab_cb(Fl_Widget *, void *data);
static void move_tab_cb(Fl_Widget *, void *data);
static void merge_all_windows_cb(Fl_Widget *, void *data);
#endif
Fl_MacOS_Sys_Menu_Bar_Driver* Fl_MacOS_Sys_Menu_Bar_Driver::driver() {
static Fl_MacOS_Sys_Menu_Bar_Driver *once = new Fl_MacOS_Sys_Menu_Bar_Driver();
if (driver_ != once) {
if (driver_) {
@ -36,22 +57,6 @@ Fl_Sys_Menu_Bar_Driver* Fl_MacOS_Sys_Menu_Bar_Driver::driver() {
return once;
}
#import <Cocoa/Cocoa.h>
#include "flstring.h"
#include <stdio.h>
#include <ctype.h>
#include <stdarg.h>
typedef const Fl_Menu_Item *pFl_Menu_Item;
static Fl_Menu_Bar *custom_menu;
static char *remove_ampersand(const char *s);
extern void (*fl_lock_function)();
extern void (*fl_unlock_function)();
/* Each MacOS system menu item contains a pointer to a record of type sys_menu_item defined below.
The purpose of these records is to associate each MacOS system menu item with a relevant Fl_Menu_Item.
@ -92,6 +97,9 @@ const char *Fl_Mac_App_Menu::quit = "Quit %@";
- (void) setKeyEquivalentModifierMask:(int)value;
- (void) setFltkShortcut:(int)key;
+ (int) addNewItem:(const Fl_Menu_Item*)mitem menu:(NSMenu*)menu action:(SEL)selector;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
- (BOOL)validateMenuItem:(NSMenuItem *)item;
#endif
@end
@implementation FLMenuItem
@ -197,6 +205,37 @@ const char *Fl_Mac_App_Menu::quit = "Quit %@";
[item release];
return retval;
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
- (BOOL)validateMenuItem:(NSMenuItem *)item {
// return YES for all but items of the Window menu
if (fl_mac_os_version < 101200 ||
Fl_Sys_Menu_Bar::window_menu_style() <= Fl_Sys_Menu_Bar::tabbing_mode_none ||
[item hasSubmenu]) return YES;
NSString *title = [[item parentItem] title]; // 10.6
if (!title || !localized_Window || [title compare:localized_Window] != NSOrderedSame) return YES;
const Fl_Menu_Item *flitem = [(FLMenuItem*)item getFlItem];
Fl_Callback *item_cb = flitem->callback();
if (item_cb == previous_tab_cb || item_cb == next_tab_cb || item_cb == move_tab_cb) {
// is the current window tabbed?
Fl_Window *win = Fl::first_window();
NSWindow *main = win ? (NSWindow*)fl_xid(win) : nil;
return (main && [main tabbedWindows] != nil);
} else if (item_cb == merge_all_windows_cb) {
// is there any untabbed, tabbable window?
int total = 0, untabbed = 0;
while ((++flitem)->label()) {
total++;
NSWindow *nsw = (NSWindow*)fl_xid( (Fl_Window*)flitem->user_data() );
if (![nsw tabbedWindows] && [nsw tabbingMode] != NSWindowTabbingModeDisallowed) {
untabbed++;
}
}
return (untabbed > 0 && total >= 2);
}
return YES;
}
#endif
@end
@ -341,6 +380,12 @@ static void convertToMenuBar(const Fl_Menu_Item *mm)
[fl_system_menu removeItem:[fl_system_menu itemAtIndex:i]];
}
if (mm) createSubMenu(fl_system_menu, mm, NULL, @selector(doCallback));
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
if (localized_Window) {
NSMenuItem *item = [fl_system_menu itemWithTitle:localized_Window];
if (item) [[item submenu] setAutoenablesItems:YES];
}
#endif
}
void Fl_MacOS_Sys_Menu_Bar_Driver::update()
@ -483,6 +528,145 @@ void Fl_Mac_App_Menu::custom_application_menu_items(const Fl_Menu_Item *m)
[item release];
}
}
static void minimize_win_cb(Fl_Widget *, void *data)
{
[[NSApp mainWindow] miniaturize:nil];
}
static void window_menu_cb(Fl_Widget *, void *data)
{
if (data) ((Fl_Window*)data)->show();
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
static void previous_tab_cb(Fl_Widget *, void *data)
{
[[NSApp mainWindow] selectPreviousTab:nil];
}
static void next_tab_cb(Fl_Widget *, void *data)
{
[[NSApp mainWindow] selectNextTab:nil];
}
static void move_tab_cb(Fl_Widget *, void *data)
{
[[NSApp mainWindow] moveTabToNewWindow:nil];
}
static void merge_all_windows_cb(Fl_Widget *, void *)
{
Fl_Window *first = Fl::first_window();
if (first) {
[(NSWindow*)fl_xid(first) mergeAllWindows:nil];
}
}
#endif
static bool window_menu_installed = false;
void Fl_MacOS_Sys_Menu_Bar_Driver::create_window_menu(void)
{
if (window_menu_style() == Fl_Sys_Menu_Bar::no_window_menu) return;
if (window_menu_installed) return;
window_menu_installed = true;
int rank = 0;
if (fl_sys_menu_bar && fl_sys_menu_bar->menu()) {
if (fl_sys_menu_bar->find_index("Window") >= 0) { // there's already a "Window" menu -> don't create another
window_menu_style_ = Fl_Sys_Menu_Bar::no_window_menu;
return;
}
// put the Window menu last in menu bar or before Help if it's present
const Fl_Menu_Item *item = fl_sys_menu_bar->menu();
while (item->label() && strcmp(item->label(), "Help") != 0) {
item = item->next();
}
rank = fl_sys_menu_bar->find_index(item);
} else if (!fl_sys_menu_bar) {
fl_open_display();
new Fl_Sys_Menu_Bar(0,0,0,0);
}
rank = fl_sys_menu_bar->Fl_Menu_::insert(rank, "Window", 0, NULL, 0, FL_SUBMENU);
localized_Window = NSLocalizedString(@"Window", nil);
fl_sys_menu_bar->Fl_Menu_::insert(++rank, "Minimize", FL_COMMAND+'m', minimize_win_cb, 0, FL_MENU_DIVIDER);
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
if (fl_mac_os_version >= 101200 && window_menu_style() != Fl_Sys_Menu_Bar::tabbing_mode_none) {
fl_sys_menu_bar->Fl_Menu_::insert(++rank, "Show Previous Tab", FL_SHIFT+FL_CTRL+0x9, previous_tab_cb, 0, 0);
fl_sys_menu_bar->Fl_Menu_::insert(++rank, "Show Next Tab", FL_CTRL+0x9, next_tab_cb, 0, 0);
fl_sys_menu_bar->Fl_Menu_::insert(++rank, "Move Tab To New Window", 0, move_tab_cb, 0, 0);
fl_sys_menu_bar->Fl_Menu_::insert(++rank, "Merge All Windows", 0, merge_all_windows_cb, 0, FL_MENU_DIVIDER);
}
#endif
((Fl_Menu_Item*)fl_sys_menu_bar->menu()+rank)->user_data(&window_menu_style_);
fl_sys_menu_bar->update();
}
int Fl_MacOS_Sys_Menu_Bar_Driver::find_first_window()
{
int count = bar->size(), i;
for (i = 0; i < count; i++) {
if (bar->menu()[i].user_data() == &window_menu_style_) break;
}
return i < count ? i : -1;
}
void Fl_MacOS_Sys_Menu_Bar_Driver::new_window(Fl_Window *win)
{
if (!window_menu_style() || !win->label()) return;
int index = find_first_window();
if (index < 0) return;
while ((bar->menu()+index+1)->label()) index++;
const char *p = win->iconlabel() ? win->iconlabel() : win->label();
int index2 = bar->Fl_Menu_::insert(index+1, p, 0, window_menu_cb, win, FL_MENU_RADIO);
setonly((Fl_Menu_Item*)bar->menu()+index2);
}
void Fl_MacOS_Sys_Menu_Bar_Driver::remove_window(Fl_Window *win)
{
if (!window_menu_style()) return;
int index = find_first_window() + 1;
if (index < 1) return;
while (true) {
Fl_Menu_Item *item = (Fl_Menu_Item*)bar->menu() + index;
if (!item->label()) return;
if (item->user_data() == win) {
bool doit = item->value();
remove(index);
if (doit) {
item = (Fl_Menu_Item*)bar->menu() + find_first_window() + 1;
if (item->label()) {
((Fl_Window*)item->user_data())->show();
setonly(item);
}
}
break;
}
index++;
}
}
void Fl_MacOS_Sys_Menu_Bar_Driver::rename_window(Fl_Window *win)
{
if (!window_menu_style()) return;
int index = find_first_window() + 1;
if (index < 1) return;
while (true) {
Fl_Menu_Item *item = (Fl_Menu_Item*)bar->menu() + index;
if (!item->label()) return;
if (item->user_data() == win) {
replace(index, win->iconlabel() ? win->iconlabel() : win->label());
return;
}
index++;
}
}
#endif /* __APPLE__ */
//

View File

@ -166,13 +166,58 @@ void Fl_Sys_Menu_Bar::replace(int index, const char *name)
* \param data a pointer transmitted as 2nd argument to the callback.
*/
void Fl_Sys_Menu_Bar::about(Fl_Callback *cb, void *data) {
if (fl_sys_menu_bar) fl_sys_menu_bar->driver()->about(cb, data);
driver()->about(cb, data);
}
void Fl_Sys_Menu_Bar::draw() {
driver()->draw();
}
/** Get the style of the Window menu in the system menu bar */
Fl_Sys_Menu_Bar::window_menu_style_enum Fl_Sys_Menu_Bar::window_menu_style() {
return Fl_Sys_Menu_Bar_Driver::window_menu_style();
}
/** Set the desired style of the Window menu in the system menu bar.
This function, to be called before the first call to Fl_Window::show(), allows to
control whether the system menu bar should contain a Window menu,
and if yes, whether new windows should be displayed in tabbed form. These are
the effects of various values for \p style :
\li \c no_window_menu : don't add a Window menu to the system menu bar
\li \c tabbing_mode_none : add a simple Window menu to the system menu bar
\li \c tabbing_mode_automatic : the window menu also contains "Merge All Windows" to group
all windows in a single tabbed display mode. This is the \b default Window menu style
for FLTK apps.
\li \c tabbing_mode_preferred : new windows are displayed in tabbed mode when first created
The Window menu, if present, is entirely created and controlled by the FLTK library.
Mac OS version 10.12 or later must be running for windows to be displayed in tabbed form.
Under non MacOS platforms, this function does nothing.
\version 1.4
*/
void Fl_Sys_Menu_Bar::window_menu_style(Fl_Sys_Menu_Bar::window_menu_style_enum style) {
Fl_Sys_Menu_Bar_Driver::window_menu_style(style);
}
/** Adds a Window menu, to the end of the system menu bar.
FLTK apps typically don't need to call this function which is automatically
called by the library the first time a window is shown. The default system menu bar
contains a Window menu with a "Merge All Windows" item.
Other Window menu styles can be obtained calling
Fl_Sys_Menu_Bar::window_menu_style(window_menu_style_enum) before the first Fl_Window::show().
Alternatively, an app can call create_window_menu() after having populated the system menu bar,
for example with menu(const Fl_Menu_Item *), and before the first Fl_Window::show().
This function does nothing on non MacOS platforms.
\version 1.4
*/
void Fl_Sys_Menu_Bar::create_window_menu() {
fl_open_display();
driver()->create_window_menu();
}
#if !defined(FL_DOXYGEN)
Fl_Sys_Menu_Bar_Driver *Fl_Sys_Menu_Bar::driver() {
if (!Fl_Sys_Menu_Bar_Driver::driver_) { // initialize this static variable if it was not initialized previously
@ -186,6 +231,8 @@ Fl_Sys_Menu_Bar_Driver *Fl_Sys_Menu_Bar_Driver::driver_ = 0;
Fl_Sys_Menu_Bar_Driver::Fl_Sys_Menu_Bar_Driver() {bar = NULL;}
Fl_Sys_Menu_Bar_Driver::~Fl_Sys_Menu_Bar_Driver() {}
Fl_Sys_Menu_Bar::window_menu_style_enum Fl_Sys_Menu_Bar_Driver::window_menu_style_ = Fl_Sys_Menu_Bar::tabbing_mode_automatic;
#endif // !defined(FL_DOXYGEN)
//

View File

@ -1309,9 +1309,14 @@ static FLWindowDelegate *flwindowdelegate_instance = nil;
}
- (void)windowDidMove:(NSNotification *)notif
{
fl_lock_function();
FLWindow *nsw = (FLWindow*)[notif object];
Fl_Window *window = [nsw getFl_Window];
if (abs([[nsw contentView] frame].size.height - window->h() * fl_graphics_driver->scale()) > 0.5) {
// the contentView, but not the window frame, is resized. This happens with tabbed windows.
[self windowDidResize:notif];
return;
}
fl_lock_function();
resize_from_system = window;
NSPoint pt2;
pt2 = [nsw convertBaseToScreen:NSMakePoint(0, [[nsw contentView] frame].size.height)];
@ -1402,6 +1407,19 @@ static FLWindowDelegate *flwindowdelegate_instance = nil;
Fl_Window *window = [nsw getFl_Window];
Fl::first_window(window);
update_e_xy_and_e_xy_root(nsw);
if (fl_sys_menu_bar && Fl_MacOS_Sys_Menu_Bar_Driver::window_menu_style()) {
// select the corresponding Window menu item
int index = Fl_MacOS_Sys_Menu_Bar_Driver::driver()->find_first_window() + 1;
while (index > 0) {
Fl_Menu_Item *item = (Fl_Menu_Item*)fl_sys_menu_bar->menu() + index;
if (!item->label()) break;
if (item->user_data() == window) {
fl_sys_menu_bar->setonly(item);
break;
}
index++;
}
}
fl_unlock_function();
}
- (void)windowDidDeminiaturize:(NSNotification *)notif
@ -1868,7 +1886,13 @@ void Fl_Cocoa_Screen_Driver::disable_im() {
// Gets the border sizes and the titlebar size
static void get_window_frame_sizes(int &bx, int &by, int &bt) {
static void get_window_frame_sizes(int &bx, int &by, int &bt, Fl_Window *win) {
FLWindow *flw = fl_xid(win);
if (flw) {
bt = [flw frame].size.height - [[flw contentView] frame].size.height;
bx = by = 0;
return;
}
static int top = 0, left, bottom;
if (!top) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@ -1952,7 +1976,7 @@ static int fake_X_wm(Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) {
} else {
ret = 1;
}
get_window_frame_sizes(bx, by, bt);
get_window_frame_sizes(bx, by, bt, w);
}
// The coordinates of the whole window, including non-client area
xoff = bx;
@ -2278,6 +2302,11 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
fl_lock_function();
FLWindow *cw = (FLWindow*)[self window];
Fl_Window *window = [cw getFl_Window];
if ( !window->parent() && window->border() && abs(rect.size.height - window->h() * fl_graphics_driver->scale()) > 0.5 ) { // this happens with tabbed window
window->resize([cw frame].origin.x/fl_graphics_driver->scale(),
(main_screen_height - ([cw frame].origin.y + rect.size.height))/fl_graphics_driver->scale(),
rect.size.width/fl_graphics_driver->scale(), rect.size.height/fl_graphics_driver->scale());
}
through_drawRect = YES;
Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(window);
if (fl_mac_os_version >= 100700) { // determine whether window is mapped to a retina display
@ -2919,6 +2948,7 @@ Fl_X* Fl_Cocoa_Window_Driver::makeWindow()
fl_open_display();
NSInteger winlevel = NSNormalWindowLevel;
NSUInteger winstyle;
Fl_Sys_Menu_Bar::driver()->create_window_menu(); // effective once at most
Fl_Window* w = pWindow;
if (w->parent()) {
w->border(0);
@ -3029,6 +3059,18 @@ Fl_X* Fl_Cocoa_Window_Driver::makeWindow()
contentRect:crect
styleMask:winstyle];
[cw setFrameOrigin:crect.origin];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
if (fl_mac_os_version >= 101200) {
if (!w->parent() && (winstyle & NSTitledWindowMask) && (winstyle & NSResizableWindowMask)
&& !w->modal() && !w->non_modal() && Fl_MacOS_Sys_Menu_Bar_Driver::window_menu_style() > Fl_Sys_Menu_Bar::tabbing_mode_none) {
if (Fl_MacOS_Sys_Menu_Bar_Driver::window_menu_style() == Fl_Sys_Menu_Bar::tabbing_mode_preferred)
[cw setTabbingMode:NSWindowTabbingModePreferred];
else [cw setTabbingMode:NSWindowTabbingModeAutomatic];
} else {
[cw setTabbingMode:NSWindowTabbingModeDisallowed];
}
}
#endif
if (!w->parent()) {
[cw setHasShadow:YES];
[cw setAcceptsMouseMovedEvents:YES];
@ -3105,7 +3147,10 @@ Fl_X* Fl_Cocoa_Window_Driver::makeWindow()
} else { // a top-level window
[cw makeKeyAndOrderFront:nil];
}
if (fl_sys_menu_bar && Fl_MacOS_Sys_Menu_Bar_Driver::window_menu_style() && !w->parent() && w->border() &&
!w->modal() && !w->non_modal()) {
Fl_MacOS_Sys_Menu_Bar_Driver::driver()->new_window(w);
}
int old_event = Fl::e_number;
w->handle(Fl::e_number = FL_SHOW);
Fl::e_number = old_event;
@ -3121,7 +3166,7 @@ Fl_X* Fl_Cocoa_Window_Driver::makeWindow()
*/
void Fl_Cocoa_Window_Driver::size_range() {
int bx, by, bt;
get_window_frame_sizes(bx, by, bt);
get_window_frame_sizes(bx, by, bt, pWindow);
Fl_Window_Driver::size_range();
NSSize minSize = NSMakeSize(minw(), minh() + bt);
NSSize maxSize = NSMakeSize(maxw() ? maxw():32000, maxh() ? maxh() + bt:32000);
@ -3172,6 +3217,8 @@ const char *Fl_Darwin_System_Driver::filename_name( const char *name )
void Fl_Cocoa_Window_Driver::label(const char *name, const char *mininame) {
if (shown() || Fl_X::i(pWindow)) {
q_set_window_title(fl_xid(pWindow), name, mininame);
if (fl_sys_menu_bar && Fl_Sys_Menu_Bar_Driver::window_menu_style())
Fl_MacOS_Sys_Menu_Bar_Driver::driver()->rename_window(pWindow);
}
}
@ -3230,7 +3277,7 @@ void Fl_Cocoa_Window_Driver::resize(int X,int Y,int W,int H) {
}
pWindow->Fl_Group::resize(X,Y,W,H);
// transmit changes in FLTK coords to cocoa
get_window_frame_sizes(bx, by, bt);
get_window_frame_sizes(bx, by, bt, pWindow);
bx = X; by = Y;
parent = pWindow->window();
while (parent) {
@ -3552,6 +3599,8 @@ int Fl_Darwin_System_Driver::clipboard_contains(const char *type) {
}
void Fl_Cocoa_Window_Driver::destroy(FLWindow *xid) {
if (fl_sys_menu_bar && Fl_Sys_Menu_Bar_Driver::window_menu_style())
Fl_MacOS_Sys_Menu_Bar_Driver::driver()->remove_window([xid getFl_Window]);
[xid close];
}
@ -4291,7 +4340,7 @@ int Fl_Cocoa_Window_Driver::decorated_w()
if (!shown() || parent() || !border() || !visible())
return w();
int bx, by, bt;
get_window_frame_sizes(bx, by, bt);
get_window_frame_sizes(bx, by, bt, pWindow);
return w() + 2 * bx;
}
@ -4300,7 +4349,7 @@ int Fl_Cocoa_Window_Driver::decorated_h()
if (!shown() || parent() || !border() || !visible())
return h();
int bx, by, bt;
get_window_frame_sizes(bx, by, bt);
get_window_frame_sizes(bx, by, bt, pWindow);
return h() + bt + by;
}

View File

@ -1,7 +1,7 @@
//
// "$Id$"
//
// system menu bar widget for the Fast Light Tool Kit (FLTK).
// Definition of class Fl_MacOS_Sys_Menu_Bar_Driver for the Fast Light Tool Kit (FLTK).
//
// Copyright 2017 by Bill Spitzak and others.
//
@ -39,7 +39,12 @@ public:
virtual void remove(int index);
virtual void replace(int index, const char *name);
virtual void mode(int i, int fl);
static Fl_Sys_Menu_Bar_Driver* driver();
virtual void create_window_menu();
int find_first_window();
void new_window(Fl_Window *win);
void remove_window(Fl_Window *win);
void rename_window(Fl_Window *win);
static Fl_MacOS_Sys_Menu_Bar_Driver* driver();
};

View File

@ -3,7 +3,7 @@
//
// Menubar test program for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2010 by Bill Spitzak and others.
// Copyright 1998-2017 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -199,6 +199,7 @@ void menu_location_cb(Fl_Widget* w, void* data)
smenubar->callback(test_cb);
}
else { // switch to window menu bar
menubar->menu(smenubar->menu());
smenubar->clear();
delete smenubar;
menubar->show();
@ -246,6 +247,8 @@ int main(int argc, char **argv) {
Fl_Choice ch2(500,100,150,25,"Use:");
ch2.menu(menu_location);
ch2.callback(menu_location_cb, &menubar);
ch2.value(1);
menu_location_cb(&ch2, &menubar);
#endif
window.end();
@ -257,6 +260,7 @@ int main(int argc, char **argv) {
{0}
};
Fl_Mac_App_Menu::custom_application_menu_items(custom);
//Fl_Sys_Menu_Bar::window_menu_style(Fl_Sys_Menu_Bar::no_window_menu);
#endif
window.show(argc, argv);
return Fl::run();