見えないスクロールバー問題
Safariはスクロールバーが描かれるのに、自前WebKit COMプログラムでスクロールバーが出ないのでずっと追っていたところ、長い調査の末やっと理解に辿り着いた。SafariThemeがキーワードとなって改めてWebCoreのCHANGELOGを見たら…そういうことだったのね。orz
2007-11-05 Adam Roben <aroben@apple.com> Don't crash if SafariTheme can't be loaded PlatformScrollBarSafari and RenderThemeSafari were not checking whether SafariTheme was successfully loaded. All other uses of SafariTheme already check this. Reviewed by Steve. * platform/win/PlatformScrollBarSafari.cpp: Don't paint if SafariTheme couldn't be loaded.
よく見ると、Safariのインストールディレクトリには、「SafariTheme.dll」と「SafariTheme.resources」ディレクトリが。。。これらがロードできなければ描画されないということだったのだ。そんなわけでカレントディレクトリを合わせるか、PATHに通すしかないんだけど、あいにくJavaはそういうことが標準ではできないようになっている。BAT作るにしてもSafariのパスを調べてからセットしなければならないし、BATファイルを介するのはかっこ悪い。かといって実行中にカレントディレクトリは変えられない。PATH環境変数も実行中は変えられない。けど背に腹なので、SetEnvironmentVariableを呼べるようにした。SWT-WINが用意してくれていたら良かったんだけど無かったので一度不要としていたJawinに再登場してもらった。以下のメソッドを作成して、WebViewのCoCreateInstance以前に、getenv("PATH")にSafariのインストールディレクトリを付け足してメソッドを呼び出すことで、サクっとスクロールバーが表示されるようになった。
public static boolean SetEnvironmentVariable(String name, String newValue) { FuncPtr setEnvironmentVariable = null; try { setEnvironmentVariable = new FuncPtr("Kernel32.DLL", "SetEnvironmentVariableW"); NakedByteStream nbs = new NakedByteStream(); LittleEndianOutputStream leos = new LittleEndianOutputStream(nbs); leos.writeStringUnicode(name); leos.writeStringUnicode(newValue); byte[] result = setEnvironmentVariable.invoke( "GG:I:", 8, nbs, null, ReturnFlags.CHECK_FALSE); LittleEndianInputStream leis = new LittleEndianInputStream(new ByteArrayInputStream(result)); int retVal = leis.readInt(); return (retVal != 0); } catch (COMException e) { // handle fatal exception } catch (IOException e) { // handle fatal exception } finally { if (setEnvironmentVariable != null) { try { setEnvironmentVariable.close(); } catch (COMException e) { // handle fatal exception } } } return false; }