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:
parent
f24ee501b9
commit
d361de4d0d
12
CHANGES
12
CHANGES
@ -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
|
||||
|
@ -24,29 +24,44 @@
|
||||
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();
|
||||
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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__ */
|
||||
|
||||
//
|
||||
|
@ -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)
|
||||
|
||||
//
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user