summaryrefslogtreecommitdiff
path: root/src/drivers/Cocoa
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2016-03-13 22:16:37 +0000
committerMatthias Melcher <fltk@matthiasm.com>2016-03-13 22:16:37 +0000
commitb496d18b85917106c48e8e6f74115b3122b603d1 (patch)
tree4d96befa4377a81c89c6a32f4d66220199572938 /src/drivers/Cocoa
parent30756ae3500a62bd8f63b4df3eb3ca8f6b8b0b70 (diff)
Fixed 'flush()' code for single, double, and overlay buffering
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11359 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/drivers/Cocoa')
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H9
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx120
2 files changed, 114 insertions, 15 deletions
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
index 419469df7..8a5c8d42e 100644
--- a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
+++ b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
@@ -52,11 +52,13 @@ struct Fl_Window_Driver::shape_data_type {
CGImageRef mask;
};
+
class FL_EXPORT Fl_Cocoa_Window_Driver : public Fl_Window_Driver
{
private:
void shape_bitmap_(Fl_Image* b);
void shape_alpha_(Fl_Image* img, int offset);
+
public:
Fl_Cocoa_Window_Driver(Fl_Window*);
~Fl_Cocoa_Window_Driver();
@@ -65,7 +67,14 @@ public:
virtual int decorated_w();
virtual int decorated_h();
+ // --- window management
virtual void take_focus();
+ virtual void flush_single();
+ virtual void flush_double();
+ virtual void flush_overlay();
+ virtual void draw_begin();
+ virtual void draw_end();
+
virtual void shape(const Fl_Image* img);
virtual void draw();
// that one is implemented in Fl_Cocoa.mm because it uses Objective-c
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx
index 6a4e141d7..0285af9df 100644
--- a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx
+++ b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx
@@ -20,25 +20,14 @@
#include "../../config_lib.h"
#include "Fl_Cocoa_Window_Driver.h"
#include <FL/Fl_Double_Window.H>
+#include <FL/Fl_Overlay_Window.H>
#include <FL/fl_draw.H>
#include <FL/Fl.H>
-// class used for Fl_Double_Window but not for Fl_Overlay_Window
-class Fl_Cocoa_Double_Window_Driver : public Fl_Cocoa_Window_Driver {
-public:
- Fl_Cocoa_Double_Window_Driver(Fl_Window *w) : Fl_Cocoa_Window_Driver(w) {}
- int double_flush(int eraseoverlay) {
- draw();
- return 0;
- }
-};
Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
{
- if (w->as_double_window() && !w->as_double_window()->as_overlay_window())
- return new Fl_Cocoa_Double_Window_Driver(w);
- else
- return new Fl_Cocoa_Window_Driver(w);
+ return new Fl_Cocoa_Window_Driver(w);
}
@@ -47,6 +36,7 @@ Fl_Cocoa_Window_Driver::Fl_Cocoa_Window_Driver(Fl_Window *win)
{
}
+
Fl_Cocoa_Window_Driver::~Fl_Cocoa_Window_Driver()
{
if (shape_data_) {
@@ -57,8 +47,6 @@ Fl_Cocoa_Window_Driver::~Fl_Cocoa_Window_Driver()
}
}
-extern Fl_Window *fl_xfocus;
-
void Fl_Cocoa_Window_Driver::take_focus()
{
@@ -67,6 +55,108 @@ void Fl_Cocoa_Window_Driver::take_focus()
}
+void Fl_Cocoa_Window_Driver::flush_single()
+{
+ if (!pWindow->shown()) return;
+ pWindow->make_current();
+ Fl_X *i = Fl_X::i(pWindow);
+ if (!i) return; // window not yet created
+ fl_clip_region(i->region); i->region = 0;
+ pWindow->draw();
+}
+
+
+void Fl_Cocoa_Window_Driver::flush_double()
+{
+ if (!pWindow->shown()) return;
+ pWindow->make_current();
+ Fl_X *i = Fl_X::i(pWindow);
+ if (!i) return; // window not yet created
+ fl_clip_region(i->region); i->region = 0;
+ pWindow->draw();
+}
+
+
+void Fl_Cocoa_Window_Driver::flush_overlay()
+{
+ Fl_Overlay_Window *oWindow = pWindow->as_overlay_window();
+ if (!oWindow) return flush_single();
+
+ if (!pWindow->shown()) return;
+ pWindow->make_current(); // make sure fl_gc is non-zero
+ Fl_X *i = Fl_X::i(pWindow);
+ if (!i) return; // window not yet created
+
+ int erase_overlay = (pWindow->damage()&FL_DAMAGE_OVERLAY);
+ pWindow->clear_damage((uchar)(pWindow->damage()&~FL_DAMAGE_OVERLAY));
+
+ if (!i->other_xid) {
+ i->other_xid = fl_create_offscreen(pWindow->w(), pWindow->h());
+ pWindow->clear_damage(FL_DAMAGE_ALL);
+ }
+ if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) {
+ fl_clip_region(i->region); i->region = 0;
+ if ( i->other_xid ) {
+ fl_begin_offscreen( i->other_xid );
+ fl_clip_region( 0 );
+ draw();
+ fl_end_offscreen();
+ } else {
+ draw();
+ }
+ }
+ if (erase_overlay) fl_clip_region(0);
+
+ int X,Y,W,H; fl_clip_box(0,0,pWindow->w(),pWindow->h(),X,Y,W,H);
+ if (i->other_xid) fl_copy_offscreen(X, Y, W, H, i->other_xid, X, Y);
+
+ if (oWindow->overlay_ == oWindow) oWindow->draw_overlay();
+}
+
+
+void Fl_Cocoa_Window_Driver::draw_begin()
+{
+ if (shape_data_) {
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if (shape_data_->mask && (&CGContextClipToMask != NULL)) {
+ CGContextClipToMask(fl_gc, CGRectMake(0,0,pWindow->w(),pWindow->h()), shape_data_->mask); // requires Mac OS 10.4
+ }
+ CGContextSaveGState(fl_gc);
+# endif
+ }
+}
+
+
+void Fl_Cocoa_Window_Driver::draw_end()
+{
+ // on OS X, windows have no frame. Before OS X 10.7, to resize a window, we drag the lower right
+ // corner. This code draws a little ribbed triangle for dragging.
+ if (fl_mac_os_version < 100700 && fl_gc && !pWindow->parent() && pWindow->resizable() &&
+ (!pWindow->size_range_set || pWindow->minh!=pWindow->maxh || pWindow->minw!=pWindow->maxw)) {
+ int dx = Fl::box_dw(pWindow->box())-Fl::box_dx(pWindow->box());
+ int dy = Fl::box_dh(pWindow->box())-Fl::box_dy(pWindow->box());
+ if (dx<=0) dx = 1;
+ if (dy<=0) dy = 1;
+ int x1 = pWindow->w()-dx-1, x2 = x1, y1 = pWindow->h()-dx-1, y2 = y1;
+ Fl_Color c[4] = {
+ pWindow->color(),
+ fl_color_average(pWindow->color(), FL_WHITE, 0.7f),
+ fl_color_average(pWindow->color(), FL_BLACK, 0.6f),
+ fl_color_average(pWindow->color(), FL_BLACK, 0.8f),
+ };
+ int i;
+ for (i=dx; i<12; i++) {
+ fl_color(c[i&3]);
+ fl_line(x1--, y1, x2, y2--);
+ }
+ }
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if (shape_data_) CGContextRestoreGState(fl_gc);
+# endif
+}
+
+
+
static void MyProviderReleaseData (void *info, const void *data, size_t size) {
delete[] (uchar*)data;
}