void Layout::updateRepaintWidget() { XOJ_CHECK_TYPE(Layout); GtkWidget* widget = this->view->getWidget(); GtkXournal* xournal = GTK_XOURNAL(widget); xournal->x = this->scrollHorizontal->getValue(); xournal->y = this->scrollVertical->getValue(); gtk_widget_queue_draw(widget); }
static gboolean gtk_xournal_key_press_event(GtkWidget* widget, GdkEventKey* event) { g_return_val_if_fail(widget != NULL, false); g_return_val_if_fail(GTK_IS_XOURNAL(widget), false); g_return_val_if_fail(event != NULL, false); GtkXournal* xournal = GTK_XOURNAL(widget); EditSelection* selection = xournal->selection; if (selection) { int d = 3; if ((event->state & GDK_MOD1_MASK) || (event->state & GDK_SHIFT_MASK)) { if ( event->state & GDK_MOD1_MASK ) { d = 1; } else { d = 20; } } if (event->keyval == GDK_Left) { selection->moveSelection(d, 0); return true; } else if (event->keyval == GDK_Up) { selection->moveSelection(0, d); return true; } else if (event->keyval == GDK_Right) { selection->moveSelection(-d, 0); return true; } else if (event->keyval == GDK_Down) { selection->moveSelection(0, -d); return true; } } return xournal->view->onKeyPressEvent(event); }
static void gtk_xournal_size_allocate(GtkWidget * widget, GtkAllocation * allocation) { g_return_if_fail(widget != NULL); g_return_if_fail(GTK_IS_XOURNAL(widget)); g_return_if_fail(allocation != NULL); widget->allocation = *allocation; if (GTK_WIDGET_REALIZED(widget)) { gdk_window_move_resize(widget->window, allocation->x, allocation->y, allocation->width, allocation->height); } GtkXournal * xournal = GTK_XOURNAL(widget); xournal->layout->setSize(allocation->width, allocation->height); }
cairo_t * gtk_xournal_create_cairo_for(GtkWidget * widget, PageView * view) { g_return_val_if_fail(widget != NULL, FALSE); g_return_val_if_fail(GTK_IS_XOURNAL(widget), FALSE); GtkXournal * xournal = GTK_XOURNAL(widget); double zoom = xournal->view->getZoom(); // TODO LOW PRIO: stroke draw to this cairo surface look a little different than rendererd to a cairo surface cairo_t * cr = gdk_cairo_create(GTK_WIDGET(widget)->window); int x = view->getX() - xournal->x; int y = view->getY() - xournal->y; cairo_translate(cr, x, y); cairo_scale(cr, zoom, zoom); return cr; }
gboolean gtk_xournal_motion_notify_event(GtkWidget * widget, GdkEventMotion * event) { #ifdef INPUT_DEBUG bool is_core = (event->device == gdk_device_get_core_pointer()); INPUTDBG("MotionNotify (%s) (x,y)=(%.2f,%.2f), modifier %x", is_core ? "core" : "xinput", event->x, event->y, event->state); #endif XInputUtils::fixXInputCoords((GdkEvent*) event, widget); GtkXournal * xournal = GTK_XOURNAL(widget); ToolHandler * h = xournal->view->getControl()->getToolHandler(); if (h->getToolType() == TOOL_HAND) { if (xournal->inScrolling) { gtk_xournal_scroll_mouse_event(xournal, event); return true; } return false; } else if (xournal->selection) { EditSelection * selection = xournal->selection; PageView * view = selection->getView(); GdkEventMotion ev = *event; view->translateEvent((GdkEvent*) &ev, xournal->x, xournal->y); if (xournal->selection->isMoving()) { selection->mouseMove(ev.x, ev.y); } else { CursorSelectionType selType = selection->getSelectionTypeForPos(ev.x, ev.y, xournal->view->getZoom()); xournal->view->getCursor()->setMouseSelectionType(selType); } return true; } PageView * pv = gtk_xournal_get_page_view_for_pos_cached(xournal, event->x, event->y); xournal->view->getCursor()->setInsidePage(pv != NULL); if (pv) { // allow events only to a single page! if (xournal->currentInputPage == NULL || pv == xournal->currentInputPage) { pv->translateEvent((GdkEvent*) event, xournal->x, xournal->y); return pv->onMotionNotifyEvent(widget, event);; } } return false; }
gboolean gtk_xournal_button_release_event(GtkWidget * widget, GdkEventButton * event) { #ifdef INPUT_DEBUG gboolean isCore = (event->device == gdk_device_get_core_pointer()); INPUTDBG("ButtonRelease (%s) (x,y)=(%.2f,%.2f), button %d, modifier %x, isCore %i", gdk_device_get_name(event->device), event->x, event->y, event->button, event->state, isCore); #endif XInputUtils::fixXInputCoords((GdkEvent*) event, widget); if (event->button > 3) { // scroll wheel events return true; } GtkXournal * xournal = GTK_XOURNAL(widget); Cursor * cursor = xournal->view->getCursor(); ToolHandler * h = xournal->view->getControl()->getToolHandler(); cursor->setMouseDown(false); xournal->inScrolling = false; EditSelection * sel = xournal->view->getSelection(); if (sel) { sel->mouseUp(); } bool res = false; if (xournal->currentInputPage) { xournal->currentInputPage->translateEvent((GdkEvent*) event, xournal->x, xournal->y); res = xournal->currentInputPage->onButtonReleaseEvent(widget, event); xournal->currentInputPage = NULL; } EditSelection * tmpSelection = xournal->selection; xournal->selection = NULL; h->restoreLastConfig(); // we need this workaround so it's possible to select something with the middle button if (tmpSelection) { xournal->view->setSelection(tmpSelection); } return res; }
static void gtk_xournal_destroy(GtkObject * object) { g_return_if_fail(object != NULL); g_return_if_fail(GTK_IS_XOURNAL(object)); GtkXournal * xournal = GTK_XOURNAL(object); delete xournal->pagePositionCache; xournal->pagePositionCache = NULL; delete xournal->selection; xournal->selection = NULL; delete xournal->layout; xournal->layout = NULL; GtkXournalClass * klass = (GtkXournalClass *) gtk_type_class(gtk_widget_get_type()); if (GTK_OBJECT_CLASS(klass)->destroy) { (*GTK_OBJECT_CLASS(klass)->destroy)(object); } }
void XournalView::setSelection(EditSelection* selection) { XOJ_CHECK_TYPE(XournalView); clearSelection(); GTK_XOURNAL(this->widget)->selection = selection; control->setClipboardHandlerSelection(getSelection()); bool canChangeSize = false; bool canChangeColor = false; ListIterator<Element*> it = selection->getElements(); while (it.hasNext()) { Element* e = it.next(); if (e->getType() == ELEMENT_TEXT) { canChangeColor = true; } else if (e->getType() == ELEMENT_STROKE) { Stroke* s = (Stroke*) e; if (s->getToolType() != STROKE_TOOL_ERASER) { canChangeColor = true; } canChangeSize = true; } if (canChangeColor && canChangeSize) { break; } } control->getToolHandler()->setSelectionEditTools(canChangeColor, canChangeSize); repaintSelection(); }
GtkWidget * gtk_xournal_new(XournalView * view) { GtkXournal * xoj = GTK_XOURNAL(gtk_type_new(gtk_xournal_get_type())); xoj->view = view; xoj->scrollX = 0; xoj->scrollY = 0; xoj->x = 0; xoj->y = 0; xoj->layout = new Layout(view); xoj->currentInputPage = NULL; xoj->pagePositionCache = new PagePositionCache(); xoj->lastMousePositionX = 0; xoj->lastMousePositionY = 0; xoj->scrollOffsetX = 0; xoj->scrollOffsetY = 0; xoj->inScrolling = false; xoj->selection = NULL; return GTK_WIDGET(xoj); }
Rectangle* gtk_xournal_get_visible_area(GtkWidget* widget, PageView* p) { g_return_val_if_fail(widget != NULL, NULL); g_return_val_if_fail(GTK_IS_XOURNAL(widget), NULL); GtkXournal* xournal = GTK_XOURNAL(widget); GtkAllocation allocation = { 0 }; gtk_widget_get_allocation(widget, &allocation); int viewHeight = allocation.height; int viewWidth = allocation.width; GdkRectangle r1; GdkRectangle r2; GdkRectangle r3 = { 0, 0, 0, 0 }; r1.x = p->getX(); r1.y = p->getY(); r1.width = p->getDisplayWidth(); r1.height = p->getDisplayHeight(); r2.x = xournal->x; r2.y = xournal->y; r2.width = viewWidth; r2.height = viewHeight; gdk_rectangle_intersect(&r1, &r2, &r3); if (r3.width == 0 && r3.height == 0) { return NULL; } double zoom = xournal->view->getZoom(); return new Rectangle(MAX(r3.x, 0) / zoom, MAX(r3.y, 0) / zoom, r3.width / zoom, r3.height / zoom); }
void gtk_xournal_repaint_area(GtkWidget * widget, int x1, int y1, int x2, int y2) { g_return_if_fail(widget != NULL); g_return_if_fail(GTK_IS_XOURNAL(widget)); GtkXournal * xournal = GTK_XOURNAL(widget); x1 -= xournal->x; x2 -= xournal->x; y1 -= xournal->y; y2 -= xournal->y; if (x2 < 0 || y2 < 0) { return; // outside visible area } GtkAllocation alloc = { 0 }; gtk_widget_get_allocation(widget, &alloc); if (x1 > alloc.width || y1 > alloc.height) { return; // outside visible area } gtk_widget_queue_draw_area(widget, x1, y1, x2 - x1, y2 - y1); }
/** * Change event handling between XInput and Core */ void gtk_xournal_update_xevent(GtkWidget * widget) { g_return_if_fail(widget != NULL); g_return_if_fail(GTK_IS_XOURNAL(widget)); GtkXournal * xournal = GTK_XOURNAL(widget); Settings * settings = xournal->view->getControl()->getSettings(); if (!gtk_check_version(2, 17, 0)) { /* GTK+ 2.17 and later: everybody shares a single native window, so we'll never get any core events, and we might as well set extension events the way we're supposed to. Doing so helps solve crasher bugs in 2.17, and prevents us from losing two-button events in 2.18 */ gtk_widget_set_extension_events(widget, settings->isUseXInput() ? GDK_EXTENSION_EVENTS_ALL : GDK_EXTENSION_EVENTS_NONE); } else { /* GTK+ 2.16 and earlier: we only activate extension events on the PageViews's parent GdkWindow. This allows us to keep receiving core events. */ gdk_input_set_extension_events(widget->window, GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK, settings->isUseXInput() ? GDK_EXTENSION_EVENTS_ALL : GDK_EXTENSION_EVENTS_NONE); } }
static gboolean gtk_xournal_expose(GtkWidget* widget, GdkEventExpose* event) { g_return_val_if_fail(widget != NULL, FALSE); g_return_val_if_fail(GTK_IS_XOURNAL(widget), FALSE); g_return_val_if_fail(event != NULL, FALSE); GtkXournal* xournal = GTK_XOURNAL(widget); gdk_threads_enter(); cairo_t* cr = gdk_cairo_create(GTK_WIDGET(widget)->window); ArrayIterator<PageView*> it = xournal->view->pageViewIterator(); GtkAllocation alloc = { 0 }; gtk_widget_get_allocation(widget, &alloc); int lastVisibleX = alloc.width + xournal->x + 10; int lastVisibleY = alloc.height + xournal->y + 10; //+10 fix to draw the shadow int firstVisibleX = xournal->x - 10; int firstVisibleY = xournal->y - 10; while (it.hasNext()) { PageView* pv = it.next(); int px = pv->getX(); int py = pv->getY(); int pw = pv->getDisplayWidth(); int ph = pv->getDisplayHeight(); // not visible, its on the right side of the visible area if (px > lastVisibleX) { continue; } // not visible, its on the left side of the visible area if (px + pw < firstVisibleX) { continue; } // not visible, its on the bottom side of the visible area if (py > lastVisibleY) { continue; } // not visible, its on the top side of the visible area if (py + ph < firstVisibleY) { continue; } int x = px - xournal->x; int y = py - xournal->y; gtk_xournal_draw_shadow(xournal, cr, x, y, pw, ph, pv->isSelected()); cairo_save(cr); cairo_translate(cr, x, y); GdkRectangle rect = event->area; rect.x -= x; rect.y -= y; pv->paintPage(cr, &rect); cairo_restore(cr); } if (xournal->selection) { double zoom = xournal->view->getZoom(); int px = xournal->selection->getXOnView() * zoom; int py = xournal->selection->getYOnView() * zoom; // int pw = xournal->selection->getWidth() * zoom; // int ph = xournal->selection->getHeight() * zoom; // not visible, its on the right side of the visible area if (px > lastVisibleX) { printf("Warning: object on right side of visible area.\n"); } else // not visible, its on the left side of the visible area // TODO LOW PRIO this is not working correct if the zoom is small, xournal->x is never smaller than 0 // if (px + pw < firstVisibleX) { // printf("test2\n"); // } else // not visible, its on the bottom side of the visible area if (py > lastVisibleY) { printf("Warning: object below visible area.\n"); // } else // // not visible, its on the top side of the visible area // if (py + ph < firstVisibleY) { // printf("test4 %i:: %i\n", py + ph, firstVisibleY); } else { Redrawable* red = xournal->selection->getView(); cairo_translate(cr, red->getX() - xournal->x, red->getY() - xournal->y); xournal->selection->paint(cr, zoom); } } cairo_destroy(cr); gdk_threads_leave(); return true; }
gboolean gtk_xournal_button_press_event(GtkWidget* widget, GdkEventButton* event) { /** * true: Core event, false: XInput event */ gboolean isCore = (event->device == gdk_device_get_core_pointer()); INPUTDBG("ButtonPress (%s) (x,y)=(%.2f,%.2f), button %d, modifier %x, isCore %i", gdk_device_get_name(event->device), event->x, event->y, event->button, event->state, isCore); GtkXournal* xournal = GTK_XOURNAL(widget); Settings* settings = xournal->view->getControl()->getSettings(); if(isCore && settings->isXinputEnabled() && settings->isIgnoreCoreEvents()) { INPUTDBG2("gtk_xournal_button_press_event return false (ignore core)"); return false; } XInputUtils::fixXInputCoords((GdkEvent*) event, widget); if (event->type != GDK_BUTTON_PRESS) { INPUTDBG2("gtk_xournal_button_press_event return false (event->type != GDK_BUTTON_PRESS)"); return false; // this event is not handled here } if (event->button > 3) // scroll wheel events { XInputUtils::handleScrollEvent(event, widget); INPUTDBG2("gtk_xournal_button_press_event return true handled scroll event"); return true; } gtk_widget_grab_focus(widget); // none button release event was sent, send one now if (xournal->currentInputPage) { INPUTDBG2("gtk_xournal_button_press_event (xournal->currentInputPage != NULL)"); GdkEventButton ev = *event; xournal->currentInputPage->translateEvent((GdkEvent*) &ev, xournal->x, xournal->y); xournal->currentInputPage->onButtonReleaseEvent(widget, &ev); } ToolHandler* h = xournal->view->getControl()->getToolHandler(); // Change the tool depending on the key or device if(change_tool(settings, event, xournal)) return true; // hand tool don't change the selection, so you can scroll e.g. // with your touchscreen without remove the selection if (h->getToolType() == TOOL_HAND) { Cursor* cursor = xournal->view->getCursor(); cursor->setMouseDown(true); xournal->lastMousePositionX = 0; xournal->lastMousePositionY = 0; xournal->inScrolling = true; gtk_widget_get_pointer(widget, &xournal->lastMousePositionX, &xournal->lastMousePositionY); INPUTDBG2("gtk_xournal_button_press_event (h->getToolType() == TOOL_HAND) return true"); return true; } else if (xournal->selection) { EditSelection* selection = xournal->selection; PageView* view = selection->getView(); GdkEventButton ev = *event; view->translateEvent((GdkEvent*) &ev, xournal->x, xournal->y); CursorSelectionType selType = selection->getSelectionTypeForPos(ev.x, ev.y, xournal->view->getZoom()); if (selType) { if(selType == CURSOR_SELECTION_MOVE && event->button == 3) { selection->copySelection(); } xournal->view->getCursor()->setMouseDown(true); xournal->selection->mouseDown(selType, ev.x, ev.y); INPUTDBG2("gtk_xournal_button_press_event (selection) return true"); return true; } else { xournal->view->clearSelection(); if(change_tool(settings, event, xournal)) return true; } } PageView* pv = gtk_xournal_get_page_view_for_pos_cached(xournal, event->x, event->y); current_view = pv; if (pv) { xournal->currentInputPage = pv; pv->translateEvent((GdkEvent*) event, xournal->x, xournal->y); INPUTDBG2("gtk_xournal_button_press_event (pv->onButtonPressEvent) return"); xournal->view->getDocument()->indexOf(pv->getPage()); return pv->onButtonPressEvent(widget, event); } INPUTDBG2("gtk_xournal_button_press_event (not handled) return false"); return false; // not handled }
gboolean gtk_xournal_button_press_event(GtkWidget * widget, GdkEventButton * event) { /** * true: Core event, false: XInput event */ gboolean isCore = (event->device == gdk_device_get_core_pointer()); INPUTDBG("ButtonPress (%s) (x,y)=(%.2f,%.2f), button %d, modifier %x, isCore %i", gdk_device_get_name(event->device), event->x, event->y, event->button, event->state, isCore); GtkXournal * xournal = GTK_XOURNAL(widget); Settings * settings = xournal->view->getControl()->getSettings(); if(isCore && settings->isXinputEnabled() && settings->isIgnoreCoreEvents()) { INPUTDBG2("gtk_xournal_button_press_event return false (ignore core)"); return false; } XInputUtils::fixXInputCoords((GdkEvent*) event, widget); if (event->type != GDK_BUTTON_PRESS) { INPUTDBG2("gtk_xournal_button_press_event return false (event->type != GDK_BUTTON_PRESS)"); return false; // this event is not handled here } if (event->button > 3) { // scroll wheel events XInputUtils::handleScrollEvent(event, widget); INPUTDBG2("gtk_xournal_button_press_event return true handled scroll event"); return true; } gtk_widget_grab_focus(widget); ToolHandler * h = xournal->view->getControl()->getToolHandler(); // none button release event was sent, send one now if (xournal->currentInputPage) { INPUTDBG2("gtk_xournal_button_press_event (xournal->currentInputPage != NULL)"); GdkEventButton ev = *event; xournal->currentInputPage->translateEvent((GdkEvent*) &ev, xournal->x, xournal->y); xournal->currentInputPage->onButtonReleaseEvent(widget, &ev); } // Change the tool depending on the key or device ButtonConfig * cfg = NULL; ButtonConfig * cfgTouch = settings->getTouchButtonConfig(); if (event->button == 2) { // Middle Button cfg = settings->getMiddleButtonConfig(); } else if (event->button == 3) { // Right Button cfg = settings->getRightButtonConfig(); } else if (event->device->source == GDK_SOURCE_ERASER) { cfg = settings->getEraserButtonConfig(); } else if (cfgTouch->device == event->device->name) { cfg = cfgTouch; // If an action is defined we do it, even if it's a drawing action... if (cfg->getDisableDrawing() && cfg->getAction() == TOOL_NONE) { ToolType tool = h->getToolType(); if (tool == TOOL_PEN || tool == TOOL_ERASER || tool == TOOL_HILIGHTER) { printf("ignore touchscreen for drawing!\n"); return true; } } } if (cfg && cfg->getAction() != TOOL_NONE) { h->copyCurrentConfig(); cfg->acceptActions(h); } // hand tool don't change the selection, so you can scroll e.g. // with your touchscreen without remove the selection if (h->getToolType() == TOOL_HAND) { Cursor * cursor = xournal->view->getCursor(); cursor->setMouseDown(true); xournal->lastMousePositionX = 0; xournal->lastMousePositionY = 0; xournal->inScrolling = true; gtk_widget_get_pointer(widget, &xournal->lastMousePositionX, &xournal->lastMousePositionY); INPUTDBG2("gtk_xournal_button_press_event (h->getToolType() == TOOL_HAND) return true"); return true; } else if (xournal->selection) { EditSelection * selection = xournal->selection; PageView * view = selection->getView(); GdkEventButton ev = *event; view->translateEvent((GdkEvent*) &ev, xournal->x, xournal->y); CursorSelectionType selType = selection->getSelectionTypeForPos(ev.x, ev.y, xournal->view->getZoom()); if (selType) { xournal->view->getCursor()->setMouseDown(true); xournal->selection->mouseDown(selType, ev.x, ev.y); INPUTDBG2("gtk_xournal_button_press_event (selection) return true"); return true; } else { xournal->view->clearSelection(); } } PageView * pv = gtk_xournal_get_page_view_for_pos_cached(xournal, event->x, event->y); if (pv) { xournal->currentInputPage = pv; pv->translateEvent((GdkEvent*) event, xournal->x, xournal->y); INPUTDBG2("gtk_xournal_button_press_event (pv->onButtonPressEvent) return"); xournal->view->getDocument()->indexOf(pv->getPage()); return pv->onButtonPressEvent(widget, event); } INPUTDBG2("gtk_xournal_button_press_event (not handled) return false"); return false; // not handled }