]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/xforms/XWorkArea.C
get rid of broken_header.h and some unneeded tests
[lyx.git] / src / frontends / xforms / XWorkArea.C
index ccd54b484c0675cf309b982f2f1ce5fd7ea93a11..51f9a4e405b439b75818cbdeacb50ee1f926a4f8 100644 (file)
@@ -6,27 +6,38 @@
  * \author unknown
  * \author John Levon
  *
- * Full author contact details are available in file CREDITS
+ * Full author contact details are available in file CREDITS.
  */
 
 #include <config.h>
 
-
 #include "XWorkArea.h"
-#include "debug.h"
+
+#include "Color.h"
+#include "XFormsView.h"
 #include "XLyXKeySym.h"
+
+#include "debug.h"
 #include "funcrequest.h"
+#include "LColor.h"
 #include "Timeout.h"
 
-using std::endl;
+#include <boost/bind.hpp>
+
+using boost::shared_ptr;
+
 using std::abs;
-using std::hex;
 using std::dec;
+using std::endl;
+using std::hex;
+using std::string;
+
+namespace lyx {
+namespace frontend {
 
 namespace {
 
-inline
-void waitForX(bool discard)
+inline void waitForX(bool discard)
 {
        XSync(fl_get_display(), discard);
 }
@@ -95,25 +106,27 @@ int C_event_cb(FL_FORM * form, void * xev)
 } // namespace anon
 
 
-XWorkArea::XWorkArea(int x, int y, int w, int h)
+XWorkArea::XWorkArea(LyXView & owner, int w, int h)
        : workareapixmap(0), painter_(*this)
 {
-       if (lyxerr.debugging(Debug::WORKAREA)) {
-               lyxerr << "\tbackground box: +"
-                      << x << '+' << y << ' '
-                      << w - 15 << 'x' << h << endl;
-       }
-
        fl_freeze_all_forms();
 
        FL_OBJECT * obj;
+       FL_OBJECT * frame;
 
-       obj = fl_add_box(FL_BORDER_BOX, x, y, w - 15, h, "");
+       // A frame around the work area.
+       frame = obj = fl_add_box(FL_BORDER_BOX, 0, 0, w, h, "");
        fl_set_object_resize(obj, FL_RESIZE_ALL);
        fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity);
 
-       scrollbar = obj = fl_add_scrollbar(FL_VERT_SCROLLBAR,
-                                          x + w - 15, y, 17, h, "");
+       unsigned int r, g, b;
+       if (getRGBColor(LColor::background, r, g, b)) {
+               fl_mapcolor(FL_FREE_COL12, r, g, b);
+               fl_set_object_color(obj, FL_FREE_COL12, FL_MCOL);
+       }
+
+       // The scrollbar.
+       scrollbar = obj = fl_add_scrollbar(FL_VERT_SCROLLBAR, 0, 0, w, h, "");
        fl_set_object_boxtype(obj, FL_UP_BOX);
        fl_set_object_resize(obj, FL_RESIZE_ALL);
        fl_set_object_gravity(obj, NorthEastGravity, SouthEastGravity);
@@ -123,24 +136,8 @@ XWorkArea::XWorkArea(int x, int y, int w, int h)
        fl_set_scrollbar_value(scrollbar, 0.0);
        fl_set_scrollbar_size(scrollbar, scrollbar->h);
 
-       int const bw = int(abs(fl_get_border_width()));
-
-       // Create the workarea pixmap
-       // FIXME remove redraw(w - 15 - 2 * bw, h - 2 * bw);
-
-       if (lyxerr.debugging(Debug::WORKAREA))
-               lyxerr << "\tfree object: +"
-                      << x + bw << '+' << y + bw << ' '
-                      << w - 15 - 2 * bw << 'x'
-                      << h - 2 * bw << endl;
-
-       // We add this object as late as possible to avoid problems
-       // with drawing.
-       // FIXME: like ??
-       work_area = obj = fl_add_free(FL_ALL_FREE,
-                                     x + bw, y + bw,
-                                     w - 15 - 2 * bw,
-                                     h - 2 * bw, "",
+       // The work area itself
+       work_area = obj = fl_add_free(FL_ALL_FREE, 0, 0, w, h, "",
                                      C_work_area_handler);
        obj->wantkey = FL_KEY_ALL;
        obj->u_vdata = this;
@@ -149,6 +146,26 @@ XWorkArea::XWorkArea(int x, int y, int w, int h)
        fl_set_object_resize(obj, FL_RESIZE_ALL);
        fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity);
 
+       // Hand control of the layout of these widgets to the
+       // Layout Engine.
+       XFormsView & xview = dynamic_cast<XFormsView &>(owner);
+       BoxList & boxlist = xview.getBox(XFormsView::Center)->children();
+
+       wa_box_ = boxlist.push_back(Box(0,0));
+       wa_box_->set(Box::Horizontal);
+
+       shared_ptr<Box> frame_box = widgets_.add(frame, wa_box_->children(), 0, 0);
+       frame_box->set(Box::Expand);
+
+       int const bw = int(abs(fl_get_border_width()));
+       shared_ptr<Box> wa_box = embed(work_area, frame_box->children(), widgets_, bw);
+       wa_box->set(Box::Expand);
+
+       widgets_.add(scrollbar, wa_box_->children(), 17, 0);
+
+       xview.metricsUpdated.connect(boost::bind(&WidgetMap::updateMetrics,
+                                                &widgets_));
+
        /// X selection hook - xforms gets it wrong
        fl_current_form->u_vdata = this;
        fl_register_raw_callback(fl_current_form, FL_ALL_EVENT, C_event_cb);
@@ -158,8 +175,9 @@ XWorkArea::XWorkArea(int x, int y, int w, int h)
        XGCValues val;
 
        val.function = GXcopy;
+       val.graphics_exposures = false;
        copy_gc = XCreateGC(fl_get_display(), RootWindow(fl_get_display(), 0),
-                           GCFunction, &val);
+                           GCFunction | GCGraphicsExposures, &val);
 }
 
 
