Skip to content

Add experimental GDK GUI backend#2782

Merged
jtanx merged 122 commits intofontforge:masterfrom
jtanx:gdk2
Mar 17, 2018
Merged

Add experimental GDK GUI backend#2782
jtanx merged 122 commits intofontforge:masterfrom
jtanx:gdk2

Conversation

@jtanx
Copy link
Copy Markdown
Contributor

@jtanx jtanx commented Aug 23, 2016

Note: Not to be merged as of yet.


This adds an experimental GDK backend to GDraw. It is meant to be more or less a drop-in replacement for the X11 backend. This backend is enabled by passing --enable-gdk at the configure stage. This will add a dependency on libgdk-3.0 or libgdk-2.0 (provided by libgtk-3-dev and libgtk2.0-dev or equivalent respectively) - it will prefer libgdk-3.0 to libgdk-2.0, but either should work. If you wish, you may force it to explicitly build with either GDK2 or GDK3 by passing --enable-gdk=gdk2 or --enable-gdk=gdk3.

Motivation and Context

By using the GDK backend, it removes the hard dependency on X11. This is beneficial on Windows and OS X as it removes the need to run an X server (VcXsrv or XQuartz). Note that most of the benefits of this backend would be on Windows.

Side-effects of using GDK:

Technically the GUI can now also be built on Homebrew using this backend (#2668), although I don't have enough experience with the OS X packaging.

Caveats

Expect this backend to crash a bit more than on X11. I have been testing quite a lot, but it's difficult to emulate the behaviour of that backend exactly. There may be differences in behaviour that I may have overlooked which causes odd things to happen.

Types of changes

Changes to FontForge outside of adding this backend have been kept as minimal as possible. However, some changes did have to be made:

  • Removal of XOR mode drawing. It's simply not supported by Cairo, which is the only way to draw things when using GDK. Luckily this only affects a few things - the cursor blinking, the ruler position markers and the guidelines in the charview. I've made changes to all three of these to make sure that they still work (either by doing expose calls - or in the case of the cursor, using 'difference' mode). There may be more efficient ways to do this.
    • Update 2016/09/12: I've made rulers get drawn to an offscreen pixmap which then gets drawn to the screen. When the marker position changes, I copy part of that pixmap back over the screen where the old marker was before drawing the new marker. Performance is now roughly equivalent to what it was with just XOR mode drawing.
  • Removal of all code that used the reparenting feature - which was only the palette toolbars. GDK's support of this was flakey - especially on OS X. Even XQuartz couldn't do it right (try undocking then docking the palettes on a current version of FF). Anyway, this was fixed by simply destroying then re-creating the palettes whenever it's docked/undocked, which I don't think is a big deal.
  • I implemented the DrawArc function in Cairo for the X11 backend.
  • Popups (tooltips) no longer show if FF doesn't have focus
  • Undocked palette windows now behave properly especially on Windows - they remain above the charview even if the charview has focus.

Known remaining issues

  • I still don't understand the start routine for OS X. To be honest, startui.c is in particularly bad shape. I remember Command-line processing and "main program" #1277. What I do know is that it has a separate event loop to Windows and Linux, which seems odd.
  • I don't know if resolution is detected correctly on OS X (particularly on HiDPI displays). GDK has a function (gdk_screen_get_resolution) to get it, but on my test rig (cough) it reports 72dpi, even though it should be rendered at 96dpi. Anyway, I added a property called "ScreenResolution", so this value can be manually set (no messing around with "ScreenWidth..." settings).
  • The clipboard should work on all three platforms. Note however, that copy/pasting to/from external applications on OS X is limited to text only.
  • Drag and drop to/from external applications is not supported. Although I'm led to believe that this didn't actually work with the current version anyway.
  • IME support doesn't exist on OS X/Linux. Unlikely to change because this support lies in the GTK layer.
  • The palette windows now lack a black border around them when docked - they relied on the window manager to do this (as reparented toplevel windows), but this no longer happens because they're implemented as child windows now.
  • Minimum size windows (GDK constraint vs FF asking for ridiculous min widths)
  • Modal focus is sometimes broken - FF allows for some really weird window combinations.
  • Repeated mouse events when the mouse isn't moving is a bug(difference?) of VcXsrv on Windows - can reproduce with FF running on Linux X-forwarded to Windows

@ghost
Copy link
Copy Markdown

ghost commented Aug 23, 2016

I'd be happier to see a move away from GDraw than a patch to make it easier to continue using GDraw, but this is impressive work and if it makes the package play better with desktop environments, it's a good thing.

@jtanx
Copy link
Copy Markdown
Contributor Author

jtanx commented Aug 23, 2016

IMO, the only option of moving away from GDraw would be to move to Qt. Now I've had time to see it, I hate GTK (in particular GTK3). In any case, that would be a major undertaking, far greater than this patch would ever be.

@jtanx jtanx force-pushed the gdk2 branch 6 times, most recently from 21f2637 to a88bfeb Compare September 7, 2016 09:55
@jtanx jtanx force-pushed the gdk2 branch 4 times, most recently from bac1216 to f084bc9 Compare September 14, 2016 06:23
@jtanx
Copy link
Copy Markdown
Contributor Author

jtanx commented Sep 14, 2016

Here's a GDK2 build for Windows: https://ci.appveyor.com/project/fontforge/fontforge/build/1.0.111/artifacts (I set it to GDK2 because I normally build GDK3 and I want to ensure it still builds on GDK2)

Some noted differences between GDK2 and GDK3:

  • GDK2 and GDK3 seem to have different drawing models. On GDK3, invalidating a child window (which can happen by calling gdk_window_invalidate_region, or by resizing or raising the window) will cause the parent window to also be invalidated, which results in flicker. The same doesn't happen on GDK2
  • GDK3 appears to have better drawing performance, at least on Windows
  • The API instability on GDK3 is insane. Functions deprecated left right and centre. Not looking forward to GDK 3.22, although apparently that's meant to be the one with a stable API.
  • GDK3 can apply motion compression whereas the same cannot be done easily on GDK2 (this was the point of GDrawSkipMouseEvents, but GDK doesn't really provide much in the way of event queue manipulation). This means that on complex glyphs, using GDK2 can appear to lag behind.

Known issues remaining:

  • Ctrl clicking + dragging in the charview lags, especially on GDK2. Yet to investigate, but the hand tool does some pretty stupid things like invalidate the whole window if the rulers are enabled.
  • Sometimes modals break things - such as right clicking in font view -> expand stroke. The way FontForge handles modals is... interesting.

@jtanx
Copy link
Copy Markdown
Contributor Author

jtanx commented Sep 16, 2016

Uh. So I noticed a slow-down when you zoomed in too far on a glyph - see here. I had fixed a bug where a path that was indicated as to be drawn with a dashed line was not actually drawn as such (see here).

So old FF was mistakenly drawing a solid line while I was drawing a dashed line. It turns out if you zoom in too far on a dashed line, Cairo runs slow.

So... does anyone know what the dashed vs solid line is meant to mean?

stroke

@pathumego
Copy link
Copy Markdown
Member

@jtanx I can arrange testing on Win and Mac on a daily workflow if you require.

@davelab6
Copy link
Copy Markdown
Member

@jtanx this is awesome work!!

@jtanx
Copy link
Copy Markdown
Contributor Author

jtanx commented Dec 29, 2016

gnulib is broken again.

@davelab6
Copy link
Copy Markdown
Member

davelab6 commented Feb 1, 2017

@jtanx wrote,

So... does anyone know what the dashed vs solid line is meant to mean?

That's odd. I thought it was meant to be solid, not dashed.

jtanx added 12 commits October 10, 2017 17:26
…sible

_GWidget_TopLevel_eh will return without processing if GDrawNativeWindowExists
returns false. This means that under the old code, for windows containing
child windows that are only properly sized by GWidgetFlowGadgets, this will
only happen when the window becomes visible and when a configure message is
received after that.

By removing the visibility check from GGDKDRawNativeWindowExists, we allow
the configure events to get send and this means that the window can be
properly sized before it becomes visible.

The second change in this commit is to filter out et_resize messages that
are only the result of moving. They are unnecessary (if any parts need
to be redrawn due to a move, an expose message will/should be sent).

Furthermore, on Windows in particular, it causes excessive CPU usage
because repeated move messages are sent as the window is moved around -
in comparison to Linux/X11 which only sends one at the end of the move,
or even OS X, which compresses the sizing events.
I cannot specify wam_noresize on the tools window because under
KDE it plays up
My code is under the 2-clause BSD license. GWW's code in ggdkcdraw.c
remains under the original license he used.
I did this before? I must have lost it with the force.
from exposed areas.

I really hope this works.
Ugh this is getting messy.
It causes a notable performance hit e.g. for the ruler tool

Also: Try to minimise expose/raise calls within cvuler itself
@khaledhosny
Copy link
Copy Markdown
Contributor

I don't know if resolution is detected correctly on OS X (particularly on HiDPI displays). GDK has a function (gdk_screen_get_resolution) to get it, but on my test rig (cough) it reports 72dpi, even though it should be rendered at 96dpi. Anyway, I added a property called "ScreenResolution", so this value can be manually set (no messing around with "ScreenWidth..." settings).

Is this for hi-dpi auto detection? You may want to use gdk_monitor_get_scale_factor () for this instead.

@khaledhosny
Copy link
Copy Markdown
Contributor

khaledhosny commented Dec 23, 2017

I just tried this on Linux and it is working on hi-dpi screen without any manual settings:
image
(The glyphs in the fontview are blurry, but that is probably because they did not take the scale factor into account when rasterized, and Cairo just scaled the bitmaps.)

@khaledhosny
Copy link
Copy Markdown
Contributor

Any updates here? Since this keeps the default X backend essentially unchanged, I think it should be merged and further work on GDK backend can be continued (potentially allowing others to contribute).

@jtanx
Copy link
Copy Markdown
Contributor Author

jtanx commented Mar 10, 2018

Sorry about the delay, yeah I'm fairly happy to merge it (any objections, @frank-trampe?); it more or less works. I got busier, and then I saw the breaking changes coming in GDK4. That coupled with debating what version of GDK to support, or if this would have been possible/better done at the GTK level, and I kind of got put off by making any further changes.

I'll see if I can clean it up a little before merging though.

@khaledhosny
Copy link
Copy Markdown
Contributor

I think GTK3/GDK3 will be around for some time and the API is now stabilized, so that is a win. GTK3 was first released in 2011 and GTK2 is still a thing today.

Doing this work with GTK instead of GDK is something to explore indeed, but I think it would be easier to do on top of this work.

@davelab6
Copy link
Copy Markdown
Member

davelab6 commented Mar 10, 2018 via email

@jtanx jtanx changed the title [WIP] Add experimental GDK GUI backend Add experimental GDK GUI backend Mar 17, 2018
@jtanx jtanx merged commit 7cf00ff into fontforge:master Mar 17, 2018
@liZe
Copy link
Copy Markdown

liZe commented May 28, 2018

Thanks a lot for this PR! 😍

Technically supports running natively on Wayland by virtue of GDK supporting it - but this is untested - and server side decorations would have to be provided, which I don't think happens as of now.

What works on Wayland:

  • Application starts
  • Dialog windows
  • Menus, buttons, almost everything UI-related is rendered correctly

What doesn't work:

  • Missing decorations (you knew it),
  • Some UI interactions, for example when clicking on menus while moving the mouse (probably related to some missing focus-related stuff from the window manager),
  • Everything that displays a character, ie the main window, the metrics window (the characters are never drawn),
  • The character editor, including the buttons (the content is displayed once, but never re-drawn when modified).

Looks like the drawing areas are not refreshed. I'd love to help debugging! Should I open a new issue?

@jtanx
Copy link
Copy Markdown
Contributor Author

jtanx commented May 28, 2018

Thanks for testing! Yeah sure, feel free to create issues for anything you find.

@liZe liZe mentioned this pull request May 28, 2018
12 tasks
@MaddTheSane
Copy link
Copy Markdown
Contributor

GDK has a function (gdk_screen_get_resolution) to get [the desktop DPI], but on my test rig (cough) it reports 72dpi, even though it should be rendered at 96dpi.

For historical reasons, Mac OS X uses 72 DPI for the base 1x resolution.

@jtanx jtanx deleted the gdk2 branch February 1, 2019 08:31
Omnikron13 pushed a commit to Omnikron13/fontforge that referenced this pull request May 31, 2022
Add experimental GDK GUI backend
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

6 participants