summaryrefslogtreecommitdiff
path: root/src/Fl_cocoa.mm
diff options
context:
space:
mode:
authorManolo Gouy <Manolo>2014-12-20 07:19:23 +0000
committerManolo Gouy <Manolo>2014-12-20 07:19:23 +0000
commitf3a84c0ee5f88fe664d759106724f786c706f817 (patch)
tree3541953164e2d24c31ae46ef11f2c2e86b3873a3 /src/Fl_cocoa.mm
parenta7dc3ea9e24399f318a9478fbcffe04ff2870de6 (diff)
Changed OpenGL support for the Mac OS X platform: use cocoa instead of deprecated AGL.
All changes are mac-specific, except a very minor change in file src/gl_draw.cxx where string drawing wrongly claimed to support @symbol, not possible because symbols are drawn using non-GL primitives. Unchanged application code can use the new FLTK code. In addition, the new code allows mac applications to draw OpenGL scenes at high resolution on so-called 'retina' displays, but this requires some support from app code. They must call, before opening GL windows, Fl::use_high_resolution(1); and change their glViewport() calls as follows glViewport(0, 0, pxel_w(), pixel_h()); This uses 2 new member functions of the Fl_Gl_Window class, pixel_w() and pixel_h() returning the window dimensions in pixel units, that is, twice the w() and h() when the window is mapped on a retina display. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10498 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/Fl_cocoa.mm')
-rw-r--r--src/Fl_cocoa.mm206
1 files changed, 189 insertions, 17 deletions
diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm
index dbbeda052..2d6fca7a0 100644
--- a/src/Fl_cocoa.mm
+++ b/src/Fl_cocoa.mm
@@ -1107,7 +1107,10 @@ static void position_subwindows(Fl_Window *parent, BOOL is_a_move)
NSRect rchild;
Fl_Window *sub = [child getFl_Window];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
- Fl_X::i(sub)->mapped_to_retina( Fl_X::i(parent)->mapped_to_retina() );
+ Fl_X *subx = Fl_X::i(sub);
+ bool previous = subx->mapped_to_retina();
+ subx->mapped_to_retina( Fl_X::i(parent)->mapped_to_retina() );
+ if (previous != subx->mapped_to_retina()) subx->changed_resolution(true);
#endif
rchild.origin = NSMakePoint(pframe.origin.x + sub->x(), pframe.origin.y + parent->h() - (sub->h() + sub->y()));
rchild.size = NSMakeSize(sub->w(), sub->h());
@@ -1143,8 +1146,9 @@ static void compute_mapped_to_retina(Fl_Window *window)
if (fl_mac_os_version >= 100700) { // determine whether window is now mapped to a retina display
Fl_X *flx = Fl_X::i(window);
bool previous = flx->mapped_to_retina();
- NSSize s = [[fl_xid(window) contentView] convertSizeToBacking:NSMakeSize(10, 10)];
+ NSSize s = [[flx->xid contentView] convertSizeToBacking:NSMakeSize(10, 10)];
flx->mapped_to_retina( int(s.width + 0.5) > 10 );
+ if (previous != flx->mapped_to_retina()) flx->changed_resolution(true);
// window needs redrawn when moving from low res to retina
if ((!previous) && flx->mapped_to_retina()) {
window->redraw();
@@ -1152,19 +1156,47 @@ static void compute_mapped_to_retina(Fl_Window *window)
}
}
+#if FLTK_ABI_VERSION >= 10304
+static const unsigned mapped_mask = 1;
+static const unsigned changed_mask = 2;
+#else
+static const unsigned long mapped_mask = 1; // sizeof(unsigned long) = sizeof(Fl_X*)
+static const unsigned long changed_mask = 2;
+#endif
+
bool Fl_X::mapped_to_retina() {
#if FLTK_ABI_VERSION >= 10304
- return (bool)mapped_to_retina_;
+ return mapped_to_retina_ & mapped_mask;
#else
- return xidChildren != NULL;
+ return (unsigned long)xidChildren & mapped_mask;
#endif
}
void Fl_X::mapped_to_retina(bool b) {
#if FLTK_ABI_VERSION >= 10304
- mapped_to_retina_ = b;
+ if (b) mapped_to_retina_ |= mapped;
+ else mapped_to_retina_ &= ~mapped;
+#else
+ if (b) xidChildren = (Fl_X*)((unsigned long)xidChildren | mapped_mask);
+ else xidChildren = (Fl_X*)((unsigned long)xidChildren & ~mapped_mask);
+#endif
+}
+
+bool Fl_X::changed_resolution() {
+#if FLTK_ABI_VERSION >= 10304
+ return mapped_to_retina_ & changed_mask;
#else
- xidChildren = (b ? (Fl_X*)1 : NULL);
+ return (unsigned long)xidChildren & changed_mask;
+#endif
+}
+
+void Fl_X::changed_resolution(bool b) {
+#if FLTK_ABI_VERSION >= 10304
+ if (b) mapped_to_retina_ |= changed_mask;
+ else mapped_to_retina_ &= ~changed_mask;
+#else
+ if (b) xidChildren = (Fl_X*)((unsigned long)xidChildren | changed_mask);
+ else xidChildren = (Fl_X*)((unsigned long)xidChildren & ~changed_mask);
#endif
}
@@ -2162,20 +2194,21 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
cocoaKeyboardHandler(theEvent);
BOOL handled;
NSUInteger mods = [theEvent modifierFlags];
- if ( (mods & NSControlKeyMask) || (mods & NSCommandKeyMask) ) {
+ Fl_Window *w = [(FLWindow*)[theEvent window] getFl_Window];
+ if ( (mods & NSControlKeyMask) || (mods & NSCommandKeyMask) || (w->as_gl_window() && Fl::focus() == w)) {
NSString *s = [theEvent characters];
if ( (mods & NSShiftKeyMask) && (mods & NSCommandKeyMask) ) {
s = [s uppercaseString]; // US keyboards return lowercase letter in s if cmd-shift-key is hit
}
[FLView prepareEtext:s];
Fl::compose_state = 0;
- handled = Fl::handle(FL_KEYBOARD, [(FLWindow*)[theEvent window] getFl_Window]);
+ handled = Fl::handle(FL_KEYBOARD, w);
}
else {
in_key_event = YES;
need_handle = NO;
handled = [self fl_handle_keydown_event:theEvent];
- if (need_handle) handled = Fl::handle(FL_KEYBOARD, [(FLWindow*)[theEvent window] getFl_Window]);
+ if (need_handle) handled = Fl::handle(FL_KEYBOARD, w);
in_key_event = NO;
}
fl_unlock_function();
@@ -2238,8 +2271,13 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
Fl::first_window(window);
cocoaKeyboardHandler(theEvent);
in_key_event = YES;
- need_handle = NO;
- [self fl_handle_keydown_event:theEvent];
+ if (window->as_gl_window() && Fl::focus() == window ) { // ignore text input methods for GL windows
+ need_handle = YES;
+ [FLView prepareEtext:[theEvent characters]];
+ } else {
+ need_handle = NO;
+ [self fl_handle_keydown_event:theEvent];
+ }
if (need_handle) Fl::handle(FL_KEYBOARD, window);
in_key_event = NO;
fl_unlock_function();
@@ -2588,6 +2626,125 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
}
@end
+
+// For Fl_Gl_Window on retina display, returns 2, otherwise 1
+int Fl_X::resolution_scaling_factor(Fl_Window* win)
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+ return (win->as_gl_window() && Fl::use_high_res_GL() && win->i->mapped_to_retina()) ? 2 : 1;
+#else
+ return 1;
+#endif
+}
+
+
+NSOpenGLPixelFormat* Fl_X::mode_to_NSOpenGLPixelFormat(int m, const int *alistp)
+{
+ NSOpenGLPixelFormatAttribute attribs[32];
+ int n = 0;
+ // AGL-style code remains commented out for comparison
+ if (!alistp) {
+ if (m & FL_INDEX) {
+ //list[n++] = AGL_BUFFER_SIZE; list[n++] = 8;
+ } else {
+ //list[n++] = AGL_RGBA;
+ //list[n++] = AGL_GREEN_SIZE;
+ //list[n++] = (m & FL_RGB8) ? 8 : 1;
+ attribs[n++] = NSOpenGLPFAColorSize;
+ attribs[n++] = (m & FL_RGB8) ? 32 : 1;
+ if (m & FL_ALPHA) {
+ //list[n++] = AGL_ALPHA_SIZE;
+ attribs[n++] = NSOpenGLPFAAlphaSize;
+ attribs[n++] = (m & FL_RGB8) ? 8 : 1;
+ }
+ if (m & FL_ACCUM) {
+ //list[n++] = AGL_ACCUM_GREEN_SIZE; list[n++] = 1;
+ attribs[n++] = NSOpenGLPFAAccumSize;
+ attribs[n++] = 1;
+ if (m & FL_ALPHA) {
+ //list[n++] = AGL_ACCUM_ALPHA_SIZE; list[n++] = 1;
+ }
+ }
+ }
+ if (m & FL_DOUBLE) {
+ //list[n++] = AGL_DOUBLEBUFFER;
+ attribs[n++] = NSOpenGLPFADoubleBuffer;
+ }
+ if (m & FL_DEPTH) {
+ //list[n++] = AGL_DEPTH_SIZE; list[n++] = 24;
+ attribs[n++] = NSOpenGLPFADepthSize;
+ attribs[n++] = 24;
+ }
+ if (m & FL_STENCIL) {
+ //list[n++] = AGL_STENCIL_SIZE; list[n++] = 1;
+ attribs[n++] = NSOpenGLPFAStencilSize;
+ attribs[n++] = 1;
+ }
+ if (m & FL_STEREO) {
+ //list[n++] = AGL_STEREO;
+ attribs[n++] = NSOpenGLPFAStereo;
+ }
+ if (m & FL_MULTISAMPLE) {
+ attribs[n++] = NSOpenGLPFAMultisample,
+ attribs[n++] = NSOpenGLPFASampleBuffers; attribs[n++] = 1;
+ attribs[n++] = NSOpenGLPFASamples; attribs[n++] = 4;
+ }
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+ if (fl_mac_os_version >= 100700) {
+ attribs[n++] = NSOpenGLPFAOpenGLProfile;
+ attribs[n++] = NSOpenGLProfileVersionLegacy;
+ }
+#endif
+ } else {
+ while (alistp[n] && n < 30) {
+ attribs[n] = alistp[n];
+ n++;
+ }
+ }
+ attribs[n] = 0;
+ NSOpenGLPixelFormat *pixform = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
+ /*GLint color,alpha,accum,depth;
+ [pixform getValues:&color forAttribute:NSOpenGLPFAColorSize forVirtualScreen:0];
+ [pixform getValues:&alpha forAttribute:NSOpenGLPFAAlphaSize forVirtualScreen:0];
+ [pixform getValues:&accum forAttribute:NSOpenGLPFAAccumSize forVirtualScreen:0];
+ [pixform getValues:&depth forAttribute:NSOpenGLPFADepthSize forVirtualScreen:0];
+ NSLog(@"color=%d alpha=%d accum=%d depth=%d",color,alpha,accum,depth);*/
+ return pixform;
+}
+
+NSOpenGLContext* gl_create_context_for_window(NSOpenGLPixelFormat *pixelformat,
+ NSOpenGLContext *shared_ctx, Fl_Window *window)
+{
+ NSOpenGLContext *context = [[NSOpenGLContext alloc] initWithFormat:pixelformat shareContext:shared_ctx];
+ if (context) [context setView:[fl_xid(window) contentView]];
+ return context;
+}
+
+void gl_context_update(NSOpenGLContext* ctxt)
+{
+ [ctxt update];
+}
+
+void gl_context_flushbuffer(NSOpenGLContext* ctxt)
+{
+ [ctxt flushBuffer];
+}
+
+void gl_context_release(NSOpenGLContext* ctxt)
+{
+ [ctxt release];
+}
+
+void gl_cleardrawable(void)
+{
+ [[NSOpenGLContext currentContext] clearDrawable];
+}
+
+void gl_context_makecurrent(NSOpenGLContext* ctxt)
+{
+ [ctxt makeCurrentContext];
+}
+
void Fl_Window::fullscreen_x() {
_set_fullscreen();
/* On OS X < 10.6, it is necessary to recreate the window. This is done
@@ -2610,15 +2767,19 @@ void Fl_Window::fullscreen_off_x(int X, int Y, int W, int H) {
*/
void Fl_X::flush()
{
- if (through_drawRect || w->as_gl_window()) {
- make_current_counts = 1;
- w->flush();
- make_current_counts = 0;
- Fl_X::q_release_context();
+ if (through_drawRect) {
+ if (w->as_gl_window()) {
+ w->flush();
+ } else {
+ make_current_counts = 1;
+ w->flush();
+ make_current_counts = 0;
+ Fl_X::q_release_context();
+ }
return;
}
// have Cocoa immediately redraw the window's view
- FLView *view = (FLView*)[fl_xid(w) contentView];
+ FLView *view = (FLView*)[xid contentView];
fl_x_to_redraw = this;
[view setNeedsDisplay:YES];
// will send the drawRect: message to the window's view after having prepared the adequate NSGraphicsContext
@@ -2717,6 +2878,7 @@ void Fl_X::make(Fl_Window* w)
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (w->parent()) x->mapped_to_retina( w->top_window()->i->mapped_to_retina() );
else x->mapped_to_retina(false);
+ x->changed_resolution(false);
#endif
NSRect crect;
@@ -2781,6 +2943,11 @@ void Fl_X::make(Fl_Window* w)
Fl_X::first = x;
}
FLView *myview = [[FLView alloc] initWithFrame:crect];
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+ if (w->as_gl_window() && fl_mac_os_version >= 100700 && Fl::use_high_res_GL()) {
+ [myview setWantsBestResolutionOpenGLSurface:YES];
+ }
+#endif
[cw setContentView:myview];
[myview release];
[cw setLevel:winlevel];
@@ -2835,6 +3002,10 @@ void Fl_X::make(Fl_Window* w)
FLWindow *pxid = fl_xid(w->top_window());
[pxid makeFirstResponder:[pxid contentView]];
} else {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+ compute_mapped_to_retina(w);
+ x->changed_resolution(false);
+#endif
[cw makeKeyAndOrderFront:nil];
}
@@ -3928,6 +4099,7 @@ static void write_bitmap_inside(NSBitmapImageRep *to, int to_width, NSBitmapImag
static NSBitmapImageRep* GL_rect_to_nsbitmap(Fl_Window *win, int x, int y, int w, int h)
// captures a rectangle from a GL window and returns it as an allocated NSBitmapImageRep
+// the capture has high res on retina
{
Fl_Plugin_Manager pm("fltk:device");
Fl_Device_Plugin *pi = (Fl_Device_Plugin*)pm.plugin("opengl.device.fltk.org");