mirror of
https://github.com/fltk/fltk.git
synced 2026-06-01 23:06:54 +08:00
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:
@@ -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.
|
||||||
|
|||||||
@@ -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
@@ -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();
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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*);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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
@@ -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) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user