@@ -171,17 +189,13 @@ XWorkArea::~XWorkArea()
 }
 
 
-void XWorkArea::redraw(int width, int height)
+void XWorkArea::updateGeometry(int width, int height)
 {
        static int cur_width = -1;
        static int cur_height = -1;
 
-       if (cur_width == width && cur_height == height && workareapixmap) {
-               XCopyArea(fl_get_display(),
-                         getPixmap(), getWin(), copy_gc,
-                         0, 0, width, height, xpos(), ypos());
+       if (cur_width == width && cur_height == height && workareapixmap)
                return;
-       }
 
        cur_width = width;
        cur_height = height;
@@ -205,6 +219,20 @@ void XWorkArea::redraw(int width, int height)
 }
 
 
+void XWorkArea::paint(int x, int y, int w, int h)
+{
+       lyxerr[Debug::WORKAREA]
+               << "XWorkarea::paint " << w << 'x' << h
+               << '+' << x << '+' << y << endl;
+
+       updateGeometry(workWidth(), workHeight());
+       XCopyArea(fl_get_display(),
+                 getPixmap(), getWin(),
+                 copy_gc, x, y, w, h,
+                 work_area->x + x, work_area->y + y);
+}
+
+
 void XWorkArea::setScrollbarParams(int height, int pos, int line_height)
 {
        // we need to cache this for scroll_cb
@@ -262,25 +290,78 @@ void XWorkArea::scroll_cb()
        waitForX(false);
 }
 
