gboolean XInputUtils::onMouseLeaveNotifyEvent(GtkWidget* widget, GdkEventCrossing* event) { if(!XInputUtils::enableLeafEnterWorkaround) { return FALSE; } INPUTDBG("leave notify (mode=%d, details=%d)\n", event->mode, event->detail); /* emergency disable XInput to avoid segfaults (GTK+ 2.17) or interface non-responsiveness (GTK+ 2.18) */ if (!gtk_check_version(2, 17, 0)) { gdk_flush(); gdk_error_trap_push(); for (GList* dev_list = gdk_devices_list(); dev_list != NULL; dev_list = dev_list->next) { GdkDevice* dev = GDK_DEVICE(dev_list->data); gdk_device_set_mode(dev, GDK_MODE_DISABLED); } gdk_flush(); gdk_error_trap_pop(); } return FALSE; }
gboolean XInputUtils::onMouseEnterNotifyEvent(GtkWidget* widget, GdkEventCrossing* event) { if(!XInputUtils::enableLeafEnterWorkaround) { return FALSE; } INPUTDBG("enter notify\n"); /* re-enable input devices after they've been emergency-disabled by leave_notify */ if (!gtk_check_version(2, 17, 0)) { gdk_flush(); gdk_error_trap_push(); for (GList* dev_list = gdk_devices_list(); dev_list != NULL; dev_list = dev_list->next) { GdkDevice* dev = GDK_DEVICE(dev_list->data); gdk_device_set_mode(dev, GDK_MODE_SCREEN); } gdk_flush(); gdk_error_trap_pop(); } 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; } current_view = NULL; 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; }
gboolean gtk_xournal_scroll_event(GtkWidget * widget, GdkEventScroll * event) { #ifdef INPUT_DEBUG // true: Core event, false: XInput event gboolean isCore = (event->device == gdk_device_get_core_pointer()); INPUTDBG("Scroll (%s) (x,y)=(%.2f,%.2f), direction %d, modifier %x, isCore %i", gdk_device_get_name(event->device), event->x, event->y, event->direction, event->state, isCore); #endif g_return_val_if_fail(GTK_XOURNAL(widget), FALSE); g_return_val_if_fail(event != NULL, FALSE); GtkXournal * xournal = GTK_XOURNAL(widget); return xournal->layout->scrollEvent(event); }
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_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 }
void InputHandler::onButtonReleaseEvent(GdkEventButton * event, PageRef page) { XOJ_CHECK_TYPE(InputHandler); if (!this->tmpStroke) { return; } // Backward compatibility and also easier to handle for me;-) // I cannot draw a line with one point, to draw a visible line I need two points, // twice the same Point is also OK if (this->tmpStroke->getPointCount() == 1) { ArrayIterator<Point> it = this->tmpStroke->pointIterator(); if (it.hasNext()) { this->tmpStroke->addPoint(it.next()); } // No pressure sensitivity this->tmpStroke->clearPressure(); } this->tmpStroke->freeUnusedPointItems(); if (page.getSelectedLayerId() < 1) { // This creates a layer if none exists page.getSelectedLayer(); page.setSelectedLayerId(1); xournal->getControl()->getWindow()->updateLayerCombobox(); } Layer * layer = page.getSelectedLayer(); UndoRedoHandler * undo = xournal->getControl()->getUndoRedoHandler(); undo->addUndoAction(new InsertUndoAction(page, layer, this->tmpStroke, this->redrawable)); ToolHandler * h = xournal->getControl()->getToolHandler(); if (h->isShapeRecognizer()) { if (this->reco == NULL) { this->reco = new ShapeRecognizer(); } ShapeRecognizerResult * result = this->reco->recognizePatterns(this->tmpStroke); if (result != NULL) { UndoRedoHandler * undo = xournal->getControl()->getUndoRedoHandler(); Stroke * recognized = result->getRecognized(); RecognizerUndoAction * recognizerUndo = new RecognizerUndoAction(page, this->redrawable, layer, this->tmpStroke, recognized); undo->addUndoAction(recognizerUndo); layer->addElement(result->getRecognized()); Range range(recognized->getX(), recognized->getY()); range.addPoint(recognized->getX() + recognized->getElementWidth(), recognized->getY() + recognized->getElementHeight()); range.addPoint(this->tmpStroke->getX(), this->tmpStroke->getY()); range.addPoint(this->tmpStroke->getX() + this->tmpStroke->getElementWidth(), this->tmpStroke->getY() + this->tmpStroke->getElementHeight()); ListIterator<Stroke *> l = result->getSources(); while (l.hasNext()) { Stroke * s = l.next(); layer->removeElement(s, false); recognizerUndo->addSourceElement(s); range.addPoint(s->getX(), s->getY()); range.addPoint(s->getX() + s->getElementWidth(), s->getY() + s->getElementHeight()); } this->redrawable->rerenderRange(range); // delete the result object, this is not needed anymore, the stroke are not deleted with this delete result; } else { layer->addElement(this->tmpStroke); this->redrawable->rerenderElement(this->tmpStroke); } } else { layer->addElement(this->tmpStroke); this->redrawable->rerenderElement(this->tmpStroke); } this->tmpStroke = NULL; if (currentInputDevice == event->device) { currentInputDevice = NULL; INPUTDBG("currentInputDevice = NULL\n", 0); } this->tmpStrokeDrawElem = 0; }
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 }