MozillaZine


Repaint content after Font-Smoothing settings have changed

Talk about add-ons and extension development.
Yaron10
 
Posts: 449
Joined: July 5th, 2011, 6:32 am

Post Posted July 9th, 2015, 6:53 am

Hello,

I use the following code to toggle Font-Smoothing (thank you Noitidart :) ).

Code: Select all
Components.utils.import("resource://gre/modules/ctypes.jsm");
var lib = ctypes.open("user32.dll");

var boolObjFunc = function() { this.BOOL = ctypes.bool; }
var boolObj = new boolObjFunc();
var fontSmooth = lib.declare("SystemParametersInfoW", ctypes.winapi_abi, boolObj.BOOL, ctypes.unsigned_int, ctypes.unsigned_int, ctypes.voidptr_t, ctypes.unsigned_int);
var isFontSmoothOn = boolObj.BOOL();

fontSmooth(0x004A, 0, isFontSmoothOn.address(), 0);   // 0x004A = SPI_GETFONTSMOOTHING.
fontSmooth(0x004B, ! isFontSmoothOn.value, ctypes.voidptr_t(0), 0);    // 0x004B = SPI_SETFONTSMOOTHING.
lib.close();

In Pale Moon (based partly on Firefox 24), the page's content is immediately repainted and displayed according to the new value.
In Firefox 39, however, I need to force repainting (i.e. minimize/restore the window, zoom-in/out etc.).

What causes this behavior in FF 39? What's the best/simplest way to force repainting programmatically?

I can use:

Code: Select all
FullZoom.enlarge();
FullZoom.reduce();

////Or////

BrowserFullScreen();
BrowserFullScreen();

////Or////

window.minimize();
window.restore();

but obviously it's not elagant.

Thank you.

Yaron10
 
Posts: 449
Joined: July 5th, 2011, 6:32 am

Post Posted July 9th, 2015, 6:16 pm

I've found out that OMTC (layers.offmainthreadcomposition.enabled) is the cause.
I've filed this bug.

Still, I'd appreciate a simple way to force repainting.

Regards.

Noitidart
 
Posts: 1168
Joined: September 16th, 2007, 8:01 am

Post Posted July 9th, 2015, 7:36 pm

This is a good question for winapi tagg on stackoverflow people here aren't so familiar with winapi.

http://stackoverflow.com/questions/tagged/winapi

:)

Noitidart
 
Posts: 1168
Joined: September 16th, 2007, 8:01 am

Post Posted July 9th, 2015, 7:38 pm

Although you might be able to find some repaint events specific to firefox from XPCOM like in nsIDOMWindowUtils: https://developer.mozilla.org/en-US/doc ... indowUtils

lithopsian
 
Posts: 3664
Joined: September 15th, 2010, 9:03 am

Post Posted July 10th, 2015, 2:00 am

The standard method would be do call InvalidateRect for the whole client area. This generates a WM_PAINT message which should cause Firefox to redraw the window. This used to work. The Invalidate should happen automatically if you change the font smoothing settings, and Firefox used to receive the message and repaint. I can only assume that the off-thread compositing broke this, hence your bug.

Yaron10
 
Posts: 449
Joined: July 5th, 2011, 6:32 am

Post Posted July 10th, 2015, 9:10 am

Hello Noitidart and lithopsian,

Thank you so much for your help. I really appreciate it.

Unfortunately, I couldn't find a solution using nsIDOMWindowUtils.
Googling InvalidateRect, I came across the UpdateWindow function; - if I understand correctly, using it would be better in this case.

Code: Select all
var UpdateWindow = lib.declare("UpdateWindow",  ctypes.winapi_abi, ctypes.bool, ctypes.voidptr_t);
UpdateWindow(----);

Is the "lib.declare" line correct? What should be the arguments in the next line?

I posted the question here too.

***
@Noitidart,
I've learned how to use "isFontSmoothOn.address()" from one of your repos on GitHub. Thanks for that too. :)

Best regards.

Noitidart
 
Posts: 1168
Joined: September 16th, 2007, 8:01 am

Post Posted July 10th, 2015, 8:21 pm

Cool yaron thats real great to see a person being able to use the open source resources!

For the argument to UpdateWindow you need to give it a window handle. To do that you can learn about it here: https://developer.mozilla.org/en-US/Add ... tiveHandle


Then you would iterate through all of the firefox windows and call UpdateWindow on its handle so like this:

Code: Select all
      let DOMWindows = Services.wm.getEnumerator(null);
      while (DOMWindows.hasMoreElements()) {
         let aDOMWindow = DOMWindows.getNext();
         let aBaseWindow = aDOMWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                              .getInterface(Ci.nsIWebNavigation)
                              .QueryInterface(Ci.nsIDocShellTreeItem)
                              .treeOwner
                              .QueryInterface(Ci.nsIInterfaceRequestor)
                              .getInterface(Ci.nsIBaseWindow);
let aHwnd = ctypes.voidptr_t(ctypes.UInt64(aBaseWindow.nativeHandle));
var rez_UW = UpdateWindow(aHwnd);
      }

