1 // Scintilla source code edit control 2 // ScintillaGTK.h - GTK+ specific subclass of ScintillaBase 3 // Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org> 4 // The License.txt file describes the conditions under which this software may be distributed. 5 6 #ifndef SCINTILLAGTK_H 7 #define SCINTILLAGTK_H 8 9 namespace Scintilla { 10 11 class ScintillaGTKAccessible; 12 13 #define OBJECT_CLASS GObjectClass 14 15 class ScintillaGTK : public ScintillaBase { 16 friend class ScintillaGTKAccessible; 17 18 _ScintillaObject *sci; 19 Window wText; 20 Window scrollbarv; 21 Window scrollbarh; 22 GtkAdjustment *adjustmentv; 23 GtkAdjustment *adjustmenth; 24 Window wSelection; 25 int verticalScrollBarWidth; 26 int horizontalScrollBarHeight; 27 28 SelectionText primary; 29 30 GdkEvent *evbtn; 31 guint buttonMouse; 32 bool capturedMouse; 33 bool dragWasDropped; 34 int lastKey; 35 int rectangularSelectionModifier; 36 37 GtkWidgetClass *parentClass; 38 39 static inline GdkAtom atomUTF8 {}; 40 static inline GdkAtom atomUTF8Mime {}; 41 static inline GdkAtom atomString {}; 42 static inline GdkAtom atomUriList {}; 43 static inline GdkAtom atomDROPFILES_DND {}; 44 GdkAtom atomSought; 45 46 #if PLAT_GTK_WIN32 47 CLIPFORMAT cfColumnSelect; 48 #endif 49 50 bool preeditInitialized; 51 Window wPreedit; 52 Window wPreeditDraw; 53 GtkIMContext *im_context; 54 GUnicodeScript lastNonCommonScript; 55 56 // Wheel mouse support 57 unsigned int linesPerScroll; 58 gint64 lastWheelMouseTime; 59 gint lastWheelMouseDirection; 60 gint wheelMouseIntensity; 61 gdouble smoothScrollY; 62 gdouble smoothScrollX; 63 64 #if GTK_CHECK_VERSION(3,0,0) 65 cairo_rectangle_list_t *rgnUpdate; 66 #else 67 GdkRegion *rgnUpdate; 68 #endif 69 bool repaintFullWindow; 70 71 guint styleIdleID; 72 int accessibilityEnabled; 73 AtkObject *accessible; 74 75 public: 76 explicit ScintillaGTK(_ScintillaObject *sci_); 77 // Deleted so ScintillaGTK objects can not be copied. 78 ScintillaGTK(const ScintillaGTK &) = delete; 79 ScintillaGTK(ScintillaGTK &&) = delete; 80 ScintillaGTK &operator=(const ScintillaGTK &) = delete; 81 ScintillaGTK &operator=(ScintillaGTK &&) = delete; 82 virtual ~ScintillaGTK(); 83 static ScintillaGTK *FromWidget(GtkWidget *widget) noexcept; 84 static void ClassInit(OBJECT_CLASS *object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class); 85 private: 86 void Init(); 87 void Finalise() override; 88 bool AbandonPaint() override; 89 void DisplayCursor(Window::Cursor c) override; 90 bool DragThreshold(Point ptStart, Point ptNow) override; 91 void StartDrag() override; 92 Sci::Position TargetAsUTF8(char *text) const; 93 Sci::Position EncodedFromUTF8(const char *utf8, char *encoded) const; 94 bool ValidCodePage(int codePage) const override; 95 public: // Public for scintilla_send_message 96 sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) override; 97 private: 98 sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) override; 99 struct TimeThunk { 100 TickReason reason; 101 ScintillaGTK *scintilla; 102 guint timer; TimeThunkTimeThunk103 TimeThunk() noexcept : reason(tickCaret), scintilla(nullptr), timer(0) {} 104 }; 105 TimeThunk timers[tickDwell+1]; 106 bool FineTickerRunning(TickReason reason) override; 107 void FineTickerStart(TickReason reason, int millis, int tolerance) override; 108 void FineTickerCancel(TickReason reason) override; 109 bool SetIdle(bool on) override; 110 void SetMouseCapture(bool on) override; 111 bool HaveMouseCapture() override; 112 bool PaintContains(PRectangle rc) override; 113 void FullPaint(); 114 PRectangle GetClientRectangle() const override; 115 void ScrollText(Sci::Line linesToMove) override; 116 void SetVerticalScrollPos() override; 117 void SetHorizontalScrollPos() override; 118 bool ModifyScrollBars(Sci::Line nMax, Sci::Line nPage) override; 119 void ReconfigureScrollBars() override; 120 void NotifyChange() override; 121 void NotifyFocus(bool focus) override; 122 void NotifyParent(SCNotification scn) override; 123 void NotifyKey(int key, int modifiers); 124 void NotifyURIDropped(const char *list); 125 const char *CharacterSetID() const; 126 CaseFolder *CaseFolderForEncoding() override; 127 std::string CaseMapString(const std::string &s, int caseMapping) override; 128 int KeyDefault(int key, int modifiers) override; 129 void CopyToClipboard(const SelectionText &selectedText) override; 130 void Copy() override; 131 void RequestSelection(GdkAtom atomSelection); 132 void Paste() override; 133 void CreateCallTipWindow(PRectangle rc) override; 134 void AddToPopUp(const char *label, int cmd = 0, bool enabled = true) override; 135 bool OwnPrimarySelection(); 136 void ClaimSelection() override; 137 static bool IsStringAtom(GdkAtom type); 138 void GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText); 139 void InsertSelection(GtkClipboard *clipBoard, GtkSelectionData *selectionData); 140 public: // Public for SelectionReceiver 141 GObject *MainObject() const noexcept; 142 void ReceivedClipboard(GtkClipboard *clipBoard, GtkSelectionData *selection_data) noexcept; 143 private: 144 void ReceivedSelection(GtkSelectionData *selection_data); 145 void ReceivedDrop(GtkSelectionData *selection_data); 146 static void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *text); 147 void StoreOnClipboard(SelectionText *clipText); 148 static void ClipboardGetSelection(GtkClipboard *clip, GtkSelectionData *selection_data, guint info, void *data); 149 static void ClipboardClearSelection(GtkClipboard *clip, void *data); 150 151 void UnclaimSelection(GdkEventSelection *selection_event); 152 static void PrimarySelection(GtkWidget *widget, GtkSelectionData *selection_data, guint info, guint time_stamp, ScintillaGTK *sciThis); 153 static gboolean PrimaryClear(GtkWidget *widget, GdkEventSelection *event, ScintillaGTK *sciThis); 154 void Resize(int width, int height); 155 156 // Callback functions 157 void RealizeThis(GtkWidget *widget); 158 static void Realize(GtkWidget *widget); 159 void UnRealizeThis(GtkWidget *widget); 160 static void UnRealize(GtkWidget *widget); 161 void MapThis(); 162 static void Map(GtkWidget *widget); 163 void UnMapThis(); 164 static void UnMap(GtkWidget *widget); 165 gint FocusInThis(GtkWidget *widget); 166 static gint FocusIn(GtkWidget *widget, GdkEventFocus *event); 167 gint FocusOutThis(GtkWidget *widget); 168 static gint FocusOut(GtkWidget *widget, GdkEventFocus *event); 169 static void SizeRequest(GtkWidget *widget, GtkRequisition *requisition); 170 #if GTK_CHECK_VERSION(3,0,0) 171 static void GetPreferredWidth(GtkWidget *widget, gint *minimalWidth, gint *naturalWidth); 172 static void GetPreferredHeight(GtkWidget *widget, gint *minimalHeight, gint *naturalHeight); 173 #endif 174 static void SizeAllocate(GtkWidget *widget, GtkAllocation *allocation); 175 #if GTK_CHECK_VERSION(3,0,0) 176 gboolean DrawTextThis(cairo_t *cr); 177 static gboolean DrawText(GtkWidget *widget, cairo_t *cr, ScintillaGTK *sciThis); 178 gboolean DrawThis(cairo_t *cr); 179 static gboolean DrawMain(GtkWidget *widget, cairo_t *cr); 180 #else 181 gboolean ExposeTextThis(GtkWidget *widget, GdkEventExpose *ose); 182 static gboolean ExposeText(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis); 183 gboolean Expose(GtkWidget *widget, GdkEventExpose *ose); 184 static gboolean ExposeMain(GtkWidget *widget, GdkEventExpose *ose); 185 #endif 186 void ForAll(GtkCallback callback, gpointer callback_data); 187 static void MainForAll(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data); 188 189 static void ScrollSignal(GtkAdjustment *adj, ScintillaGTK *sciThis); 190 static void ScrollHSignal(GtkAdjustment *adj, ScintillaGTK *sciThis); 191 gint PressThis(GdkEventButton *event); 192 static gint Press(GtkWidget *widget, GdkEventButton *event); 193 static gint MouseRelease(GtkWidget *widget, GdkEventButton *event); 194 static gint ScrollEvent(GtkWidget *widget, GdkEventScroll *event); 195 static gint Motion(GtkWidget *widget, GdkEventMotion *event); 196 gboolean KeyThis(GdkEventKey *event); 197 static gboolean KeyPress(GtkWidget *widget, GdkEventKey *event); 198 static gboolean KeyRelease(GtkWidget *widget, GdkEventKey *event); 199 #if GTK_CHECK_VERSION(3,0,0) 200 gboolean DrawPreeditThis(GtkWidget *widget, cairo_t *cr); 201 static gboolean DrawPreedit(GtkWidget *widget, cairo_t *cr, ScintillaGTK *sciThis); 202 #else 203 gboolean ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose); 204 static gboolean ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis); 205 #endif 206 AtkObject *GetAccessibleThis(GtkWidget *widget); 207 static AtkObject *GetAccessible(GtkWidget *widget); 208 209 bool KoreanIME(); 210 void CommitThis(char *commitStr); 211 static void Commit(GtkIMContext *context, char *str, ScintillaGTK *sciThis); 212 void PreeditChangedInlineThis(); 213 void PreeditChangedWindowedThis(); 214 static void PreeditChanged(GtkIMContext *context, ScintillaGTK *sciThis); 215 void MoveImeCarets(int pos); 216 void DrawImeIndicator(int indicator, int len); 217 void SetCandidateWindowPos(); 218 219 static void StyleSetText(GtkWidget *widget, GtkStyle *previous, void *); 220 static void RealizeText(GtkWidget *widget, void *); 221 static void Dispose(GObject *object); 222 static void Destroy(GObject *object); 223 static void SelectionReceived(GtkWidget *widget, GtkSelectionData *selection_data, 224 guint time); 225 static void SelectionGet(GtkWidget *widget, GtkSelectionData *selection_data, 226 guint info, guint time); 227 static gint SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event); 228 gboolean DragMotionThis(GdkDragContext *context, gint x, gint y, guint dragtime); 229 static gboolean DragMotion(GtkWidget *widget, GdkDragContext *context, 230 gint x, gint y, guint dragtime); 231 static void DragLeave(GtkWidget *widget, GdkDragContext *context, 232 guint time); 233 static void DragEnd(GtkWidget *widget, GdkDragContext *context); 234 static gboolean Drop(GtkWidget *widget, GdkDragContext *context, 235 gint x, gint y, guint time); 236 static void DragDataReceived(GtkWidget *widget, GdkDragContext *context, 237 gint x, gint y, GtkSelectionData *selection_data, guint info, guint time); 238 static void DragDataGet(GtkWidget *widget, GdkDragContext *context, 239 GtkSelectionData *selection_data, guint info, guint time); 240 static gboolean TimeOut(gpointer ptt); 241 static gboolean IdleCallback(gpointer pSci); 242 static gboolean StyleIdle(gpointer pSci); 243 void IdleWork() override; 244 void QueueIdleWork(WorkNeeded::workItems items, Sci::Position upTo) override; 245 void SetDocPointer(Document *document) override; 246 static void PopUpCB(GtkMenuItem *menuItem, ScintillaGTK *sciThis); 247 248 #if GTK_CHECK_VERSION(3,0,0) 249 static gboolean DrawCT(GtkWidget *widget, cairo_t *cr, CallTip *ctip); 250 #else 251 static gboolean ExposeCT(GtkWidget *widget, GdkEventExpose *ose, CallTip *ctip); 252 #endif 253 static gboolean PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis); 254 255 static sptr_t DirectFunction(sptr_t ptr, 256 unsigned int iMessage, uptr_t wParam, sptr_t lParam); 257 }; 258 259 // helper class to watch a GObject lifetime and get notified when it dies 260 class GObjectWatcher { 261 GObject *weakRef; 262 WeakNotifyThis(GObject * obj G_GNUC_UNUSED)263 void WeakNotifyThis(GObject *obj G_GNUC_UNUSED) { 264 PLATFORM_ASSERT(obj == weakRef); 265 266 Destroyed(); 267 weakRef = nullptr; 268 } 269 WeakNotify(gpointer data,GObject * obj)270 static void WeakNotify(gpointer data, GObject *obj) { 271 static_cast<GObjectWatcher *>(data)->WeakNotifyThis(obj); 272 } 273 274 public: GObjectWatcher(GObject * obj)275 GObjectWatcher(GObject *obj) : 276 weakRef(obj) { 277 g_object_weak_ref(weakRef, WeakNotify, this); 278 } 279 280 // Deleted so GObjectWatcher objects can not be copied. 281 GObjectWatcher(const GObjectWatcher&) = delete; 282 GObjectWatcher(GObjectWatcher&&) = delete; 283 GObjectWatcher&operator=(const GObjectWatcher&) = delete; 284 GObjectWatcher&operator=(GObjectWatcher&&) = delete; 285 ~GObjectWatcher()286 virtual ~GObjectWatcher() { 287 if (weakRef) { 288 g_object_weak_unref(weakRef, WeakNotify, this); 289 } 290 } 291 Destroyed()292 virtual void Destroyed() {} 293 IsDestroyed()294 bool IsDestroyed() const { 295 return weakRef != nullptr; 296 } 297 }; 298 299 std::string ConvertText(const char *s, size_t len, const char *charSetDest, 300 const char *charSetSource, bool transliterations, bool silent=false); 301 302 } 303 304 #endif 305