Mac OS: support for high resolution OpenGL windows.

Methods Fl::event_x_pixel() and Fl::event_y_pixel() committed at r.10941
are removed. Instead method Fl_Gl_Window::pixels_per_unit() is added.

The documentation explains in more detail how to write cross-platform
FLTK code supporting high resolution OpenGL windows on retina displays.

The examples/OpenGL3test.cxx app exercises Fl_Gl_Window::pixels_per_unit().

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10945 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Manolo Gouy
2015-12-02 09:59:37 +00:00
parent 30e572985b
commit 22af09dae7
13 changed files with 38 additions and 97 deletions
+2 -2
View File
@@ -34,8 +34,8 @@ CHANGES IN FLTK 1.3.4 RELEASED: ??? ?? ????
(Apple GL library) to draw OpenGL data. Instead, it uses standard (Apple GL library) to draw OpenGL data. Instead, it uses standard
cocoa APIs. This allows FLTK to support drawing GL scenes at high cocoa APIs. This allows FLTK to support drawing GL scenes at high
resolution when an Fl_Gl_Window is mapped to a 'retina' display. resolution when an Fl_Gl_Window is mapped to a 'retina' display.
- Added Fl_Gl_Window::pixel_w(), Fl_Gl_Window::pixel_h(), Fl::event_x_pixel(), - Added Fl_Gl_Window::pixel_w(), Fl_Gl_Window::pixel_h(), and
and Fl::event_y_pixel() useful for high resolution OpenGL windows. Fl_Gl_Window::pixels_per_unit() useful for high resolution OpenGL windows.
- fl_read_image() now captures all pixels within the rectangle - fl_read_image() now captures all pixels within the rectangle
described by its arguments, whether they belong to a GL scene described by its arguments, whether they belong to a GL scene
or not (STR #3142). It also captures subwindows of GL windows. or not (STR #3142). It also captures subwindows of GL windows.
-26
View File
@@ -135,9 +135,6 @@ public: // should be private!
static int e_y; static int e_y;
static int e_x_root; static int e_x_root;
static int e_y_root; static int e_y_root;
#ifdef __APPLE__
static Fl_Window *e_window_;
#endif
static int e_dx; static int e_dx;
static int e_dy; static int e_dy;
static int e_state; static int e_state;
@@ -604,29 +601,6 @@ public:
event_x(),event_y(). event_x(),event_y().
*/ */
static int event_y_root() {return e_y_root;} static int event_y_root() {return e_y_root;}
#ifdef __APPLE__
static int event_x_pixel();
static int event_y_pixel();
#else
/** Horizontal position in pixels of the mouse event relative to the Fl_Window it was passed to.
Generally identical with Fl::event_x(), but for OpenGL windows of macintosh computers
with a 'retina' display, and if Fl::use_high_res_GL(bool) is set to true,
the returned position, measured in pixels, differs from Fl::event_x(), measured in FLTK units.
\version 1.3.4
*/
static int event_x_pixel() {
return e_x;
}
/** Vertical position in pixels of the mouse event relative to the Fl_Window it was passed to.
Generally identical with Fl::event_y(), but for OpenGL windows of macintosh computers
with a 'retina' display, and if Fl::use_high_res_GL(bool) is set to true,
the returned position, measured in pixels, differs from Fl::event_y(), measured in FLTK units.
\version 1.3.4
*/
static int event_y_pixel() {
return e_y;
}
#endif
/** /**
Returns the current horizontal mouse scrolling associated with the Returns the current horizontal mouse scrolling associated with the
FL_MOUSEWHEEL event. Right is positive. FL_MOUSEWHEEL event. Right is positive.
+15 -6
View File
@@ -229,10 +229,20 @@ public:
// Note: Doxygen docs in Fl_Widget.H to avoid redundancy. // Note: Doxygen docs in Fl_Widget.H to avoid redundancy.
virtual Fl_Gl_Window* as_gl_window() {return this;} virtual Fl_Gl_Window* as_gl_window() {return this;}
#if defined(__APPLE__) #ifdef __APPLE__
int pixel_w(); int pixels_per_unit();
int pixel_h();
#else #else
/** The number of pixels per FLTK unit of length for the window.
Returns 1, except for a window mapped to
an Apple 'retina' display, and if Fl::use_high_res_GL(bool) is set to true,
when it returns 2. This method dynamically adjusts its value when the window
is moved to/from a retina display. This method is useful, e.g., to convert,
in a window's handle() method, the FLTK units returned by Fl::event_x() and
Fl::event_y() to the pixel units used by the OpenGL source code.
\version 1.3.4
*/
int pixels_per_unit() { return 1; }
#endif
/** Gives the window width in OpenGL pixels. /** Gives the window width in OpenGL pixels.
Generally identical with the result of the w() function, but for a window mapped to Generally identical with the result of the w() function, but for a window mapped to
an Apple 'retina' display, and if Fl::use_high_res_GL(bool) is set to true, an Apple 'retina' display, and if Fl::use_high_res_GL(bool) is set to true,
@@ -240,7 +250,7 @@ public:
between low and high resolution displays and automatically adjusts the returned value. between low and high resolution displays and automatically adjusts the returned value.
\version 1.3.4 \version 1.3.4
*/ */
int pixel_w() { return w(); } int pixel_w() { return pixels_per_unit() * w(); }
/** Gives the window height in OpenGL pixels. /** Gives the window height in OpenGL pixels.
Generally identical with the result of the h() function, but for a window mapped to Generally identical with the result of the h() function, but for a window mapped to
an Apple 'retina' display, and if Fl::use_high_res_GL(bool) is set to true, an Apple 'retina' display, and if Fl::use_high_res_GL(bool) is set to true,
@@ -248,8 +258,7 @@ public:
between low and high resolution displays and automatically adjusts the returned value. between low and high resolution displays and automatically adjusts the returned value.
\version 1.3.4 \version 1.3.4
*/ */
int pixel_h() { return h(); } int pixel_h() { return pixels_per_unit() * h(); }
#endif
~Fl_Gl_Window(); ~Fl_Gl_Window();
/** /**
-1
View File
@@ -181,7 +181,6 @@ public:
static void q_begin_image(CGRect&, int x, int y, int w, int h); static void q_begin_image(CGRect&, int x, int y, int w, int h);
static void q_end_image(); static void q_end_image();
// Cocoa additions // Cocoa additions
static int resolution_scaling_factor(Fl_Window*);
static NSOpenGLPixelFormat *mode_to_NSOpenGLPixelFormat(int mode, const int*); // computes NSOpenGLPixelFormat from Gl window's mode static NSOpenGLPixelFormat *mode_to_NSOpenGLPixelFormat(int mode, const int*); // computes NSOpenGLPixelFormat from Gl window's mode
static NSOpenGLContext* create_GLcontext_for_window(NSOpenGLPixelFormat *pixelformat, NSOpenGLContext *shared_ctx, Fl_Window *window); static NSOpenGLContext* create_GLcontext_for_window(NSOpenGLPixelFormat *pixelformat, NSOpenGLContext *shared_ctx, Fl_Window *window);
static void GLcontext_update(NSOpenGLContext*); static void GLcontext_update(NSOpenGLContext*);
+13 -8
View File
@@ -839,16 +839,21 @@ by
\verbatim \verbatim
glViewport(0, 0, pixel_w(), pixel_h()); glViewport(0, 0, pixel_w(), pixel_h());
\endverbatim \endverbatim
making use of the Fl_Gl_Window::pixel_w() and Fl_Gl_Window::pixel_h() functions that return the width and height of making use of the Fl_Gl_Window::pixel_w() and Fl_Gl_Window::pixel_h() methods that return the width and height of
the GL scene in pixels: if the Fl_Gl_Window is mapped on a retina display, these functions return twice as much as the GL scene in pixels: if the Fl_Gl_Window is mapped on a retina display, these methods return twice as much as
reported by Fl_Widget::w() and Fl_Widget::h(); if it's mapped on a regular display, they return the same values as w() and h(). reported by Fl_Widget::w() and Fl_Widget::h(); if it's mapped on a regular display, they return the same values
If you don't call Fl::use_high_res_GL(1), your Fl_Gl_Window 's will be drawn with low resolution. as w() and h(). These methods dynamically change their values if the window is moved into/out from a retina
These functions are synonyms of w() and h() on non-Mac OS X platforms, so your source code remains cross-platform. display. If Fl::use_high_res_GL(1) is not called, all Fl_Gl_Window 's are drawn at low resolution.
These methods are synonyms of w() and h() on non-Mac OS X platforms, so the source code remains cross-platform.
Fl_Double_Window The Fl_Gl_Window::pixels_per_unit() method is useful when the OpenGL code depends on the pixel dimension
of the GL scene. This occurs, e.g., if a window's handle() method uses Fl::event_x() and Fl::event_y()
whose returned values should be multiplied by Fl_Gl_Window::pixels_per_unit() to obtain the adequate pixel units.
This method may also be useful, for example, to adjust the width of a line in a high resolution GL scene.
OS X double-buffers all windows automatically. On OS X, \subsection double_window Fl_Double_Window
Fl_Window and Fl_Double_Window are handled
OS X double-buffers all windows automatically. On OS X, Fl_Window and Fl_Double_Window are handled
internally in the same way. internally in the same way.
\subsection osissues_mac_files Mac File System Specifics \subsection osissues_mac_files Mac File System Specifics
+1 -1
View File
@@ -149,7 +149,7 @@ public:
data[0] *= factor; data[0] *= factor;
glBufferSubData(GL_ARRAY_BUFFER, 24*sizeof(GLfloat), 4*sizeof(GLfloat), data); glBufferSubData(GL_ARRAY_BUFFER, 24*sizeof(GLfloat), 4*sizeof(GLfloat), data);
redraw(); redraw();
add_output("push Fl::event_x_pixel()=%d Fl::event_y_pixel()=%d\n",Fl::event_x_pixel(), Fl::event_y_pixel()); add_output("push Fl_Gl_Window::pixels_per_unit()=%d\n", pixels_per_unit());
return 1; return 1;
} }
return Fl_Gl_Window::handle(event); return Fl_Gl_Window::handle(event);
-15
View File
@@ -86,9 +86,6 @@ Fl_Widget *Fl::belowmouse_,
*Fl::pushed_, *Fl::pushed_,
*Fl::focus_, *Fl::focus_,
*Fl::selection_owner_; *Fl::selection_owner_;
#ifdef __APPLE__
Fl_Window *Fl::e_window_; // the window relative to which Fl::e_x and Fl::e_y are measured
#endif
int Fl::damage_, int Fl::damage_,
Fl::e_number, Fl::e_number,
Fl::e_x, Fl::e_x,
@@ -1093,9 +1090,6 @@ void fl_fix_focus() {
// send a FL_MOVE event so the enter/leave state is up to date // send a FL_MOVE event so the enter/leave state is up to date
Fl::e_x = Fl::e_x_root-fl_xmousewin->x(); Fl::e_x = Fl::e_x_root-fl_xmousewin->x();
Fl::e_y = Fl::e_y_root-fl_xmousewin->y(); Fl::e_y = Fl::e_y_root-fl_xmousewin->y();
#ifdef __APPLE__
Fl::e_window_ = fl_xmousewin;
#endif
int old_event = Fl::e_number; int old_event = Fl::e_number;
w->handle(Fl::e_number = FL_MOVE); w->handle(Fl::e_number = FL_MOVE);
Fl::e_number = old_event; Fl::e_number = old_event;
@@ -1186,19 +1180,10 @@ static int send_event(int event, Fl_Widget* to, Fl_Window* window) {
if (w->type()>=FL_WINDOW) {dx -= w->x(); dy -= w->y();} if (w->type()>=FL_WINDOW) {dx -= w->x(); dy -= w->y();}
int save_x = Fl::e_x; Fl::e_x += dx; int save_x = Fl::e_x; Fl::e_x += dx;
int save_y = Fl::e_y; Fl::e_y += dy; int save_y = Fl::e_y; Fl::e_y += dy;
#ifdef __APPLE__
Fl_Window *save_e_window = Fl::e_window_;
if (dx || dy) {
Fl::e_window_ = (to->as_window() ? to->as_window() : to->window());
}
#endif
int ret = to->handle(Fl::e_number = event); int ret = to->handle(Fl::e_number = event);
Fl::e_number = old_event; Fl::e_number = old_event;
Fl::e_y = save_y; Fl::e_y = save_y;
Fl::e_x = save_x; Fl::e_x = save_x;
#ifdef __APPLE__
Fl::e_window_ = save_e_window;
#endif
return ret; return ret;
} }
+1 -1
View File
@@ -53,7 +53,7 @@ static Fl_RGB_Image* capture_gl_rectangle(Fl_Gl_Window *glw, int x, int y, int w
{ {
#if defined(__APPLE__) #if defined(__APPLE__)
const int bytesperpixel = 4; const int bytesperpixel = 4;
int factor = Fl_X::resolution_scaling_factor(glw); int factor = glw->pixels_per_unit();
if (factor > 1) { if (factor > 1) {
w *= factor; h *= factor; x *= factor; y *= factor; w *= factor; h *= factor; x *= factor; y *= factor;
} }
+2 -7
View File
@@ -96,14 +96,9 @@ void Fl_Gl_Window::show() {
#if defined(__APPLE__) #if defined(__APPLE__)
int Fl_Gl_Window::pixel_w() int Fl_Gl_Window::pixels_per_unit()
{ {
return Fl_X::resolution_scaling_factor(this) * w(); return (fl_mac_os_version >= 100700 && Fl::use_high_res_GL() && Fl_X::i(this) && Fl_X::i(this)->mapped_to_retina()) ? 2 : 1;
}
int Fl_Gl_Window::pixel_h()
{
return Fl_X::resolution_scaling_factor(this) * h();
} }
#endif // __APPLE__ #endif // __APPLE__
-7
View File
@@ -105,16 +105,9 @@ static int send(Fl_Widget* o, int event) {
} }
int save_x = Fl::e_x; Fl::e_x -= o->x(); int save_x = Fl::e_x; Fl::e_x -= o->x();
int save_y = Fl::e_y; Fl::e_y -= o->y(); int save_y = Fl::e_y; Fl::e_y -= o->y();
#ifdef __APPLE__
Fl_Window *save_e_window = Fl::e_window_;
Fl::e_window_ = o->as_window();
#endif
int ret = o->handle(event); int ret = o->handle(event);
Fl::e_y = save_y; Fl::e_y = save_y;
Fl::e_x = save_x; Fl::e_x = save_x;
#ifdef __APPLE__
Fl::e_window_ = save_e_window;
#endif
switch ( event ) switch ( event )
{ {
case FL_ENTER: /* FALLTHROUGH */ case FL_ENTER: /* FALLTHROUGH */
-15
View File
@@ -972,7 +972,6 @@ static void update_e_xy_and_e_xy_root(NSWindow *nsw)
{ {
NSPoint pt; NSPoint pt;
pt = [nsw mouseLocationOutsideOfEventStream]; pt = [nsw mouseLocationOutsideOfEventStream];
Fl::e_window_ = [(FLWindow*)nsw getFl_Window];
Fl::e_x = int(pt.x); Fl::e_x = int(pt.x);
Fl::e_y = int([[nsw contentView] frame].size.height - pt.y); Fl::e_y = int([[nsw contentView] frame].size.height - pt.y);
pt = [NSEvent mouseLocation]; pt = [NSEvent mouseLocation];
@@ -980,13 +979,6 @@ static void update_e_xy_and_e_xy_root(NSWindow *nsw)
Fl::e_y_root = int(main_screen_height - pt.y); Fl::e_y_root = int(main_screen_height - pt.y);
} }
int Fl::event_x_pixel() {
return e_x * Fl_X::resolution_scaling_factor(Fl::e_window_);
}
int Fl::event_y_pixel() {
return e_y * Fl_X::resolution_scaling_factor(Fl::e_window_);
}
/* /*
* Cocoa Mousewheel handler * Cocoa Mousewheel handler
@@ -2740,13 +2732,6 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
@end @end
// For Fl_Gl_Window on retina display, returns 2, otherwise 1
int Fl_X::resolution_scaling_factor(Fl_Window* win)
{
return (fl_mac_os_version >= 100700 && win && win->as_gl_window() && Fl::use_high_res_GL() && win->i && win->i->mapped_to_retina()) ? 2 : 1;
}
NSOpenGLPixelFormat* Fl_X::mode_to_NSOpenGLPixelFormat(int m, const int *alistp) NSOpenGLPixelFormat* Fl_X::mode_to_NSOpenGLPixelFormat(int m, const int *alistp)
{ {
NSOpenGLPixelFormatAttribute attribs[32]; NSOpenGLPixelFormatAttribute attribs[32];
+1 -1
View File
@@ -520,7 +520,7 @@ static gl_texture_fifo *gl_fifo = NULL; // points to the texture pile class inst
// draws a utf8 string using pre-computed texture if available // draws a utf8 string using pre-computed texture if available
static void gl_draw_textures(const char* str, int n) static void gl_draw_textures(const char* str, int n)
{ {
gl_scale = Fl_X::resolution_scaling_factor(Fl_Window::current()); gl_scale = Fl_Window::current()->as_gl_window()->pixels_per_unit();
//fprintf(stderr,"gl_scale=%d\n",gl_scale); //fprintf(stderr,"gl_scale=%d\n",gl_scale);
if (! gl_fifo) gl_fifo = new gl_texture_fifo(); if (! gl_fifo) gl_fifo = new gl_texture_fifo();
if (!gl_fifo->textures_generated) { if (!gl_fifo->textures_generated) {
+1 -5
View File
@@ -83,13 +83,9 @@ int Fl_Glut_Window::handle(int event) {
make_current(); make_current();
int ex = Fl::event_x(); int ex = Fl::event_x();
int ey = Fl::event_y(); int ey = Fl::event_y();
#ifdef __APPLE__ int factor = pixels_per_unit();
if (shown()) {
int factor = Fl_X::resolution_scaling_factor(this);
ex *= factor; ex *= factor;
ey *= factor; ey *= factor;
}
#endif
int button; int button;
switch (event) { switch (event) {