Yaron10
 
Posts: 449
Joined: July 5th, 2011, 6:32 am

Post Posted July 11th, 2015, 7:49 am

Hello Noitidart,

Thanks for the detailed explanation. I really appreciate it.

Well, the content is not repainted after calling UpdateWindow. :)
If it did work, updating other windows wouldn't be necessary; - the content is repainted after switching windows.
(I'll use "FullZoom.enlarge(); FullZoom.reduce();" as a workaround for the time being).

With your permission, one more question:
I use "ctypes" in two functions in the same JS file.
- Should I put the line "Components.utils.import("resource://gre/modules/ctypes.jsm");" at the top of the file or at the beginning of the first function?
IOW: If I put it at the top of the file, isn't it unnecessarily parsed on start-up?

Best regards.

Noitidart
 
Posts: 1168
Joined: September 16th, 2007, 8:01 am

Post Posted July 12th, 2015, 4:48 am

Oh thats weird, if UpdateWindow was supposed to trigger repaint it should have when you called it on the hwnd. Nice work around but that actually sets a value in site specific memory, so you are adding to site specific zoom store :( Please try to find alternative, maybe in next version of addon.

Import ctypes at the top, it's a pointer so it happens without any overhead at all. Its convention to import at top. So no unnecessary parsing, just a simple pointer, I asked that question and got a good answer from litho: viewtopic.php?f=19&t=2795549&hilit=+import

Yaron10
 
Posts: 449
Joined: July 5th, 2011, 6:32 am

Post Posted July 12th, 2015, 10:38 am

Hello Noitidart,

Thanks again. Truly grateful.

That's a good point. Also, if the zoom was originally enlarged to max - I'll end up with one level down.
domWindowUtils.redraw() doesn't work either. Indeed weird.
I hope the bug is fixed soon. :)

Thanks also for the explanation regarding "Components.utils.import". Thanks to litho as well.

***
As a token of appreciation, three links you might find useful. :)

1) The HighlightPlugin for Process Hacker. - You can highlight each process in a different color regardless of category (Own Processes, System Processes etc.).

2) POP Peeper. The best Email Notifier I've come across; - solid, lightweight and highly customizable (Tools -> PPTweaker).

3) SysTrayMeter. A great lightweight RAM and CPU monitor in the System Tray (read the ReadMe file).

Best wishes.

Noitidart
 
Posts: 1168
Joined: September 16th, 2007, 8:01 am

Post Posted July 12th, 2015, 1:12 pm

Yaron10 wrote:Hello Noitidart,

Thanks again. Truly grateful.

That's a good point. Also, if the zoom was originally enlarged to max - I'll end up with one level down.
domWindowUtils.redraw() doesn't work either. Indeed weird.
I hope the bug is fixed soon. :)

Thanks also for the explanation regarding "Components.utils.import". Thanks to litho as well.

***
As a token of appreciation, three links you might find useful. :)

1) The HighlightPlugin for Process Hacker. - You can highlight each process in a different color regardless of category (Own Processes, System Processes etc.).

2) POP Peeper. The best Email Notifier I've come across; - solid, lightweight and highly customizable (Tools -> PPTweaker).

3) SysTrayMeter. A great lightweight RAM and CPU monitor in the System Tray (read the ReadMe file).

Best wishes.



Thanks for the links! More then anyhting I love collaboration! :)

Super point on that zoom if at max thing!

Yaron10
 
Posts: 449
Joined: July 5th, 2011, 6:32 am

Post Posted July 12th, 2015, 1:24 pm

My pleasure.
Thank you again. Your kindness is unique. :)

I wish you the best.

morat
 
Posts: 4254
Joined: February 3rd, 2009, 6:29 pm

Post Posted July 13th, 2015, 5:15 pm

Yaron10 wrote:use "FullZoom.enlarge(); FullZoom.reduce();" as a workaround

I've seen a developer use this trick to force a repaint.

Code: Select all
element.style.opacity = "0.99";

Code: Select all
content.document.getElementsByTagName("*")[0].style.opacity = "0.99";

Yaron10
 
Posts: 449
Joined: July 5th, 2011, 6:32 am

Post Posted July 14th, 2015, 8:20 am

Hello morat,

Thanks for posting. I really appreciate it.

That's a nice workaround.
It only works for the first time; - once "opacity = "0.99" has been executed, the page is not repainted when it's called again.
So, "opacity = "0.99" and then "opacity = "1".

I understand the code changes the first element in the page. Is that correct?
What if the element's opacity was originally set to "0.20"? I suppose I'd have to get that value first, right?

*
Another not-very-elegant workaround: change and then re-change "browser.display.use_document_fonts" (or a similar pref).

Best regards.

Return to Extension Development


Who is online

Users browsing this forum: No registered users and 1 guest