+
 int XWorkArea::work_area_handler(FL_OBJECT * ob, int event,
                                 FL_Coord, FL_Coord,
                                 int key, void * xev)
 {
+       if (event != 11)
+               lyxerr[Debug::WORKAREA] << "Workarea event: EVENT: " << event << endl;
+
        XEvent * ev = static_cast<XEvent*>(xev);
        XWorkArea * area = static_cast<XWorkArea*>(ob->u_vdata);
 
-       if (!area) return 1;
+       if (!area)
+               return 1;
 
        switch (event) {
-       case FL_DRAW:
+
+       case FL_DRAW: {
                if (!area->work_area || !area->work_area->form->visible)
                        return 1;
-               lyxerr[Debug::WORKAREA] << "Workarea event: DRAW" << endl;
-               area->redraw(area->workWidth(), area->workHeight());
+
+               if (ev) {
+                       lyxerr[Debug::WORKAREA]
+                               << "work_area_handler, handling X11 "
+                               "expose event "
+                               << ev->xexpose.width << 'x'
+                               << ev->xexpose.height << '+'
+                               << ev->xexpose.x << '+'
+                               << ev->xexpose.y << endl;
+
+                       // X11 generates XEvents with x, y relative to the
+                       // top left corner of the window.
+                       // XScreen::expose emulates this behaviour.
+                       // We therefore need to remove this offset before
+                       // generating the pixmap.
+                        int const x = ev->xexpose.x - ob->x;
+                        int const y = ev->xexpose.y - ob->y;
+
+                       area->paint(x, y,
+                                   ev->xexpose.width, ev->xexpose.height);
+               } else
+                       area->paint(0, 0,
+                                   area->workWidth(), area->workHeight());
+
                break;
+       }
+
        case FL_PUSH:
                if (!ev || ev->xbutton.button == 0) break;
+
+               if (ev->xbutton.button == 4 || ev->xbutton.button == 5) {
+                       static long last_wheel;
+
+                       long cur_wheel = ev->xbutton.time;
+                       if (last_wheel == cur_wheel)
+                               break;
+
+                       last_wheel = cur_wheel;
+
+                       float l, r;
+                       fl_get_scrollbar_increment(area->scrollbar, &l, &r);
+
+                       if (ev->xbutton.button == 4)
+                               l *= -1.0;
+
+                       fl_set_scrollbar_value(
+                               area->scrollbar,
+                               fl_get_scrollbar_value(area->scrollbar) + l);
+
+                       area->scroll_cb();
+                       break;
+               }
+
                // Should really have used xbutton.state
                lyxerr[Debug::WORKAREA] << "Workarea event: PUSH" << endl;
                area->dispatch(
@@ -289,18 +370,28 @@ int XWorkArea::work_area_handler(FL_OBJECT * ob, int event,
                                    ev->xbutton.y - ob->y,
                                    x_button_state(key)));
                break;
+
        case FL_RELEASE:
                if (!ev || ev->xbutton.button == 0) break;
                // Should really have used xbutton.state
+
+               if (ev->xbutton.button == 4 || ev->xbutton.button == 5) {
+                       // We ingnore wheel event here
+                       break;
+               }
+
                lyxerr[Debug::WORKAREA] << "Workarea event: RELEASE" << endl;
+
                area->dispatch(
                        FuncRequest(LFUN_MOUSE_RELEASE,
                                    ev->xbutton.x - ob->x,
                                    ev->xbutton.y - ob->y,
                                    x_button_state(key)));
                break;
-       case FL_DRAG:
-       {
+
+       case FL_DRAG: {
+               lyxerr[Debug::WORKAREA] << "Workarea event: DRAG 0" << endl;
+
                if (!ev || !area->scrollbar)
                        break;
 
@@ -365,8 +456,7 @@ int XWorkArea::work_area_handler(FL_OBJECT * ob, int event,
                break;
        }
 
-       case FL_KEYPRESS:
-       {
+       case FL_KEYPRESS: {
                lyxerr[Debug::WORKAREA] << "Workarea event: KEYPRESS" << endl;
 
                KeySym keysym = 0;
@@ -454,8 +544,8 @@ int XWorkArea::work_area_handler(FL_OBJECT * ob, int event,
 
                area->workAreaKeyPress(LyXKeySymPtr(xlk),
                                       x_key_state(ret_state));
+               break;
        }
-       break;
 
        case FL_KEYRELEASE:
                lyxerr[Debug::WORKAREA] << "Workarea event: KEYRELEASE" << endl;
@@ -465,13 +555,21 @@ int XWorkArea::work_area_handler(FL_OBJECT * ob, int event,
                lyxerr[Debug::WORKAREA] << "Workarea event: ENTER" << endl;
                fl_set_cursor(FL_ObjWin(area->work_area), XC_xterm);
                break;
+
        case FL_LEAVE:
                lyxerr[Debug::WORKAREA] << "Workarea event: LEAVE" << endl;
                // There should be no need for this. But there is.
                fl_set_cursor(FL_ObjWin(area->work_area), FL_DEFAULT_CURSOR);
                break;
+
        case FL_DBLCLICK:
                if (ev) {
+                       if (ev->xbutton.button == 4 || ev->xbutton.button == 5) {
+                               // Ignore wheel events
+                               break;
+                       }
+
+
                        lyxerr[Debug::WORKAREA] << "Workarea event: DBLCLICK" << endl;
                        FuncRequest cmd(LFUN_MOUSE_DOUBLE,
                                        ev->xbutton.x - ob->x,
@@ -480,8 +578,14 @@ int XWorkArea::work_area_handler(FL_OBJECT * ob, int event,
                        area->dispatch(cmd);
                }
                break;
+
        case FL_TRPLCLICK:
                if (ev) {
+                       if (ev->xbutton.button == 4 || ev->xbutton.button == 5) {
+                               // Ignore wheel events
+                               break;
+                       }
+
                        lyxerr[Debug::WORKAREA] << "Workarea event: TRPLCLICK" << endl;
                        FuncRequest cmd(LFUN_MOUSE_TRIPLE,
                                        ev->xbutton.x - ob->x,
@@ -490,6 +594,7 @@ int XWorkArea::work_area_handler(FL_OBJECT * ob, int event,
                        area->dispatch(cmd);
                }
                break;
+
        case FL_OTHER:
                if (ev)
                        lyxerr[Debug::WORKAREA] << "Workarea event: OTHER" << endl;
@@ -576,3 +681,6 @@ void XWorkArea::putClipboard(string const & s) const
 
        fl_stuff_clipboard(work_area, 0, hold.data(), hold.size(), 0);
 }
+
+} // namespace frontend
+} // namespace lyx