From c49721950cb3d897b35f08bf871239308680b18e Mon Sep 17 00:00:00 2001 From: Tor Lillqvist Date: Thu, 5 Dec 2013 22:01:05 +0200 Subject: Re-organize OS X and iOS code in vcl a bit Now with the ATSUI code gone is a good time for some re-organisation. Get rid of "aqua" in file names and the separate "coretext" folders. CoreText is all we use now for OS X (and has always been so for iOS), so no need for a "coretext" folder, we can keep the CoreText-using code under "quartz". Keep OS X -specific code in "osx". Ditto for headers. Keep "Aqua" as part of class names for now, though. This is also preparation for planned further unification between OS X and iOS code. Change-Id: Ic60bd73fea4ab98183e7c8a09c7d3f66b9a34223 --- include/sal/log-areas.dox | 1 + vcl/Library_vcl.mk | 124 +- vcl/Package_osxres.mk | 2 +- vcl/README | 10 +- vcl/aqua/source/a11y/aqua11yactionwrapper.h | 35 - vcl/aqua/source/a11y/aqua11yactionwrapper.mm | 77 - vcl/aqua/source/a11y/aqua11ycomponentwrapper.h | 39 - vcl/aqua/source/a11y/aqua11ycomponentwrapper.mm | 102 -- vcl/aqua/source/a11y/aqua11yfactory.mm | 219 --- vcl/aqua/source/a11y/aqua11yfocuslistener.cxx | 110 -- vcl/aqua/source/a11y/aqua11yfocuslistener.hxx | 54 - vcl/aqua/source/a11y/aqua11yfocustracker.cxx | 284 --- vcl/aqua/source/a11y/aqua11ylistener.cxx | 153 -- vcl/aqua/source/a11y/aqua11yrolehelper.h | 36 - vcl/aqua/source/a11y/aqua11yrolehelper.mm | 270 --- vcl/aqua/source/a11y/aqua11yselectionwrapper.h | 37 - vcl/aqua/source/a11y/aqua11yselectionwrapper.mm | 88 - vcl/aqua/source/a11y/aqua11ytablewrapper.h | 38 - vcl/aqua/source/a11y/aqua11ytablewrapper.mm | 204 --- .../source/a11y/aqua11ytextattributeswrapper.h | 32 - .../source/a11y/aqua11ytextattributeswrapper.mm | 355 ---- vcl/aqua/source/a11y/aqua11ytextwrapper.h | 58 - vcl/aqua/source/a11y/aqua11ytextwrapper.mm | 293 ---- vcl/aqua/source/a11y/aqua11yutil.h | 32 - vcl/aqua/source/a11y/aqua11yutil.mm | 46 - vcl/aqua/source/a11y/aqua11yvaluewrapper.h | 40 - vcl/aqua/source/a11y/aqua11yvaluewrapper.mm | 87 - vcl/aqua/source/a11y/aqua11ywrapper.mm | 1150 ------------- vcl/aqua/source/a11y/aqua11ywrapperbutton.h | 35 - vcl/aqua/source/a11y/aqua11ywrapperbutton.mm | 54 - vcl/aqua/source/a11y/aqua11ywrappercheckbox.h | 35 - vcl/aqua/source/a11y/aqua11ywrappercheckbox.mm | 58 - vcl/aqua/source/a11y/aqua11ywrappercombobox.h | 44 - vcl/aqua/source/a11y/aqua11ywrappercombobox.mm | 155 -- vcl/aqua/source/a11y/aqua11ywrappergroup.h | 34 - vcl/aqua/source/a11y/aqua11ywrappergroup.mm | 49 - vcl/aqua/source/a11y/aqua11ywrapperlist.h | 33 - vcl/aqua/source/a11y/aqua11ywrapperlist.mm | 40 - vcl/aqua/source/a11y/aqua11ywrapperradiobutton.h | 35 - vcl/aqua/source/a11y/aqua11ywrapperradiobutton.mm | 57 - vcl/aqua/source/a11y/aqua11ywrapperradiogroup.h | 33 - vcl/aqua/source/a11y/aqua11ywrapperradiogroup.mm | 40 - vcl/aqua/source/a11y/aqua11ywrapperrow.h | 34 - vcl/aqua/source/a11y/aqua11ywrapperrow.mm | 49 - vcl/aqua/source/a11y/aqua11ywrapperscrollarea.h | 35 - vcl/aqua/source/a11y/aqua11ywrapperscrollarea.mm | 77 - vcl/aqua/source/a11y/aqua11ywrapperscrollbar.h | 33 - vcl/aqua/source/a11y/aqua11ywrapperscrollbar.mm | 43 - vcl/aqua/source/a11y/aqua11ywrappersplitter.h | 33 - vcl/aqua/source/a11y/aqua11ywrappersplitter.mm | 40 - vcl/aqua/source/a11y/aqua11ywrapperstatictext.h | 34 - vcl/aqua/source/a11y/aqua11ywrapperstatictext.mm | 48 - vcl/aqua/source/a11y/aqua11ywrappertabgroup.h | 33 - vcl/aqua/source/a11y/aqua11ywrappertabgroup.mm | 42 - vcl/aqua/source/a11y/aqua11ywrappertextarea.h | 33 - vcl/aqua/source/a11y/aqua11ywrappertextarea.mm | 40 - vcl/aqua/source/a11y/aqua11ywrappertoolbar.h | 33 - vcl/aqua/source/a11y/aqua11ywrappertoolbar.mm | 42 - vcl/aqua/source/a11y/documentfocuslistener.cxx | 241 --- vcl/aqua/source/a11y/documentfocuslistener.hxx | 91 - vcl/aqua/source/a11y/readme.txt | 8 - vcl/aqua/source/app/saldata.cxx | 265 --- vcl/aqua/source/app/salinst.cxx | 1207 ------------- vcl/aqua/source/app/salnstimer.mm | 48 - vcl/aqua/source/app/salsys.cxx | 190 --- vcl/aqua/source/app/saltimer.cxx | 126 -- vcl/aqua/source/app/vclnsapp.mm | 517 ------ vcl/aqua/source/dtrans/DataFlavorMapping.cxx | 741 -------- vcl/aqua/source/dtrans/DataFlavorMapping.hxx | 141 -- vcl/aqua/source/dtrans/DragActionConversion.cxx | 86 - vcl/aqua/source/dtrans/DragActionConversion.hxx | 40 - vcl/aqua/source/dtrans/DragSource.cxx | 372 ---- vcl/aqua/source/dtrans/DragSource.hxx | 136 -- vcl/aqua/source/dtrans/DragSourceContext.cxx | 61 - vcl/aqua/source/dtrans/DragSourceContext.hxx | 61 - vcl/aqua/source/dtrans/DropTarget.cxx | 596 ------- vcl/aqua/source/dtrans/DropTarget.hxx | 163 -- vcl/aqua/source/dtrans/HtmlFmtFlt.cxx | 168 -- vcl/aqua/source/dtrans/HtmlFmtFlt.hxx | 41 - vcl/aqua/source/dtrans/OSXTransferable.cxx | 203 --- vcl/aqua/source/dtrans/OSXTransferable.hxx | 90 - vcl/aqua/source/dtrans/PictToBmpFlt.cxx | 76 - vcl/aqua/source/dtrans/PictToBmpFlt.hxx | 39 - vcl/aqua/source/dtrans/aqua_clipboard.cxx | 372 ---- vcl/aqua/source/dtrans/aqua_clipboard.hxx | 175 -- vcl/aqua/source/dtrans/service_entry.cxx | 68 - vcl/aqua/source/gdi/aquaprintaccessoryview.mm | 1381 --------------- vcl/aqua/source/gdi/aquaprintview.mm | 75 - vcl/aqua/source/gdi/salgdicommon.cxx | 1755 ------------------- vcl/aqua/source/gdi/salgdiutils.cxx | 299 ---- vcl/aqua/source/gdi/salmathutils.cxx | 154 -- vcl/aqua/source/gdi/salnativewidgets.cxx | 1462 ---------------- vcl/aqua/source/gdi/salprn.cxx | 755 -------- vcl/aqua/source/gdi/salvd.cxx | 261 --- vcl/aqua/source/res/MainMenu.nib/classes.nib | 4 - vcl/aqua/source/res/MainMenu.nib/info.nib | 21 - vcl/aqua/source/res/MainMenu.nib/keyedobjects.nib | Bin 3615 -> 0 bytes vcl/aqua/source/res/cursors/airbrush.png | Bin 253 -> 0 bytes vcl/aqua/source/res/cursors/ase.png | Bin 214 -> 0 bytes vcl/aqua/source/res/cursors/asn.png | Bin 212 -> 0 bytes vcl/aqua/source/res/cursors/asne.png | Bin 240 -> 0 bytes vcl/aqua/source/res/cursors/asns.png | Bin 234 -> 0 bytes vcl/aqua/source/res/cursors/asnswe.png | Bin 285 -> 0 bytes vcl/aqua/source/res/cursors/asnw.png | Bin 246 -> 0 bytes vcl/aqua/source/res/cursors/ass.png | Bin 222 -> 0 bytes vcl/aqua/source/res/cursors/asse.png | Bin 243 -> 0 bytes vcl/aqua/source/res/cursors/assw.png | Bin 236 -> 0 bytes vcl/aqua/source/res/cursors/asw.png | Bin 212 -> 0 bytes vcl/aqua/source/res/cursors/aswe.png | Bin 228 -> 0 bytes vcl/aqua/source/res/cursors/chain.png | Bin 344 -> 0 bytes vcl/aqua/source/res/cursors/chainnot.png | Bin 390 -> 0 bytes vcl/aqua/source/res/cursors/chart.png | Bin 270 -> 0 bytes vcl/aqua/source/res/cursors/copydata.png | Bin 336 -> 0 bytes vcl/aqua/source/res/cursors/copydlnk.png | Bin 340 -> 0 bytes vcl/aqua/source/res/cursors/copyf.png | Bin 329 -> 0 bytes vcl/aqua/source/res/cursors/copyf2.png | Bin 344 -> 0 bytes vcl/aqua/source/res/cursors/copyflnk.png | Bin 339 -> 0 bytes vcl/aqua/source/res/cursors/crook.png | Bin 291 -> 0 bytes vcl/aqua/source/res/cursors/crop.png | Bin 239 -> 0 bytes vcl/aqua/source/res/cursors/darc.png | Bin 172 -> 0 bytes vcl/aqua/source/res/cursors/dbezier.png | Bin 185 -> 0 bytes vcl/aqua/source/res/cursors/dcapt.png | Bin 183 -> 0 bytes vcl/aqua/source/res/cursors/dcirccut.png | Bin 185 -> 0 bytes vcl/aqua/source/res/cursors/dconnect.png | Bin 183 -> 0 bytes vcl/aqua/source/res/cursors/dellipse.png | Bin 176 -> 0 bytes vcl/aqua/source/res/cursors/detectiv.png | Bin 268 -> 0 bytes vcl/aqua/source/res/cursors/dfree.png | Bin 188 -> 0 bytes vcl/aqua/source/res/cursors/dline.png | Bin 177 -> 0 bytes vcl/aqua/source/res/cursors/dpie.png | Bin 183 -> 0 bytes vcl/aqua/source/res/cursors/dpolygon.png | Bin 191 -> 0 bytes vcl/aqua/source/res/cursors/drect.png | Bin 172 -> 0 bytes vcl/aqua/source/res/cursors/dtext.png | Bin 174 -> 0 bytes vcl/aqua/source/res/cursors/fill.png | Bin 255 -> 0 bytes vcl/aqua/source/res/cursors/help.png | Bin 303 -> 0 bytes vcl/aqua/source/res/cursors/hourglass.png | Bin 246 -> 0 bytes vcl/aqua/source/res/cursors/hshear.png | Bin 223 -> 0 bytes vcl/aqua/source/res/cursors/linkdata.png | Bin 348 -> 0 bytes vcl/aqua/source/res/cursors/linkf.png | Bin 336 -> 0 bytes vcl/aqua/source/res/cursors/magnify.png | Bin 282 -> 0 bytes vcl/aqua/source/res/cursors/mirror.png | Bin 304 -> 0 bytes vcl/aqua/source/res/cursors/movebw.png | Bin 320 -> 0 bytes vcl/aqua/source/res/cursors/movedata.png | Bin 290 -> 0 bytes vcl/aqua/source/res/cursors/movedlnk.png | Bin 318 -> 0 bytes vcl/aqua/source/res/cursors/movef.png | Bin 294 -> 0 bytes vcl/aqua/source/res/cursors/movef2.png | Bin 314 -> 0 bytes vcl/aqua/source/res/cursors/moveflnk.png | Bin 307 -> 0 bytes vcl/aqua/source/res/cursors/movept.png | Bin 275 -> 0 bytes vcl/aqua/source/res/cursors/neswsize.png | Bin 312 -> 0 bytes vcl/aqua/source/res/cursors/notallow.png | Bin 297 -> 0 bytes vcl/aqua/source/res/cursors/nullptr.png | Bin 150 -> 0 bytes vcl/aqua/source/res/cursors/nwsesize.png | Bin 313 -> 0 bytes vcl/aqua/source/res/cursors/pen.png | Bin 351 -> 0 bytes vcl/aqua/source/res/cursors/pivotcol.png | Bin 293 -> 0 bytes vcl/aqua/source/res/cursors/pivotdel.png | Bin 264 -> 0 bytes vcl/aqua/source/res/cursors/pivotfld.png | Bin 272 -> 0 bytes vcl/aqua/source/res/cursors/pivotrow.png | Bin 295 -> 0 bytes vcl/aqua/source/res/cursors/pntbrsh.png | Bin 268 -> 0 bytes vcl/aqua/source/res/cursors/rotate.png | Bin 274 -> 0 bytes vcl/aqua/source/res/cursors/tblsele.png | Bin 174 -> 0 bytes vcl/aqua/source/res/cursors/tblsels.png | Bin 171 -> 0 bytes vcl/aqua/source/res/cursors/tblselse.png | Bin 183 -> 0 bytes vcl/aqua/source/res/cursors/tblselsw.png | Bin 183 -> 0 bytes vcl/aqua/source/res/cursors/tblselw.png | Bin 174 -> 0 bytes vcl/aqua/source/res/cursors/timemove.png | Bin 249 -> 0 bytes vcl/aqua/source/res/cursors/timesize.png | Bin 241 -> 0 bytes vcl/aqua/source/res/cursors/vshear.png | Bin 228 -> 0 bytes vcl/aqua/source/res/cursors/vtext.png | Bin 162 -> 0 bytes vcl/aqua/source/window/salframe.cxx | 1769 ------------------- vcl/aqua/source/window/salframeview.mm | 1805 -------------------- vcl/aqua/source/window/salmenu.cxx | 963 ----------- vcl/aqua/source/window/salnsmenu.mm | 207 --- vcl/aqua/source/window/salobj.cxx | 206 --- vcl/coretext/ctfonts.cxx | 478 ------ vcl/coretext/ctfonts.hxx | 28 - vcl/coretext/ctlayout.cxx | 501 ------ vcl/coretext/salgdi.cxx | 889 ---------- vcl/inc/aqua/aqua11yfactory.h | 41 - vcl/inc/aqua/aqua11yfocustracker.hxx | 100 -- vcl/inc/aqua/aqua11ylistener.hxx | 58 - vcl/inc/aqua/aqua11ywrapper.h | 110 -- vcl/inc/aqua/aquaprintview.h | 61 - vcl/inc/aqua/aquavcltypes.h | 30 - vcl/inc/aqua/keyboardfocuslistener.hxx | 38 - vcl/inc/aqua/saldata.hxx | 120 -- vcl/inc/aqua/salframe.h | 217 --- vcl/inc/aqua/salframeview.h | 208 --- vcl/inc/aqua/salinst.h | 175 -- vcl/inc/aqua/salmathutils.hxx | 81 - vcl/inc/aqua/salmenu.h | 114 -- vcl/inc/aqua/salnativewidgets.h | 64 - vcl/inc/aqua/salnsmenu.h | 62 - vcl/inc/aqua/salnstimer.h | 34 - vcl/inc/aqua/salobj.h | 75 - vcl/inc/aqua/salprn.h | 165 -- vcl/inc/aqua/salsys.h | 51 - vcl/inc/aqua/saltimer.h | 48 - vcl/inc/aqua/salvd.h | 85 - vcl/inc/aqua/svsys.h | 29 - vcl/inc/aqua/vclnsapp.h | 68 - vcl/inc/coretext/common.h | 53 - vcl/inc/coretext/salgdi.h | 433 ----- vcl/inc/headless/svpframe.hxx | 2 + vcl/inc/headless/svpgdi.hxx | 2 +- vcl/inc/osx/a11yfactory.h | 42 + vcl/inc/osx/a11yfocustracker.hxx | 100 ++ vcl/inc/osx/a11ylistener.hxx | 58 + vcl/inc/osx/a11ywrapper.h | 110 ++ vcl/inc/osx/keyboardfocuslistener.hxx | 39 + vcl/inc/osx/osxvcltypes.h | 30 + vcl/inc/osx/printview.h | 60 + vcl/inc/osx/saldata.hxx | 120 ++ vcl/inc/osx/salframe.h | 217 +++ vcl/inc/osx/salframeview.h | 208 +++ vcl/inc/osx/salinst.h | 175 ++ vcl/inc/osx/salmenu.h | 114 ++ vcl/inc/osx/salnativewidgets.h | 64 + vcl/inc/osx/salnsmenu.h | 61 + vcl/inc/osx/salnstimer.h | 35 + vcl/inc/osx/salobj.h | 75 + vcl/inc/osx/salprn.h | 165 ++ vcl/inc/osx/salsys.h | 51 + vcl/inc/osx/saltimer.h | 48 + vcl/inc/osx/salvd.h | 85 + vcl/inc/osx/svsys.h | 29 + vcl/inc/osx/vclnsapp.h | 68 + vcl/inc/quartz/common.h | 53 + vcl/inc/quartz/salbmp.h | 2 +- vcl/inc/quartz/salgdi.h | 433 +++++ vcl/inc/quartz/salmathutils.hxx | 81 + vcl/inc/saldatabasic.hxx | 2 +- vcl/inc/svsys.h | 2 +- vcl/osx/DataFlavorMapping.cxx | 741 ++++++++ vcl/osx/DataFlavorMapping.hxx | 141 ++ vcl/osx/DragActionConversion.cxx | 86 + vcl/osx/DragActionConversion.hxx | 40 + vcl/osx/DragSource.cxx | 372 ++++ vcl/osx/DragSource.hxx | 135 ++ vcl/osx/DragSourceContext.cxx | 61 + vcl/osx/DragSourceContext.hxx | 59 + vcl/osx/DropTarget.cxx | 596 +++++++ vcl/osx/DropTarget.hxx | 163 ++ vcl/osx/HtmlFmtFlt.cxx | 168 ++ vcl/osx/HtmlFmtFlt.hxx | 41 + vcl/osx/OSXTransferable.cxx | 203 +++ vcl/osx/OSXTransferable.hxx | 90 + vcl/osx/PictToBmpFlt.cxx | 76 + vcl/osx/PictToBmpFlt.hxx | 39 + vcl/osx/README.a11y | 7 + vcl/osx/a11yactionwrapper.h | 35 + vcl/osx/a11yactionwrapper.mm | 77 + vcl/osx/a11ycomponentwrapper.h | 39 + vcl/osx/a11ycomponentwrapper.mm | 102 ++ vcl/osx/a11yfactory.mm | 219 +++ vcl/osx/a11yfocuslistener.cxx | 110 ++ vcl/osx/a11yfocuslistener.hxx | 54 + vcl/osx/a11yfocustracker.cxx | 284 +++ vcl/osx/a11ylistener.cxx | 153 ++ vcl/osx/a11yrolehelper.h | 36 + vcl/osx/a11yrolehelper.mm | 270 +++ vcl/osx/a11yselectionwrapper.h | 37 + vcl/osx/a11yselectionwrapper.mm | 88 + vcl/osx/a11ytablewrapper.h | 38 + vcl/osx/a11ytablewrapper.mm | 204 +++ vcl/osx/a11ytextattributeswrapper.h | 32 + vcl/osx/a11ytextattributeswrapper.mm | 355 ++++ vcl/osx/a11ytextwrapper.h | 58 + vcl/osx/a11ytextwrapper.mm | 293 ++++ vcl/osx/a11yutil.h | 32 + vcl/osx/a11yutil.mm | 46 + vcl/osx/a11yvaluewrapper.h | 40 + vcl/osx/a11yvaluewrapper.mm | 87 + vcl/osx/a11ywrapper.mm | 1150 +++++++++++++ vcl/osx/a11ywrapperbutton.h | 35 + vcl/osx/a11ywrapperbutton.mm | 54 + vcl/osx/a11ywrappercheckbox.h | 35 + vcl/osx/a11ywrappercheckbox.mm | 58 + vcl/osx/a11ywrappercombobox.h | 44 + vcl/osx/a11ywrappercombobox.mm | 155 ++ vcl/osx/a11ywrappergroup.h | 34 + vcl/osx/a11ywrappergroup.mm | 49 + vcl/osx/a11ywrapperlist.h | 33 + vcl/osx/a11ywrapperlist.mm | 40 + vcl/osx/a11ywrapperradiobutton.h | 35 + vcl/osx/a11ywrapperradiobutton.mm | 57 + vcl/osx/a11ywrapperradiogroup.h | 33 + vcl/osx/a11ywrapperradiogroup.mm | 40 + vcl/osx/a11ywrapperrow.h | 34 + vcl/osx/a11ywrapperrow.mm | 49 + vcl/osx/a11ywrapperscrollarea.h | 35 + vcl/osx/a11ywrapperscrollarea.mm | 77 + vcl/osx/a11ywrapperscrollbar.h | 33 + vcl/osx/a11ywrapperscrollbar.mm | 43 + vcl/osx/a11ywrappersplitter.h | 33 + vcl/osx/a11ywrappersplitter.mm | 40 + vcl/osx/a11ywrapperstatictext.h | 34 + vcl/osx/a11ywrapperstatictext.mm | 48 + vcl/osx/a11ywrappertabgroup.h | 33 + vcl/osx/a11ywrappertabgroup.mm | 42 + vcl/osx/a11ywrappertextarea.h | 33 + vcl/osx/a11ywrappertextarea.mm | 40 + vcl/osx/a11ywrappertoolbar.h | 33 + vcl/osx/a11ywrappertoolbar.mm | 42 + vcl/osx/clipboard.cxx | 372 ++++ vcl/osx/clipboard.hxx | 175 ++ vcl/osx/documentfocuslistener.cxx | 241 +++ vcl/osx/documentfocuslistener.hxx | 92 + vcl/osx/printaccessoryview.mm | 1381 +++++++++++++++ vcl/osx/printview.mm | 75 + vcl/osx/res/MainMenu.nib/classes.nib | 4 + vcl/osx/res/MainMenu.nib/info.nib | 21 + vcl/osx/res/MainMenu.nib/keyedobjects.nib | Bin 0 -> 3615 bytes vcl/osx/res/cursors/airbrush.png | Bin 0 -> 253 bytes vcl/osx/res/cursors/ase.png | Bin 0 -> 214 bytes vcl/osx/res/cursors/asn.png | Bin 0 -> 212 bytes vcl/osx/res/cursors/asne.png | Bin 0 -> 240 bytes vcl/osx/res/cursors/asns.png | Bin 0 -> 234 bytes vcl/osx/res/cursors/asnswe.png | Bin 0 -> 285 bytes vcl/osx/res/cursors/asnw.png | Bin 0 -> 246 bytes vcl/osx/res/cursors/ass.png | Bin 0 -> 222 bytes vcl/osx/res/cursors/asse.png | Bin 0 -> 243 bytes vcl/osx/res/cursors/assw.png | Bin 0 -> 236 bytes vcl/osx/res/cursors/asw.png | Bin 0 -> 212 bytes vcl/osx/res/cursors/aswe.png | Bin 0 -> 228 bytes vcl/osx/res/cursors/chain.png | Bin 0 -> 344 bytes vcl/osx/res/cursors/chainnot.png | Bin 0 -> 390 bytes vcl/osx/res/cursors/chart.png | Bin 0 -> 270 bytes vcl/osx/res/cursors/copydata.png | Bin 0 -> 336 bytes vcl/osx/res/cursors/copydlnk.png | Bin 0 -> 340 bytes vcl/osx/res/cursors/copyf.png | Bin 0 -> 329 bytes vcl/osx/res/cursors/copyf2.png | Bin 0 -> 344 bytes vcl/osx/res/cursors/copyflnk.png | Bin 0 -> 339 bytes vcl/osx/res/cursors/crook.png | Bin 0 -> 291 bytes vcl/osx/res/cursors/crop.png | Bin 0 -> 239 bytes vcl/osx/res/cursors/darc.png | Bin 0 -> 172 bytes vcl/osx/res/cursors/dbezier.png | Bin 0 -> 185 bytes vcl/osx/res/cursors/dcapt.png | Bin 0 -> 183 bytes vcl/osx/res/cursors/dcirccut.png | Bin 0 -> 185 bytes vcl/osx/res/cursors/dconnect.png | Bin 0 -> 183 bytes vcl/osx/res/cursors/dellipse.png | Bin 0 -> 176 bytes vcl/osx/res/cursors/detectiv.png | Bin 0 -> 268 bytes vcl/osx/res/cursors/dfree.png | Bin 0 -> 188 bytes vcl/osx/res/cursors/dline.png | Bin 0 -> 177 bytes vcl/osx/res/cursors/dpie.png | Bin 0 -> 183 bytes vcl/osx/res/cursors/dpolygon.png | Bin 0 -> 191 bytes vcl/osx/res/cursors/drect.png | Bin 0 -> 172 bytes vcl/osx/res/cursors/dtext.png | Bin 0 -> 174 bytes vcl/osx/res/cursors/fill.png | Bin 0 -> 255 bytes vcl/osx/res/cursors/help.png | Bin 0 -> 303 bytes vcl/osx/res/cursors/hourglass.png | Bin 0 -> 246 bytes vcl/osx/res/cursors/hshear.png | Bin 0 -> 223 bytes vcl/osx/res/cursors/linkdata.png | Bin 0 -> 348 bytes vcl/osx/res/cursors/linkf.png | Bin 0 -> 336 bytes vcl/osx/res/cursors/magnify.png | Bin 0 -> 282 bytes vcl/osx/res/cursors/mirror.png | Bin 0 -> 304 bytes vcl/osx/res/cursors/movebw.png | Bin 0 -> 320 bytes vcl/osx/res/cursors/movedata.png | Bin 0 -> 290 bytes vcl/osx/res/cursors/movedlnk.png | Bin 0 -> 318 bytes vcl/osx/res/cursors/movef.png | Bin 0 -> 294 bytes vcl/osx/res/cursors/movef2.png | Bin 0 -> 314 bytes vcl/osx/res/cursors/moveflnk.png | Bin 0 -> 307 bytes vcl/osx/res/cursors/movept.png | Bin 0 -> 275 bytes vcl/osx/res/cursors/neswsize.png | Bin 0 -> 312 bytes vcl/osx/res/cursors/notallow.png | Bin 0 -> 297 bytes vcl/osx/res/cursors/nullptr.png | Bin 0 -> 150 bytes vcl/osx/res/cursors/nwsesize.png | Bin 0 -> 313 bytes vcl/osx/res/cursors/pen.png | Bin 0 -> 351 bytes vcl/osx/res/cursors/pivotcol.png | Bin 0 -> 293 bytes vcl/osx/res/cursors/pivotdel.png | Bin 0 -> 264 bytes vcl/osx/res/cursors/pivotfld.png | Bin 0 -> 272 bytes vcl/osx/res/cursors/pivotrow.png | Bin 0 -> 295 bytes vcl/osx/res/cursors/pntbrsh.png | Bin 0 -> 268 bytes vcl/osx/res/cursors/rotate.png | Bin 0 -> 274 bytes vcl/osx/res/cursors/tblsele.png | Bin 0 -> 174 bytes vcl/osx/res/cursors/tblsels.png | Bin 0 -> 171 bytes vcl/osx/res/cursors/tblselse.png | Bin 0 -> 183 bytes vcl/osx/res/cursors/tblselsw.png | Bin 0 -> 183 bytes vcl/osx/res/cursors/tblselw.png | Bin 0 -> 174 bytes vcl/osx/res/cursors/timemove.png | Bin 0 -> 249 bytes vcl/osx/res/cursors/timesize.png | Bin 0 -> 241 bytes vcl/osx/res/cursors/vshear.png | Bin 0 -> 228 bytes vcl/osx/res/cursors/vtext.png | Bin 0 -> 162 bytes vcl/osx/saldata.cxx | 265 +++ vcl/osx/salframe.cxx | 1769 +++++++++++++++++++ vcl/osx/salframeview.mm | 1805 ++++++++++++++++++++ vcl/osx/salinst.cxx | 1207 +++++++++++++ vcl/osx/salmenu.cxx | 963 +++++++++++ vcl/osx/salnativewidgets.cxx | 1462 ++++++++++++++++ vcl/osx/salnsmenu.mm | 207 +++ vcl/osx/salnstimer.mm | 48 + vcl/osx/salobj.cxx | 206 +++ vcl/osx/salprn.cxx | 755 ++++++++ vcl/osx/salsys.cxx | 190 +++ vcl/osx/saltimer.cxx | 126 ++ vcl/osx/salvd.cxx | 261 +++ vcl/osx/service_entry.cxx | 68 + vcl/osx/vclnsapp.mm | 517 ++++++ vcl/quartz/ctfonts.cxx | 478 ++++++ vcl/quartz/ctfonts.hxx | 28 + vcl/quartz/ctlayout.cxx | 501 ++++++ vcl/quartz/salbmp.cxx | 2 +- vcl/quartz/salgdi.cxx | 889 ++++++++++ vcl/quartz/salgdicommon.cxx | 1755 +++++++++++++++++++ vcl/quartz/salgdiutils.cxx | 299 ++++ vcl/quartz/salmathutils.cxx | 154 ++ vcl/source/app/svapp.cxx | 2 +- vcl/source/app/svmainhook.cxx | 2 +- vcl/source/control/edit.cxx | 8 +- vcl/source/control/scrbar.cxx | 4 +- vcl/source/control/spinfld.cxx | 2 +- vcl/source/window/brdwin.cxx | 6 +- vcl/source/window/window.cxx | 2 +- 411 files changed, 27133 insertions(+), 27130 deletions(-) delete mode 100644 vcl/aqua/source/a11y/aqua11yactionwrapper.h delete mode 100644 vcl/aqua/source/a11y/aqua11yactionwrapper.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ycomponentwrapper.h delete mode 100644 vcl/aqua/source/a11y/aqua11ycomponentwrapper.mm delete mode 100644 vcl/aqua/source/a11y/aqua11yfactory.mm delete mode 100644 vcl/aqua/source/a11y/aqua11yfocuslistener.cxx delete mode 100644 vcl/aqua/source/a11y/aqua11yfocuslistener.hxx delete mode 100644 vcl/aqua/source/a11y/aqua11yfocustracker.cxx delete mode 100644 vcl/aqua/source/a11y/aqua11ylistener.cxx delete mode 100644 vcl/aqua/source/a11y/aqua11yrolehelper.h delete mode 100644 vcl/aqua/source/a11y/aqua11yrolehelper.mm delete mode 100644 vcl/aqua/source/a11y/aqua11yselectionwrapper.h delete mode 100644 vcl/aqua/source/a11y/aqua11yselectionwrapper.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ytablewrapper.h delete mode 100644 vcl/aqua/source/a11y/aqua11ytablewrapper.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ytextattributeswrapper.h delete mode 100644 vcl/aqua/source/a11y/aqua11ytextattributeswrapper.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ytextwrapper.h delete mode 100644 vcl/aqua/source/a11y/aqua11ytextwrapper.mm delete mode 100644 vcl/aqua/source/a11y/aqua11yutil.h delete mode 100644 vcl/aqua/source/a11y/aqua11yutil.mm delete mode 100644 vcl/aqua/source/a11y/aqua11yvaluewrapper.h delete mode 100644 vcl/aqua/source/a11y/aqua11yvaluewrapper.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapper.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapperbutton.h delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapperbutton.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ywrappercheckbox.h delete mode 100644 vcl/aqua/source/a11y/aqua11ywrappercheckbox.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ywrappercombobox.h delete mode 100644 vcl/aqua/source/a11y/aqua11ywrappercombobox.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ywrappergroup.h delete mode 100644 vcl/aqua/source/a11y/aqua11ywrappergroup.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapperlist.h delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapperlist.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapperradiobutton.h delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapperradiobutton.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapperradiogroup.h delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapperradiogroup.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapperrow.h delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapperrow.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapperscrollarea.h delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapperscrollarea.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapperscrollbar.h delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapperscrollbar.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ywrappersplitter.h delete mode 100644 vcl/aqua/source/a11y/aqua11ywrappersplitter.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapperstatictext.h delete mode 100644 vcl/aqua/source/a11y/aqua11ywrapperstatictext.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ywrappertabgroup.h delete mode 100644 vcl/aqua/source/a11y/aqua11ywrappertabgroup.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ywrappertextarea.h delete mode 100644 vcl/aqua/source/a11y/aqua11ywrappertextarea.mm delete mode 100644 vcl/aqua/source/a11y/aqua11ywrappertoolbar.h delete mode 100644 vcl/aqua/source/a11y/aqua11ywrappertoolbar.mm delete mode 100644 vcl/aqua/source/a11y/documentfocuslistener.cxx delete mode 100644 vcl/aqua/source/a11y/documentfocuslistener.hxx delete mode 100644 vcl/aqua/source/a11y/readme.txt delete mode 100644 vcl/aqua/source/app/saldata.cxx delete mode 100644 vcl/aqua/source/app/salinst.cxx delete mode 100644 vcl/aqua/source/app/salnstimer.mm delete mode 100644 vcl/aqua/source/app/salsys.cxx delete mode 100644 vcl/aqua/source/app/saltimer.cxx delete mode 100644 vcl/aqua/source/app/vclnsapp.mm delete mode 100644 vcl/aqua/source/dtrans/DataFlavorMapping.cxx delete mode 100644 vcl/aqua/source/dtrans/DataFlavorMapping.hxx delete mode 100644 vcl/aqua/source/dtrans/DragActionConversion.cxx delete mode 100644 vcl/aqua/source/dtrans/DragActionConversion.hxx delete mode 100644 vcl/aqua/source/dtrans/DragSource.cxx delete mode 100644 vcl/aqua/source/dtrans/DragSource.hxx delete mode 100644 vcl/aqua/source/dtrans/DragSourceContext.cxx delete mode 100644 vcl/aqua/source/dtrans/DragSourceContext.hxx delete mode 100644 vcl/aqua/source/dtrans/DropTarget.cxx delete mode 100644 vcl/aqua/source/dtrans/DropTarget.hxx delete mode 100644 vcl/aqua/source/dtrans/HtmlFmtFlt.cxx delete mode 100644 vcl/aqua/source/dtrans/HtmlFmtFlt.hxx delete mode 100644 vcl/aqua/source/dtrans/OSXTransferable.cxx delete mode 100644 vcl/aqua/source/dtrans/OSXTransferable.hxx delete mode 100644 vcl/aqua/source/dtrans/PictToBmpFlt.cxx delete mode 100644 vcl/aqua/source/dtrans/PictToBmpFlt.hxx delete mode 100644 vcl/aqua/source/dtrans/aqua_clipboard.cxx delete mode 100644 vcl/aqua/source/dtrans/aqua_clipboard.hxx delete mode 100644 vcl/aqua/source/dtrans/service_entry.cxx delete mode 100644 vcl/aqua/source/gdi/aquaprintaccessoryview.mm delete mode 100644 vcl/aqua/source/gdi/aquaprintview.mm delete mode 100644 vcl/aqua/source/gdi/salgdicommon.cxx delete mode 100644 vcl/aqua/source/gdi/salgdiutils.cxx delete mode 100644 vcl/aqua/source/gdi/salmathutils.cxx delete mode 100644 vcl/aqua/source/gdi/salnativewidgets.cxx delete mode 100644 vcl/aqua/source/gdi/salprn.cxx delete mode 100644 vcl/aqua/source/gdi/salvd.cxx delete mode 100644 vcl/aqua/source/res/MainMenu.nib/classes.nib delete mode 100644 vcl/aqua/source/res/MainMenu.nib/info.nib delete mode 100644 vcl/aqua/source/res/MainMenu.nib/keyedobjects.nib delete mode 100644 vcl/aqua/source/res/cursors/airbrush.png delete mode 100644 vcl/aqua/source/res/cursors/ase.png delete mode 100644 vcl/aqua/source/res/cursors/asn.png delete mode 100644 vcl/aqua/source/res/cursors/asne.png delete mode 100644 vcl/aqua/source/res/cursors/asns.png delete mode 100644 vcl/aqua/source/res/cursors/asnswe.png delete mode 100644 vcl/aqua/source/res/cursors/asnw.png delete mode 100644 vcl/aqua/source/res/cursors/ass.png delete mode 100644 vcl/aqua/source/res/cursors/asse.png delete mode 100644 vcl/aqua/source/res/cursors/assw.png delete mode 100644 vcl/aqua/source/res/cursors/asw.png delete mode 100644 vcl/aqua/source/res/cursors/aswe.png delete mode 100644 vcl/aqua/source/res/cursors/chain.png delete mode 100644 vcl/aqua/source/res/cursors/chainnot.png delete mode 100644 vcl/aqua/source/res/cursors/chart.png delete mode 100644 vcl/aqua/source/res/cursors/copydata.png delete mode 100644 vcl/aqua/source/res/cursors/copydlnk.png delete mode 100644 vcl/aqua/source/res/cursors/copyf.png delete mode 100644 vcl/aqua/source/res/cursors/copyf2.png delete mode 100644 vcl/aqua/source/res/cursors/copyflnk.png delete mode 100644 vcl/aqua/source/res/cursors/crook.png delete mode 100644 vcl/aqua/source/res/cursors/crop.png delete mode 100644 vcl/aqua/source/res/cursors/darc.png delete mode 100644 vcl/aqua/source/res/cursors/dbezier.png delete mode 100644 vcl/aqua/source/res/cursors/dcapt.png delete mode 100644 vcl/aqua/source/res/cursors/dcirccut.png delete mode 100644 vcl/aqua/source/res/cursors/dconnect.png delete mode 100644 vcl/aqua/source/res/cursors/dellipse.png delete mode 100644 vcl/aqua/source/res/cursors/detectiv.png delete mode 100644 vcl/aqua/source/res/cursors/dfree.png delete mode 100644 vcl/aqua/source/res/cursors/dline.png delete mode 100644 vcl/aqua/source/res/cursors/dpie.png delete mode 100644 vcl/aqua/source/res/cursors/dpolygon.png delete mode 100644 vcl/aqua/source/res/cursors/drect.png delete mode 100644 vcl/aqua/source/res/cursors/dtext.png delete mode 100644 vcl/aqua/source/res/cursors/fill.png delete mode 100644 vcl/aqua/source/res/cursors/help.png delete mode 100644 vcl/aqua/source/res/cursors/hourglass.png delete mode 100644 vcl/aqua/source/res/cursors/hshear.png delete mode 100644 vcl/aqua/source/res/cursors/linkdata.png delete mode 100644 vcl/aqua/source/res/cursors/linkf.png delete mode 100644 vcl/aqua/source/res/cursors/magnify.png delete mode 100644 vcl/aqua/source/res/cursors/mirror.png delete mode 100644 vcl/aqua/source/res/cursors/movebw.png delete mode 100644 vcl/aqua/source/res/cursors/movedata.png delete mode 100644 vcl/aqua/source/res/cursors/movedlnk.png delete mode 100644 vcl/aqua/source/res/cursors/movef.png delete mode 100644 vcl/aqua/source/res/cursors/movef2.png delete mode 100644 vcl/aqua/source/res/cursors/moveflnk.png delete mode 100644 vcl/aqua/source/res/cursors/movept.png delete mode 100644 vcl/aqua/source/res/cursors/neswsize.png delete mode 100644 vcl/aqua/source/res/cursors/notallow.png delete mode 100644 vcl/aqua/source/res/cursors/nullptr.png delete mode 100644 vcl/aqua/source/res/cursors/nwsesize.png delete mode 100644 vcl/aqua/source/res/cursors/pen.png delete mode 100644 vcl/aqua/source/res/cursors/pivotcol.png delete mode 100644 vcl/aqua/source/res/cursors/pivotdel.png delete mode 100644 vcl/aqua/source/res/cursors/pivotfld.png delete mode 100644 vcl/aqua/source/res/cursors/pivotrow.png delete mode 100644 vcl/aqua/source/res/cursors/pntbrsh.png delete mode 100644 vcl/aqua/source/res/cursors/rotate.png delete mode 100644 vcl/aqua/source/res/cursors/tblsele.png delete mode 100644 vcl/aqua/source/res/cursors/tblsels.png delete mode 100644 vcl/aqua/source/res/cursors/tblselse.png delete mode 100644 vcl/aqua/source/res/cursors/tblselsw.png delete mode 100644 vcl/aqua/source/res/cursors/tblselw.png delete mode 100644 vcl/aqua/source/res/cursors/timemove.png delete mode 100644 vcl/aqua/source/res/cursors/timesize.png delete mode 100644 vcl/aqua/source/res/cursors/vshear.png delete mode 100644 vcl/aqua/source/res/cursors/vtext.png delete mode 100644 vcl/aqua/source/window/salframe.cxx delete mode 100644 vcl/aqua/source/window/salframeview.mm delete mode 100644 vcl/aqua/source/window/salmenu.cxx delete mode 100644 vcl/aqua/source/window/salnsmenu.mm delete mode 100644 vcl/aqua/source/window/salobj.cxx delete mode 100644 vcl/coretext/ctfonts.cxx delete mode 100644 vcl/coretext/ctfonts.hxx delete mode 100644 vcl/coretext/ctlayout.cxx delete mode 100644 vcl/coretext/salgdi.cxx delete mode 100644 vcl/inc/aqua/aqua11yfactory.h delete mode 100644 vcl/inc/aqua/aqua11yfocustracker.hxx delete mode 100644 vcl/inc/aqua/aqua11ylistener.hxx delete mode 100644 vcl/inc/aqua/aqua11ywrapper.h delete mode 100644 vcl/inc/aqua/aquaprintview.h delete mode 100644 vcl/inc/aqua/aquavcltypes.h delete mode 100644 vcl/inc/aqua/keyboardfocuslistener.hxx delete mode 100644 vcl/inc/aqua/saldata.hxx delete mode 100644 vcl/inc/aqua/salframe.h delete mode 100644 vcl/inc/aqua/salframeview.h delete mode 100644 vcl/inc/aqua/salinst.h delete mode 100644 vcl/inc/aqua/salmathutils.hxx delete mode 100644 vcl/inc/aqua/salmenu.h delete mode 100644 vcl/inc/aqua/salnativewidgets.h delete mode 100644 vcl/inc/aqua/salnsmenu.h delete mode 100644 vcl/inc/aqua/salnstimer.h delete mode 100644 vcl/inc/aqua/salobj.h delete mode 100644 vcl/inc/aqua/salprn.h delete mode 100644 vcl/inc/aqua/salsys.h delete mode 100644 vcl/inc/aqua/saltimer.h delete mode 100644 vcl/inc/aqua/salvd.h delete mode 100644 vcl/inc/aqua/svsys.h delete mode 100644 vcl/inc/aqua/vclnsapp.h delete mode 100644 vcl/inc/coretext/common.h delete mode 100644 vcl/inc/coretext/salgdi.h create mode 100644 vcl/inc/osx/a11yfactory.h create mode 100644 vcl/inc/osx/a11yfocustracker.hxx create mode 100644 vcl/inc/osx/a11ylistener.hxx create mode 100644 vcl/inc/osx/a11ywrapper.h create mode 100644 vcl/inc/osx/keyboardfocuslistener.hxx create mode 100644 vcl/inc/osx/osxvcltypes.h create mode 100644 vcl/inc/osx/printview.h create mode 100644 vcl/inc/osx/saldata.hxx create mode 100644 vcl/inc/osx/salframe.h create mode 100644 vcl/inc/osx/salframeview.h create mode 100644 vcl/inc/osx/salinst.h create mode 100644 vcl/inc/osx/salmenu.h create mode 100644 vcl/inc/osx/salnativewidgets.h create mode 100644 vcl/inc/osx/salnsmenu.h create mode 100644 vcl/inc/osx/salnstimer.h create mode 100644 vcl/inc/osx/salobj.h create mode 100644 vcl/inc/osx/salprn.h create mode 100644 vcl/inc/osx/salsys.h create mode 100644 vcl/inc/osx/saltimer.h create mode 100644 vcl/inc/osx/salvd.h create mode 100644 vcl/inc/osx/svsys.h create mode 100644 vcl/inc/osx/vclnsapp.h create mode 100644 vcl/inc/quartz/common.h create mode 100644 vcl/inc/quartz/salgdi.h create mode 100644 vcl/inc/quartz/salmathutils.hxx create mode 100644 vcl/osx/DataFlavorMapping.cxx create mode 100644 vcl/osx/DataFlavorMapping.hxx create mode 100644 vcl/osx/DragActionConversion.cxx create mode 100644 vcl/osx/DragActionConversion.hxx create mode 100644 vcl/osx/DragSource.cxx create mode 100644 vcl/osx/DragSource.hxx create mode 100644 vcl/osx/DragSourceContext.cxx create mode 100644 vcl/osx/DragSourceContext.hxx create mode 100644 vcl/osx/DropTarget.cxx create mode 100644 vcl/osx/DropTarget.hxx create mode 100644 vcl/osx/HtmlFmtFlt.cxx create mode 100644 vcl/osx/HtmlFmtFlt.hxx create mode 100644 vcl/osx/OSXTransferable.cxx create mode 100644 vcl/osx/OSXTransferable.hxx create mode 100644 vcl/osx/PictToBmpFlt.cxx create mode 100644 vcl/osx/PictToBmpFlt.hxx create mode 100644 vcl/osx/README.a11y create mode 100644 vcl/osx/a11yactionwrapper.h create mode 100644 vcl/osx/a11yactionwrapper.mm create mode 100644 vcl/osx/a11ycomponentwrapper.h create mode 100644 vcl/osx/a11ycomponentwrapper.mm create mode 100644 vcl/osx/a11yfactory.mm create mode 100644 vcl/osx/a11yfocuslistener.cxx create mode 100644 vcl/osx/a11yfocuslistener.hxx create mode 100644 vcl/osx/a11yfocustracker.cxx create mode 100644 vcl/osx/a11ylistener.cxx create mode 100644 vcl/osx/a11yrolehelper.h create mode 100644 vcl/osx/a11yrolehelper.mm create mode 100644 vcl/osx/a11yselectionwrapper.h create mode 100644 vcl/osx/a11yselectionwrapper.mm create mode 100644 vcl/osx/a11ytablewrapper.h create mode 100644 vcl/osx/a11ytablewrapper.mm create mode 100644 vcl/osx/a11ytextattributeswrapper.h create mode 100644 vcl/osx/a11ytextattributeswrapper.mm create mode 100644 vcl/osx/a11ytextwrapper.h create mode 100644 vcl/osx/a11ytextwrapper.mm create mode 100644 vcl/osx/a11yutil.h create mode 100644 vcl/osx/a11yutil.mm create mode 100644 vcl/osx/a11yvaluewrapper.h create mode 100644 vcl/osx/a11yvaluewrapper.mm create mode 100644 vcl/osx/a11ywrapper.mm create mode 100644 vcl/osx/a11ywrapperbutton.h create mode 100644 vcl/osx/a11ywrapperbutton.mm create mode 100644 vcl/osx/a11ywrappercheckbox.h create mode 100644 vcl/osx/a11ywrappercheckbox.mm create mode 100644 vcl/osx/a11ywrappercombobox.h create mode 100644 vcl/osx/a11ywrappercombobox.mm create mode 100644 vcl/osx/a11ywrappergroup.h create mode 100644 vcl/osx/a11ywrappergroup.mm create mode 100644 vcl/osx/a11ywrapperlist.h create mode 100644 vcl/osx/a11ywrapperlist.mm create mode 100644 vcl/osx/a11ywrapperradiobutton.h create mode 100644 vcl/osx/a11ywrapperradiobutton.mm create mode 100644 vcl/osx/a11ywrapperradiogroup.h create mode 100644 vcl/osx/a11ywrapperradiogroup.mm create mode 100644 vcl/osx/a11ywrapperrow.h create mode 100644 vcl/osx/a11ywrapperrow.mm create mode 100644 vcl/osx/a11ywrapperscrollarea.h create mode 100644 vcl/osx/a11ywrapperscrollarea.mm create mode 100644 vcl/osx/a11ywrapperscrollbar.h create mode 100644 vcl/osx/a11ywrapperscrollbar.mm create mode 100644 vcl/osx/a11ywrappersplitter.h create mode 100644 vcl/osx/a11ywrappersplitter.mm create mode 100644 vcl/osx/a11ywrapperstatictext.h create mode 100644 vcl/osx/a11ywrapperstatictext.mm create mode 100644 vcl/osx/a11ywrappertabgroup.h create mode 100644 vcl/osx/a11ywrappertabgroup.mm create mode 100644 vcl/osx/a11ywrappertextarea.h create mode 100644 vcl/osx/a11ywrappertextarea.mm create mode 100644 vcl/osx/a11ywrappertoolbar.h create mode 100644 vcl/osx/a11ywrappertoolbar.mm create mode 100644 vcl/osx/clipboard.cxx create mode 100644 vcl/osx/clipboard.hxx create mode 100644 vcl/osx/documentfocuslistener.cxx create mode 100644 vcl/osx/documentfocuslistener.hxx create mode 100644 vcl/osx/printaccessoryview.mm create mode 100644 vcl/osx/printview.mm create mode 100644 vcl/osx/res/MainMenu.nib/classes.nib create mode 100644 vcl/osx/res/MainMenu.nib/info.nib create mode 100644 vcl/osx/res/MainMenu.nib/keyedobjects.nib create mode 100644 vcl/osx/res/cursors/airbrush.png create mode 100644 vcl/osx/res/cursors/ase.png create mode 100644 vcl/osx/res/cursors/asn.png create mode 100644 vcl/osx/res/cursors/asne.png create mode 100644 vcl/osx/res/cursors/asns.png create mode 100644 vcl/osx/res/cursors/asnswe.png create mode 100644 vcl/osx/res/cursors/asnw.png create mode 100644 vcl/osx/res/cursors/ass.png create mode 100644 vcl/osx/res/cursors/asse.png create mode 100644 vcl/osx/res/cursors/assw.png create mode 100644 vcl/osx/res/cursors/asw.png create mode 100644 vcl/osx/res/cursors/aswe.png create mode 100644 vcl/osx/res/cursors/chain.png create mode 100644 vcl/osx/res/cursors/chainnot.png create mode 100644 vcl/osx/res/cursors/chart.png create mode 100644 vcl/osx/res/cursors/copydata.png create mode 100644 vcl/osx/res/cursors/copydlnk.png create mode 100644 vcl/osx/res/cursors/copyf.png create mode 100644 vcl/osx/res/cursors/copyf2.png create mode 100644 vcl/osx/res/cursors/copyflnk.png create mode 100644 vcl/osx/res/cursors/crook.png create mode 100644 vcl/osx/res/cursors/crop.png create mode 100644 vcl/osx/res/cursors/darc.png create mode 100644 vcl/osx/res/cursors/dbezier.png create mode 100644 vcl/osx/res/cursors/dcapt.png create mode 100644 vcl/osx/res/cursors/dcirccut.png create mode 100644 vcl/osx/res/cursors/dconnect.png create mode 100644 vcl/osx/res/cursors/dellipse.png create mode 100644 vcl/osx/res/cursors/detectiv.png create mode 100644 vcl/osx/res/cursors/dfree.png create mode 100644 vcl/osx/res/cursors/dline.png create mode 100644 vcl/osx/res/cursors/dpie.png create mode 100644 vcl/osx/res/cursors/dpolygon.png create mode 100644 vcl/osx/res/cursors/drect.png create mode 100644 vcl/osx/res/cursors/dtext.png create mode 100644 vcl/osx/res/cursors/fill.png create mode 100644 vcl/osx/res/cursors/help.png create mode 100644 vcl/osx/res/cursors/hourglass.png create mode 100644 vcl/osx/res/cursors/hshear.png create mode 100644 vcl/osx/res/cursors/linkdata.png create mode 100644 vcl/osx/res/cursors/linkf.png create mode 100644 vcl/osx/res/cursors/magnify.png create mode 100644 vcl/osx/res/cursors/mirror.png create mode 100644 vcl/osx/res/cursors/movebw.png create mode 100644 vcl/osx/res/cursors/movedata.png create mode 100644 vcl/osx/res/cursors/movedlnk.png create mode 100644 vcl/osx/res/cursors/movef.png create mode 100644 vcl/osx/res/cursors/movef2.png create mode 100644 vcl/osx/res/cursors/moveflnk.png create mode 100644 vcl/osx/res/cursors/movept.png create mode 100644 vcl/osx/res/cursors/neswsize.png create mode 100644 vcl/osx/res/cursors/notallow.png create mode 100644 vcl/osx/res/cursors/nullptr.png create mode 100644 vcl/osx/res/cursors/nwsesize.png create mode 100644 vcl/osx/res/cursors/pen.png create mode 100644 vcl/osx/res/cursors/pivotcol.png create mode 100644 vcl/osx/res/cursors/pivotdel.png create mode 100644 vcl/osx/res/cursors/pivotfld.png create mode 100644 vcl/osx/res/cursors/pivotrow.png create mode 100644 vcl/osx/res/cursors/pntbrsh.png create mode 100644 vcl/osx/res/cursors/rotate.png create mode 100644 vcl/osx/res/cursors/tblsele.png create mode 100644 vcl/osx/res/cursors/tblsels.png create mode 100644 vcl/osx/res/cursors/tblselse.png create mode 100644 vcl/osx/res/cursors/tblselsw.png create mode 100644 vcl/osx/res/cursors/tblselw.png create mode 100644 vcl/osx/res/cursors/timemove.png create mode 100644 vcl/osx/res/cursors/timesize.png create mode 100644 vcl/osx/res/cursors/vshear.png create mode 100644 vcl/osx/res/cursors/vtext.png create mode 100644 vcl/osx/saldata.cxx create mode 100644 vcl/osx/salframe.cxx create mode 100644 vcl/osx/salframeview.mm create mode 100644 vcl/osx/salinst.cxx create mode 100644 vcl/osx/salmenu.cxx create mode 100644 vcl/osx/salnativewidgets.cxx create mode 100644 vcl/osx/salnsmenu.mm create mode 100644 vcl/osx/salnstimer.mm create mode 100644 vcl/osx/salobj.cxx create mode 100644 vcl/osx/salprn.cxx create mode 100644 vcl/osx/salsys.cxx create mode 100644 vcl/osx/saltimer.cxx create mode 100644 vcl/osx/salvd.cxx create mode 100644 vcl/osx/service_entry.cxx create mode 100644 vcl/osx/vclnsapp.mm create mode 100644 vcl/quartz/ctfonts.cxx create mode 100644 vcl/quartz/ctfonts.hxx create mode 100644 vcl/quartz/ctlayout.cxx create mode 100644 vcl/quartz/salgdi.cxx create mode 100644 vcl/quartz/salgdicommon.cxx create mode 100644 vcl/quartz/salgdiutils.cxx create mode 100644 vcl/quartz/salmathutils.cxx diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox index 3463a05fde14..3d916e67d8ae 100644 --- a/include/sal/log-areas.dox +++ b/include/sal/log-areas.dox @@ -346,6 +346,7 @@ certain functionality. @li @c vcl.kde4 - KDE4 @li @c vcl.layout - Widget layout @li @c vcl.plugadapt - the Unix/X11 backend plugin mechanism +@li @c vcl.osx.print @li @c vcl.scrollbar - Scroll Bars @li @c vcl.sm - Session Manager @li @c vcl.unity diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index fb7816f79070..72d665a72920 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -341,9 +341,9 @@ vcl_quartz_code= \ vcl/quartz/utils \ vcl_coretext_code= \ - vcl/coretext/ctfonts \ - vcl/coretext/ctlayout \ - vcl/coretext/salgdi \ + vcl/quartz/ctfonts \ + vcl/quartz/ctlayout \ + vcl/quartz/salgdi \ # GUIBASE specific stuff @@ -366,68 +366,68 @@ $(eval $(call gb_Library_use_system_darwin_frameworks,vcl,\ )) $(eval $(call gb_Library_add_objcxxobjects,vcl,\ - vcl/aqua/source/a11y/aqua11yactionwrapper \ - vcl/aqua/source/a11y/aqua11ycomponentwrapper \ - vcl/aqua/source/a11y/aqua11yfactory \ - vcl/aqua/source/a11y/aqua11yrolehelper \ - vcl/aqua/source/a11y/aqua11yselectionwrapper \ - vcl/aqua/source/a11y/aqua11ytablewrapper \ - vcl/aqua/source/a11y/aqua11ytextattributeswrapper \ - vcl/aqua/source/a11y/aqua11ytextwrapper \ - vcl/aqua/source/a11y/aqua11yutil \ - vcl/aqua/source/a11y/aqua11yvaluewrapper \ - vcl/aqua/source/a11y/aqua11ywrapper \ - vcl/aqua/source/a11y/aqua11ywrapperbutton \ - vcl/aqua/source/a11y/aqua11ywrappercheckbox \ - vcl/aqua/source/a11y/aqua11ywrappercombobox \ - vcl/aqua/source/a11y/aqua11ywrappergroup \ - vcl/aqua/source/a11y/aqua11ywrapperlist \ - vcl/aqua/source/a11y/aqua11ywrapperradiobutton \ - vcl/aqua/source/a11y/aqua11ywrapperradiogroup \ - vcl/aqua/source/a11y/aqua11ywrapperrow \ - vcl/aqua/source/a11y/aqua11ywrapperscrollarea \ - vcl/aqua/source/a11y/aqua11ywrapperscrollbar \ - vcl/aqua/source/a11y/aqua11ywrappersplitter \ - vcl/aqua/source/a11y/aqua11ywrapperstatictext \ - vcl/aqua/source/a11y/aqua11ywrappertabgroup \ - vcl/aqua/source/a11y/aqua11ywrappertextarea \ - vcl/aqua/source/a11y/aqua11ywrappertoolbar \ - vcl/aqua/source/app/salnstimer \ - vcl/aqua/source/app/vclnsapp \ - vcl/aqua/source/gdi/aquaprintaccessoryview \ - vcl/aqua/source/gdi/aquaprintview \ - vcl/aqua/source/window/salframeview \ - vcl/aqua/source/window/salnsmenu \ + vcl/osx/a11yactionwrapper \ + vcl/osx/a11ycomponentwrapper \ + vcl/osx/a11yfactory \ + vcl/osx/a11yrolehelper \ + vcl/osx/a11yselectionwrapper \ + vcl/osx/a11ytablewrapper \ + vcl/osx/a11ytextattributeswrapper \ + vcl/osx/a11ytextwrapper \ + vcl/osx/a11yutil \ + vcl/osx/a11yvaluewrapper \ + vcl/osx/a11ywrapper \ + vcl/osx/a11ywrapperbutton \ + vcl/osx/a11ywrappercheckbox \ + vcl/osx/a11ywrappercombobox \ + vcl/osx/a11ywrappergroup \ + vcl/osx/a11ywrapperlist \ + vcl/osx/a11ywrapperradiobutton \ + vcl/osx/a11ywrapperradiogroup \ + vcl/osx/a11ywrapperrow \ + vcl/osx/a11ywrapperscrollarea \ + vcl/osx/a11ywrapperscrollbar \ + vcl/osx/a11ywrappersplitter \ + vcl/osx/a11ywrapperstatictext \ + vcl/osx/a11ywrappertabgroup \ + vcl/osx/a11ywrappertextarea \ + vcl/osx/a11ywrappertoolbar \ + vcl/osx/salnstimer \ + vcl/osx/vclnsapp \ + vcl/osx/printaccessoryview \ + vcl/osx/printview \ + vcl/osx/salframeview \ + vcl/osx/salnsmenu \ )) $(eval $(call gb_Library_add_exception_objects,vcl,\ - vcl/aqua/source/a11y/aqua11yfocuslistener \ - vcl/aqua/source/a11y/aqua11yfocustracker \ - vcl/aqua/source/a11y/aqua11ylistener \ - vcl/aqua/source/a11y/documentfocuslistener \ - vcl/aqua/source/app/saldata \ - vcl/aqua/source/app/salinst \ - vcl/aqua/source/app/salsys \ - vcl/aqua/source/app/saltimer \ - vcl/aqua/source/dtrans/DataFlavorMapping \ - vcl/aqua/source/dtrans/DragActionConversion \ - vcl/aqua/source/dtrans/DragSource \ - vcl/aqua/source/dtrans/DragSourceContext \ - vcl/aqua/source/dtrans/DropTarget \ - vcl/aqua/source/dtrans/HtmlFmtFlt \ - vcl/aqua/source/dtrans/OSXTransferable \ - vcl/aqua/source/dtrans/PictToBmpFlt \ - vcl/aqua/source/dtrans/aqua_clipboard \ - vcl/aqua/source/dtrans/service_entry \ + vcl/osx/a11yfocuslistener \ + vcl/osx/a11yfocustracker \ + vcl/osx/a11ylistener \ + vcl/osx/documentfocuslistener \ + vcl/osx/saldata \ + vcl/osx/salinst \ + vcl/osx/salsys \ + vcl/osx/saltimer \ + vcl/osx/DataFlavorMapping \ + vcl/osx/DragActionConversion \ + vcl/osx/DragSource \ + vcl/osx/DragSourceContext \ + vcl/osx/DropTarget \ + vcl/osx/HtmlFmtFlt \ + vcl/osx/OSXTransferable \ + vcl/osx/PictToBmpFlt \ + vcl/osx/clipboard \ + vcl/osx/service_entry \ $(vcl_quartz_code) \ - vcl/aqua/source/gdi/salgdicommon \ - vcl/aqua/source/gdi/salgdiutils \ - vcl/aqua/source/gdi/salmathutils \ - vcl/aqua/source/gdi/salnativewidgets \ - vcl/aqua/source/gdi/salprn \ - vcl/aqua/source/gdi/salvd \ - vcl/aqua/source/window/salframe \ - vcl/aqua/source/window/salmenu \ - vcl/aqua/source/window/salobj \ + vcl/quartz/salgdicommon \ + vcl/quartz/salgdiutils \ + vcl/quartz/salmathutils \ + vcl/osx/salnativewidgets \ + vcl/osx/salprn \ + vcl/osx/salvd \ + vcl/osx/salframe \ + vcl/osx/salmenu \ + vcl/osx/salobj \ )) $(eval $(call gb_Library_use_system_darwin_frameworks,vcl,\ $(if $(filter X86_64,$(CPUNAME)),,QuickTime) \ diff --git a/vcl/Package_osxres.mk b/vcl/Package_osxres.mk index bc669eec5f50..224853f25993 100644 --- a/vcl/Package_osxres.mk +++ b/vcl/Package_osxres.mk @@ -7,7 +7,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # -$(eval $(call gb_Package_Package,vcl_osxres,$(SRCDIR)/vcl/aqua/source/res)) +$(eval $(call gb_Package_Package,vcl_osxres,$(SRCDIR)/vcl/osx/res)) $(eval $(call gb_Package_add_files_with_dir,vcl_osxres,Resources,\ MainMenu.nib/classes.nib \ diff --git a/vcl/README b/vcl/README index e386843b076b..5d3a7602e5fd 100644 --- a/vcl/README +++ b/vcl/README @@ -17,14 +17,16 @@ headless/ + a backend renderer that draws to bitmaps android/ - + Android backend (work in progress, does work to some extent) + + Android backend -aqua/ +osx/ + OS X backend ios/ - + iOS backend (work in progres, does not work, needs re-think - and re-write) + + iOS backend + +quartz/ + + code common to OS X and iOS win/ + Windows backend diff --git a/vcl/aqua/source/a11y/aqua11yactionwrapper.h b/vcl/aqua/source/a11y/aqua11yactionwrapper.h deleted file mode 100644 index c92473ccb080..000000000000 --- a/vcl/aqua/source/a11y/aqua11yactionwrapper.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YACTIONWRAPPER_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YACTIONWRAPPER_H - -#include "aqua/aquavcltypes.h" -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yActionWrapper : NSObject -{ -} -+(NSArray *)actionNamesForElement:(AquaA11yWrapper *)wrapper; -+(void)doAction:(NSString *)action ofElement:(AquaA11yWrapper *)wrapper; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YACTIONWRAPPER_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11yactionwrapper.mm b/vcl/aqua/source/a11y/aqua11yactionwrapper.mm deleted file mode 100644 index d9842a81e526..000000000000 --- a/vcl/aqua/source/a11y/aqua11yactionwrapper.mm +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" -#include "quartz/utils.h" - -#include "aqua11yactionwrapper.h" - -// Wrapper for XAccessibleAction - -@implementation AquaA11yActionWrapper : NSObject - -+(NSString *)nativeActionNameFor:(NSString *)actionName { - // TODO: Optimize ? - // Use NSAccessibilityActionDescription - if ( [ actionName isEqualToString: @"click" ] ) { - return NSAccessibilityPressAction; - } else if ( [ actionName isEqualToString: @"togglePopup" ] ) { - return NSAccessibilityShowMenuAction; - } else if ( [ actionName isEqualToString: @"select" ] ) { - return NSAccessibilityPickAction; - } else if ( [ actionName isEqualToString: @"incrementLine" ] ) { - return NSAccessibilityIncrementAction; - } else if ( [ actionName isEqualToString: @"decrementLine" ] ) { - return NSAccessibilityDecrementAction; - } else if ( [ actionName isEqualToString: @"incrementBlock" ] ) { - return NSAccessibilityIncrementAction; // TODO ? - } else if ( [ actionName isEqualToString: @"decrementBlock" ] ) { - return NSAccessibilityDecrementAction; // TODO ? - } else if ( [ actionName isEqualToString: @"Browse" ] ) { - return NSAccessibilityPressAction; // TODO ? - } else { - return [ NSString string ]; - } -} - -+(NSArray *)actionNamesForElement:(AquaA11yWrapper *)wrapper { - NSMutableArray * actionNames = [ [ NSMutableArray alloc ] init ]; - if ( [ wrapper accessibleAction ] != nil ) { - for ( int cnt = 0; cnt < [ wrapper accessibleAction ] -> getAccessibleActionCount(); cnt++ ) { - [ actionNames addObject: [ AquaA11yActionWrapper nativeActionNameFor: CreateNSString ( [ wrapper accessibleAction ] -> getAccessibleActionDescription ( cnt ) ) ] ]; - } - } - return actionNames; -} - -+(void)doAction:(NSString *)action ofElement:(AquaA11yWrapper *)wrapper { - if ( [ wrapper accessibleAction ] != nil ) { - for ( int cnt = 0; cnt < [ wrapper accessibleAction ] -> getAccessibleActionCount(); cnt++ ) { - if ( [ action isEqualToString: [ AquaA11yActionWrapper nativeActionNameFor: CreateNSString ( [ wrapper accessibleAction ] -> getAccessibleActionDescription ( cnt ) ) ] ] ) { - [ wrapper accessibleAction ] -> doAccessibleAction ( cnt ); - break; - } - } - } -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ycomponentwrapper.h b/vcl/aqua/source/a11y/aqua11ycomponentwrapper.h deleted file mode 100644 index 74d804e74d91..000000000000 --- a/vcl/aqua/source/a11y/aqua11ycomponentwrapper.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YCOMPONENTWRAPPER_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YCOMPONENTWRAPPER_H - -#include "aqua/aquavcltypes.h" -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yComponentWrapper : NSObject -{ -} -+(id)sizeAttributeForElement:(AquaA11yWrapper *)wrapper; -+(id)positionAttributeForElement:(AquaA11yWrapper *)wrapper; -+(id)descriptionAttributeForElement:(AquaA11yWrapper *)wrapper; -+(void)addAttributeNamesTo:(NSMutableArray *)attributeNames; -+(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper; -+(void)setFocusedAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YCOMPONENTWRAPPER_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ycomponentwrapper.mm b/vcl/aqua/source/a11y/aqua11ycomponentwrapper.mm deleted file mode 100644 index 41df52bf10e0..000000000000 --- a/vcl/aqua/source/a11y/aqua11ycomponentwrapper.mm +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include "quartz/utils.h" -#include "aqua11ycomponentwrapper.h" -#include "aqua11yrolehelper.h" -#include - -using namespace ::com::sun::star::accessibility; -using namespace ::com::sun::star::awt; -using namespace ::com::sun::star::uno; - -// Wrapper for XAccessibleComponent and XAccessibleExtendedComponent - -@implementation AquaA11yComponentWrapper : NSObject - -+(id)sizeAttributeForElement:(AquaA11yWrapper *)wrapper { - Size size = [ wrapper accessibleComponent ] -> getSize(); - NSSize nsSize = NSMakeSize ( (float) size.Width, (float) size.Height ); - return [ NSValue valueWithSize: nsSize ]; -} - -// TODO: should be merged with AquaSalFrame::VCLToCocoa... to a general helper method -+(id)positionAttributeForElement:(AquaA11yWrapper *)wrapper { - // VCL coordinates are in upper-left-notation, Cocoa likes it the Cartesian way (lower-left) - NSRect screenRect = [ [ NSScreen mainScreen ] frame ]; - Size size = [ wrapper accessibleComponent ] -> getSize(); - Point location = [ wrapper accessibleComponent ] -> getLocationOnScreen(); - NSPoint nsPoint = NSMakePoint ( (float) location.X, (float) ( screenRect.size.height - size.Height - location.Y ) ); - return [ NSValue valueWithPoint: nsPoint ]; -} - -+(id)descriptionAttributeForElement:(AquaA11yWrapper *)wrapper { - if ( [ wrapper accessibleExtendedComponent ] != nil ) { - return CreateNSString ( [ wrapper accessibleExtendedComponent ] -> getToolTipText() ); - } else { - return nil; - } -} - -+(void)addAttributeNamesTo:(NSMutableArray *)attributeNames { - NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; - [ attributeNames addObjectsFromArray: [ NSArray arrayWithObjects: - NSAccessibilitySizeAttribute, - NSAccessibilityPositionAttribute, - NSAccessibilityFocusedAttribute, - NSAccessibilityEnabledAttribute, - nil ] ]; - [ pool release ]; -} - -+(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper { - BOOL isSettable = NO; - NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; - if ( [ attribute isEqualToString: NSAccessibilityFocusedAttribute ] - && ! [ [ AquaA11yRoleHelper getNativeRoleFrom: [ wrapper accessibleContext ] ] isEqualToString: NSAccessibilityScrollBarRole ] - && ! [ [ AquaA11yRoleHelper getNativeRoleFrom: [ wrapper accessibleContext ] ] isEqualToString: NSAccessibilityStaticTextRole ] ) { - isSettable = YES; - } - [ pool release ]; - return isSettable; -} - -+(void)setFocusedAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value { - if ( [ value boolValue ] == YES ) { - if ( [ wrapper accessibleContext ] -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) { - // special treatment for comboboxes: find the corresponding PANEL and set focus to it - Reference < XAccessible > rxParent = [ wrapper accessibleContext ] -> getAccessibleParent(); - if ( rxParent.is() ) { - Reference < XAccessibleContext > rxContext = rxParent->getAccessibleContext(); - if ( rxContext.is() && rxContext -> getAccessibleRole() == AccessibleRole::PANEL ) { - Reference < XAccessibleComponent > rxComponent = Reference < XAccessibleComponent > ( rxParent -> getAccessibleContext(), UNO_QUERY ); - if ( rxComponent.is() ) { - rxComponent -> grabFocus(); - } - } - } - } else { - [ wrapper accessibleComponent ] -> grabFocus(); - } - } -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11yfactory.mm b/vcl/aqua/source/a11y/aqua11yfactory.mm deleted file mode 100644 index 64f178314a38..000000000000 --- a/vcl/aqua/source/a11y/aqua11yfactory.mm +++ /dev/null @@ -1,219 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" -#include "aqua/aqua11yfactory.h" -#include "aqua/aqua11yfocustracker.hxx" - -#include "aqua11yfocuslistener.hxx" -#include "aqua11yrolehelper.h" -#include "aqua11ywrapperbutton.h" -#include "aqua11ywrapperstatictext.h" -#include "aqua11ywrappertextarea.h" -#include "aqua11ywrappercheckbox.h" -#include "aqua11ywrappercombobox.h" -#include "aqua11ywrappergroup.h" -#include "aqua11ywrapperlist.h" -#include "aqua11ywrapperradiobutton.h" -#include "aqua11ywrapperradiogroup.h" -#include "aqua11ywrapperrow.h" -#include "aqua11ywrapperscrollarea.h" -#include "aqua11ywrapperscrollbar.h" -#include "aqua11ywrappersplitter.h" -#include "aqua11ywrappertabgroup.h" -#include "aqua11ywrappertoolbar.h" -#include "aqua11ytablewrapper.h" - -#include - -using namespace ::com::sun::star::accessibility; -using namespace ::com::sun::star::uno; - -static bool enabled = false; - -@implementation AquaA11yFactory : NSObject - -#pragma mark - -#pragma mark Wrapper Repository - -+(NSMutableDictionary *)allWrapper { - static NSMutableDictionary * mdAllWrapper = nil; - if ( mdAllWrapper == nil ) { - mdAllWrapper = [ [ [ NSMutableDictionary alloc ] init ] retain ]; - // initialize keyboard focus tracker - rtl::Reference< AquaA11yFocusListener > listener( AquaA11yFocusListener::get() ); - AquaA11yFocusTracker::get().setFocusListener(listener.get()); - enabled = true; - } - return mdAllWrapper; -} - -+(NSValue *)keyForAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext { - return [ NSValue valueWithPointer: rxAccessibleContext.get() ]; -} - -+(NSValue *)keyForAccessibleContextAsRadioGroup: (Reference < XAccessibleContext >) rxAccessibleContext { - return [ NSValue valueWithPointer: ( rxAccessibleContext.get() + 2 ) ]; -} - -+(AquaA11yWrapper *)wrapperForAccessible: (Reference < XAccessible >) rxAccessible { - if ( rxAccessible.is() ) { - Reference< XAccessibleContext > xAccessibleContext = rxAccessible->getAccessibleContext(); - if( xAccessibleContext.is() ) { - return [ AquaA11yFactory wrapperForAccessibleContext: xAccessibleContext ]; - } - } - return nil; -} - -+(AquaA11yWrapper *)wrapperForAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext { - return [ AquaA11yFactory wrapperForAccessibleContext: rxAccessibleContext createIfNotExists: YES asRadioGroup: NO ]; -} - -+(AquaA11yWrapper *)wrapperForAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext createIfNotExists:(BOOL) bCreate { - return [ AquaA11yFactory wrapperForAccessibleContext: rxAccessibleContext createIfNotExists: bCreate asRadioGroup: NO ]; -} - -+(AquaA11yWrapper *)wrapperForAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext createIfNotExists:(BOOL) bCreate asRadioGroup:(BOOL) asRadioGroup{ - NSMutableDictionary * dAllWrapper = [ AquaA11yFactory allWrapper ]; - NSValue * nKey = nil; - if ( asRadioGroup ) { - nKey = [ AquaA11yFactory keyForAccessibleContextAsRadioGroup: rxAccessibleContext ]; - } else { - nKey = [ AquaA11yFactory keyForAccessibleContext: rxAccessibleContext ]; - } - AquaA11yWrapper * aWrapper = (AquaA11yWrapper *) [ dAllWrapper objectForKey: nKey ]; - if ( aWrapper != nil ) { - [ aWrapper retain ]; - } else if ( bCreate ) { - NSString * nativeRole = [ AquaA11yRoleHelper getNativeRoleFrom: rxAccessibleContext.get() ]; - // TODO: reflection - if ( [ nativeRole isEqualToString: NSAccessibilityButtonRole ] ) { - aWrapper = [ [ AquaA11yWrapperButton alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } else if ( [ nativeRole isEqualToString: NSAccessibilityTextAreaRole ] ) { - aWrapper = [ [ AquaA11yWrapperTextArea alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } else if ( [ nativeRole isEqualToString: NSAccessibilityStaticTextRole ] ) { - aWrapper = [ [ AquaA11yWrapperStaticText alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } else if ( [ nativeRole isEqualToString: NSAccessibilityComboBoxRole ] ) { - aWrapper = [ [ AquaA11yWrapperComboBox alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } else if ( [ nativeRole isEqualToString: NSAccessibilityGroupRole ] ) { - aWrapper = [ [ AquaA11yWrapperGroup alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } else if ( [ nativeRole isEqualToString: NSAccessibilityToolbarRole ] ) { - aWrapper = [ [ AquaA11yWrapperToolbar alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } else if ( [ nativeRole isEqualToString: NSAccessibilityScrollAreaRole ] ) { - aWrapper = [ [ AquaA11yWrapperScrollArea alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } else if ( [ nativeRole isEqualToString: NSAccessibilityTabGroupRole ] ) { - aWrapper = [ [ AquaA11yWrapperTabGroup alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } else if ( [ nativeRole isEqualToString: NSAccessibilityScrollBarRole ] ) { - aWrapper = [ [ AquaA11yWrapperScrollBar alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } else if ( [ nativeRole isEqualToString: NSAccessibilityCheckBoxRole ] ) { - aWrapper = [ [ AquaA11yWrapperCheckBox alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } else if ( [ nativeRole isEqualToString: NSAccessibilityRadioGroupRole ] ) { - aWrapper = [ [ AquaA11yWrapperRadioGroup alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } else if ( [ nativeRole isEqualToString: NSAccessibilityRadioButtonRole ] ) { - aWrapper = [ [ AquaA11yWrapperRadioButton alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } else if ( [ nativeRole isEqualToString: NSAccessibilityRowRole ] ) { - aWrapper = [ [ AquaA11yWrapperRow alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } else if ( [ nativeRole isEqualToString: NSAccessibilityListRole ] ) { - aWrapper = [ [ AquaA11yWrapperList alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } else if ( [ nativeRole isEqualToString: NSAccessibilitySplitterRole ] ) { - aWrapper = [ [ AquaA11yWrapperSplitter alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } else if ( [ nativeRole isEqualToString: NSAccessibilityTableRole ] ) { - aWrapper = [ [ AquaA11yTableWrapper alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } else { - aWrapper = [ [ AquaA11yWrapper alloc ] initWithAccessibleContext: rxAccessibleContext ]; - } - [ nativeRole release ]; - [ aWrapper setActsAsRadioGroup: asRadioGroup ]; - #if 0 - /* #i102033# NSAccessibility does not seemt to know an equivalent for transient children. - That means we need to cache this, else e.g. tree list boxes are not accessible (moreover - it crashes by notifying dead objects - which would seemt o be another bug) - - FIXME: - Unfortunately this can increase memory consumption drastically until the non transient parent - is destroyed an finally all the transients are released. - */ - if ( ! rxAccessibleContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::TRANSIENT ) ) - #endif - { - [ dAllWrapper setObject: aWrapper forKey: nKey ]; - /* fdo#67410: Accessibility notifications are not delivered on NSView subclasses that do not - "reasonably" participate in NSView hierarchy (perhaps the only important point is - that the view is a transitive subview of the NSWindow's content view, but I - did not try to verify that). - - So let the superview-subviews relationship mirror the AXParent-AXChildren relationship. - */ - id parent = [aWrapper accessibilityAttributeValue:NSAccessibilityParentAttribute]; - if (parent) { - if ([parent isKindOfClass:[NSView class]]) { - // SAL_DEBUG("Wrapper INIT: " << [[aWrapper description] UTF8String] << " ==> " << [[parent description] UTF8String]); - NSView *parentView = (NSView *)parent; - [parentView addSubview:aWrapper positioned:NSWindowBelow relativeTo:nil]; - } else if ([parent isKindOfClass:NSClassFromString(@"SalFrameWindow")]) { - NSWindow *window = (NSWindow *)parent; - NSView *salView = [window contentView]; - // SAL_DEBUG("Wrapper INIT SAL: " << [[aWrapper description] UTF8String] << " ==> " << [[salView description] UTF8String]); - [salView addSubview:aWrapper positioned:NSWindowBelow relativeTo:nil]; - } else { - // SAL_DEBUG("Wrapper INIT: !! " << [[aWrapper description] UTF8String] << " !==>! " << [[parent description] UTF8String] << "!!"); - } - } else { - // SAL_DEBUG("Wrapper INIT: " << [[aWrapper description] UTF8String] << " ==> NO PARENT"); - } - } - } - return aWrapper; -} - -+(void)insertIntoWrapperRepository: (NSView *) viewElement forAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext { - NSMutableDictionary * dAllWrapper = [ AquaA11yFactory allWrapper ]; - [ dAllWrapper setObject: viewElement forKey: [ AquaA11yFactory keyForAccessibleContext: rxAccessibleContext ] ]; -} - -+(void)removeFromWrapperRepositoryFor: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) rxAccessibleContext { - // TODO: when RADIO_BUTTON search for associated RadioGroup-wrapper and delete that as well - AquaA11yWrapper * theWrapper = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessibleContext createIfNotExists: NO ]; - if ( theWrapper != nil ) { - if (![theWrapper isKindOfClass:NSClassFromString(@"SalFrameView")]) { - [theWrapper removeFromSuperview]; - } - [ [ AquaA11yFactory allWrapper ] removeObjectForKey: [ AquaA11yFactory keyForAccessibleContext: rxAccessibleContext ] ]; - [ theWrapper release ]; - } -} - -+(void)registerView: (NSView *) theView { - if ( enabled && [ theView isKindOfClass: [ AquaA11yWrapper class ] ] ) { - // insertIntoWrapperRepository gets called from SalFrameView itself to bootstrap the bridge initially - [ (AquaA11yWrapper *) theView accessibleContext ]; - } -} - -+(void)revokeView: (NSView *) theView { - if ( enabled && [ theView isKindOfClass: [ AquaA11yWrapper class ] ] ) { - [ AquaA11yFactory removeFromWrapperRepositoryFor: [ (AquaA11yWrapper *) theView accessibleContext ] ]; - } -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11yfocuslistener.cxx b/vcl/aqua/source/a11y/aqua11yfocuslistener.cxx deleted file mode 100644 index 5a0c339af27b..000000000000 --- a/vcl/aqua/source/a11y/aqua11yfocuslistener.cxx +++ /dev/null @@ -1,110 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include - -#include "aqua/aqua11yfocustracker.hxx" -#include "aqua/aqua11yfactory.h" - -#include "aqua11yfocuslistener.hxx" - -using namespace ::com::sun::star::accessibility; -using namespace ::com::sun::star::uno; - - -rtl::Reference< AquaA11yFocusListener > AquaA11yFocusListener::theListener; - -//------------------------------------------------------------------------------ - -rtl::Reference< AquaA11yFocusListener > AquaA11yFocusListener::get() -{ - if ( ! theListener.is() ) - theListener = new AquaA11yFocusListener(); - - return theListener; -} - -//------------------------------------------------------------------------------ - -AquaA11yFocusListener::AquaA11yFocusListener() : m_focusedObject(nil) -{ -} - -//------------------------------------------------------------------------------ - -id AquaA11yFocusListener::getFocusedUIElement() -{ - if ( nil == m_focusedObject ) { - Reference< XAccessible > xAccessible( AquaA11yFocusTracker::get().getFocusedObject() ); - try { - if( xAccessible.is() ) { - Reference< XAccessibleContext > xContext(xAccessible->getAccessibleContext()); - if( xContext.is() ) - m_focusedObject = [ AquaA11yFactory wrapperForAccessibleContext: xContext ]; - } - } catch(const RuntimeException &) { - // intentionally do nothing .. - } - } - - return m_focusedObject; -} - -//------------------------------------------------------------------------------ - -void SAL_CALL -AquaA11yFocusListener::focusedObjectChanged(const Reference< XAccessible >& xAccessible) -{ - if ( nil != m_focusedObject ) { - [ m_focusedObject release ]; - m_focusedObject = nil; - } - - try { - if( xAccessible.is() ) { - Reference< XAccessibleContext > xContext(xAccessible->getAccessibleContext()); - if( xContext.is() ) - { - m_focusedObject = [ AquaA11yFactory wrapperForAccessibleContext: xContext ]; - NSAccessibilityPostNotification(m_focusedObject, NSAccessibilityFocusedUIElementChangedNotification); - } - } - } catch(const RuntimeException &) { - // intentionally do nothing .. - } -} - -//------------------------------------------------------------------------------ - -oslInterlockedCount SAL_CALL -AquaA11yFocusListener::acquire() SAL_THROW(()) -{ - return ReferenceObject::acquire(); -} - -//------------------------------------------------------------------------------ - -oslInterlockedCount SAL_CALL -AquaA11yFocusListener::release() SAL_THROW(()) -{ - return ReferenceObject::release(); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11yfocuslistener.hxx b/vcl/aqua/source/a11y/aqua11yfocuslistener.hxx deleted file mode 100644 index a889683a4304..000000000000 --- a/vcl/aqua/source/a11y/aqua11yfocuslistener.hxx +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YFOCUSLISTENER_HXX -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YFOCUSLISTENER_HXX - -#include - -#include "aqua/keyboardfocuslistener.hxx" -#include "aqua/aquavcltypes.h" - -class AquaA11yFocusListener : - public KeyboardFocusListener, - public salhelper::ReferenceObject -{ - id m_focusedObject; - - static rtl::Reference< AquaA11yFocusListener > theListener; - - AquaA11yFocusListener(); - virtual ~AquaA11yFocusListener() {}; -public: - - static rtl::Reference< AquaA11yFocusListener > get(); - - id getFocusedUIElement(); - - // KeyboardFocusListener - virtual void SAL_CALL focusedObjectChanged(const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible); - - // rtl::IReference - virtual oslInterlockedCount SAL_CALL acquire() SAL_THROW(()); - virtual oslInterlockedCount SAL_CALL release() SAL_THROW(()); -}; - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YFOCUSLISTENER_HXX - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11yfocustracker.cxx b/vcl/aqua/source/a11y/aqua11yfocustracker.cxx deleted file mode 100644 index b38af805630c..000000000000 --- a/vcl/aqua/source/a11y/aqua11yfocustracker.cxx +++ /dev/null @@ -1,284 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "vcl/svapp.hxx" -#include "vcl/window.hxx" -#include "vcl/toolbox.hxx" -#include "vcl/menu.hxx" - -#include "aqua/aqua11yfocustracker.hxx" - -#include "documentfocuslistener.hxx" - -#include -#include -#include -#include -#include - -using namespace ::com::sun::star::accessibility; -using namespace ::com::sun::star::uno; - -//------------------------------------------------------------------------------ - -static inline Window * -getWindow(const ::VclSimpleEvent *pEvent) -{ - return static_cast< const ::VclWindowEvent *> (pEvent)->GetWindow(); -} - - -//------------------------------------------------------------------------------ - -// callback function for Application::addEventListener - -long AquaA11yFocusTracker::WindowEventHandler(AquaA11yFocusTracker *pFocusTracker, ::VclSimpleEvent const *pEvent) -{ - switch (pEvent->GetId()) - { - case VCLEVENT_WINDOW_PAINT: - pFocusTracker-> toolbox_open_floater( getWindow(pEvent) ); - break; - case VCLEVENT_WINDOW_GETFOCUS: - pFocusTracker->window_got_focus( getWindow(pEvent) ); - break; - case VCLEVENT_OBJECT_DYING: - pFocusTracker->m_aDocumentWindowList.erase( getWindow(pEvent) ); - // intentional pass through .. - case VCLEVENT_TOOLBOX_HIGHLIGHTOFF: - pFocusTracker->toolbox_highlight_off( getWindow(pEvent) ); - break; - case VCLEVENT_TOOLBOX_HIGHLIGHT: - pFocusTracker->toolbox_highlight_on( getWindow(pEvent) ); - break; - case VCLEVENT_TABPAGE_ACTIVATE: - pFocusTracker->tabpage_activated( getWindow(pEvent) ); - break; - case VCLEVENT_MENU_HIGHLIGHT: - // Inspired by code in WindowEventHandler in - // vcl/unx/gtk/a11y/atkutil.cxx, find out what kind of event - // it is to avoid blindly using a static_cast and crash, - // fdo#47275. - if( const VclMenuEvent* pMenuEvent = dynamic_cast < const VclMenuEvent* > (pEvent) ) - { - pFocusTracker->menu_highlighted( pMenuEvent ); - } - else if( const VclAccessibleEvent* pAccEvent = dynamic_cast < const VclAccessibleEvent* > (pEvent) ) - { - Reference< XAccessible > xAccessible = pAccEvent->GetAccessible(); - if( xAccessible.is() ) - pFocusTracker->setFocusedObject( xAccessible ); - } - break; - default: - break; - }; - - return 0; -} - -//------------------------------------------------------------------------------ - -AquaA11yFocusTracker::AquaA11yFocusTracker() : - m_aWindowEventLink(this, (PSTUB) WindowEventHandler), - m_xDocumentFocusListener(new DocumentFocusListener(*this)) -{ - Application::AddEventListener(m_aWindowEventLink); - window_got_focus(Application::GetFocusWindow()); -} - -//------------------------------------------------------------------------------ - -void AquaA11yFocusTracker::setFocusedObject(const Reference< XAccessible >& xAccessible) -{ - if( xAccessible != m_xFocusedObject ) - { - m_xFocusedObject = xAccessible; - - if( m_aFocusListener.is() ) - m_aFocusListener->focusedObjectChanged(xAccessible); - } -} - -//------------------------------------------------------------------------------ - -void AquaA11yFocusTracker::notify_toolbox_item_focus(ToolBox *pToolBox) -{ - Reference< XAccessible > xAccessible( pToolBox->GetAccessible() ); - - if( xAccessible.is() ) - { - Reference< XAccessibleContext > xContext(xAccessible->getAccessibleContext()); - - if( xContext.is() ) - { - sal_Int32 nPos = pToolBox->GetItemPos( pToolBox->GetHighlightItemId() ); - if( nPos != TOOLBOX_ITEM_NOTFOUND ) - setFocusedObject( xContext->getAccessibleChild( nPos ) ); - } - } -} - -//------------------------------------------------------------------------------ - -void AquaA11yFocusTracker::toolbox_open_floater(Window *pWindow) -{ - bool bToolboxFound = false; - bool bFloatingWindowFound = false; - Window * pFloatingWindow = NULL; - while ( pWindow != NULL ) { - if ( pWindow->GetType() == WINDOW_TOOLBOX ) { - bToolboxFound = true; - } else if ( pWindow->GetType() == WINDOW_FLOATINGWINDOW ) { - bFloatingWindowFound = true; - pFloatingWindow = pWindow; - } - pWindow = pWindow->GetParent(); - } - if ( bToolboxFound && bFloatingWindowFound ) { - Reference < XAccessible > rxAccessible = pFloatingWindow -> GetAccessible(); - if ( ! rxAccessible.is() ) { - return; - } - Reference < XAccessibleContext > rxContext = rxAccessible -> getAccessibleContext(); - if ( ! rxContext.is() ) { - return; - } - if ( rxContext -> getAccessibleChildCount() > 0 ) { - Reference < XAccessible > rxAccessibleChild = rxContext -> getAccessibleChild( 0 ); - if ( ! rxAccessibleChild.is() ) { - return; - } - setFocusedObject ( rxAccessibleChild ); - } - } -} - -//------------------------------------------------------------------------------ - -void AquaA11yFocusTracker::toolbox_highlight_on(Window *pWindow) -{ - // Make sure either the toolbox or its parent toolbox has the focus - if ( ! pWindow->HasFocus() ) - { - ToolBox* pToolBoxParent = dynamic_cast< ToolBox * >( pWindow->GetParent() ); - if ( ! pToolBoxParent || ! pToolBoxParent->HasFocus() ) - return; - } - - notify_toolbox_item_focus(static_cast (pWindow)); -} - -//------------------------------------------------------------------------------ - -void AquaA11yFocusTracker::toolbox_highlight_off(Window *pWindow) -{ - ToolBox* pToolBoxParent = dynamic_cast< ToolBox * >( pWindow->GetParent() ); - - // Notify when leaving sub toolboxes - if( pToolBoxParent && pToolBoxParent->HasFocus() ) - notify_toolbox_item_focus( pToolBoxParent ); -} - -//------------------------------------------------------------------------------ - -void AquaA11yFocusTracker::tabpage_activated(Window *pWindow) -{ - Reference< XAccessible > xAccessible( pWindow->GetAccessible() ); - - if( xAccessible.is() ) - { - Reference< XAccessibleSelection > xSelection(xAccessible->getAccessibleContext(), UNO_QUERY); - - if( xSelection.is() ) - setFocusedObject( xSelection->getSelectedAccessibleChild(0) ); - } -} - -//------------------------------------------------------------------------------ - -void AquaA11yFocusTracker::menu_highlighted(const VclMenuEvent *pEvent) -{ - Menu * pMenu = pEvent->GetMenu(); - - if( pMenu ) - { - Reference< XAccessible > xAccessible( pMenu->GetAccessible() ); - - if( xAccessible.is() ) - setFocusedObject( xAccessible ); - } -} - -//------------------------------------------------------------------------------ - -void AquaA11yFocusTracker::window_got_focus(Window *pWindow) -{ - // The menu bar is handled through VCLEVENT_MENU_HIGHLIGHTED - if( ! pWindow || !pWindow->IsReallyVisible() || pWindow->GetType() == WINDOW_MENUBARWINDOW ) - return; - - // ToolBoxes are handled through VCLEVENT_TOOLBOX_HIGHLIGHT - if( pWindow->GetType() == WINDOW_TOOLBOX ) - return; - - if( pWindow->GetType() == WINDOW_TABCONTROL ) - { - tabpage_activated( pWindow ); - return; - } - - Reference< XAccessible > xAccessible(pWindow->GetAccessible()); - - if( ! xAccessible.is() ) - return; - - Reference< XAccessibleContext > xContext = xAccessible->getAccessibleContext(); - - if( ! xContext.is() ) - return; - - Reference< XAccessibleStateSet > xStateSet = xContext->getAccessibleStateSet(); - - if( ! xStateSet.is() ) - return; - -/* the UNO ToolBox wrapper does not (yet?) support XAccessibleSelection, so we - * need to add listeners to the children instead of re-using the tabpage stuff - */ - if( xStateSet->contains(AccessibleStateType::FOCUSED) && (pWindow->GetType() != WINDOW_TREELISTBOX) ) - { - setFocusedObject( xAccessible ); - } - else - { - if( m_aDocumentWindowList.find(pWindow) == m_aDocumentWindowList.end() ) - { - m_aDocumentWindowList.insert(pWindow); - m_xDocumentFocusListener->attachRecursive(xAccessible, xContext, xStateSet); - } -#ifdef ENABLE_TRACING - else - fprintf(stderr, "Window %p already in the list\n", pWindow ); -#endif - } -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ylistener.cxx b/vcl/aqua/source/a11y/aqua11ylistener.cxx deleted file mode 100644 index 46babf97f357..000000000000 --- a/vcl/aqua/source/a11y/aqua11ylistener.cxx +++ /dev/null @@ -1,153 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include "aqua/salinst.h" -#include "aqua/aqua11ylistener.hxx" -#include "aqua/aqua11yfactory.h" -#include "aqua/aqua11yfocustracker.hxx" -#include "aqua/aqua11ywrapper.h" - -#include "aqua11ytextwrapper.h" - -#include -#include -#include -#include - -using namespace ::com::sun::star::accessibility; -using namespace ::com::sun::star::awt; -using namespace ::com::sun::star::lang; -using namespace ::com::sun::star::uno; - -NSString * getTableNotification( const AccessibleEventObject& aEvent ) -{ - AccessibleTableModelChange aChange; - NSString * notification = nil; - - if( (aEvent.NewValue >>= aChange) && - ( AccessibleTableModelChangeType::INSERT == aChange.Type || AccessibleTableModelChangeType::DELETE == aChange.Type ) && - aChange.FirstRow != aChange.LastRow ) - { - notification = NSAccessibilityRowCountChangedNotification; - } - - return notification; -} - -//------------------------------------------------------------------------------ - -AquaA11yEventListener::AquaA11yEventListener(id wrapperObject, sal_Int16 role) : m_wrapperObject(wrapperObject), m_role(role) -{ - [ m_wrapperObject retain ]; -} - -//------------------------------------------------------------------------------ - -AquaA11yEventListener::~AquaA11yEventListener() -{ - [ m_wrapperObject release ]; -} - -//------------------------------------------------------------------------------ - -void SAL_CALL -AquaA11yEventListener::disposing( const EventObject& ) throw( RuntimeException ) -{ - [ AquaA11yFactory removeFromWrapperRepositoryFor: [ (AquaA11yWrapper *) m_wrapperObject accessibleContext ] ]; -} - -//------------------------------------------------------------------------------ - -void SAL_CALL -AquaA11yEventListener::notifyEvent( const AccessibleEventObject& aEvent ) throw( RuntimeException ) -{ - NSString * notification = nil; - id element = m_wrapperObject; - Rectangle bounds; - - // TODO: NSAccessibilityValueChanged, NSAccessibilitySelectedRowsChangedNotification - switch( aEvent.EventId ) - { - case AccessibleEventId::ACTIVE_DESCENDANT_CHANGED: - if( m_role != AccessibleRole::LIST ) { - Reference< XAccessible > xAccessible; - if( aEvent.NewValue >>= xAccessible ) - AquaA11yFocusTracker::get().setFocusedObject( xAccessible ); - } - break; - - case AccessibleEventId::NAME_CHANGED: - notification = NSAccessibilityTitleChangedNotification; - break; - - case AccessibleEventId::CHILD: - // only needed for tooltips (says Apple) - if ( m_role == AccessibleRole::TOOL_TIP ) { - if(aEvent.NewValue.hasValue()) { - notification = NSAccessibilityCreatedNotification; - } else if(aEvent.OldValue.hasValue()) { - notification = NSAccessibilityUIElementDestroyedNotification; - } - } - break; - - case AccessibleEventId::INVALIDATE_ALL_CHILDREN: - // TODO: depricate or remember all children - break; - - case AccessibleEventId::BOUNDRECT_CHANGED: - bounds = [ element accessibleComponent ] -> getBounds(); - if ( m_oldBounds.X != 0 && ( bounds.X != m_oldBounds.X || bounds.Y != m_oldBounds.Y ) ) { - NSAccessibilityPostNotification(element, NSAccessibilityMovedNotification); // post directly since both cases can happen simultaneously - } - if ( m_oldBounds.X != 0 && ( bounds.Width != m_oldBounds.Width || bounds.Height != m_oldBounds.Height ) ) { - NSAccessibilityPostNotification(element, NSAccessibilityResizedNotification); // post directly since both cases can happen simultaneously - } - m_oldBounds = bounds; - break; - - case AccessibleEventId::SELECTION_CHANGED: - notification = NSAccessibilitySelectedChildrenChangedNotification; - break; - - case AccessibleEventId::TEXT_SELECTION_CHANGED: - notification = NSAccessibilitySelectedTextChangedNotification; - break; - - case AccessibleEventId::TABLE_MODEL_CHANGED: - notification = getTableNotification(aEvent); - break; - - case AccessibleEventId::CARET_CHANGED: - notification = NSAccessibilitySelectedTextChangedNotification; - break; - - case AccessibleEventId::TEXT_CHANGED: - notification = NSAccessibilityValueChangedNotification; - break; - - default: - break; - } - - if( nil != notification ) - NSAccessibilityPostNotification(element, notification); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11yrolehelper.h b/vcl/aqua/source/a11y/aqua11yrolehelper.h deleted file mode 100644 index a45cde447ff6..000000000000 --- a/vcl/aqua/source/a11y/aqua11yrolehelper.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YROLEHELPER_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YROLEHELPER_H - -#include "aqua/salinst.h" -#include - -@interface AquaA11yRoleHelper : NSObject -{ -} -+(id)getNativeRoleFrom: (::com::sun::star::accessibility::XAccessibleContext *) accessibleContext; -+(id)getNativeSubroleFrom: (sal_Int16) nRole; -+(id)getRoleDescriptionFrom: (NSString *) role with: (NSString *) subRole; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YROLEHELPER_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11yrolehelper.mm b/vcl/aqua/source/a11y/aqua11yrolehelper.mm deleted file mode 100644 index 0d55279823ac..000000000000 --- a/vcl/aqua/source/a11y/aqua11yrolehelper.mm +++ /dev/null @@ -1,270 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/aqua11yfactory.h" - -#include "aqua11yrolehelper.h" - -#include -#include - -using namespace ::com::sun::star::accessibility; -using namespace ::com::sun::star::uno; - -@implementation AquaA11yRoleHelper - -+(id)simpleMapNativeRoleFrom: (XAccessibleContext *) accessibleContext { - id nativeRole = nil; - - if (accessibleContext == NULL) - return nativeRole; - - switch( accessibleContext -> getAccessibleRole() ) { -#define MAP(a,b) \ - case a: nativeRole = b; break - - MAP( AccessibleRole::UNKNOWN, NSAccessibilityUnknownRole ); - MAP( AccessibleRole::ALERT, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::COLUMN_HEADER, NSAccessibilityColumnRole ); - MAP( AccessibleRole::CANVAS, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::CHECK_BOX, NSAccessibilityCheckBoxRole ); - MAP( AccessibleRole::CHECK_MENU_ITEM, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::COLOR_CHOOSER, NSAccessibilityColorWellRole ); // FIXME - MAP( AccessibleRole::COMBO_BOX, NSAccessibilityComboBoxRole ); - MAP( AccessibleRole::DATE_EDITOR, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::DESKTOP_ICON, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::DESKTOP_PANE, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::DIRECTORY_PANE, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::DIALOG, NSAccessibilityGroupRole ); - MAP( AccessibleRole::DOCUMENT, NSAccessibilityGroupRole ); - MAP( AccessibleRole::EMBEDDED_OBJECT, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::END_NOTE, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::FILE_CHOOSER, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::FILLER, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::FONT_CHOOSER, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::FOOTER, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::FOOTNOTE, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::FRAME, NSAccessibilityWindowRole ); - MAP( AccessibleRole::GLASS_PANE, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::GRAPHIC, NSAccessibilityImageRole ); - MAP( AccessibleRole::GROUP_BOX, NSAccessibilityGroupRole ); - MAP( AccessibleRole::HEADER, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::HEADING, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::HYPER_LINK, NSAccessibilityLinkRole ); - MAP( AccessibleRole::ICON, NSAccessibilityImageRole ); - MAP( AccessibleRole::INTERNAL_FRAME, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::LABEL, NSAccessibilityStaticTextRole ); - MAP( AccessibleRole::LAYERED_PANE, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::LIST, NSAccessibilityMenuRole ); - MAP( AccessibleRole::LIST_ITEM, NSAccessibilityMenuItemRole ); - MAP( AccessibleRole::MENU, NSAccessibilityMenuRole ); - MAP( AccessibleRole::MENU_BAR, NSAccessibilityMenuBarRole ); - MAP( AccessibleRole::MENU_ITEM, NSAccessibilityMenuItemRole ); - MAP( AccessibleRole::OPTION_PANE, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::PAGE_TAB, NSAccessibilityButtonRole ); - MAP( AccessibleRole::PAGE_TAB_LIST, NSAccessibilityTabGroupRole ); - MAP( AccessibleRole::PANEL, NSAccessibilityGroupRole ); - MAP( AccessibleRole::PARAGRAPH, NSAccessibilityTextAreaRole ); - MAP( AccessibleRole::PASSWORD_TEXT, NSAccessibilityTextFieldRole ); - MAP( AccessibleRole::POPUP_MENU, NSAccessibilityMenuRole ); - MAP( AccessibleRole::PUSH_BUTTON, NSAccessibilityButtonRole ); - MAP( AccessibleRole::PROGRESS_BAR, NSAccessibilityProgressIndicatorRole ); - MAP( AccessibleRole::RADIO_BUTTON, NSAccessibilityRadioButtonRole ); - MAP( AccessibleRole::RADIO_MENU_ITEM, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::ROW_HEADER, NSAccessibilityRowRole ); - MAP( AccessibleRole::ROOT_PANE, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::SCROLL_BAR, NSAccessibilityScrollBarRole ); - MAP( AccessibleRole::SCROLL_PANE, NSAccessibilityScrollAreaRole ); - MAP( AccessibleRole::SHAPE, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::SEPARATOR, NSAccessibilitySplitterRole ); // FIXME - MAP( AccessibleRole::SLIDER, NSAccessibilitySliderRole ); - MAP( AccessibleRole::SPIN_BOX, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::SPLIT_PANE, NSAccessibilitySplitterRole ); - MAP( AccessibleRole::STATUS_BAR, NSAccessibilityGroupRole ); // FIXME - MAP( AccessibleRole::TABLE, NSAccessibilityTableRole ); - MAP( AccessibleRole::TABLE_CELL, NSAccessibilityTextFieldRole ); - MAP( AccessibleRole::TEXT, NSAccessibilityTextAreaRole ); - MAP( AccessibleRole::TEXT_FRAME, NSAccessibilityGroupRole ); - MAP( AccessibleRole::TOGGLE_BUTTON, NSAccessibilityCheckBoxRole ); - MAP( AccessibleRole::TOOL_BAR, NSAccessibilityToolbarRole ); - MAP( AccessibleRole::TOOL_TIP, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::TREE, NSAccessibilityGroupRole ); - MAP( AccessibleRole::VIEW_PORT, NSAccessibilityUnknownRole ); // FIXME - MAP( AccessibleRole::WINDOW, NSAccessibilityWindowRole ); - - MAP( AccessibleRole::BUTTON_DROPDOWN, NSAccessibilityMenuButtonRole ); - MAP( AccessibleRole::BUTTON_MENU, NSAccessibilityMenuButtonRole ); - MAP( AccessibleRole::CAPTION, NSAccessibilityUnknownRole ); - MAP( AccessibleRole::CHART, NSAccessibilityUnknownRole ); - MAP( AccessibleRole::FORM, NSAccessibilityUnknownRole ); - MAP( AccessibleRole::IMAGE_MAP, NSAccessibilityUnknownRole ); - MAP( AccessibleRole::NOTE, NSAccessibilityUnknownRole ); - MAP( AccessibleRole::PAGE, NSAccessibilityUnknownRole ); - MAP( AccessibleRole::RULER, NSAccessibilityUnknownRole ); - MAP( AccessibleRole::SECTION, NSAccessibilityUnknownRole ); - MAP( AccessibleRole::TREE_ITEM, NSAccessibilityUnknownRole ); - MAP( AccessibleRole::TREE_TABLE, NSAccessibilityUnknownRole ); - -#undef MAP - default: - break; - } - return nativeRole; -} - -+(id)getNativeRoleFrom: (XAccessibleContext *) accessibleContext { - id nativeRole = [ AquaA11yRoleHelper simpleMapNativeRoleFrom: accessibleContext ]; - if ( accessibleContext -> getAccessibleRole() == AccessibleRole::LABEL ) { - if ( accessibleContext -> getAccessibleChildCount() > 0 ) { - [ nativeRole release ]; - nativeRole = NSAccessibilityOutlineRole; - } else if ( accessibleContext -> getAccessibleParent().is() ) { - Reference < XAccessibleContext > rxParentContext = accessibleContext -> getAccessibleParent() -> getAccessibleContext(); - if ( rxParentContext.is() ) { - NSString * roleParent = (NSString *) [ AquaA11yRoleHelper simpleMapNativeRoleFrom: rxParentContext.get() ]; - if ( [ roleParent isEqualToString: NSAccessibilityOutlineRole ] ) { - [ nativeRole release ]; - nativeRole = NSAccessibilityRowRole; - } - [ roleParent release ]; - } - } - } else if ( accessibleContext -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) { - Reference < XAccessible > rxAccessible = accessibleContext -> getAccessibleChild(0); - if ( rxAccessible.is() ) { - Reference < XAccessibleContext > rxAccessibleContext = rxAccessible -> getAccessibleContext(); - if ( rxAccessibleContext.is() && rxAccessibleContext -> getAccessibleRole() == AccessibleRole::TEXT ) { - if ( ! rxAccessibleContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::EDITABLE ) ) { - [ nativeRole release ]; - nativeRole = NSAccessibilityPopUpButtonRole; - } - } - } - } - return nativeRole; -} - -+(id)getNativeSubroleFrom: (sal_Int16) nRole { - id nativeSubrole = nil; - switch( nRole ) { -#define MAP(a,b) \ - case a: nativeSubrole = b; break - - MAP( AccessibleRole::UNKNOWN, NSAccessibilityUnknownSubrole ); - MAP( AccessibleRole::ALERT, NSAccessibilitySystemDialogSubrole ); - MAP( AccessibleRole::COLUMN_HEADER, @"" ); - MAP( AccessibleRole::CANVAS, @"" ); - MAP( AccessibleRole::CHECK_BOX, @"" ); - MAP( AccessibleRole::CHECK_MENU_ITEM, @"" ); - MAP( AccessibleRole::COLOR_CHOOSER, @"" ); - MAP( AccessibleRole::COMBO_BOX, @"" ); - MAP( AccessibleRole::DATE_EDITOR, @"" ); - MAP( AccessibleRole::DESKTOP_ICON, @"" ); - MAP( AccessibleRole::DESKTOP_PANE, @"" ); - MAP( AccessibleRole::DIRECTORY_PANE, @"" ); - MAP( AccessibleRole::DIALOG, NSAccessibilityDialogSubrole ); - MAP( AccessibleRole::DOCUMENT, @"" ); - MAP( AccessibleRole::EMBEDDED_OBJECT, @"" ); - MAP( AccessibleRole::END_NOTE, @"" ); - MAP( AccessibleRole::FILE_CHOOSER, @"" ); - MAP( AccessibleRole::FILLER, @"" ); - MAP( AccessibleRole::FONT_CHOOSER, @"" ); - MAP( AccessibleRole::FOOTER, @"" ); - MAP( AccessibleRole::FOOTNOTE, @"" ); - MAP( AccessibleRole::FRAME, @"" ); - MAP( AccessibleRole::GLASS_PANE, @"" ); - MAP( AccessibleRole::GRAPHIC, @"" ); - MAP( AccessibleRole::GROUP_BOX, @"" ); - MAP( AccessibleRole::HEADER, @"" ); - MAP( AccessibleRole::HEADING, @"" ); - MAP( AccessibleRole::HYPER_LINK, NSAccessibilityTextLinkSubrole ); - MAP( AccessibleRole::ICON, @"" ); - MAP( AccessibleRole::INTERNAL_FRAME, @"" ); - MAP( AccessibleRole::LABEL, @"" ); - MAP( AccessibleRole::LAYERED_PANE, @"" ); - MAP( AccessibleRole::LIST, @"" ); - MAP( AccessibleRole::LIST_ITEM, NSAccessibilityOutlineRowSubrole ); - MAP( AccessibleRole::MENU, @"" ); - MAP( AccessibleRole::MENU_BAR, @"" ); - MAP( AccessibleRole::MENU_ITEM, @"" ); - MAP( AccessibleRole::OPTION_PANE, @"" ); - MAP( AccessibleRole::PAGE_TAB, @"" ); - MAP( AccessibleRole::PAGE_TAB_LIST, @"" ); - MAP( AccessibleRole::PANEL, @"" ); - MAP( AccessibleRole::PARAGRAPH, @"" ); - MAP( AccessibleRole::PASSWORD_TEXT, NSAccessibilitySecureTextFieldSubrole ); - MAP( AccessibleRole::POPUP_MENU, @"" ); - MAP( AccessibleRole::PUSH_BUTTON, @"" ); - MAP( AccessibleRole::PROGRESS_BAR, @"" ); - MAP( AccessibleRole::RADIO_BUTTON, @"" ); - MAP( AccessibleRole::RADIO_MENU_ITEM, @"" ); - MAP( AccessibleRole::ROW_HEADER, @"" ); - MAP( AccessibleRole::ROOT_PANE, @"" ); - MAP( AccessibleRole::SCROLL_BAR, @"" ); - MAP( AccessibleRole::SCROLL_PANE, @"" ); - MAP( AccessibleRole::SHAPE, @"" ); - MAP( AccessibleRole::SEPARATOR, @"" ); - MAP( AccessibleRole::SLIDER, @"" ); - MAP( AccessibleRole::SPIN_BOX, @"" ); - MAP( AccessibleRole::SPLIT_PANE, @"" ); - MAP( AccessibleRole::STATUS_BAR, @"" ); - MAP( AccessibleRole::TABLE, @"" ); - MAP( AccessibleRole::TABLE_CELL, @"" ); - MAP( AccessibleRole::TEXT, @"" ); - MAP( AccessibleRole::TEXT_FRAME, @"" ); - MAP( AccessibleRole::TOGGLE_BUTTON, @"" ); - MAP( AccessibleRole::TOOL_BAR, @"" ); - MAP( AccessibleRole::TOOL_TIP, @"" ); - MAP( AccessibleRole::TREE, @"" ); - MAP( AccessibleRole::VIEW_PORT, @"" ); - MAP( AccessibleRole::WINDOW, NSAccessibilityStandardWindowSubrole ); - - MAP( AccessibleRole::BUTTON_DROPDOWN, @"" ); - MAP( AccessibleRole::BUTTON_MENU, @"" ); - MAP( AccessibleRole::CAPTION, @"" ); - MAP( AccessibleRole::CHART, @"" ); - MAP( AccessibleRole::FORM, @"" ); - MAP( AccessibleRole::IMAGE_MAP, @"" ); - MAP( AccessibleRole::NOTE, @"" ); - MAP( AccessibleRole::PAGE, @"" ); - MAP( AccessibleRole::RULER, @"" ); - MAP( AccessibleRole::SECTION, @"" ); - MAP( AccessibleRole::TREE_ITEM, @"" ); - MAP( AccessibleRole::TREE_TABLE, @"" ); - -#undef MAP - default: - break; - } - return nativeSubrole; -} - -+(id)getRoleDescriptionFrom: (NSString *) role with: (NSString *) subRole { - id roleDescription; - if ( [ subRole length ] == 0 ) - roleDescription = NSAccessibilityRoleDescription( role, nil ); - else - roleDescription = NSAccessibilityRoleDescription( role, subRole ); - return roleDescription; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11yselectionwrapper.h b/vcl/aqua/source/a11y/aqua11yselectionwrapper.h deleted file mode 100644 index af3c297dd363..000000000000 --- a/vcl/aqua/source/a11y/aqua11yselectionwrapper.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YSELECTIONWRAPPER_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YSELECTIONWRAPPER_H - -#include "aqua/aquavcltypes.h" -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11ySelectionWrapper : NSObject -{ -} -+(id)selectedChildrenAttributeForElement:(AquaA11yWrapper *)wrapper; -+(void)addAttributeNamesTo:(NSMutableArray *)attributeNames; -+(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper; -+(void)setSelectedChildrenAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YSELECTIONWRAPPER_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11yselectionwrapper.mm b/vcl/aqua/source/a11y/aqua11yselectionwrapper.mm deleted file mode 100644 index 929d45443061..000000000000 --- a/vcl/aqua/source/a11y/aqua11yselectionwrapper.mm +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" -#include "aqua/aqua11yfactory.h" - -#include "aqua11yselectionwrapper.h" - -using namespace ::com::sun::star::accessibility; -using namespace ::com::sun::star::uno; - -@implementation AquaA11ySelectionWrapper : NSObject - -+(id)selectedChildrenAttributeForElement:(AquaA11yWrapper *)wrapper -{ - Reference< XAccessibleSelection > xAccessibleSelection = [ wrapper accessibleSelection ]; - if( xAccessibleSelection.is() ) - { - NSMutableArray * children = [ [ NSMutableArray alloc ] init ]; - try { - sal_Int32 n = xAccessibleSelection -> getSelectedAccessibleChildCount(); - for ( sal_Int32 i=0 ; i < n ; ++i ) { - [ children addObject: [ AquaA11yFactory wrapperForAccessible: xAccessibleSelection -> getSelectedAccessibleChild( i ) ] ]; - } - - return children; - - } catch ( Exception& e) - { - } - } - - return nil; -} - - -+(void)addAttributeNamesTo:(NSMutableArray *)attributeNames -{ - [ attributeNames addObject: NSAccessibilitySelectedChildrenAttribute ]; -} - -+(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper -{ - (void)wrapper; - if ( [ attribute isEqualToString: NSAccessibilitySelectedChildrenAttribute ] ) - { - return YES; - } - else - { - return NO; - } -} - -+(void)setSelectedChildrenAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value -{ - Reference< XAccessibleSelection > xAccessibleSelection = [ wrapper accessibleSelection ]; - try { - xAccessibleSelection -> clearAccessibleSelection(); - - unsigned c = [ value count ]; - for ( unsigned i = 0 ; i < c ; ++i ) { - xAccessibleSelection -> selectAccessibleChild( [ [ value objectAtIndex: i ] accessibleContext ] -> getAccessibleIndexInParent() ); - } - } catch ( Exception& e) { - } -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ytablewrapper.h b/vcl/aqua/source/a11y/aqua11ytablewrapper.h deleted file mode 100644 index 09b3ff733759..000000000000 --- a/vcl/aqua/source/a11y/aqua11ytablewrapper.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YTABLEWRAPPER_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YTABLEWRAPPER_H - -#include "aqua/aqua11ywrapper.h" - -#define MAXIMUM_ACCESSIBLE_TABLE_CELLS 1000 - -@interface AquaA11yTableWrapper : AquaA11yWrapper -{ -} -+(id)childrenAttributeForElement:(AquaA11yTableWrapper *)wrapper; -+(void)addAttributeNamesTo: (NSMutableArray *)attributeNames object: (AquaA11yWrapper*)pObject; - --(id)rowsAttribute; --(id)columnsAttribute; -@end -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YTABLEWRAPPER_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ytablewrapper.mm b/vcl/aqua/source/a11y/aqua11ytablewrapper.mm deleted file mode 100644 index 52ff2a8d2d76..000000000000 --- a/vcl/aqua/source/a11y/aqua11ytablewrapper.mm +++ /dev/null @@ -1,204 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/aqua11yfactory.h" - -#include "aqua11ytablewrapper.h" - -using namespace ::com::sun::star::accessibility; -using namespace ::com::sun::star::awt; -using namespace ::com::sun::star::uno; - -@implementation AquaA11yTableWrapper : AquaA11yWrapper - -+(id)childrenAttributeForElement:(AquaA11yTableWrapper *)wrapper -{ - XAccessibleTable * accessibleTable = [ wrapper accessibleTable ]; - NSArray* pResult = nil; - if( accessibleTable ) - { - NSMutableArray * cells = [ [ NSMutableArray alloc ] init ]; - try - { - sal_Int32 nRows = accessibleTable->getAccessibleRowCount(); - sal_Int32 nCols = accessibleTable->getAccessibleColumnCount(); - - if( nRows * nCols < MAXIMUM_ACCESSIBLE_TABLE_CELLS ) - { - // make all children visible to the hierarchy - for ( sal_Int32 rowCount = 0; rowCount < nRows; rowCount++ ) - { - for ( sal_Int32 columnCount = 0; columnCount < nCols; columnCount++ ) - { - Reference < XAccessible > rAccessibleCell = accessibleTable -> getAccessibleCellAt ( rowCount, columnCount ); - if ( rAccessibleCell.is() ) - { - id cell_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rAccessibleCell -> getAccessibleContext() ]; - [ cells addObject: cell_wrapper ]; - [ cell_wrapper release ]; - } - } - } - } - else - { - XAccessibleComponent * accessibleComponent = [ wrapper accessibleComponent ]; - // find out which cells are actually visible by determining the top-left-cell and the bottom-right-cell - Size tableSize = accessibleComponent -> getSize(); - Point point; - point.X = 0; - point.Y = 0; - Reference < XAccessible > rAccessibleTopLeft = accessibleComponent -> getAccessibleAtPoint ( point ); - point.X = tableSize.Width - 1; - point.Y = tableSize.Height - 1; - Reference < XAccessible > rAccessibleBottomRight = accessibleComponent -> getAccessibleAtPoint ( point ); - if ( rAccessibleTopLeft.is() && rAccessibleBottomRight.is() ) - { - sal_Int32 idxTopLeft = rAccessibleTopLeft -> getAccessibleContext() -> getAccessibleIndexInParent(); - sal_Int32 idxBottomRight = rAccessibleBottomRight -> getAccessibleContext() -> getAccessibleIndexInParent(); - sal_Int32 rowTopLeft = accessibleTable -> getAccessibleRow ( idxTopLeft ); - sal_Int32 columnTopLeft = accessibleTable -> getAccessibleColumn ( idxTopLeft ); - sal_Int32 rowBottomRight = accessibleTable -> getAccessibleRow ( idxBottomRight ); - sal_Int32 columnBottomRight = accessibleTable -> getAccessibleColumn ( idxBottomRight ); - // create an array containing the visible cells - for ( sal_Int32 rowCount = rowTopLeft; rowCount <= rowBottomRight; rowCount++ ) - { - for ( sal_Int32 columnCount = columnTopLeft; columnCount <= columnBottomRight; columnCount++ ) - { - Reference < XAccessible > rAccessibleCell = accessibleTable -> getAccessibleCellAt ( rowCount, columnCount ); - if ( rAccessibleCell.is() ) - { - id cell_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rAccessibleCell -> getAccessibleContext() ]; - [ cells addObject: cell_wrapper ]; - [ cell_wrapper release ]; - } - } - } - } - } - pResult = NSAccessibilityUnignoredChildren( cells ); - } - catch (const Exception &e) - { - } - [cells autorelease]; - } - - return pResult; -} - -+(void)addAttributeNamesTo: (NSMutableArray *)attributeNames object: (AquaA11yWrapper*)pObject -{ - XAccessibleTable * accessibleTable = [ pObject accessibleTable ]; - if( accessibleTable ) - { - sal_Int32 nRows = accessibleTable->getAccessibleRowCount(); - sal_Int32 nCols = accessibleTable->getAccessibleColumnCount(); - - - if( nRows*nCols < MAXIMUM_ACCESSIBLE_TABLE_CELLS ) - { - [ attributeNames addObject: NSAccessibilityRowsAttribute ]; - [ attributeNames addObject: NSAccessibilityColumnsAttribute ]; - } - } -} - --(id)rowsAttribute -{ - NSArray* pResult = nil; - - XAccessibleTable * accessibleTable = [ self accessibleTable ]; - if( accessibleTable ) - { - sal_Int32 nRows = accessibleTable->getAccessibleRowCount(); - sal_Int32 nCols = accessibleTable->getAccessibleColumnCount(); - if( nRows * nCols < MAXIMUM_ACCESSIBLE_TABLE_CELLS ) - { - NSMutableArray * cells = [ [ NSMutableArray alloc ] init ]; - try - { - // find out number of rows - sal_Int32 nRows = accessibleTable->getAccessibleRowCount(); - for( sal_Int32 n = 0; n < nRows; n++ ) - { - Reference < XAccessible > rAccessibleCell = accessibleTable -> getAccessibleCellAt ( n, 0 ); - if ( rAccessibleCell.is() ) - { - id cell_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rAccessibleCell -> getAccessibleContext() ]; - [ cells addObject: cell_wrapper ]; - [ cell_wrapper release ]; - } - } - pResult = NSAccessibilityUnignoredChildren( cells ); - } - catch (const Exception &e) - { - pResult = nil; - } - [ cells autorelease ]; - } - } - - return pResult; -} - --(id)columnsAttribute -{ - NSArray* pResult = nil; - - XAccessibleTable * accessibleTable = [ self accessibleTable ]; - - if( accessibleTable ) - { - sal_Int32 nRows = accessibleTable->getAccessibleRowCount(); - sal_Int32 nCols = accessibleTable->getAccessibleColumnCount(); - if( nRows * nCols < MAXIMUM_ACCESSIBLE_TABLE_CELLS ) - { - NSMutableArray * cells = [ [ NSMutableArray alloc ] init ]; - try - { - // find out number of columns - for( sal_Int32 n = 0; n < nCols; n++ ) - { - Reference < XAccessible > rAccessibleCell = accessibleTable -> getAccessibleCellAt ( 0, n ); - if ( rAccessibleCell.is() ) - { - id cell_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rAccessibleCell -> getAccessibleContext() ]; - [ cells addObject: cell_wrapper ]; - [ cell_wrapper release ]; - } - } - pResult = NSAccessibilityUnignoredChildren( cells ); - } - catch (const Exception &e) - { - pResult = nil; - } - [ cells autorelease ]; - } - } - - return pResult; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ytextattributeswrapper.h b/vcl/aqua/source/a11y/aqua11ytextattributeswrapper.h deleted file mode 100644 index 4464bd32bfaf..000000000000 --- a/vcl/aqua/source/a11y/aqua11ytextattributeswrapper.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YTEXTATTRIBUTESWRAPPER_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YTEXTATTRIBUTESWRAPPER_H - -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yTextAttributesWrapper : NSObject -{ -} -+(NSMutableAttributedString *)createAttributedStringForElement:(AquaA11yWrapper *)wrapper inOrigRange:(id)origRange; -@end -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YTEXTATTRIBUTESWRAPPER_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ytextattributeswrapper.mm b/vcl/aqua/source/a11y/aqua11ytextattributeswrapper.mm deleted file mode 100644 index a30b8d2c242a..000000000000 --- a/vcl/aqua/source/a11y/aqua11ytextattributeswrapper.mm +++ /dev/null @@ -1,355 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" -#include "quartz/utils.h" -#include "coretext/salgdi.h" - -#include "aqua11ytextattributeswrapper.h" - -#include -#include -#include -#include -#include -#include - -namespace css_awt = ::com::sun::star::awt; -using namespace ::com::sun::star::accessibility; -using namespace ::com::sun::star::beans; -using namespace ::com::sun::star::lang; -using namespace ::com::sun::star::uno; -using namespace ::rtl; - -// cannot use NSFontDescriptor as it has no notion of explicit NSUn{bold,italic}FontMask -@interface AquaA11yFontDescriptor : NSObject -{ - NSString *_name; - NSFontTraitMask _traits; - CGFloat _size; -} --(void)setName:(NSString*)name; --(void)setBold:(NSFontTraitMask)bold; --(void)setItalic:(NSFontTraitMask)italic; --(void)setSize:(CGFloat)size; --(NSFont*)font; -@end - -@implementation AquaA11yFontDescriptor -- (id)init -{ - if((self = [super init])) - { - _name = nil; - _traits = 0; - _size = 0.0; - } - return self; -} - -- (id)initWithDescriptor:(AquaA11yFontDescriptor*)descriptor { - if((self = [super init])) - { - _name = [descriptor->_name retain]; - _traits = descriptor->_traits; - _size = descriptor->_size; - } - return self; -} - -- (void)dealloc { - [_name release]; - [super dealloc]; -} - --(void)setName:(NSString*)name { - if (_name != name) { - [name retain]; - [_name release]; - _name = name; - } -} - --(void)setBold:(NSFontTraitMask)bold { - _traits &= ~(NSBoldFontMask | NSUnboldFontMask); - _traits |= bold & (NSBoldFontMask | NSUnboldFontMask); -}; - --(void)setItalic:(NSFontTraitMask)italic { - _traits &= ~(NSItalicFontMask | NSUnitalicFontMask); - _traits |= italic & (NSItalicFontMask | NSUnitalicFontMask); -}; - --(void)setSize:(CGFloat)size { _size = size; } - --(NSFont*)font { - return [[NSFontManager sharedFontManager] fontWithFamily:_name traits:_traits weight:0 size:_size]; -} -@end - -@implementation AquaA11yTextAttributesWrapper : NSObject - -+(int)convertUnderlineStyle:(PropertyValue)property { - int underlineStyle = NSNoUnderlineStyle; - sal_Int16 value = 0; - property.Value >>= value; - if ( value != ::css_awt::FontUnderline::NONE - && value != ::css_awt::FontUnderline::DONTKNOW) { - underlineStyle = NSSingleUnderlineStyle; - } - return underlineStyle; -} - -+(int)convertBoldStyle:(PropertyValue)property { - int boldStyle = NSUnboldFontMask; - float value = 0; - property.Value >>= value; - if ( value == ::css_awt::FontWeight::SEMIBOLD - || value == ::css_awt::FontWeight::BOLD - || value == ::css_awt::FontWeight::ULTRABOLD - || value == ::css_awt::FontWeight::BLACK ) { - boldStyle = NSBoldFontMask; - } - return boldStyle; -} - -+(int)convertItalicStyle:(PropertyValue)property { - int italicStyle = NSUnitalicFontMask; - sal_Int16 value = property.Value.get< ::css_awt::FontSlant>(); - if ( value == ::css_awt::FontSlant_ITALIC ) { - italicStyle = NSItalicFontMask; - } - return italicStyle; -} - -+(BOOL)isStrikethrough:(PropertyValue)property { - BOOL strikethrough = NO; - sal_Int16 value = 0; - property.Value >>= value; - if ( value != ::css_awt::FontStrikeout::NONE - && value != ::css_awt::FontStrikeout::DONTKNOW ) { - strikethrough = YES; - } - return strikethrough; -} - -+(BOOL)convertBoolean:(PropertyValue)property { - BOOL myBoolean = NO; - bool value = sal_False; - property.Value >>= value; - if ( value ) { - myBoolean = YES; - } - return myBoolean; -} - -+(NSNumber *)convertShort:(PropertyValue)property { - sal_Int16 value = 0; - property.Value >>= value; - return [ NSNumber numberWithShort: value ]; -} - -+(void)addColor:(SalColor)nSalColor forAttribute:(NSString *)attribute andRange:(NSRange)range toString:(NSMutableAttributedString *)string { - if( nSalColor == COL_TRANSPARENT ) - return; - const RGBAColor aRGBAColor( nSalColor); - CGColorRef aColorRef = CGColorCreate ( CGColorSpaceCreateWithName ( kCGColorSpaceGenericRGB ), aRGBAColor.AsArray() ); - [ string addAttribute: attribute value: (id) aColorRef range: range ]; - CGColorRelease( aColorRef ); -} - -+(void)addFont:(NSFont *)font toString:(NSMutableAttributedString *)string forRange:(NSRange)range { - if ( font != nil ) { - NSDictionary * fontDictionary = [ NSDictionary dictionaryWithObjectsAndKeys: - [ font fontName ], NSAccessibilityFontNameKey, - [ font familyName ], NSAccessibilityFontFamilyKey, - [ font displayName ], NSAccessibilityVisibleNameKey, - [ NSNumber numberWithFloat: [ font pointSize ] ], NSAccessibilityFontSizeKey, - nil - ]; - [ string addAttribute: NSAccessibilityFontTextAttribute - value: fontDictionary - range: range - ]; - } -} - -+(void)applyAttributesFrom:(Sequence < PropertyValue >)attributes toString:(NSMutableAttributedString *)string forRange:(NSRange)range fontDescriptor:(AquaA11yFontDescriptor*)fontDescriptor { - NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; - // constants - static const OUString attrUnderline("CharUnderline"); - static const OUString attrBold("CharWeight"); - static const OUString attrFontname("CharFontName"); - static const OUString attrItalic("CharPosture"); - static const OUString attrHeight("CharHeight"); - static const OUString attrStrikethrough("CharStrikeout"); - static const OUString attrShadow("CharShadowed"); - static const OUString attrUnderlineColor("CharUnderlineColor"); - static const OUString attrUnderlineHasColor("CharUnderlineHasColor"); - static const OUString attrForegroundColor("CharColor"); - static const OUString attrBackgroundColor("CharBackColor"); - static const OUString attrSuperscript("CharEscapement"); - static const OUString attrTextAlignment("ParaAdjust"); - // vars - sal_Int32 underlineColor = 0; - BOOL underlineHasColor = NO; - // add attributes to string - for ( int attrIndex = 0; attrIndex < attributes.getLength(); attrIndex++ ) { - PropertyValue property = attributes [ attrIndex ]; - // TODO: NSAccessibilityMisspelledTextAttribute, NSAccessibilityAttachmentTextAttribute, NSAccessibilityLinkTextAttribute - // NSAccessibilityStrikethroughColorTextAttribute is unsupported by UNP-API - if ( property.Value.hasValue() ) { - if ( property.Name.equals ( attrUnderline ) ) { - int style = [ AquaA11yTextAttributesWrapper convertUnderlineStyle: property ]; - if ( style != NSNoUnderlineStyle ) { - [ string addAttribute: NSAccessibilityUnderlineTextAttribute value: [ NSNumber numberWithInt: style ] range: range ]; - } - } else if ( property.Name.equals ( attrFontname ) ) { - OUString fontname; - property.Value >>= fontname; - [fontDescriptor setName:CreateNSString(fontname)]; - } else if ( property.Name.equals ( attrBold ) ) { - [fontDescriptor setBold:[AquaA11yTextAttributesWrapper convertBoldStyle:property]]; - } else if ( property.Name.equals ( attrItalic ) ) { - [fontDescriptor setItalic:[AquaA11yTextAttributesWrapper convertItalicStyle:property]]; - } else if ( property.Name.equals ( attrHeight ) ) { - float size; - property.Value >>= size; - [fontDescriptor setSize:size]; - } else if ( property.Name.equals ( attrStrikethrough ) ) { - if ( [ AquaA11yTextAttributesWrapper isStrikethrough: property ] ) { - [ string addAttribute: NSAccessibilityStrikethroughTextAttribute value: [ NSNumber numberWithBool: YES ] range: range ]; - } - } else if ( property.Name.equals ( attrShadow ) ) { - if ( [ AquaA11yTextAttributesWrapper convertBoolean: property ] ) { - [ string addAttribute: NSAccessibilityShadowTextAttribute value: [ NSNumber numberWithBool: YES ] range: range ]; - } - } else if ( property.Name.equals ( attrUnderlineColor ) ) { - property.Value >>= underlineColor; - } else if ( property.Name.equals ( attrUnderlineHasColor ) ) { - underlineHasColor = [ AquaA11yTextAttributesWrapper convertBoolean: property ]; - } else if ( property.Name.equals ( attrForegroundColor ) ) { - [ AquaA11yTextAttributesWrapper addColor: property.Value.get() forAttribute: NSAccessibilityForegroundColorTextAttribute andRange: range toString: string ]; - } else if ( property.Name.equals ( attrBackgroundColor ) ) { - [ AquaA11yTextAttributesWrapper addColor: property.Value.get() forAttribute: NSAccessibilityBackgroundColorTextAttribute andRange: range toString: string ]; - } else if ( property.Name.equals ( attrSuperscript ) ) { - // values < zero mean subscript - // values > zero mean superscript - // this is true for both NSAccessibility-API and UNO-API - NSNumber * number = [ AquaA11yTextAttributesWrapper convertShort: property ]; - if ( [ number shortValue ] != 0 ) { - [ string addAttribute: NSAccessibilitySuperscriptTextAttribute value: number range: range ]; - } - } else if ( property.Name.equals ( attrTextAlignment ) ) { - sal_Int32 alignment; - property.Value >>= alignment; - NSNumber *textAlignment = nil; - switch(alignment) { - case ::com::sun::star::style::ParagraphAdjust_RIGHT : textAlignment = [NSNumber numberWithInteger:NSRightTextAlignment] ; break; - case ::com::sun::star::style::ParagraphAdjust_CENTER: textAlignment = [NSNumber numberWithInteger:NSCenterTextAlignment] ; break; - case ::com::sun::star::style::ParagraphAdjust_BLOCK : textAlignment = [NSNumber numberWithInteger:NSJustifiedTextAlignment]; break; - case ::com::sun::star::style::ParagraphAdjust_LEFT : - default : textAlignment = [NSNumber numberWithInteger:NSLeftTextAlignment] ; break; - } - NSDictionary *paragraphStyle = [NSDictionary dictionaryWithObjectsAndKeys:textAlignment, @"AXTextAlignment", textAlignment, @"AXVisualTextAlignment", nil]; - [string addAttribute:@"AXParagraphStyle" value:paragraphStyle range:range]; - } - } - } - // add underline information - if ( underlineHasColor ) { - [ AquaA11yTextAttributesWrapper addColor: underlineColor forAttribute: NSAccessibilityUnderlineColorTextAttribute andRange: range toString: string ]; - } - // add font information - NSFont * font = [fontDescriptor font]; - [AquaA11yTextAttributesWrapper addFont:font toString:string forRange:range]; - [ pool release ]; -} - -+(void)addMarkup:(XAccessibleTextMarkup*)markup withType:(long)type toString:(NSMutableAttributedString*)string inRange:(NSRange)range { - const long markupCount = markup->getTextMarkupCount(type); - for (long markupIndex = 0; markupIndex < markupCount; ++markupIndex) { - TextSegment markupSegment = markup->getTextMarkup(markupIndex, type); - NSRange markupRange = NSMakeRange(markupSegment.SegmentStart, markupSegment.SegmentEnd - markupSegment.SegmentStart); - markupRange = NSIntersectionRange(range, markupRange); - if (markupRange.length > 0) { - markupRange.location -= range.location; - switch(type) { - case ::com::sun::star::text::TextMarkupType::SPELLCHECK: { - [string addAttribute:NSAccessibilityMisspelledTextAttribute value:[NSNumber numberWithBool:YES] range:markupRange]; - [string addAttribute:@"AXMarkedMisspelled" value:[NSNumber numberWithBool:YES] range:markupRange]; - break; - } - } - } - } -} - -+(void)addMarkup:(XAccessibleTextMarkup*)markup toString:(NSMutableAttributedString*)string inRange:(NSRange)range { - [AquaA11yTextAttributesWrapper addMarkup:markup withType:(::com::sun::star::text::TextMarkupType::SPELLCHECK) toString:string inRange:range]; -} - -+(NSMutableAttributedString *)createAttributedStringForElement:(AquaA11yWrapper *)wrapper inOrigRange:(id)origRange { - static const Sequence < OUString > emptySequence; - // vars - NSMutableAttributedString * string = nil; - int loc = [ origRange rangeValue ].location; - int len = [ origRange rangeValue ].length; - int endIndex = loc + len; - int currentIndex = loc; - try { - NSString * myString = CreateNSString ( [ wrapper accessibleText ] -> getText() ); // TODO: dirty fix for i87817 - string = [ [ NSMutableAttributedString alloc ] initWithString: CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) ]; - if ( [ wrapper accessibleTextAttributes ] != nil && [myString characterAtIndex:0] != 57361) { // TODO: dirty fix for i87817 - [ string beginEditing ]; - // add default attributes for whole string - Sequence < PropertyValue > defaultAttributes = [ wrapper accessibleTextAttributes ] -> getDefaultAttributes ( emptySequence ); - AquaA11yFontDescriptor *defaultFontDescriptor = [[AquaA11yFontDescriptor alloc] init]; - [ AquaA11yTextAttributesWrapper applyAttributesFrom: defaultAttributes toString: string forRange: NSMakeRange ( 0, len ) fontDescriptor: defaultFontDescriptor ]; - // add attributes for attribute run(s) - while ( currentIndex < endIndex ) { - TextSegment textSegment = [ wrapper accessibleText ] -> getTextAtIndex ( currentIndex, AccessibleTextType::ATTRIBUTE_RUN ); - int endOfRange = endIndex > textSegment.SegmentEnd ? textSegment.SegmentEnd : endIndex; - NSRange rangeForAttributeRun = NSMakeRange ( currentIndex - loc , endOfRange - currentIndex ); - // add run attributes - Sequence < PropertyValue > attributes = [ wrapper accessibleTextAttributes ] -> getRunAttributes ( currentIndex, emptySequence ); - AquaA11yFontDescriptor *fontDescriptor = [[AquaA11yFontDescriptor alloc] initWithDescriptor:defaultFontDescriptor]; - [ AquaA11yTextAttributesWrapper applyAttributesFrom: attributes toString: string forRange: rangeForAttributeRun fontDescriptor: fontDescriptor ]; - [fontDescriptor release]; - currentIndex = textSegment.SegmentEnd; - } - [defaultFontDescriptor release]; - if ([wrapper accessibleTextMarkup]) - [AquaA11yTextAttributesWrapper addMarkup:[wrapper accessibleTextMarkup] toString:string inRange:[origRange rangeValue]]; - [ string endEditing ]; - } - } catch ( IllegalArgumentException & e ) { - // empty - } catch ( IndexOutOfBoundsException & e ) { - // empty - } catch ( RuntimeException& ) { - // at least don't crash - } - return string; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ytextwrapper.h b/vcl/aqua/source/a11y/aqua11ytextwrapper.h deleted file mode 100644 index 91b2bd929538..000000000000 --- a/vcl/aqua/source/a11y/aqua11ytextwrapper.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YTEXTWRAPPER_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YTEXTWRAPPER_H - -#include "aqua/aquavcltypes.h" -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yTextWrapper : NSObject -{ -} -+(id)valueAttributeForElement:(AquaA11yWrapper *)wrapper; -+(id)numberOfCharactersAttributeForElement:(AquaA11yWrapper *)wrapper; -+(id)selectedTextAttributeForElement:(AquaA11yWrapper *)wrapper; -+(id)selectedTextRangeAttributeForElement:(AquaA11yWrapper *)wrapper; -+(id)visibleCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper; -+(id)sharedTextUIElementsAttributeForElement:(AquaA11yWrapper *)wrapper; -+(id)sharedCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper; -+(id)stringForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range; -+(id)attributedStringForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range; -+(id)rangeForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index; -+(id)rangeForPositionAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)point; -+(id)boundsForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range; -+(id)styleRangeForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index; -+(id)rTFForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range; -+(id)lineForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index; -+(id)rangeForLineAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)line; -+(void)addAttributeNamesTo:(NSMutableArray *)attributeNames; -+(void)addParameterizedAttributeNamesTo:(NSMutableArray *)attributeNames; -+(NSArray *)specialAttributeNames; -+(NSArray *)specialParameterizedAttributeNames; -+(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper; -+(void)setVisibleCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value; -+(void)setSelectedTextRangeAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value; -+(void)setSelectedTextAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value; -+(void)setValueAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YTEXTWRAPPER_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ytextwrapper.mm b/vcl/aqua/source/a11y/aqua11ytextwrapper.mm deleted file mode 100644 index ab02eaf7ef3a..000000000000 --- a/vcl/aqua/source/a11y/aqua11ytextwrapper.mm +++ /dev/null @@ -1,293 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" -#include "quartz/utils.h" -#include "aqua11ytextwrapper.h" -#include "aqua11ytextattributeswrapper.h" -#include "aqua11yutil.h" - -#include -#include - -using namespace ::com::sun::star::accessibility; -using namespace ::com::sun::star::awt; -using namespace ::com::sun::star::lang; -using namespace ::com::sun::star::uno; -using namespace ::rtl; - -// Wrapper for XAccessibleText, XAccessibleEditableText and XAccessibleMultiLineText - -@implementation AquaA11yTextWrapper : NSObject - -+(id)valueAttributeForElement:(AquaA11yWrapper *)wrapper { - return CreateNSString ( [ wrapper accessibleText ] -> getText() ); -} - -+(void)setValueAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value -{ - // TODO - (void)wrapper; - (void)value; -} - -+(id)numberOfCharactersAttributeForElement:(AquaA11yWrapper *)wrapper { - return [ NSNumber numberWithLong: [ wrapper accessibleText ] -> getCharacterCount() ]; -} - -+(id)selectedTextAttributeForElement:(AquaA11yWrapper *)wrapper { - return CreateNSString ( [ wrapper accessibleText ] -> getSelectedText() ); -} - -+(void)setSelectedTextAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value { - if ( [ wrapper accessibleEditableText ] != nil ) { - NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; - OUString newText = GetOUString ( (NSString *) value ); - NSRange selectedTextRange = [ [ AquaA11yTextWrapper selectedTextRangeAttributeForElement: wrapper ] rangeValue ]; - try { - [ wrapper accessibleEditableText ] -> replaceText ( selectedTextRange.location, selectedTextRange.location + selectedTextRange.length, newText ); - } catch ( const Exception & e ) { - // empty - } - [ pool release ]; - } -} - -+(id)selectedTextRangeAttributeForElement:(AquaA11yWrapper *)wrapper { - sal_Int32 start = [ wrapper accessibleText ] -> getSelectionStart(); - sal_Int32 end = [ wrapper accessibleText ] -> getSelectionEnd(); - if ( start != end ) { - return [ NSValue valueWithRange: NSMakeRange ( start, end - start ) ]; // true selection - } else { - long caretPos = [ wrapper accessibleText ] -> getCaretPosition(); - if ( caretPos < 0 || caretPos > [ wrapper accessibleText ] -> getCharacterCount() ) { - return nil; - } - return [ NSValue valueWithRange: NSMakeRange ( caretPos, 0 ) ]; // insertion point - } -} - -+(void)setSelectedTextRangeAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value { - NSRange range = [ value rangeValue ]; - try { - [ wrapper accessibleText ] -> setSelection ( range.location, range.location + range.length ); - } catch ( const Exception & e ) { - // empty - } -} - -+(id)visibleCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper { - // the OOo a11y API returns only the visible portion... - return [ NSValue valueWithRange: NSMakeRange ( 0, [ wrapper accessibleText ] -> getCharacterCount() ) ]; -} - -+(void)setVisibleCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value -{ - // do nothing - (void)wrapper; - (void)value; -} - -+(id)sharedTextUIElementsAttributeForElement:(AquaA11yWrapper *)wrapper -{ - (void)wrapper; - return [NSArray arrayWithObject:wrapper]; -} - -+(id)sharedCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper -{ - (void)wrapper; - return [ NSValue valueWithRange: NSMakeRange ( 0, [wrapper accessibleText]->getCharacterCount() ) ]; -} - -+(void)addAttributeNamesTo:(NSMutableArray *)attributeNames { - [ attributeNames addObjectsFromArray: [ AquaA11yTextWrapper specialAttributeNames ] ]; -} - -+(NSArray *)specialAttributeNames { - return [ NSArray arrayWithObjects: - NSAccessibilityValueAttribute, - NSAccessibilityNumberOfCharactersAttribute, - NSAccessibilitySelectedTextAttribute, - NSAccessibilitySelectedTextRangeAttribute, - NSAccessibilityVisibleCharacterRangeAttribute, - NSAccessibilitySharedTextUIElementsAttribute, - NSAccessibilitySharedCharacterRangeAttribute, - nil ]; -} - -+(void)addParameterizedAttributeNamesTo:(NSMutableArray *)attributeNames { - [ attributeNames addObjectsFromArray: [ AquaA11yTextWrapper specialParameterizedAttributeNames ] ]; -} - -+(NSArray *)specialParameterizedAttributeNames { - return [ NSArray arrayWithObjects: - NSAccessibilityStringForRangeParameterizedAttribute, - NSAccessibilityAttributedStringForRangeParameterizedAttribute, - NSAccessibilityRangeForIndexParameterizedAttribute, - NSAccessibilityRangeForPositionParameterizedAttribute, - NSAccessibilityBoundsForRangeParameterizedAttribute, - NSAccessibilityStyleRangeForIndexParameterizedAttribute, - NSAccessibilityRTFForRangeParameterizedAttribute, - NSAccessibilityLineForIndexParameterizedAttribute, - NSAccessibilityRangeForLineParameterizedAttribute, - nil ]; -} - -+(id)lineForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index { - NSNumber * lineNumber = nil; - try { - sal_Int32 line = [ wrapper accessibleMultiLineText ] -> getLineNumberAtIndex ( (sal_Int32) [ index intValue ] ); - lineNumber = [ NSNumber numberWithInt: line ]; - } catch ( IndexOutOfBoundsException & e ) { - // empty - } - return lineNumber; -} - -+(id)rangeForLineAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)line { - NSValue * range = nil; - try { - TextSegment textSegment = [ wrapper accessibleMultiLineText ] -> getTextAtLineNumber ( [ line intValue ] ); - range = [ NSValue valueWithRange: NSMakeRange ( textSegment.SegmentStart, textSegment.SegmentEnd - textSegment.SegmentStart ) ]; - } catch ( IndexOutOfBoundsException & e ) { - // empty - } - return range; -} - -+(id)stringForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range { - int loc = [ range rangeValue ].location; - int len = [ range rangeValue ].length; - NSMutableString * textRange = [ [ NSMutableString alloc ] init ]; - try { - [ textRange appendString: CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) ]; - } catch ( IndexOutOfBoundsException & e ) { - // empty - } - return textRange; -} - -+(id)attributedStringForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range { - return [ AquaA11yTextAttributesWrapper createAttributedStringForElement: wrapper inOrigRange: range ]; -} - -+(id)rangeForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index { - NSValue * range = nil; - try { - TextSegment textSegment = [ wrapper accessibleText ] -> getTextBeforeIndex ( [ index intValue ], AccessibleTextType::GLYPH ); - range = [ NSValue valueWithRange: NSMakeRange ( textSegment.SegmentStart, textSegment.SegmentEnd - textSegment.SegmentStart ) ]; - } catch ( IndexOutOfBoundsException & e ) { - // empty - } catch ( IllegalArgumentException & e ) { - // empty - } - return range; -} - -+(id)rangeForPositionAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)point { - NSValue * value = nil; - sal_Int32 index = [ wrapper accessibleText ] -> getIndexAtPoint ( [ AquaA11yUtil nsPointToVclPoint: point ] ); - if ( index > -1 ) { - value = [ AquaA11yTextWrapper rangeForIndexAttributeForElement: wrapper forParameter: [ NSNumber numberWithLong: index ] ]; - } - return value; -} - -+(id)boundsForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range { - NSValue * rect = nil; - try { - // TODO: this is ugly!!! - // the UNP-API can only return the bounds for a single character, not for a range - int loc = [ range rangeValue ].location; - int len = [ range rangeValue ].length; - int minx = 0x7fffffff, miny = 0x7fffffff, maxx = 0, maxy = 0; - for ( int i = 0; i < len; i++ ) { - Rectangle vclRect = [ wrapper accessibleText ] -> getCharacterBounds ( loc + i ); - if ( vclRect.X < minx ) { - minx = vclRect.X; - } - if ( vclRect.Y < miny ) { - miny = vclRect.Y; - } - if ( vclRect.Width + vclRect.X > maxx ) { - maxx = vclRect.Width + vclRect.X; - } - if ( vclRect.Height + vclRect.Y > maxy ) { - maxy = vclRect.Height + vclRect.Y; - } - } - if ( [ wrapper accessibleComponent ] != nil ) { - // get location on screen (must be added since get CharacterBounds returns values relative to parent) - Point screenPos = [ wrapper accessibleComponent ] -> getLocationOnScreen(); - Point pos ( minx + screenPos.X, miny + screenPos.Y ); - Point size ( maxx - minx, maxy - miny ); - NSValue * nsPos = [ AquaA11yUtil vclPointToNSPoint: pos ]; - rect = [ NSValue valueWithRect: NSMakeRect ( [ nsPos pointValue ].x, [ nsPos pointValue ].y - size.Y, size.X, size.Y ) ]; - //printf("Range: %s --- Rect: %s\n", [ NSStringFromRange ( [ range rangeValue ] ) UTF8String ], [ NSStringFromRect ( [ rect rectValue ] ) UTF8String ]); - } - } catch ( IndexOutOfBoundsException & e ) { - // empty - } - return rect; -} - -+(id)styleRangeForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index { - NSValue * range = nil; - try { - TextSegment textSegment = [ wrapper accessibleText ] -> getTextAtIndex ( [ index intValue ], AccessibleTextType::ATTRIBUTE_RUN ); - range = [ NSValue valueWithRange: NSMakeRange ( textSegment.SegmentStart, textSegment.SegmentEnd - textSegment.SegmentStart ) ]; - } catch ( IndexOutOfBoundsException & e ) { - // empty - } catch ( IllegalArgumentException & e ) { - // empty - } - return range; -} - -+(id)rTFForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range { - NSData * rtfData = nil; - NSAttributedString * attrString = (NSAttributedString *) [ AquaA11yTextWrapper attributedStringForRangeAttributeForElement: wrapper forParameter: range ]; - if ( attrString != nil ) { - @try { - rtfData = [ attrString RTFFromRange: [ range rangeValue ] documentAttributes: nil ]; - } @catch ( NSException * e) { - // emtpy - } - } - return rtfData; -} - -+(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper { - BOOL isSettable = NO; - if ( [ attribute isEqualToString: NSAccessibilityValueAttribute ] - || [ attribute isEqualToString: NSAccessibilitySelectedTextAttribute ] - || [ attribute isEqualToString: NSAccessibilitySelectedTextRangeAttribute ] - || [ attribute isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute ] ) { - if ( ! [ [ wrapper accessibilityAttributeValue: NSAccessibilityRoleAttribute ] isEqualToString: NSAccessibilityStaticTextRole ] ) { - isSettable = YES; - } - } - return isSettable; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11yutil.h b/vcl/aqua/source/a11y/aqua11yutil.h deleted file mode 100644 index 6f597dc354b0..000000000000 --- a/vcl/aqua/source/a11y/aqua11yutil.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YUTIL_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YUTIL_H - -#include - -@interface AquaA11yUtil : NSObject { -} -+(NSValue *)vclPointToNSPoint:(::com::sun::star::awt::Point)vclPoint; -+(::com::sun::star::awt::Point)nsPointToVclPoint:(NSValue *)nsPoint; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YUTIL_H -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11yutil.mm b/vcl/aqua/source/a11y/aqua11yutil.mm deleted file mode 100644 index 086fa0a7090d..000000000000 --- a/vcl/aqua/source/a11y/aqua11yutil.mm +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/aquavcltypes.h" - -#include "aqua11yutil.h" - -using namespace ::com::sun::star::awt; - -@implementation AquaA11yUtil : NSObject - -// TODO: should be merged with AquaSalFrame::VCLToCocoa... to a general helper method -+(NSValue *)vclPointToNSPoint:(Point)vclPoint { - // VCL coordinates are in upper-left-notation, Cocoa likes it the Cartesian way (lower-left) - NSRect screenRect = [ [ NSScreen mainScreen ] frame ]; - NSPoint nsPoint = NSMakePoint ( (float) vclPoint.X, (float) ( screenRect.size.height - vclPoint.Y ) ); - return [ NSValue valueWithPoint: nsPoint ]; -} - -// TODO: should be merged with AquaSalFrame::VCLToCocoa... to a general helper method -+(Point)nsPointToVclPoint:(NSValue *)nsPoint { - // VCL coordinates are in upper-left-notation, Cocoa likes it the Cartesian way (lower-left) - NSRect screenRect = [ [ NSScreen mainScreen ] frame ]; - return Point ( static_cast([ nsPoint pointValue ].x), static_cast(screenRect.size.height - [ nsPoint pointValue ].y) ); -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11yvaluewrapper.h b/vcl/aqua/source/a11y/aqua11yvaluewrapper.h deleted file mode 100644 index 6aa2eab1331d..000000000000 --- a/vcl/aqua/source/a11y/aqua11yvaluewrapper.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YVALUEWRAPPER_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YVALUEWRAPPER_H - -#include "aqua/salinst.h" -#include "aqua/aquavcltypes.h" -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yValueWrapper : NSObject -{ -} -+(id)valueAttributeForElement:(AquaA11yWrapper *)wrapper; -+(id)minValueAttributeForElement:(AquaA11yWrapper *)wrapper; -+(id)maxValueAttributeForElement:(AquaA11yWrapper *)wrapper; -+(void)addAttributeNamesTo:(NSMutableArray *)attributeNames; -+(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper; -+(void)setValueAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YVALUEWRAPPER_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11yvaluewrapper.mm b/vcl/aqua/source/a11y/aqua11yvaluewrapper.mm deleted file mode 100644 index 93a479a8a7a5..000000000000 --- a/vcl/aqua/source/a11y/aqua11yvaluewrapper.mm +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua11yvaluewrapper.h" -#include "aqua11ywrapperstatictext.h" - -using namespace ::com::sun::star::uno; - -// Wrapper for XAccessibleValue -// Remember: A UNO-Value is a single numeric value. Regarding the Mac A11y-API, a value can be anything! - -@implementation AquaA11yValueWrapper : NSObject - -+(id)valueAttributeForElement:(AquaA11yWrapper *)wrapper { - // TODO: Detect Type from Any - if ( [ wrapper accessibleValue ] != nil ) { - long value = 0; - [ wrapper accessibleValue ] -> getCurrentValue() >>= value; - return [ NSNumber numberWithLong: value ]; - } - return [ NSNumber numberWithLong: 0 ]; -} - -+(id)minValueAttributeForElement:(AquaA11yWrapper *)wrapper { - // TODO: Detect Type from Any - if ( [ wrapper accessibleValue ] != nil ) { - long value = 0; - [ wrapper accessibleValue ] -> getMinimumValue() >>= value; - return [ NSNumber numberWithLong: value ]; - } - return [ NSNumber numberWithLong: 0 ]; -} - -+(id)maxValueAttributeForElement:(AquaA11yWrapper *)wrapper { - // TODO: Detect Type from Any - if ( [ wrapper accessibleValue ] != nil ) { - long value = 0; - [ wrapper accessibleValue ] -> getMaximumValue() >>= value; - return [ NSNumber numberWithLong: value ]; - } - return [ NSNumber numberWithLong: 0 ]; -} - -+(void)setValueAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value { - // TODO: Detect Type from NSNumber - if ( [ value isKindOfClass: [ NSNumber class ] ] - && [ wrapper accessibleValue ] != nil ) { - NSNumber * number = (NSNumber *) value; - Any numberAny ( [ number longValue ] ); - [ wrapper accessibleValue ] -> setCurrentValue ( numberAny ); - } -} - -+(void)addAttributeNamesTo:(NSMutableArray *)attributeNames { - [ attributeNames addObject: NSAccessibilityValueAttribute ]; -} - -+(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper { - BOOL isSettable = NO; - if ( [ wrapper accessibleValue ] != nil - && [ attribute isEqualToString: NSAccessibilityValueAttribute ] - && ! [ wrapper isKindOfClass: [ AquaA11yWrapperStaticText class ] ] ) { - isSettable = YES; - } - return isSettable; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapper.mm b/vcl/aqua/source/a11y/aqua11ywrapper.mm deleted file mode 100644 index 672fad532df3..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapper.mm +++ /dev/null @@ -1,1150 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" -#include "aqua/saldata.hxx" - -#include "aqua/aqua11ywrapper.h" -#include "aqua/aqua11ylistener.hxx" -#include "aqua/aqua11yfactory.h" -#include "aqua/aqua11yfocustracker.hxx" - -#include "quartz/utils.h" - -#include "aqua11yfocuslistener.hxx" -#include "aqua11yactionwrapper.h" -#include "aqua11ycomponentwrapper.h" -#include "aqua11yselectionwrapper.h" -#include "aqua11ytablewrapper.h" -#include "aqua11ytextwrapper.h" -#include "aqua11yvaluewrapper.h" -#include "aqua11yrolehelper.h" - -#include -#include -#include -#include -#include -#include -#include - -using namespace ::com::sun::star::accessibility; -using namespace ::com::sun::star::awt; -using namespace ::com::sun::star::lang; -using namespace ::com::sun::star::uno; - -@interface SalFrameWindow : NSWindow -{ -} --(Reference)accessibleContext; -@end - -static BOOL isPopupMenuOpen = NO; - -static std::ostream &operator<<(std::ostream &s, NSObject *obj) { - return s << [[obj description] UTF8String]; -} - -#ifndef _LP64 - -// In 64-bit code NSPoint == CGPoint, and CGPoint already has -// an operator<< in vcl/inc/quartz/util.h - -static std::ostream &operator<<(std::ostream &s, NSPoint point) { - return s << NSStringFromPoint(point); -} - -#endif - -@implementation AquaA11yWrapper : NSView - -#pragma mark - -#pragma mark Init and dealloc - --(id)initWithAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext { - self = [ super init ]; - if ( self != nil ) { - [ self setDefaults: rxAccessibleContext ]; - } - return self; -} - --(void) setDefaults: (Reference < XAccessibleContext >) rxAccessibleContext { - mpReferenceWrapper = new ReferenceWrapper; - mActsAsRadioGroup = NO; - mpReferenceWrapper -> rAccessibleContext = rxAccessibleContext; - mIsTableCell = NO; - // Querying all supported interfaces - try { - // XAccessibleComponent - mpReferenceWrapper -> rAccessibleComponent = Reference < XAccessibleComponent > ( rxAccessibleContext, UNO_QUERY ); - // XAccessibleExtendedComponent - mpReferenceWrapper -> rAccessibleExtendedComponent = Reference < XAccessibleExtendedComponent > ( rxAccessibleContext, UNO_QUERY ); - // XAccessibleSelection - mpReferenceWrapper -> rAccessibleSelection = Reference< XAccessibleSelection > ( rxAccessibleContext, UNO_QUERY ); - // XAccessibleTable - mpReferenceWrapper -> rAccessibleTable = Reference < XAccessibleTable > ( rxAccessibleContext, UNO_QUERY ); - // XAccessibleText - mpReferenceWrapper -> rAccessibleText = Reference < XAccessibleText > ( rxAccessibleContext, UNO_QUERY ); - // XAccessibleEditableText - mpReferenceWrapper -> rAccessibleEditableText = Reference < XAccessibleEditableText > ( rxAccessibleContext, UNO_QUERY ); - // XAccessibleValue - mpReferenceWrapper -> rAccessibleValue = Reference < XAccessibleValue > ( rxAccessibleContext, UNO_QUERY ); - // XAccessibleAction - mpReferenceWrapper -> rAccessibleAction = Reference < XAccessibleAction > ( rxAccessibleContext, UNO_QUERY ); - // XAccessibleTextAttributes - mpReferenceWrapper -> rAccessibleTextAttributes = Reference < XAccessibleTextAttributes > ( rxAccessibleContext, UNO_QUERY ); - // XAccessibleMultiLineText - mpReferenceWrapper -> rAccessibleMultiLineText = Reference < XAccessibleMultiLineText > ( rxAccessibleContext, UNO_QUERY ); - // XAccessibleTextMarkup - mpReferenceWrapper -> rAccessibleTextMarkup = Reference < XAccessibleTextMarkup > ( rxAccessibleContext, UNO_QUERY ); - // XAccessibleEventBroadcaster - #if 0 - /* #i102033# NSAccessibility does not seemt to know an equivalent for transient children. - That means we need to cache this, else e.g. tree list boxes are not accessible (moreover - it crashes by notifying dead objects - which would seemt o be another bug) - - FIXME: - Unfortunately this can increase memory consumption drastically until the non transient parent - is destroyed an finally all the transients are released. - */ - if ( ! rxAccessibleContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::TRANSIENT ) ) - #endif - { - Reference< XAccessibleEventBroadcaster > xBroadcaster(rxAccessibleContext, UNO_QUERY); - if( xBroadcaster.is() ) { - /* - * We intentionally do not hold a reference to the event listener in the wrapper object, - * but let the listener control the life cycle of the wrapper instead .. - */ - xBroadcaster->addAccessibleEventListener( new AquaA11yEventListener( self, rxAccessibleContext -> getAccessibleRole() ) ); - } - } - // TABLE_CELL - if ( rxAccessibleContext -> getAccessibleRole() == AccessibleRole::TABLE_CELL ) { - mIsTableCell = YES; - } - } catch ( const Exception ) { - } -} - --(void)dealloc { - if ( mpReferenceWrapper != nil ) { - delete mpReferenceWrapper; - } - [ super dealloc ]; -} - -#pragma mark - -#pragma mark Utility Section - -// generates selectors for attribute name AXAttributeNameHere -// (getter without parameter) attributeNameHereAttribute -// (getter with parameter) attributeNameHereAttributeForParameter: -// (setter) setAttributeNameHereAttributeForElement:to: --(SEL)selectorForAttribute:(NSString *)attribute asGetter:(BOOL)asGetter withGetterParameter:(BOOL)withGetterParameter { - SEL selector = nil; - NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; - @try { - // step 1: create method name from attribute name - NSMutableString * methodName = [ NSMutableString string ]; - if ( ! asGetter ) { - [ methodName appendString: @"set" ]; - } - NSRange aRange = { 2, 1 }; - NSString * firstChar = [ attribute substringWithRange: aRange ]; // drop leading "AX" and get first char - if ( asGetter ) { - [ methodName appendString: [ firstChar lowercaseString ] ]; - } else { - [ methodName appendString: firstChar ]; - } - [ methodName appendString: [ attribute substringFromIndex: 3 ] ]; // append rest of attribute name - // append rest of method name - [ methodName appendString: @"Attribute" ]; - if ( ! asGetter ) { - [ methodName appendString: @"ForElement:to:" ]; - } else if ( asGetter && withGetterParameter ) { - [ methodName appendString: @"ForParameter:" ]; - } - // step 2: create selector - selector = NSSelectorFromString ( methodName ); - } @catch ( id exception ) { - selector = nil; - } - [ pool release ]; - return selector; -} - --(Reference < XAccessible >)getFirstRadioButtonInGroup { - Reference < XAccessibleRelationSet > rxAccessibleRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet(); - if( rxAccessibleRelationSet.is() ) - { - AccessibleRelation relationMemberOf = rxAccessibleRelationSet -> getRelationByType ( AccessibleRelationType::MEMBER_OF ); - if ( relationMemberOf.RelationType == AccessibleRelationType::MEMBER_OF && relationMemberOf.TargetSet.hasElements() ) - return Reference < XAccessible > ( relationMemberOf.TargetSet[0], UNO_QUERY ); - } - return Reference < XAccessible > (); -} - --(BOOL)isFirstRadioButtonInGroup { - Reference < XAccessible > rFirstMateAccessible = [ self getFirstRadioButtonInGroup ]; - if ( rFirstMateAccessible.is() && rFirstMateAccessible -> getAccessibleContext().get() == [ self accessibleContext ] ) { - return YES; - } - return NO; -} - -#pragma mark - -#pragma mark Attribute Value Getters -// ( called via Reflection by accessibilityAttributeValue ) - -/* - Radiobutton grouping is done differently in NSAccessibility and the UNO-API. In UNO related radio buttons share an entry in their - RelationSet. In NSAccessibility the relationship is axpressed through the hierarchy. A AXRadioGroup contains two or more AXRadioButton - objects. Since this group is not available in the UNO hierarchy, an extra wrapper is used for it. This wrapper shares almost all - attributes with the first radio button of the group, except for the role, subrole, role description, parent and children attributes. - So in this five methods there is a special treatment for radio buttons and groups. -*/ - --(id)roleAttribute { - if ( mActsAsRadioGroup ) { - return NSAccessibilityRadioGroupRole; - } - else { - return [ AquaA11yRoleHelper getNativeRoleFrom: [ self accessibleContext ] ]; - } -} - --(id)subroleAttribute { - if ( mActsAsRadioGroup ) { - return @""; - } else { - NSString * subRole = [ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ]; - if ( ! [ subRole isEqualToString: @"" ] ) { - return subRole; - } else { - [ subRole release ]; - return [ super accessibilityAttributeValue: NSAccessibilitySubroleAttribute ]; - } - } -} - --(id)titleAttribute { - return CreateNSString ( [ self accessibleContext ] -> getAccessibleName() ); -} - --(id)descriptionAttribute { - if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) { - return [ self titleAttribute ]; - } else if ( [ self accessibleExtendedComponent ] != nil ) { - return [ AquaA11yComponentWrapper descriptionAttributeForElement: self ]; - } else { - return CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() ); - } -} - --(id)enabledAttribute { - if ( [ self accessibleContext ] -> getAccessibleStateSet().is() ) { - return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::ENABLED ) ]; - } else { - return nil; - } -} - --(id)focusedAttribute { - if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) { - id isFocused = nil; - Reference < XAccessible > rxParent = [ self accessibleContext ] -> getAccessibleParent(); - if ( rxParent.is() ) { - Reference < XAccessibleContext > rxContext = rxParent -> getAccessibleContext(); - if ( rxContext.is() && rxContext -> getAccessibleStateSet().is() ) { - isFocused = [ NSNumber numberWithBool: rxContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::FOCUSED ) ]; - } - } - return isFocused; - } else if ( [ self accessibleContext ] -> getAccessibleStateSet().is() ) { - return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::FOCUSED ) ]; - } else { - return nil; - } -} - --(id)parentAttribute { - if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::RADIO_BUTTON && ! mActsAsRadioGroup ) { - Reference < XAccessible > rxAccessible = [ self getFirstRadioButtonInGroup ]; - if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() ) { - Reference < XAccessibleContext > rxAccessibleContext = rxAccessible -> getAccessibleContext(); - id parent_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessibleContext createIfNotExists: YES asRadioGroup: YES ]; - [ parent_wrapper autorelease ]; - return NSAccessibilityUnignoredAncestor( parent_wrapper ); - } - return nil; - } - try { - Reference< XAccessible > xParent( [ self accessibleContext ] -> getAccessibleParent() ); - if ( xParent.is() ) { - Reference< XAccessibleContext > xContext( xParent -> getAccessibleContext() ); - if ( xContext.is() ) { - id parent_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: xContext ]; - [ parent_wrapper autorelease ]; - return NSAccessibilityUnignoredAncestor( parent_wrapper ); - } - } - } catch (const Exception&) { - } - - OSL_ASSERT( 0 ); - return nil; -} - --(id)childrenAttribute { - if ( mActsAsRadioGroup ) { - NSMutableArray * children = [ [ NSMutableArray alloc ] init ]; - Reference < XAccessibleRelationSet > rxAccessibleRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet(); - AccessibleRelation relationMemberOf = rxAccessibleRelationSet -> getRelationByType ( AccessibleRelationType::MEMBER_OF ); - if ( relationMemberOf.RelationType == AccessibleRelationType::MEMBER_OF && relationMemberOf.TargetSet.hasElements() ) { - for ( int index = 0; index < relationMemberOf.TargetSet.getLength(); index++ ) { - Reference < XAccessible > rMateAccessible = Reference < XAccessible > ( relationMemberOf.TargetSet[index], UNO_QUERY ); - if ( rMateAccessible.is() ) { - Reference< XAccessibleContext > rMateAccessibleContext( rMateAccessible -> getAccessibleContext() ); - if ( rMateAccessibleContext.is() ) { - id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rMateAccessibleContext ]; - [ children addObject: wrapper ]; - [ wrapper release ]; - } - } - } - } - return children; - } else if ( [ self accessibleTable ] != nil ) - { - AquaA11yTableWrapper* pTable = [self isKindOfClass: [AquaA11yTableWrapper class]] ? (AquaA11yTableWrapper*)self : nil; - return [ AquaA11yTableWrapper childrenAttributeForElement: pTable ]; - } else { - try { - NSMutableArray * children = [ [ NSMutableArray alloc ] init ]; - Reference< XAccessibleContext > xContext( [ self accessibleContext ] ); - - sal_Int32 cnt = xContext -> getAccessibleChildCount(); - for ( sal_Int32 i = 0; i < cnt; i++ ) { - Reference< XAccessible > xChild( xContext -> getAccessibleChild( i ) ); - if( xChild.is() ) { - Reference< XAccessibleContext > xChildContext( xChild -> getAccessibleContext() ); - // the menubar is already accessible (including Apple- and Application-Menu) through NSApplication => omit it here - if ( xChildContext.is() && AccessibleRole::MENU_BAR != xChildContext -> getAccessibleRole() ) { - id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: xChildContext ]; - [ children addObject: wrapper ]; - [ wrapper release ]; - } - } - } - - // if not already acting as RadioGroup now is the time to replace RadioButtons with RadioGroups and remove RadioButtons - if ( ! mActsAsRadioGroup ) { - NSEnumerator * enumerator = [ children objectEnumerator ]; - AquaA11yWrapper * element; - while ( ( element = ( (AquaA11yWrapper *) [ enumerator nextObject ] ) ) ) { - if ( [ element accessibleContext ] -> getAccessibleRole() == AccessibleRole::RADIO_BUTTON ) { - if ( [ element isFirstRadioButtonInGroup ] ) { - id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: [ element accessibleContext ] createIfNotExists: YES asRadioGroup: YES ]; - [ children replaceObjectAtIndex: [ children indexOfObjectIdenticalTo: element ] withObject: wrapper ]; - } - [ children removeObject: element ]; - } - } - } - - [ children autorelease ]; - return NSAccessibilityUnignoredChildren( children ); - } catch (const Exception &e) { - // TODO: Log - return nil; - } - } -} - --(id)windowAttribute { - // go upstairs until reaching the broken connection - AquaA11yWrapper * aWrapper = self; - int loops = 0; - while ( [ aWrapper accessibleContext ] -> getAccessibleParent().is() ) { - AquaA11yWrapper *aTentativeParentWrapper = [ AquaA11yFactory wrapperForAccessibleContext: [ aWrapper accessibleContext ] -> getAccessibleParent() -> getAccessibleContext() ]; - // Quick-and-dirty fix for infinite loop after fixing crash in - // fdo#47275 - if ( aTentativeParentWrapper == aWrapper ) - break; - // Even dirtier fix for infinite loop in fdo#55156 - if ( loops++ == 100 ) - break; - aWrapper = aTentativeParentWrapper; - [ aWrapper autorelease ]; - } - // get associated NSWindow - NSView * theView = [ aWrapper viewElementForParent ]; - return theView; -} - --(id)topLevelUIElementAttribute { - return [ self windowAttribute ]; -} - --(id)sizeAttribute { - if ( [ self accessibleComponent ] != nil ) { - return [ AquaA11yComponentWrapper sizeAttributeForElement: self ]; - } else { - return nil; - } -} - --(id)positionAttribute { - if ( [ self accessibleComponent ] != nil ) { - return [ AquaA11yComponentWrapper positionAttributeForElement: self ]; - } else { - return nil; - } -} - --(id)helpAttribute { - return CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() ); -} - --(id)roleDescriptionAttribute { - if ( mActsAsRadioGroup ) { - return [ AquaA11yRoleHelper getRoleDescriptionFrom: NSAccessibilityRadioGroupRole with: @"" ]; - } else if( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::RADIO_BUTTON ) { - // FIXME: VO should read this because of hierarchy, this is just a workaround - // get parent and its children - AquaA11yWrapper * parent = [ self parentAttribute ]; - NSArray * children = [ parent childrenAttribute ]; - // find index of self - int index = 1; - NSEnumerator * enumerator = [ children objectEnumerator ]; - AquaA11yWrapper * child = nil; - while ( ( child = [ enumerator nextObject ] ) ) { - if ( self == child ) { - break; - } - index++; - } - // build string - NSNumber * nIndex = [ NSNumber numberWithInt: index ]; - NSNumber * nGroupsize = [ NSNumber numberWithInt: [ children count ] ]; - NSMutableString * value = [ [ NSMutableString alloc ] init ]; - [ value appendString: @"radio button " ]; - [ value appendString: [ nIndex stringValue ] ]; - [ value appendString: @" of " ]; - [ value appendString: [ nGroupsize stringValue ] ]; - // clean up and return string - [ nIndex release ]; - [ nGroupsize release ]; - [ children release ]; - return value; - } else { - return [ AquaA11yRoleHelper getRoleDescriptionFrom: - [ AquaA11yRoleHelper getNativeRoleFrom: [ self accessibleContext ] ] - with: [ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ] ]; - } -} - --(id)valueAttribute { - if ( [ [ self roleAttribute ] isEqualToString: NSAccessibilityMenuItemRole ] ) { - return nil; - } else if ( [ self accessibleText ] != nil ) { - return [ AquaA11yTextWrapper valueAttributeForElement: self ]; - } else if ( [ self accessibleValue ] != nil ) { - return [ AquaA11yValueWrapper valueAttributeForElement: self ]; - } else { - return nil; - } -} - --(id)minValueAttribute { - if ( [ self accessibleValue ] != nil ) { - return [ AquaA11yValueWrapper minValueAttributeForElement: self ]; - } else { - return nil; - } -} - --(id)maxValueAttribute { - if ( [ self accessibleValue ] != nil ) { - return [ AquaA11yValueWrapper maxValueAttributeForElement: self ]; - } else { - return nil; - } -} - --(id)contentsAttribute { - return [ self childrenAttribute ]; -} - --(id)selectedChildrenAttribute { - return [ AquaA11ySelectionWrapper selectedChildrenAttributeForElement: self ]; -} - --(id)numberOfCharactersAttribute { - if ( [ self accessibleText ] != nil ) { - return [ AquaA11yTextWrapper numberOfCharactersAttributeForElement: self ]; - } else { - return nil; - } -} - --(id)selectedTextAttribute { - if ( [ self accessibleText ] != nil ) { - return [ AquaA11yTextWrapper selectedTextAttributeForElement: self ]; - } else { - return nil; - } -} - --(id)selectedTextRangeAttribute { - if ( [ self accessibleText ] != nil ) { - return [ AquaA11yTextWrapper selectedTextRangeAttributeForElement: self ]; - } else { - return nil; - } -} - --(id)visibleCharacterRangeAttribute { - if ( [ self accessibleText ] != nil ) { - return [ AquaA11yTextWrapper visibleCharacterRangeAttributeForElement: self ]; - } else { - return nil; - } -} - --(id)tabsAttribute { - return self; // TODO ??? -} - --(id)sharedTextUIElementsAttribute { - if ( [ self accessibleText ] != nil ) { - return [ AquaA11yTextWrapper sharedTextUIElementsAttributeForElement: self ]; - } else { - return nil; - } -} - --(id)sharedCharacterRangeAttribute { - if ( [ self accessibleText ] != nil ) { - return [ AquaA11yTextWrapper sharedCharacterRangeAttributeForElement: self ]; - } else { - return nil; - } -} - --(id)expandedAttribute { - return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::EXPANDED ) ]; -} - --(id)selectedAttribute { - return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::SELECTED ) ]; -} - --(id)stringForRangeAttributeForParameter:(id)range { - if ( [ self accessibleText ] != nil ) { - return [ AquaA11yTextWrapper stringForRangeAttributeForElement: self forParameter: range ]; - } else { - return nil; - } -} - --(id)attributedStringForRangeAttributeForParameter:(id)range { - if ( [ self accessibleText ] != nil ) { - return [ AquaA11yTextWrapper attributedStringForRangeAttributeForElement: self forParameter: range ]; - } else { - return nil; - } -} - --(id)rangeForIndexAttributeForParameter:(id)index { - if ( [ self accessibleText ] != nil ) { - return [ AquaA11yTextWrapper rangeForIndexAttributeForElement: self forParameter: index ]; - } else { - return nil; - } -} - --(id)rangeForPositionAttributeForParameter:(id)point { - if ( [ self accessibleText ] != nil ) { - return [ AquaA11yTextWrapper rangeForPositionAttributeForElement: self forParameter: point ]; - } else { - return nil; - } -} - --(id)boundsForRangeAttributeForParameter:(id)range { - if ( [ self accessibleText ] != nil ) { - return [ AquaA11yTextWrapper boundsForRangeAttributeForElement: self forParameter: range ]; - } else { - return nil; - } -} - --(id)styleRangeForIndexAttributeForParameter:(id)index { - if ( [ self accessibleText ] != nil ) { - return [ AquaA11yTextWrapper styleRangeForIndexAttributeForElement: self forParameter: index ]; - } else { - return nil; - } -} - --(id)rTFForRangeAttributeForParameter:(id)range { - if ( [ self accessibleText ] != nil ) { - return [ AquaA11yTextWrapper rTFForRangeAttributeForElement: self forParameter: range ]; - } else { - return nil; - } -} - --(id)orientationAttribute { - NSString * orientation = nil; - Reference < XAccessibleStateSet > stateSet = [ self accessibleContext ] -> getAccessibleStateSet(); - if ( stateSet -> contains ( AccessibleStateType::HORIZONTAL ) ) { - orientation = NSAccessibilityHorizontalOrientationValue; - } else if ( stateSet -> contains ( AccessibleStateType::VERTICAL ) ) { - orientation = NSAccessibilityVerticalOrientationValue; - } - return orientation; -} - --(id)titleUIElementAttribute { - if ( [ self accessibleContext ] -> getAccessibleRelationSet().is() ) { - NSString * title = [ self titleAttribute ]; - id titleElement = nil; - if ( [ title length ] == 0 ) { - AccessibleRelation relationLabeledBy = [ self accessibleContext ] -> getAccessibleRelationSet() -> getRelationByType ( AccessibleRelationType::LABELED_BY ); - if ( relationLabeledBy.RelationType == AccessibleRelationType::LABELED_BY && relationLabeledBy.TargetSet.hasElements() ) { - Reference < XAccessible > rxAccessible ( relationLabeledBy.TargetSet[0], UNO_QUERY ); - titleElement = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessible -> getAccessibleContext() ]; - } - } - if ( title != nil ) { - [ title release ]; - } - return titleElement; - } else { - return nil; - } -} - --(id)servesAsTitleForUIElementsAttribute { - if ( [ self accessibleContext ] -> getAccessibleRelationSet().is() ) { - id titleForElement = nil; - AccessibleRelation relationLabelFor = [ self accessibleContext ] -> getAccessibleRelationSet() -> getRelationByType ( AccessibleRelationType::LABEL_FOR ); - if ( relationLabelFor.RelationType == AccessibleRelationType::LABEL_FOR && relationLabelFor.TargetSet.hasElements() ) { - Reference < XAccessible > rxAccessible ( relationLabelFor.TargetSet[0], UNO_QUERY ); - titleForElement = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessible -> getAccessibleContext() ]; - } - return titleForElement; - } else { - return nil; - } -} - --(id)lineForIndexAttributeForParameter:(id)index { - if ( [ self accessibleMultiLineText ] != nil ) { - return [ AquaA11yTextWrapper lineForIndexAttributeForElement: self forParameter: index ]; - } else { - return nil; - } -} - --(id)rangeForLineAttributeForParameter:(id)line { - if ( [ self accessibleMultiLineText ] != nil ) { - return [ AquaA11yTextWrapper rangeForLineAttributeForElement: self forParameter: line ]; - } else { - return nil; - } -} - -#pragma mark - -#pragma mark Accessibility Protocol - --(id)accessibilityAttributeValue:(NSString *)attribute { - SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeValue:" << attribute << "]"); - // #i90575# guard NSAccessibility protocol against unwanted access - if ( isPopupMenuOpen ) { - return nil; - } - - id value = nil; - // if we are no longer in the wrapper repository, we have been disposed - AquaA11yWrapper * theWrapper = [ AquaA11yFactory wrapperForAccessibleContext: [ self accessibleContext ] createIfNotExists: NO ]; - if ( theWrapper != nil || mIsTableCell ) { - try { - SEL methodSelector = [ self selectorForAttribute: attribute asGetter: YES withGetterParameter: NO ]; - if ( [ self respondsToSelector: methodSelector ] ) { - value = [ self performSelector: methodSelector ]; - } - } catch ( const DisposedException & e ) { - mIsTableCell = NO; // just to be sure - [ AquaA11yFactory removeFromWrapperRepositoryFor: [ self accessibleContext ] ]; - return nil; - } catch ( const Exception & e ) { - // empty - } - } - if ( theWrapper != nil ) { - [ theWrapper release ]; // the above called method calls retain on the returned Wrapper - } - return value; -} - --(BOOL)accessibilityIsIgnored { - SAL_INFO("vcl.a11y", "[" << self << " accessibilityIsIgnored]"); - // #i90575# guard NSAccessibility protocol against unwanted access - if ( isPopupMenuOpen ) { - return NO; - } - BOOL ignored = NO; - sal_Int16 nRole = [ self accessibleContext ] -> getAccessibleRole(); - switch ( nRole ) { - case AccessibleRole::PANEL: - case AccessibleRole::FRAME: - case AccessibleRole::ROOT_PANE: - case AccessibleRole::SEPARATOR: - case AccessibleRole::FILLER: - case AccessibleRole::DIALOG: - ignored = YES; - break; - default: - ignored = ! ( [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::VISIBLE ) ); - break; - } - return ignored; // TODO: to be completed -} - --(NSArray *)accessibilityAttributeNames { - SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeNames]"); - // #i90575# guard NSAccessibility protocol against unwanted access - if ( isPopupMenuOpen ) { - return nil; - } - NSString * nativeSubrole = nil; - NSString * title = nil; - NSMutableArray * attributeNames = nil; - sal_Int32 nAccessibleChildren = 0; - try { - // Default Attributes - attributeNames = [ NSMutableArray arrayWithObjects: - NSAccessibilityRoleAttribute, - NSAccessibilityDescriptionAttribute, - NSAccessibilityParentAttribute, - NSAccessibilityWindowAttribute, - NSAccessibilityHelpAttribute, - NSAccessibilityTopLevelUIElementAttribute, - NSAccessibilityRoleDescriptionAttribute, - nil ]; - nativeSubrole = (NSString *) [ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ]; - title = (NSString *) [ self titleAttribute ]; - Reference < XAccessibleRelationSet > rxRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet(); - // Special Attributes depending on attribute values - if ( nativeSubrole != nil && ! [ nativeSubrole isEqualToString: @"" ] ) { - [ attributeNames addObject: NSAccessibilitySubroleAttribute ]; - } - try - { - nAccessibleChildren = [ self accessibleContext ] -> getAccessibleChildCount(); - if ( nAccessibleChildren > 0 ) { - [ attributeNames addObject: NSAccessibilityChildrenAttribute ]; - } - } - catch( DisposedException& ) {} - catch( RuntimeException& ) {} - - if ( title != nil && ! [ title isEqualToString: @"" ] ) { - [ attributeNames addObject: NSAccessibilityTitleAttribute ]; - } - if ( [ title length ] == 0 && rxRelationSet.is() && rxRelationSet -> containsRelation ( AccessibleRelationType::LABELED_BY ) ) { - [ attributeNames addObject: NSAccessibilityTitleUIElementAttribute ]; - } - if ( rxRelationSet.is() && rxRelationSet -> containsRelation ( AccessibleRelationType::LABEL_FOR ) ) { - [ attributeNames addObject: NSAccessibilityServesAsTitleForUIElementsAttribute ]; - } - // Special Attributes depending on interface - if( [self accessibleContext ] -> getAccessibleRole() == AccessibleRole::TABLE ) - [AquaA11yTableWrapper addAttributeNamesTo: attributeNames object: self]; - - if ( [ self accessibleText ] != nil ) { - [ AquaA11yTextWrapper addAttributeNamesTo: attributeNames ]; - } - if ( [ self accessibleComponent ] != nil ) { - [ AquaA11yComponentWrapper addAttributeNamesTo: attributeNames ]; - } - if ( [ self accessibleSelection ] != nil ) { - [ AquaA11ySelectionWrapper addAttributeNamesTo: attributeNames ]; - } - if ( [ self accessibleValue ] != nil ) { - [ AquaA11yValueWrapper addAttributeNamesTo: attributeNames ]; - } - [ nativeSubrole release ]; - [ title release ]; - return attributeNames; - } catch ( DisposedException & e ) { // Object is no longer available - if ( nativeSubrole != nil ) { - [ nativeSubrole release ]; - } - if ( title != nil ) { - [ title release ]; - } - if ( attributeNames != nil ) { - [ attributeNames release ]; - } - [ AquaA11yFactory removeFromWrapperRepositoryFor: [ self accessibleContext ] ]; - return [ [ NSArray alloc ] init ]; - } -} - --(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { - SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeIsSettable:" << attribute << "]"); - BOOL isSettable = NO; - if ( [ self accessibleText ] != nil ) { - isSettable = [ AquaA11yTextWrapper isAttributeSettable: attribute forElement: self ]; - } - if ( ! isSettable && [ self accessibleComponent ] != nil ) { - isSettable = [ AquaA11yComponentWrapper isAttributeSettable: attribute forElement: self ]; - } - if ( ! isSettable && [ self accessibleSelection ] != nil ) { - isSettable = [ AquaA11ySelectionWrapper isAttributeSettable: attribute forElement: self ]; - } - if ( ! isSettable && [ self accessibleValue ] != nil ) { - isSettable = [ AquaA11yValueWrapper isAttributeSettable: attribute forElement: self ]; - } - return isSettable; // TODO: to be completed -} - --(NSArray *)accessibilityParameterizedAttributeNames { - SAL_INFO("vcl.a11y", "[" << self << " accessibilityParameterizedAttributeNames]"); - NSMutableArray * attributeNames = [ [ NSMutableArray alloc ] init ]; - // Special Attributes depending on interface - if ( [ self accessibleText ] != nil ) { - [ AquaA11yTextWrapper addParameterizedAttributeNamesTo: attributeNames ]; - } - return attributeNames; // TODO: to be completed -} - --(id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter { - SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeValue:" << attribute << " forParameter:" << ((NSObject*)parameter) << "]"); - SEL methodSelector = [ self selectorForAttribute: attribute asGetter: YES withGetterParameter: YES ]; - if ( [ self respondsToSelector: methodSelector ] ) { - return [ self performSelector: methodSelector withObject: parameter ]; - } - return nil; // TODO: to be completed -} - --(BOOL)accessibilitySetOverrideValue:(id)value forAttribute:(NSString *)attribute -{ - SAL_INFO("vcl.a11y", "[" << self << " accessibilitySetOverrideValue:" << ((NSObject*)value) << " forAttribute:" << attribute << "]"); - (void)value; - (void)attribute; - return NO; // TODO -} - --(void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute { - SAL_INFO("vcl.a11y", "[" << self << " accessibilitySetValue:" << ((NSObject*)value) << " forAttribute:" << attribute << "]"); - SEL methodSelector = [ self selectorForAttribute: attribute asGetter: NO withGetterParameter: NO ]; - if ( [ AquaA11yComponentWrapper respondsToSelector: methodSelector ] ) { - [ AquaA11yComponentWrapper performSelector: methodSelector withObject: self withObject: value ]; - } - if ( [ AquaA11yTextWrapper respondsToSelector: methodSelector ] ) { - [ AquaA11yTextWrapper performSelector: methodSelector withObject: self withObject: value ]; - } - if ( [ AquaA11ySelectionWrapper respondsToSelector: methodSelector ] ) { - [ AquaA11ySelectionWrapper performSelector: methodSelector withObject: self withObject: value ]; - } - if ( [ AquaA11yValueWrapper respondsToSelector: methodSelector ] ) { - [ AquaA11yValueWrapper performSelector: methodSelector withObject: self withObject: value ]; - } -} - --(id)accessibilityFocusedUIElement { - SAL_INFO("vcl.a11y", "[" << self << " accessibilityFocusedUIElement]"); - // #i90575# guard NSAccessibility protocol against unwanted access - if ( isPopupMenuOpen ) { - return nil; - } - - // as this seems to be the first API call on a newly created SalFrameView object, - // make sure self gets registered in the repository .. - [ self accessibleContext ]; - - AquaA11yWrapper * focusedUIElement = AquaA11yFocusListener::get()->getFocusedUIElement(); -// AquaA11yWrapper * ancestor = focusedUIElement; - - // Make sure the focused object is a descendant of self -// do { -// if( self == ancestor ) - return focusedUIElement; - -// ancestor = [ ancestor accessibilityAttributeValue: NSAccessibilityParentAttribute ]; -// } while( nil != ancestor ); - - return self; -} - --(NSString *)accessibilityActionDescription:(NSString *)action { - SAL_INFO("vcl.a11y", "[" << self << " accessibilityActionDescription:" << action << "]"); - return NSAccessibilityActionDescription(action); -} - --(AquaA11yWrapper *)actionResponder { - AquaA11yWrapper * wrapper = nil; - // get some information - NSString * role = (NSString *) [ self accessibilityAttributeValue: NSAccessibilityRoleAttribute ]; - id enabledAttr = [ self enabledAttribute ]; - BOOL enabled = [ enabledAttr boolValue ]; - NSView * parent = (NSView *) [ self accessibilityAttributeValue: NSAccessibilityParentAttribute ]; - AquaA11yWrapper * parentAsWrapper = nil; - if ( [ parent isKindOfClass: [ AquaA11yWrapper class ] ] ) { - parentAsWrapper = (AquaA11yWrapper *) parent; - } - NSString * parentRole = (NSString *) [ parent accessibilityAttributeValue: NSAccessibilityRoleAttribute ]; - // if we are a textarea inside a combobox, then the combobox is the action responder - if ( enabled - && [ role isEqualToString: NSAccessibilityTextAreaRole ] - && [ parentRole isEqualToString: NSAccessibilityComboBoxRole ] - && parentAsWrapper != nil ) { - wrapper = parentAsWrapper; - } else if ( enabled && [ self accessibleAction ] != nil ) { - wrapper = self ; - } - [ parentRole release ]; - [ enabledAttr release ]; - [ role release ]; - return wrapper; -} - --(void)accessibilityPerformAction:(NSString *)action { - SAL_INFO("vcl.a11y", "[" << self << " accessibilityPerformAction:" << action << "]"); - AquaA11yWrapper * actionResponder = [ self actionResponder ]; - if ( actionResponder != nil ) { - [ AquaA11yActionWrapper doAction: action ofElement: actionResponder ]; - } -} - --(NSArray *)accessibilityActionNames { - SAL_INFO("vcl.a11y", "[" << self << " accessibilityActionNames]"); - NSArray * actionNames = nil; - AquaA11yWrapper * actionResponder = [ self actionResponder ]; - if ( actionResponder != nil ) { - actionNames = [ AquaA11yActionWrapper actionNamesForElement: actionResponder ]; - } else { - actionNames = [ [ NSArray alloc ] init ]; - } - return actionNames; -} - -#pragma mark - -#pragma mark Hit Test - --(BOOL)isViewElement:(NSObject *)viewElement hitByPoint:(NSPoint)point { - BOOL hit = NO; - NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; - NSValue * position = [ viewElement accessibilityAttributeValue: NSAccessibilityPositionAttribute ]; - NSValue * size = [ viewElement accessibilityAttributeValue: NSAccessibilitySizeAttribute ]; - if ( position != nil && size != nil ) { - float minX = [ position pointValue ].x; - float minY = [ position pointValue ].y; - float maxX = minX + [ size sizeValue ].width; - float maxY = minY + [ size sizeValue ].height; - if ( minX < point.x && maxX > point.x && minY < point.y && maxY > point.y ) { - hit = YES; - } - } - [ pool release ]; - return hit; -} - -Reference < XAccessibleContext > hitTestRunner ( com::sun::star::awt::Point point, - Reference < XAccessibleContext > rxAccessibleContext ) { - Reference < XAccessibleContext > hitChild; - Reference < XAccessibleContext > emptyReference; - try { - Reference < XAccessibleComponent > rxAccessibleComponent ( rxAccessibleContext, UNO_QUERY ); - if ( rxAccessibleComponent.is() ) { - com::sun::star::awt::Point location = rxAccessibleComponent -> getLocationOnScreen(); - com::sun::star::awt::Point hitPoint ( point.X - location.X , point.Y - location.Y); - Reference < XAccessible > rxAccessible = rxAccessibleComponent -> getAccessibleAtPoint ( hitPoint ); - if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() && - rxAccessible -> getAccessibleContext() -> getAccessibleChildCount() == 0 ) { - hitChild = rxAccessible -> getAccessibleContext(); - } - } - - // iterate the hirerachy looking doing recursive hit testing. - // apparently necessary as a special treatment for e.g. comboboxes - if ( !hitChild.is() ) { - bool bSafeToIterate = true; - sal_Int32 nCount = rxAccessibleContext -> getAccessibleChildCount(); - - if ( nCount < 0 || nCount > SAL_MAX_UINT16 /* slow enough for anyone */ ) - bSafeToIterate = false; - else { // manages descendants is an horror from the a11y standards guys. - Reference< XAccessibleStateSet > xStateSet; - xStateSet = rxAccessibleContext -> getAccessibleStateSet(); - if (xStateSet.is() && xStateSet -> contains(AccessibleStateType::MANAGES_DESCENDANTS ) ) - bSafeToIterate = false; - } - - if( bSafeToIterate ) { - for ( int i = 0; i < rxAccessibleContext -> getAccessibleChildCount(); i++ ) { - Reference < XAccessible > rxAccessibleChild = rxAccessibleContext -> getAccessibleChild ( i ); - if ( rxAccessibleChild.is() && rxAccessibleChild -> getAccessibleContext().is() && rxAccessibleChild -> getAccessibleContext() -> getAccessibleRole() != AccessibleRole::LIST ) { - Reference < XAccessibleContext > myHitChild = hitTestRunner ( point, rxAccessibleChild -> getAccessibleContext() ); - if ( myHitChild.is() ) { - hitChild = myHitChild; - break; - } - } - } - } - } - } catch ( RuntimeException ) { - return emptyReference; - } - return hitChild; -} - --(id)accessibilityHitTest:(NSPoint)point { - SAL_INFO("vcl.a11y", "[" << self << " accessibilityHitTest:" << point << "]"); - static id wrapper = nil; - if ( nil != wrapper ) { - [ wrapper release ]; - wrapper = nil; - } - Reference < XAccessibleContext > hitChild; - NSRect screenRect = [ [ NSScreen mainScreen ] frame ]; - com::sun::star::awt::Point hitPoint ( static_cast(point.x) , static_cast(screenRect.size.height - point.y) ); - // check child windows first - NSWindow * window = (NSWindow *) [ self accessibilityAttributeValue: NSAccessibilityWindowAttribute ]; - NSArray * childWindows = [ window childWindows ]; - if ( [ childWindows count ] > 0 ) { - NSWindow * element = nil; - NSEnumerator * enumerator = [ childWindows objectEnumerator ]; - while ( ( element = [ enumerator nextObject ] ) && hitChild == nil ) { - if ( [ element isKindOfClass: [ SalFrameWindow class ] ] && [ self isViewElement: element hitByPoint: point ] ) { - // we have a child window that is hit - Reference < XAccessibleRelationSet > relationSet = [ ( ( SalFrameWindow * ) element ) accessibleContext ] -> getAccessibleRelationSet(); - if ( relationSet.is() && relationSet -> containsRelation ( AccessibleRelationType::SUB_WINDOW_OF )) { - // we have a valid relation to the parent element - AccessibleRelation relation = relationSet -> getRelationByType ( AccessibleRelationType::SUB_WINDOW_OF ); - for ( int i = 0; i < relation.TargetSet.getLength() && !hitChild.is(); i++ ) { - Reference < XAccessible > rxAccessible ( relation.TargetSet [ i ], UNO_QUERY ); - if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() ) { - // hit test for children of parent - hitChild = hitTestRunner ( hitPoint, rxAccessible -> getAccessibleContext() ); - } - } - } - } - } - } - // nothing hit yet, so check ourself - if ( ! hitChild.is() ) { - if ( mpReferenceWrapper == nil ) { - [ self setDefaults: [ self accessibleContext ] ]; - } - hitChild = hitTestRunner ( hitPoint, mpReferenceWrapper -> rAccessibleContext ); - } - if ( hitChild.is() ) { - wrapper = [ AquaA11yFactory wrapperForAccessibleContext: hitChild ]; - } - if ( wrapper != nil ) { - [ wrapper retain ]; // TODO: retain only when transient ? - } - return wrapper; -} - -#pragma mark - -#pragma mark Access Methods - --(XAccessibleAction *)accessibleAction { - return mpReferenceWrapper -> rAccessibleAction.get(); -} - --(XAccessibleContext *)accessibleContext { - return mpReferenceWrapper -> rAccessibleContext.get(); -} - --(XAccessibleComponent *)accessibleComponent { - return mpReferenceWrapper -> rAccessibleComponent.get(); -} - --(XAccessibleExtendedComponent *)accessibleExtendedComponent { - return mpReferenceWrapper -> rAccessibleExtendedComponent.get(); -} - --(XAccessibleSelection *)accessibleSelection { - return mpReferenceWrapper -> rAccessibleSelection.get(); -} - --(XAccessibleTable *)accessibleTable { - return mpReferenceWrapper -> rAccessibleTable.get(); -} - --(XAccessibleText *)accessibleText { - return mpReferenceWrapper -> rAccessibleText.get(); -} - --(XAccessibleEditableText *)accessibleEditableText { - return mpReferenceWrapper -> rAccessibleEditableText.get(); -} - --(XAccessibleValue *)accessibleValue { - return mpReferenceWrapper -> rAccessibleValue.get(); -} - --(XAccessibleTextAttributes *)accessibleTextAttributes { - return mpReferenceWrapper -> rAccessibleTextAttributes.get(); -} - --(XAccessibleMultiLineText *)accessibleMultiLineText { - return mpReferenceWrapper -> rAccessibleMultiLineText.get(); -} - --(XAccessibleTextMarkup *)accessibleTextMarkup { - return mpReferenceWrapper -> rAccessibleTextMarkup.get(); -} - --(NSView *)viewElementForParent { - return self; -} - -// These four are for AXTextAreas only. They are needed, because bold and italic -// attributes have to be bound to a font on the Mac. Our UNO-API instead handles -// and reports them independently. When they occur we bundle them to a font with -// this information here to create a according NSFont. --(void)setActsAsRadioGroup:(BOOL)actsAsRadioGroup { - mActsAsRadioGroup = actsAsRadioGroup; -} - --(BOOL)actsAsRadioGroup { - return mActsAsRadioGroup; -} - -+(void)setPopupMenuOpen:(BOOL)popupMenuOpen { - isPopupMenuOpen = popupMenuOpen; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapperbutton.h b/vcl/aqua/source/a11y/aqua11ywrapperbutton.h deleted file mode 100644 index ecb747f05016..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapperbutton.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERBUTTON_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERBUTTON_H - -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yWrapperButton : AquaA11yWrapper -{ -} --(id)valueAttribute; --(id)descriptionAttribute; --(NSArray *)accessibilityAttributeNames; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERBUTTON_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapperbutton.mm b/vcl/aqua/source/a11y/aqua11ywrapperbutton.mm deleted file mode 100644 index f1e832261156..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapperbutton.mm +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" - -#include "aqua11ywrapperbutton.h" -#include "aqua11ytextwrapper.h" - -// Wrapper for AXButton role - -@implementation AquaA11yWrapperButton : AquaA11yWrapper - --(id)valueAttribute { - return [ NSString string ]; // we propagate AXTitle, that's enough -} - --(id)descriptionAttribute { - return [ NSString string ]; // we propagate AXTitle, that's enough -} - --(NSArray *)accessibilityAttributeNames { - // Default Attributes - NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; - // Special Attributes and removing unwanted attributes depending on role - if ( [ attributeNames containsObject: NSAccessibilityTitleAttribute ] ) { - [ attributeNames removeObject: NSAccessibilityDescriptionAttribute ]; - } else { - [ attributeNames addObject: NSAccessibilityTitleAttribute ]; - } - // Remove text-specific attributes - [ attributeNames removeObjectsInArray: [ AquaA11yTextWrapper specialAttributeNames ] ]; - return attributeNames; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrappercheckbox.h b/vcl/aqua/source/a11y/aqua11ywrappercheckbox.h deleted file mode 100644 index d5d4a89f4687..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrappercheckbox.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERCHECKBOX_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERCHECKBOX_H - -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yWrapperCheckBox : AquaA11yWrapper -{ -} --(id)valueAttribute; --(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute; --(NSArray *)accessibilityAttributeNames; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERCHECKBOX_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrappercheckbox.mm b/vcl/aqua/source/a11y/aqua11ywrappercheckbox.mm deleted file mode 100644 index 288dfe9cd4c5..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrappercheckbox.mm +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" - -#include "aqua11ywrappercheckbox.h" -#include "aqua11yvaluewrapper.h" -#include "aqua11ytextwrapper.h" - -// Wrapper for AXCheckbox role - -@implementation AquaA11yWrapperCheckBox : AquaA11yWrapper - --(id)valueAttribute { - if ( [ self accessibleValue ] != nil ) { - return [ AquaA11yValueWrapper valueAttributeForElement: self ]; - } - return [ NSNumber numberWithInt: 0 ]; -} - --(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { - if ( [ attribute isEqualToString: NSAccessibilityValueAttribute ] ) { - return NO; - } - return [ super accessibilityIsAttributeSettable: attribute ]; -} - --(NSArray *)accessibilityAttributeNames { - // Default Attributes - NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; - // Remove text-specific attributes - [ attributeNames removeObjectsInArray: [ AquaA11yTextWrapper specialAttributeNames ] ]; - [ attributeNames addObject: NSAccessibilityValueAttribute ]; - [ attributeNames addObject: NSAccessibilityMinValueAttribute ]; - [ attributeNames addObject: NSAccessibilityMaxValueAttribute ]; - return attributeNames; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrappercombobox.h b/vcl/aqua/source/a11y/aqua11ywrappercombobox.h deleted file mode 100644 index 6c8c1fef190b..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrappercombobox.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERCOMBOBOX_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERCOMBOBOX_H - -#include "aqua/aqua11ywrapper.h" -#include - -@interface AquaA11yWrapperComboBox : AquaA11yWrapper -{ - AquaA11yWrapper * textArea; -} --(id)initWithAccessibleContext: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) anAccessibleContext; --(id)valueAttribute; --(id)numberOfCharactersAttribute; --(id)selectedTextAttribute; --(id)selectedTextRangeAttribute; --(id)visibleCharacterRangeAttribute; -// Accessibility Protocol --(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute; --(void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute; --(NSArray *)accessibilityAttributeNames; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERCOMBOBOX_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrappercombobox.mm b/vcl/aqua/source/a11y/aqua11ywrappercombobox.mm deleted file mode 100644 index 554a9464f7b1..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrappercombobox.mm +++ /dev/null @@ -1,155 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" - -#include "aqua11ywrappercombobox.h" -#include "aqua11yrolehelper.h" - -#include - -using namespace ::com::sun::star::accessibility; -using namespace ::com::sun::star::uno; - -// Wrapper for AXCombobox role - -@implementation AquaA11yWrapperComboBox : AquaA11yWrapper - -#pragma mark - -#pragma mark Specialized Init Method - --(id)initWithAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext { - self = [ super initWithAccessibleContext: rxAccessibleContext ]; - if ( self != nil ) - { - textArea = nil; - } - return self; -} - -#pragma mark - -#pragma mark Private Helper Method - --(AquaA11yWrapper *)textArea { - // FIXME: May cause problems when stored. Then get dynamically each time (bad performance!) - if ( textArea == nil ) { - NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; - NSArray * elementChildren = [ super childrenAttribute ]; - if ( [ elementChildren count ] > 0 ) { - NSEnumerator * enumerator = [ elementChildren objectEnumerator ]; - id child; - while ( ( child = [ enumerator nextObject ] ) ) { - AquaA11yWrapper * element = ( AquaA11yWrapper * ) child; - if ( [ [ AquaA11yRoleHelper getNativeRoleFrom: [ element accessibleContext ] ] isEqualToString: NSAccessibilityTextAreaRole ] ) { - textArea = element; - break; - } - } - } - [ pool release ]; - } - return textArea; -} - -#pragma mark - -#pragma mark Wrapped Attributes From Contained Text Area - --(id)valueAttribute { - if ( [ self textArea ] != nil ) { - return [ [ self textArea ] valueAttribute ]; - } - return @""; -} - --(id)numberOfCharactersAttribute { - if ( [ self textArea ] != nil ) { - return [ [ self textArea ] numberOfCharactersAttribute ]; - } - return [ NSNumber numberWithInt: 0 ]; -} - --(id)selectedTextAttribute { - if ( [ self textArea ] != nil ) { - return [ [ self textArea ] selectedTextAttribute ]; - } - return @""; -} - --(id)selectedTextRangeAttribute { - if ( [ self textArea ] != nil ) { - return [ [ self textArea ] selectedTextRangeAttribute ]; - } - return [ NSValue valueWithRange: NSMakeRange ( 0, 0 ) ]; -} - --(id)visibleCharacterRangeAttribute { - if ( [ self textArea ] != nil ) { - return [ [ self textArea ] visibleCharacterRangeAttribute ]; - } - return [ NSValue valueWithRange: NSMakeRange ( 0, 0 ) ]; -} - -#pragma mark - -#pragma mark Accessibility Protocol - --(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { - if ( [ self textArea ] != nil && ( - [ attribute isEqualToString: NSAccessibilitySelectedTextAttribute ] - || [ attribute isEqualToString: NSAccessibilitySelectedTextRangeAttribute ] - || [ attribute isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute ] ) ) { - return [ [ self textArea ] accessibilityIsAttributeSettable: attribute ]; - } - return [ super accessibilityIsAttributeSettable: attribute ]; -} - --(void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute { - if ( [ self textArea ] != nil && ( - [ attribute isEqualToString: NSAccessibilitySelectedTextAttribute ] - || [ attribute isEqualToString: NSAccessibilitySelectedTextRangeAttribute ] - || [ attribute isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute ] ) ) { - return [ [ self textArea ] accessibilitySetValue: value forAttribute: attribute ]; - } - return [ super accessibilitySetValue: value forAttribute: attribute ]; -} - --(NSArray *)accessibilityAttributeNames { - // Default Attributes - NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; - // Special Attributes and removing unwanted attributes depending on role - [ attributeNames removeObjectsInArray: [ NSArray arrayWithObjects: - NSAccessibilityTitleAttribute, - NSAccessibilityChildrenAttribute, - nil ] - ]; - [ attributeNames addObjectsFromArray: [ NSArray arrayWithObjects: - NSAccessibilityExpandedAttribute, - NSAccessibilityValueAttribute, - NSAccessibilityNumberOfCharactersAttribute, - NSAccessibilitySelectedTextAttribute, - NSAccessibilitySelectedTextRangeAttribute, - NSAccessibilityVisibleCharacterRangeAttribute, - nil ] - ]; - return attributeNames; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrappergroup.h b/vcl/aqua/source/a11y/aqua11ywrappergroup.h deleted file mode 100644 index d018927950c7..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrappergroup.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERGROUP_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERGROUP_H - -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yWrapperGroup : AquaA11yWrapper -{ -} --(id)titleUIElementAttribute; --(NSArray *)accessibilityAttributeNames; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERGROUP_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrappergroup.mm b/vcl/aqua/source/a11y/aqua11ywrappergroup.mm deleted file mode 100644 index 4ca15d8aacc7..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrappergroup.mm +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" -#include "aqua11ywrappergroup.h" - -// Wrapper for AXGroup role - -@implementation AquaA11yWrapperGroup : AquaA11yWrapper - --(id)titleUIElementAttribute { - return self; // TODO -} - --(NSArray *)accessibilityAttributeNames { - // Default Attributes - NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; - // Special Attributes and removing unwanted attributes depending on role - [ attributeNames removeObjectsInArray: [ NSArray arrayWithObjects: - NSAccessibilityTitleAttribute, - NSAccessibilityEnabledAttribute, - NSAccessibilitySelectedChildrenAttribute, - nil ] - ]; - [ attributeNames addObject: NSAccessibilityContentsAttribute ]; - [ attributeNames addObject: NSAccessibilityTitleUIElementAttribute ]; - return attributeNames; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapperlist.h b/vcl/aqua/source/a11y/aqua11ywrapperlist.h deleted file mode 100644 index 14fc22b4afc3..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapperlist.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERLIST_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERLIST_H - -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yWrapperList : AquaA11yWrapper -{ -} --(NSArray *)accessibilityAttributeNames; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERLIST_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapperlist.mm b/vcl/aqua/source/a11y/aqua11ywrapperlist.mm deleted file mode 100644 index e75aac496bf1..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapperlist.mm +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" -#include "aqua11ywrapperlist.h" - -using namespace ::com::sun::star::accessibility; - -// Wrapper for AXList role - -@implementation AquaA11yWrapperList : AquaA11yWrapper - --(NSArray *)accessibilityAttributeNames { - // Default Attributes - NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; - // Special Attributes and removing unwanted attributes depending on role - [ attributeNames addObject: NSAccessibilityOrientationAttribute ]; - return attributeNames; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapperradiobutton.h b/vcl/aqua/source/a11y/aqua11ywrapperradiobutton.h deleted file mode 100644 index 9b31303dfb21..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapperradiobutton.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERRADIOBUTTON_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERRADIOBUTTON_H - -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yWrapperRadioButton : AquaA11yWrapper -{ -} --(id)valueAttribute; --(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute; --(NSArray *)accessibilityAttributeNames; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERRADIOBUTTON_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapperradiobutton.mm b/vcl/aqua/source/a11y/aqua11ywrapperradiobutton.mm deleted file mode 100644 index b4f08f103565..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapperradiobutton.mm +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" -#include "aqua11ywrapperradiobutton.h" -#include "aqua11ytextwrapper.h" -#include "aqua11yvaluewrapper.h" - -// Wrapper for AXRadioButton role - -@implementation AquaA11yWrapperRadioButton : AquaA11yWrapper - --(id)valueAttribute { - if ( [ self accessibleValue ] != nil ) { - return [ AquaA11yValueWrapper valueAttributeForElement: self ]; - } - return [ NSNumber numberWithInt: 0 ]; -} - --(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { - if ( [ attribute isEqualToString: NSAccessibilityValueAttribute ] ) { - return NO; - } - return [ super accessibilityIsAttributeSettable: attribute ]; -} - --(NSArray *)accessibilityAttributeNames { - // Default Attributes - NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; - // Special Attributes and removing unwanted attributes depending on role - [ attributeNames removeObjectsInArray: [ AquaA11yTextWrapper specialAttributeNames ] ]; - [ attributeNames addObject: NSAccessibilityMinValueAttribute ]; - [ attributeNames addObject: NSAccessibilityMaxValueAttribute ]; - [ attributeNames addObject: NSAccessibilityValueAttribute ]; - return attributeNames; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapperradiogroup.h b/vcl/aqua/source/a11y/aqua11ywrapperradiogroup.h deleted file mode 100644 index d02193d05570..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapperradiogroup.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERRADIOGROUP_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERRADIOGROUP_H - -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yWrapperRadioGroup : AquaA11yWrapper -{ -} --(NSArray *)accessibilityAttributeNames; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERRADIOGROUP_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapperradiogroup.mm b/vcl/aqua/source/a11y/aqua11ywrapperradiogroup.mm deleted file mode 100644 index b8c7ddbd2909..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapperradiogroup.mm +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" -#include "aqua11ywrapperradiogroup.h" -#include "aqua11ytextwrapper.h" - -// Wrapper for AXRadioGroup role - -@implementation AquaA11yWrapperRadioGroup : AquaA11yWrapper - --(NSArray *)accessibilityAttributeNames { - // Default Attributes - NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; - // Special Attributes and removing unwanted attributes depending on role - [ attributeNames removeObjectsInArray: [ AquaA11yTextWrapper specialAttributeNames ] ]; - [ attributeNames removeObject: NSAccessibilityTitleAttribute ]; - return attributeNames; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapperrow.h b/vcl/aqua/source/a11y/aqua11ywrapperrow.h deleted file mode 100644 index fa7b64d12a5e..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapperrow.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERROW_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERROW_H - -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yWrapperRow : AquaA11yWrapper -{ -} --(id)disclosingAttribute; --(NSArray *)accessibilityAttributeNames; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERROW_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapperrow.mm b/vcl/aqua/source/a11y/aqua11ywrapperrow.mm deleted file mode 100644 index d62b3edb1ddb..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapperrow.mm +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" - -#include "aqua11ywrapperrow.h" -#include "aqua11ytextwrapper.h" - -// Wrapper for AXRow role - -@implementation AquaA11yWrapperRow : AquaA11yWrapper - --(id)disclosingAttribute { - return NULL; // TODO -} - --(NSArray *)accessibilityAttributeNames { - // Default Attributes - NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; - // Special Attributes and removing unwanted attributes depending on role - [ attributeNames removeObjectsInArray: [ AquaA11yTextWrapper specialAttributeNames ] ]; - [ attributeNames removeObject: NSAccessibilityTitleAttribute ]; - [ attributeNames removeObject: NSAccessibilityEnabledAttribute ]; - [ attributeNames removeObject: NSAccessibilityFocusedAttribute ]; - [ attributeNames addObject: NSAccessibilitySelectedAttribute ]; - [ attributeNames addObject: NSAccessibilityDisclosingAttribute ]; - return attributeNames; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapperscrollarea.h b/vcl/aqua/source/a11y/aqua11ywrapperscrollarea.h deleted file mode 100644 index e58acb207c67..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapperscrollarea.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERSCROLLAREA_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERSCROLLAREA_H - -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yWrapperScrollArea : AquaA11yWrapper -{ -} --(id)verticalScrollBarAttribute; --(id)horizontalScrollBarAttribute; --(NSArray *)accessibilityAttributeNames; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERSCROLLAREA_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapperscrollarea.mm b/vcl/aqua/source/a11y/aqua11ywrapperscrollarea.mm deleted file mode 100644 index e447ce6f9f44..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapperscrollarea.mm +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" - -#include "aqua11ywrapperscrollarea.h" -#include "aqua11ywrapperscrollbar.h" -#include "aqua11yrolehelper.h" - -// Wrapper for AXScrollArea role - -@implementation AquaA11yWrapperScrollArea : AquaA11yWrapper - --(id)scrollBarWithOrientation:(NSString *)orientation { - AquaA11yWrapper * theScrollBar = nil; - NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; - NSArray * elementChildren = [ self accessibilityAttributeValue: NSAccessibilityChildrenAttribute ]; - if ( [ elementChildren count ] > 0 ) { - NSEnumerator * enumerator = [ elementChildren objectEnumerator ]; - id child; - while ( ( child = [ enumerator nextObject ] ) ) { - AquaA11yWrapper * element = ( AquaA11yWrapper * ) child; - if ( [ element isKindOfClass: [ AquaA11yWrapperScrollBar class ] ] ) { - AquaA11yWrapperScrollBar * scrollBar = (AquaA11yWrapperScrollBar *) element; - if ( [ [ scrollBar orientationAttribute ] isEqualToString: orientation ] ) { - theScrollBar = scrollBar; - break; - } - } - } - } - [ pool release ]; - return theScrollBar; -} - --(id)verticalScrollBarAttribute { - return [ self scrollBarWithOrientation: NSAccessibilityVerticalOrientationValue ]; -} - --(id)horizontalScrollBarAttribute { - return [ self scrollBarWithOrientation: NSAccessibilityHorizontalOrientationValue ]; -} - --(NSArray *)accessibilityAttributeNames { - // Default Attributes - NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; - // Special Attributes and removing unwanted attributes depending on role - [ attributeNames removeObject: NSAccessibilityEnabledAttribute ]; - [ attributeNames addObjectsFromArray: [ NSArray arrayWithObjects: - NSAccessibilityContentsAttribute, - NSAccessibilityVerticalScrollBarAttribute, - NSAccessibilityHorizontalScrollBarAttribute, - nil ] - ]; - return attributeNames; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapperscrollbar.h b/vcl/aqua/source/a11y/aqua11ywrapperscrollbar.h deleted file mode 100644 index c2ca6d93b81e..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapperscrollbar.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERSCROLLBAR_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERSCROLLBAR_H - -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yWrapperScrollBar : AquaA11yWrapper -{ -} --(NSArray *)accessibilityAttributeNames; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERSCROLLBAR_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapperscrollbar.mm b/vcl/aqua/source/a11y/aqua11ywrapperscrollbar.mm deleted file mode 100644 index 7fdaf413a106..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapperscrollbar.mm +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" - -#include "aqua11ywrapperscrollbar.h" - -#include - -using namespace ::com::sun::star::accessibility; - -// Wrapper for AXScrollBar role - -@implementation AquaA11yWrapperScrollBar : AquaA11yWrapper - --(NSArray *)accessibilityAttributeNames { - // Default Attributes - NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; - // Special Attributes and removing unwanted attributes depending on role - [ attributeNames addObject: NSAccessibilityOrientationAttribute ]; - return attributeNames; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrappersplitter.h b/vcl/aqua/source/a11y/aqua11ywrappersplitter.h deleted file mode 100644 index 27eaa9b47272..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrappersplitter.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERSPLITTER_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERSPLITTER_H - -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yWrapperSplitter : AquaA11yWrapper -{ -} --(NSArray *)accessibilityAttributeNames; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERSPLITTER_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrappersplitter.mm b/vcl/aqua/source/a11y/aqua11ywrappersplitter.mm deleted file mode 100644 index ab2095ba0af9..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrappersplitter.mm +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" -#include "aqua11ywrappersplitter.h" - -using namespace ::com::sun::star::accessibility; - -// Wrapper for AXSplitter role - -@implementation AquaA11yWrapperSplitter : AquaA11yWrapper - --(NSArray *)accessibilityAttributeNames { - // Default Attributes - NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; - // Special Attributes and removing unwanted attributes depending on role - [ attributeNames addObject: NSAccessibilityOrientationAttribute ]; - return attributeNames; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapperstatictext.h b/vcl/aqua/source/a11y/aqua11ywrapperstatictext.h deleted file mode 100644 index 627d6e37b2a2..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapperstatictext.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERSTATICTEXT_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERSTATICTEXT_H - -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yWrapperStaticText : AquaA11yWrapper -{ -} --(id)titleAttribute; --(NSArray *)accessibilityAttributeNames; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERSTATICTEXT_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrapperstatictext.mm b/vcl/aqua/source/a11y/aqua11ywrapperstatictext.mm deleted file mode 100644 index aa871a869802..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrapperstatictext.mm +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" -#include "aqua11ywrapperstatictext.h" - -// Wrapper for AXStaticText role - -@implementation AquaA11yWrapperStaticText : AquaA11yWrapper - --(id)titleAttribute { - NSString * title = [ super titleAttribute ]; - if ( [ title isEqualToString: [ super valueAttribute ] ] ) { - return [ NSString string ]; - } - return title; -} - --(NSArray *)accessibilityAttributeNames { - // Default Attributes - NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; - // Special Attributes and removing unwanted attributes depending on role - [ attributeNames removeObject: NSAccessibilityTitleAttribute ]; - [ attributeNames removeObject: NSAccessibilitySharedTextUIElementsAttribute ]; - [ attributeNames removeObject: NSAccessibilitySharedCharacterRangeAttribute ]; - return attributeNames; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrappertabgroup.h b/vcl/aqua/source/a11y/aqua11ywrappertabgroup.h deleted file mode 100644 index bd0937e3b3f8..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrappertabgroup.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERTABGROUP_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERTABGROUP_H - -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yWrapperTabGroup : AquaA11yWrapper -{ -} --(NSArray *)accessibilityAttributeNames; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERTABGROUP_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrappertabgroup.mm b/vcl/aqua/source/a11y/aqua11ywrappertabgroup.mm deleted file mode 100644 index 65209219e0e3..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrappertabgroup.mm +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" -#include "aqua11ywrappertabgroup.h" - -// Wrapper for AXTabGroup role - -@implementation AquaA11yWrapperTabGroup : AquaA11yWrapper - --(NSArray *)accessibilityAttributeNames { - // Default Attributes - NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; - // Special Attributes and removing unwanted attributes depending on role - [ attributeNames addObjectsFromArray: [ NSArray arrayWithObjects: - NSAccessibilityContentsAttribute, - NSAccessibilityTabsAttribute, - nil ] - ]; - return attributeNames; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrappertextarea.h b/vcl/aqua/source/a11y/aqua11ywrappertextarea.h deleted file mode 100644 index e39fcdc6e39a..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrappertextarea.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERTEXTAREA_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERTEXTAREA_H - -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yWrapperTextArea : AquaA11yWrapper -{ -} --(NSArray *)accessibilityAttributeNames; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERTEXTAREA_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrappertextarea.mm b/vcl/aqua/source/a11y/aqua11ywrappertextarea.mm deleted file mode 100644 index 2949a6381624..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrappertextarea.mm +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" -#include "aqua11ywrappertextarea.h" - -// Wrapper for AXTextArea role - -@implementation AquaA11yWrapperTextArea : AquaA11yWrapper - --(NSArray *)accessibilityAttributeNames { - // Default Attributes - NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; - // Special Attributes and removing unwanted attributes depending on role - [ attributeNames removeObject: NSAccessibilityTitleAttribute ]; - [ attributeNames removeObject: NSAccessibilityEnabledAttribute ]; - [ attributeNames addObject: NSAccessibilityChildrenAttribute ]; - return attributeNames; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrappertoolbar.h b/vcl/aqua/source/a11y/aqua11ywrappertoolbar.h deleted file mode 100644 index 6c388216e565..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrappertoolbar.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERTOOLBAR_H -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERTOOLBAR_H - -#include "aqua/aqua11ywrapper.h" - -@interface AquaA11yWrapperToolbar : AquaA11yWrapper -{ -} --(NSArray *)accessibilityAttributeNames; -@end - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_AQUA11YWRAPPERTOOLBAR_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/aqua11ywrappertoolbar.mm b/vcl/aqua/source/a11y/aqua11ywrappertoolbar.mm deleted file mode 100644 index 76c1bc649058..000000000000 --- a/vcl/aqua/source/a11y/aqua11ywrappertoolbar.mm +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" -#include "aqua11ywrappertoolbar.h" - -// Wrapper for AXToolbar role - -@implementation AquaA11yWrapperToolbar : AquaA11yWrapper - --(NSArray *)accessibilityAttributeNames { - // Default Attributes - NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; - // Special Attributes and removing unwanted attributes depending on role - [ attributeNames removeObjectsInArray: [ NSArray arrayWithObjects: - NSAccessibilityTitleAttribute, - NSAccessibilityEnabledAttribute, - nil ] - ]; - return attributeNames; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/documentfocuslistener.cxx b/vcl/aqua/source/a11y/documentfocuslistener.cxx deleted file mode 100644 index ac65f1e84338..000000000000 --- a/vcl/aqua/source/a11y/documentfocuslistener.cxx +++ /dev/null @@ -1,241 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include "documentfocuslistener.hxx" - -#include - -#include - -#include - -using namespace ::com::sun::star::accessibility; -using namespace ::com::sun::star::lang; -using namespace ::com::sun::star::uno; - - -//------------------------------------------------------------------------------ - -DocumentFocusListener::DocumentFocusListener(AquaA11yFocusTracker& rTracker) : - m_aFocusTracker(rTracker) -{ -} - -//------------------------------------------------------------------------------ - -void SAL_CALL -DocumentFocusListener::disposing( const EventObject& aEvent ) - throw (RuntimeException) -{ - // Unref the object here, but do not remove as listener since the object - // might no longer be in a state that safely allows this. - if( aEvent.Source.is() ) - m_aRefList.erase(aEvent.Source); -} - -//------------------------------------------------------------------------------ - -void SAL_CALL -DocumentFocusListener::notifyEvent( const AccessibleEventObject& aEvent ) - throw( RuntimeException ) -{ - switch( aEvent.EventId ) - { - case AccessibleEventId::STATE_CHANGED: - try - { - sal_Int16 nState = AccessibleStateType::INVALID; - aEvent.NewValue >>= nState; - - if( AccessibleStateType::FOCUSED == nState ) - m_aFocusTracker.setFocusedObject( getAccessible(aEvent) ); - } - catch(const IndexOutOfBoundsException &) - { - OSL_TRACE("Focused object has invalid index in parent"); - } - break; - - case AccessibleEventId::CHILD: - { - Reference< XAccessible > xChild; - if( (aEvent.OldValue >>= xChild) && xChild.is() ) - detachRecursive(xChild); - - if( (aEvent.NewValue >>= xChild) && xChild.is() ) - attachRecursive(xChild); - } - break; - - case AccessibleEventId::INVALIDATE_ALL_CHILDREN: - { - Reference< XAccessible > xAccessible( getAccessible(aEvent) ); - detachRecursive(xAccessible); - attachRecursive(xAccessible); - } - - OSL_TRACE( "Invalidate all children called" ); - break; - default: - break; - } -} - -//------------------------------------------------------------------------------ - -Reference< XAccessible > DocumentFocusListener::getAccessible(const EventObject& aEvent ) - throw (IndexOutOfBoundsException, RuntimeException) -{ - Reference< XAccessible > xAccessible(aEvent.Source, UNO_QUERY); - - if( xAccessible.is() ) - return xAccessible; - - Reference< XAccessibleContext > xContext(aEvent.Source, UNO_QUERY); - - if( xContext.is() ) - { - Reference< XAccessible > xParent( xContext->getAccessibleParent() ); - if( xParent.is() ) - { - Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() ); - if( xParentContext.is() ) - { - return xParentContext->getAccessibleChild( xContext->getAccessibleIndexInParent() ); - } - } - } - - return Reference< XAccessible >(); -} - -//------------------------------------------------------------------------------ - -void DocumentFocusListener::attachRecursive(const Reference< XAccessible >& xAccessible) - throw (IndexOutOfBoundsException, RuntimeException) -{ - Reference< XAccessibleContext > xContext = xAccessible->getAccessibleContext(); - - if( xContext.is() ) - attachRecursive(xAccessible, xContext); -} - -//------------------------------------------------------------------------------ - -void DocumentFocusListener::attachRecursive( - const Reference< XAccessible >& xAccessible, - const Reference< XAccessibleContext >& xContext -) throw (IndexOutOfBoundsException, RuntimeException) -{ - if( xContext.is() ) - { - Reference< XAccessibleStateSet > xStateSet = xContext->getAccessibleStateSet(); - - if( xStateSet.is() ) - attachRecursive(xAccessible, xContext, xStateSet); - } -} - -//------------------------------------------------------------------------------ - -void DocumentFocusListener::attachRecursive( - const Reference< XAccessible >& xAccessible, - const Reference< XAccessibleContext >& xContext, - const Reference< XAccessibleStateSet >& xStateSet -) throw (IndexOutOfBoundsException,RuntimeException) -{ - if( xStateSet->contains(AccessibleStateType::FOCUSED ) ) - m_aFocusTracker.setFocusedObject( xAccessible ); - - Reference< XAccessibleEventBroadcaster > xBroadcaster = - Reference< XAccessibleEventBroadcaster >(xContext, UNO_QUERY); - - // If not already done, add the broadcaster to the list and attach as listener. - if( xBroadcaster.is() && m_aRefList.insert(xBroadcaster).second ) - { - xBroadcaster->addAccessibleEventListener(static_cast< XAccessibleEventListener *>(this)); - - if( ! xStateSet->contains(AccessibleStateType::MANAGES_DESCENDANTS ) ) - { - sal_Int32 n, nmax = xContext->getAccessibleChildCount(); - for( n = 0; n < nmax; n++ ) - { - Reference< XAccessible > xChild( xContext->getAccessibleChild( n ) ); - - if( xChild.is() ) - attachRecursive(xChild); - } - } - } -} - -//------------------------------------------------------------------------------ - -void DocumentFocusListener::detachRecursive(const Reference< XAccessible >& xAccessible) - throw (IndexOutOfBoundsException, RuntimeException) -{ - Reference< XAccessibleContext > xContext = xAccessible->getAccessibleContext(); - - if( xContext.is() ) - detachRecursive(xAccessible, xContext); -} - -//------------------------------------------------------------------------------ - -void DocumentFocusListener::detachRecursive( - const Reference< XAccessible >& xAccessible, - const Reference< XAccessibleContext >& xContext -) throw (IndexOutOfBoundsException, RuntimeException) -{ - Reference< XAccessibleStateSet > xStateSet = xContext->getAccessibleStateSet(); - - if( xStateSet.is() ) - detachRecursive(xAccessible, xContext, xStateSet); -} - -//------------------------------------------------------------------------------ - -void DocumentFocusListener::detachRecursive( - const Reference< XAccessible >&, - const Reference< XAccessibleContext >& xContext, - const Reference< XAccessibleStateSet >& xStateSet -) throw (IndexOutOfBoundsException, RuntimeException) -{ - Reference< XAccessibleEventBroadcaster > xBroadcaster = - Reference< XAccessibleEventBroadcaster >(xContext, UNO_QUERY); - - if( xBroadcaster.is() && 0 < m_aRefList.erase(xBroadcaster) ) - { - xBroadcaster->removeAccessibleEventListener(static_cast< XAccessibleEventListener *>(this)); - - if( ! xStateSet->contains(AccessibleStateType::MANAGES_DESCENDANTS ) ) - { - sal_Int32 n, nmax = xContext->getAccessibleChildCount(); - for( n = 0; n < nmax; n++ ) - { - Reference< XAccessible > xChild( xContext->getAccessibleChild( n ) ); - - if( xChild.is() ) - detachRecursive(xChild); - } - } - } -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/documentfocuslistener.hxx b/vcl/aqua/source/a11y/documentfocuslistener.hxx deleted file mode 100644 index 1baba33597d7..000000000000 --- a/vcl/aqua/source/a11y/documentfocuslistener.hxx +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_A11Y_DOCUMENTFOCUSLISTENER_HXX -#define INCLUDED_VCL_AQUA_SOURCE_A11Y_DOCUMENTFOCUSLISTENER_HXX - -#include - -#include - -#include "aqua/aqua11yfocustracker.hxx" - -#include - -// ------------------------- -// - DocumentFocusListener - -// ------------------------- - -class DocumentFocusListener : - public ::cppu::WeakImplHelper1< ::com::sun::star::accessibility::XAccessibleEventListener > -{ - -public: - - DocumentFocusListener(AquaA11yFocusTracker& rTracker); - - void attachRecursive( - const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible - ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); - - void attachRecursive( - const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible, - const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& xContext - ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); - - void attachRecursive( - const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible, - const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& xContext, - const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet >& xStateSet - ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); - - void detachRecursive( - const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible - ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); - - void detachRecursive( - const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible, - const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& xContext - ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); - - void detachRecursive( - const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible, - const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& xContext, - const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet >& xStateSet - ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); - - static ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getAccessible(const ::com::sun::star::lang::EventObject& aEvent ) - throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); - - // XEventListener - virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) - throw (::com::sun::star::uno::RuntimeException); - - // XAccessibleEventListener - virtual void SAL_CALL notifyEvent( const ::com::sun::star::accessibility::AccessibleEventObject& aEvent ) - throw( ::com::sun::star::uno::RuntimeException ); - -private: - std::set< ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > > m_aRefList; - - AquaA11yFocusTracker& m_aFocusTracker; -}; - -#endif // INCLUDED_VCL_AQUA_SOURCE_A11Y_DOCUMENTFOCUSLISTENER_HXX -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/a11y/readme.txt b/vcl/aqua/source/a11y/readme.txt deleted file mode 100644 index 19e80ab1a162..000000000000 --- a/vcl/aqua/source/a11y/readme.txt +++ /dev/null @@ -1,8 +0,0 @@ -Naming scheme: - -aqua11yXYZhelper: Helper class providing static methods - -aqua11yXYZwrapper: Wrapper around one (or two) UNO-interfaces - -aqua11ywrapperXYZ: Subclass of aqua11ywrapper for a specific AXRole - diff --git a/vcl/aqua/source/app/saldata.cxx b/vcl/aqua/source/app/saldata.cxx deleted file mode 100644 index 4ec95066e2fe..000000000000 --- a/vcl/aqua/source/app/saldata.cxx +++ /dev/null @@ -1,265 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include - -#include "aqua/saldata.hxx" -#include "aqua/salnsmenu.h" -#include "aqua/salinst.h" - -#import "apple_remote/RemoteMainController.h" - -oslThreadKey SalData::s_aAutoReleaseKey = 0; - -static void SAL_CALL releasePool( void* pPool ) -{ - if( pPool ) - [(NSAutoreleasePool*)pPool release]; -} - -SalData::SalData() -: - mpTimerProc( NULL ), - mpFirstInstance( NULL ), - mpFirstObject( NULL ), - mpFirstVD( NULL ), - mpFirstPrinter( NULL ), - mpFontList( NULL ), - mpStatusItem( nil ), - mxRGBSpace( CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB) ), - mxGraySpace( CGColorSpaceCreateWithName(kCGColorSpaceGenericGray) ), - mxP50Space( NULL ), - mxP50Pattern( NULL ), - maCursors( POINTER_COUNT, INVALID_CURSOR_PTR ), - mbIsScrollbarDoubleMax( false ), -#if !HAVE_FEATURE_MACOSX_SANDBOX - mpMainController( NULL ), -#endif - mpDockIconClickHandler( nil ), - mnDPIX( 0 ), - mnDPIY( 0 ) -{ - if( s_aAutoReleaseKey == 0 ) - s_aAutoReleaseKey = osl_createThreadKey( releasePool ); -} - -SalData::~SalData() -{ - CGPatternRelease( mxP50Pattern ); - CGColorSpaceRelease( mxP50Space ); - CGColorSpaceRelease( mxRGBSpace ); - CGColorSpaceRelease( mxGraySpace ); - for( unsigned int i = 0; i < maCursors.size(); i++ ) - { - NSCursor* pCurs = maCursors[i]; - if( pCurs && pCurs != INVALID_CURSOR_PTR ) - [pCurs release]; - } - if( s_aAutoReleaseKey ) - { - // release the last pool - NSAutoreleasePool* pPool = nil; - pPool = reinterpret_cast( osl_getThreadKeyData( s_aAutoReleaseKey ) ); - if( pPool ) - { - osl_setThreadKeyData( s_aAutoReleaseKey, NULL ); - [pPool release]; - } - - osl_destroyThreadKey( s_aAutoReleaseKey ); - s_aAutoReleaseKey = 0; - } -#if !HAVE_FEATURE_MACOSX_SANDBOX - if ( mpMainController ) - [mpMainController release]; -#endif -} - -void SalData::ensureThreadAutoreleasePool() -{ - NSAutoreleasePool* pPool = nil; - if( s_aAutoReleaseKey ) - { - pPool = reinterpret_cast( osl_getThreadKeyData( s_aAutoReleaseKey ) ); - if( ! pPool ) - { - pPool = [[NSAutoreleasePool alloc] init]; - osl_setThreadKeyData( s_aAutoReleaseKey, pPool ); - } - } - else - { - OSL_FAIL( "no autorelease key" ); - } -} - -struct curs_ent -{ - const char* pBaseName; - const NSPoint aHotSpot; -} -const aCursorTab[ POINTER_COUNT ] = -{ -{ NULL, { 0, 0 } }, //POINTER_ARROW -{ "nullptr", { 16, 16 } }, //POINTER_NULL -{ "hourglass", { 15, 15 } }, //POINTER_WAIT -{ NULL, { 0, 0 } }, //POINTER_TEXT -{ "help", { 0, 0 } }, //POINTER_HELP -{ NULL, { 0, 0 } }, //POINTER_CROSS -{ NULL, { 0, 0 } }, //POINTER_MOVE -{ NULL, { 0, 0 } }, //POINTER_NSIZE -{ NULL, { 0, 0 } }, //POINTER_SSIZE -{ NULL, { 0, 0 } }, //POINTER_WSIZE -{ NULL, { 0, 0 } }, //POINTER_ESIZE -{ "nwsesize", { 15, 15 } }, //POINTER_NWSIZE -{ "neswsize", { 15, 15 } }, //POINTER_NESIZE -{ "neswsize", { 15, 15 } }, //POINTER_SWSIZE -{ "nwsesize", { 15, 15 } }, //POINTER_SESIZE -{ NULL, { 0, 0 } }, //POINTER_WINDOW_NSIZE -{ NULL, { 0, 0 } }, //POINTER_WINDOW_SSIZE -{ NULL, { 0, 0 } }, //POINTER_WINDOW_WSIZE -{ NULL, { 0, 0 } }, //POINTER_WINDOW_ESIZE -{ "nwsesize", { 15, 15 } }, //POINTER_WINDOW_NWSIZE -{ "neswsize", { 15, 15 } }, //POINTER_WINDOW_NESIZE -{ "neswsize", { 15, 15 } }, //POINTER_WINDOW_SWSIZE -{ "nwsesize", { 15, 15 } }, //POINTER_WINDOW_SESIZE -{ NULL, { 0, 0 } }, //POINTER_HSPLIT -{ NULL, { 0, 0 } }, //POINTER_VSPLIT -{ NULL, { 0, 0 } }, //POINTER_HSIZEBAR -{ NULL, { 0, 0 } }, //POINTER_VSIZEBAR -{ NULL, { 0, 0 } }, //POINTER_HAND -{ NULL, { 0, 0 } }, //POINTER_REFHAND -{ "pen", { 3, 27 } }, //POINTER_PEN -{ "magnify", { 12, 13 } }, //POINTER_MAGNIFY -{ "fill", { 10, 22 } }, //POINTER_FILL -{ "rotate", { 15, 15 } }, //POINTER_ROTATE -{ "hshear", { 15, 15 } }, //POINTER_HSHEAR -{ "vshear", { 15, 15 } }, //POINTER_VSHEAR -{ "mirror", { 14, 12 } }, //POINTER_MIRROR -{ "crook", { 15, 14 } }, //POINTER_CROOK -{ "crop", { 9, 9 } }, //POINTER_CROP -{ "movept", { 0, 0 } }, //POINTER_MOVEPOINT -{ "movebw", { 0, 0 } }, //POINTER_MOVEBEZIERWEIGHT -{ "movedata", { 0, 0 } }, //POINTER_MOVEDATA -{ "copydata", { 0, 0 } }, //POINTER_COPYDATA -{ "linkdata", { 0, 0 } }, //POINTER_LINKDATA -{ "movedlnk", { 0, 0 } }, //POINTER_MOVEDATALINK -{ "copydlnk", { 0, 0 } }, //POINTER_COPYDATALINK -{ "movef", { 8, 8 } }, //POINTER_MOVEFILE -{ "copyf", { 8, 8 } }, //POINTER_COPYFILE -{ "linkf", { 8, 8 } }, //POINTER_LINKFILE -{ "moveflnk", { 8, 8 } }, //POINTER_MOVEFILELINK -{ "copyflnk", { 8, 8 } }, //POINTER_COPYFILELINK -{ "movef2", { 7, 8 } }, //POINTER_MOVEFILES -{ "copyf2", { 7, 8 } }, //POINTER_COPYFILES -{ "notallow", { 15, 15 } }, //POINTER_NOTALLOWED -{ "dline", { 8, 8 } }, //POINTER_DRAW_LINE -{ "drect", { 8, 8 } }, //POINTER_DRAW_RECT -{ "dpolygon", { 8, 8 } }, //POINTER_DRAW_POLYGON -{ "dbezier", { 8, 8 } }, //POINTER_DRAW_BEZIER -{ "darc", { 8, 8 } }, //POINTER_DRAW_ARC -{ "dpie", { 8, 8 } }, //POINTER_DRAW_PIE -{ "dcirccut", { 8, 8 } }, //POINTER_DRAW_CIRCLECUT -{ "dellipse", { 8, 8 } }, //POINTER_DRAW_ELLIPSE -{ "dfree", { 8, 8 } }, //POINTER_DRAW_FREEHAND -{ "dconnect", { 8, 8 } }, //POINTER_DRAW_CONNECT -{ "dtext", { 8, 8 } }, //POINTER_DRAW_TEXT -{ "dcapt", { 8, 8 } }, //POINTER_DRAW_CAPTION -{ "chart", { 15, 16 } }, //POINTER_CHART -{ "detectiv", { 12, 13 } }, //POINTER_DETECTIVE -{ "pivotcol", { 7, 5 } }, //POINTER_PIVOT_COL -{ "pivotrow", { 8, 7 } }, //POINTER_PIVOT_ROW -{ "pivotfld", { 8, 7 } }, //POINTER_PIVOT_FIELD -{ "chain", { 0, 2 } }, //POINTER_CHAIN -{ "chainnot", { 2, 2 } }, //POINTER_CHAIN_NOTALLOWED -{ "timemove", { 16, 16 } }, //POINTER_TIMEEVENT_MOVE -{ "timesize", { 16, 17 } }, //POINTER_TIMEEVENT_SIZE -{ "asn", { 16, 12 } }, //POINTER_AUTOSCROLL_N -{ "ass", { 15, 19 } }, //POINTER_AUTOSCROLL_S -{ "asw", { 12, 15 } }, //POINTER_AUTOSCROLL_W -{ "ase", { 19, 16 } }, //POINTER_AUTOSCROLL_E -{ "asnw", { 10, 10 } }, //POINTER_AUTOSCROLL_NW -{ "asne", { 21, 10 } }, //POINTER_AUTOSCROLL_NE -{ "assw", { 21, 21 } }, //POINTER_AUTOSCROLL_SW -{ "asse", { 21, 21 } }, //POINTER_AUTOSCROLL_SE -{ "asns", { 15, 15 } }, //POINTER_AUTOSCROLL_NS -{ "aswe", { 15, 15 } }, //POINTER_AUTOSCROLL_WE -{ "asnswe", { 15, 15 } }, //POINTER_AUTOSCROLL_NSWE -{ "airbrush", { 5, 22 } }, //POINTER_AIRBRUSH -{ "vtext", { 15, 15 } }, //POINTER_TEXT_VERTICAL -{ "pivotdel", { 18, 15 } }, //POINTER_PIVOT_DELETE -{ "tblsels", { 15, 30 } }, //POINTER_TAB_SELECT_S -{ "tblsele", { 30, 16 } }, //POINTER_TAB_SELECT_E -{ "tblselse", { 30, 30 } }, //POINTER_TAB_SELECT_SE -{ "tblselw", { 1, 16 } }, //POINTER_TAB_SELECT_W -{ "tblselsw", { 1, 30 } }, //POINTER_TAB_SELECT_SW -{ "pntbrsh", { 9, 16 } } //POINTER_PAINTBRUSH -}; - -NSCursor* SalData::getCursor( PointerStyle i_eStyle ) -{ - if( i_eStyle >= POINTER_COUNT ) - return nil; - - NSCursor* pCurs = maCursors[ i_eStyle ]; - if( pCurs == INVALID_CURSOR_PTR ) - { - pCurs = nil; - if( aCursorTab[ i_eStyle ].pBaseName ) - { - NSPoint aHotSpot = aCursorTab[ i_eStyle ].aHotSpot; - CFStringRef pCursorName = - CFStringCreateWithCStringNoCopy( - kCFAllocatorDefault, - aCursorTab[ i_eStyle ].pBaseName, - kCFStringEncodingASCII, - kCFAllocatorNull ); - CFBundleRef hMain = CFBundleGetMainBundle(); - CFURLRef hURL = CFBundleCopyResourceURL( hMain, pCursorName, CFSTR("png"), CFSTR("cursors") ); - if( hURL ) - { - pCurs = [[NSCursor alloc] initWithImage: [[NSImage alloc] initWithContentsOfURL: (NSURL*)hURL] hotSpot: aHotSpot]; - CFRelease( hURL ); - } - CFRelease( pCursorName ); - } - maCursors[ i_eStyle ] = pCurs; - } - return pCurs; -} - -NSStatusItem* SalData::getStatusItem() -{ - SalData* pData = GetSalData(); - if( ! pData->mpStatusItem ) - { - NSStatusBar* pStatBar =[NSStatusBar systemStatusBar]; - if( pStatBar ) - { - pData->mpStatusItem = [pStatBar statusItemWithLength: NSVariableStatusItemLength]; - [pData->mpStatusItem retain]; - OOStatusItemView* pView = [[OOStatusItemView alloc] init]; - [pData->mpStatusItem setView: pView ]; - [pView display]; - } - } - return pData->mpStatusItem; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/app/salinst.cxx b/vcl/aqua/source/app/salinst.cxx deleted file mode 100644 index 999a19f77ce1..000000000000 --- a/vcl/aqua/source/app/salinst.cxx +++ /dev/null @@ -1,1207 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include - -#include - -#include - -#include "osl/process.h" - -#include "rtl/ustrbuf.hxx" - -#include "vcl/svapp.hxx" -#include "vcl/window.hxx" -#include "vcl/timer.hxx" -#include "vcl/solarmutex.hxx" - -#include "aqua/saldata.hxx" -#include "aqua/salinst.h" -#include "aqua/salframe.h" -#include "aqua/salobj.h" -#include "aqua/salsys.h" -#include "aqua/salvd.h" -#include "quartz/salbmp.h" -#include "quartz/utils.h" -#include "aqua/salprn.h" -#include "aqua/saltimer.h" -#include "aqua/vclnsapp.h" - -#include "print.h" -#include "impbmp.hxx" -#include "salimestatus.hxx" - -#include - -#include -#include -#include - -#include "premac.h" -#include -#include -#import "apple_remote/RemoteMainController.h" -#include "apple_remote/RemoteControl.h" -#include "postmac.h" - -using namespace std; -using namespace ::com::sun::star; - -extern sal_Bool ImplSVMain(); - -static int* gpnInit = 0; -static NSMenu* pDockMenu = nil; -static bool bNoSVMain = true; -static bool bLeftMain = false; -// ----------------------------------------------------------------------- - -class AquaDelayedSettingsChanged : public Timer -{ - bool mbInvalidate; - public: - AquaDelayedSettingsChanged( bool bInvalidate ) : - mbInvalidate( bInvalidate ) - { - } - - virtual void Timeout() - { - SalData* pSalData = GetSalData(); - if( ! pSalData->maFrames.empty() ) - pSalData->maFrames.front()->CallCallback( SALEVENT_SETTINGSCHANGED, NULL ); - - if( mbInvalidate ) - { - for( std::list< AquaSalFrame* >::iterator it = pSalData->maFrames.begin(); - it != pSalData->maFrames.end(); ++it ) - { - if( (*it)->mbShown ) - (*it)->SendPaintEvent( NULL ); - } - } - Stop(); - delete this; - } -}; - -void AquaSalInstance::delayedSettingsChanged( bool bInvalidate ) -{ - osl::Guard< comphelper::SolarMutex > aGuard( *mpSalYieldMutex ); - AquaDelayedSettingsChanged* pTimer = new AquaDelayedSettingsChanged( bInvalidate ); - pTimer->SetTimeout( 50 ); - pTimer->Start(); -} - - -// the AppEventList must be available before any SalData/SalInst/etc. objects are ready -AquaSalInstance::AppEventList AquaSalInstance::aAppEventList; - -NSMenu* AquaSalInstance::GetDynamicDockMenu() -{ - if( ! pDockMenu && ! bLeftMain ) - pDockMenu = [[NSMenu alloc] initWithTitle: @""]; - return pDockMenu; -} - -bool AquaSalInstance::isOnCommandLine( const OUString& rArg ) -{ - sal_uInt32 nArgs = osl_getCommandArgCount(); - for( sal_uInt32 i = 0; i < nArgs; i++ ) - { - OUString aArg; - osl_getCommandArg( i, &aArg.pData ); - if( aArg.equals( rArg ) ) - return true; - } - return false; -} - - -// initialize the cocoa VCL_NSApplication object -// returns an NSAutoreleasePool that must be released when the event loop begins -static void initNSApp() -{ - // create our cocoa NSApplication - [VCL_NSApplication sharedApplication]; - - SalData::ensureThreadAutoreleasePool(); - - // put cocoa into multithreaded mode - [NSThread detachNewThreadSelector:@selector(enableCocoaThreads:) toTarget:[[CocoaThreadEnabler alloc] init] withObject:nil]; - - // activate our delegate methods - [NSApp setDelegate: NSApp]; - - [[NSNotificationCenter defaultCenter] addObserver: NSApp - selector: @selector(systemColorsChanged:) - name: NSSystemColorsDidChangeNotification - object: nil ]; - [[NSNotificationCenter defaultCenter] addObserver: NSApp - selector: @selector(screenParametersChanged:) - name: NSApplicationDidChangeScreenParametersNotification - object: nil ]; - // add observers for some settings changes that affect vcl's settings - // scrollbar variant - [[NSDistributedNotificationCenter defaultCenter] addObserver: NSApp - selector: @selector(scrollbarVariantChanged:) - name: @"AppleAquaScrollBarVariantChanged" - object: nil ]; - // scrollbar page behavior ("jump to here" or not) - [[NSDistributedNotificationCenter defaultCenter] addObserver: NSApp - selector: @selector(scrollbarSettingsChanged:) - name: @"AppleNoRedisplayAppearancePreferenceChanged" - object: nil ]; -#if !HAVE_FEATURE_MACOSX_SANDBOX - // Initialize Apple Remote - GetSalData()->mpMainController = [[MainController alloc] init]; - - [[NSDistributedNotificationCenter defaultCenter] addObserver: NSApp - selector: @selector(applicationWillBecomeActive:) - name: @"AppleRemoteWillBecomeActive" - object: nil ]; - - [[NSDistributedNotificationCenter defaultCenter] addObserver: NSApp - selector: @selector(applicationWillResignActive:) - name: @"AppleRemoteWillResignActive" - object: nil ]; -#endif -} - -sal_Bool ImplSVMainHook( int * pnInit ) -{ - unlink([[NSString stringWithFormat:@"%@/Library/Saved Application State/%s.savedState/restorecount.plist", NSHomeDirectory(), MACOSX_BUNDLE_IDENTIFIER] UTF8String]); - - gpnInit = pnInit; - - bNoSVMain = false; - initNSApp(); - - NSPoint aPt = { 0, 0 }; - NSEvent* pEvent = [NSEvent otherEventWithType: NSApplicationDefined - location: aPt - modifierFlags: 0 - timestamp: 0 - windowNumber: 0 - context: nil - subtype: AquaSalInstance::AppExecuteSVMain - data1: 0 - data2: 0 ]; - if( pEvent ) - { - [NSApp postEvent: pEvent atStart: NO]; - - OUString aExeURL, aExe; - osl_getExecutableFile( &aExeURL.pData ); - osl_getSystemPathFromFileURL( aExeURL.pData, &aExe.pData ); - OString aByteExe( OUStringToOString( aExe, osl_getThreadTextEncoding() ) ); - -#ifdef DEBUG - aByteExe += OString ( " NSAccessibilityDebugLogLevel 1" ); - const char* pArgv[] = { aByteExe.getStr(), NULL }; - NSApplicationMain( 3, pArgv ); -#else - const char* pArgv[] = { aByteExe.getStr(), NULL }; - NSApplicationMain( 1, pArgv ); -#endif - } - else - { - OSL_FAIL( "NSApplication initialization could not be done" ); - } - - return TRUE; // indicate that ImplSVMainHook is implemented -} - -// ======================================================================= - -void SalAbort( const OUString& rErrorText, bool bDumpCore ) -{ - if( rErrorText.isEmpty() ) - fprintf( stderr, "Application Error " ); - else - fprintf( stderr, "%s ", - OUStringToOString( rErrorText, osl_getThreadTextEncoding() ).getStr() ); - if( bDumpCore ) - abort(); - else - _exit(1); -} - -// ----------------------------------------------------------------------- - -void InitSalData() -{ - SalData *pSalData = new SalData; - SetSalData( pSalData ); -} - -// ----------------------------------------------------------------------- - -const OUString& SalGetDesktopEnvironment() -{ - static OUString aDesktopEnvironment( "MacOSX" ); - return aDesktopEnvironment; -} - -// ----------------------------------------------------------------------- - -void DeInitSalData() -{ - SalData *pSalData = GetSalData(); - if( pSalData->mpStatusItem ) - { - [pSalData->mpStatusItem release]; - pSalData->mpStatusItem = nil; - } - delete pSalData; - SetSalData( NULL ); -} - -// ----------------------------------------------------------------------- - -extern "C" { -#include -} - -// ----------------------------------------------------------------------- - -void InitSalMain() -{ -} - -// ======================================================================= - -SalYieldMutex::SalYieldMutex() -{ - mnCount = 0; - mnThreadId = 0; -} - -void SalYieldMutex::acquire() -{ - SolarMutexObject::acquire(); - mnThreadId = osl::Thread::getCurrentIdentifier(); - mnCount++; -} - -void SalYieldMutex::release() -{ - if ( mnThreadId == osl::Thread::getCurrentIdentifier() ) - { - if ( mnCount == 1 ) - mnThreadId = 0; - mnCount--; - } - SolarMutexObject::release(); -} - -bool SalYieldMutex::tryToAcquire() -{ - if ( SolarMutexObject::tryToAcquire() ) - { - mnThreadId = osl::Thread::getCurrentIdentifier(); - mnCount++; - return true; - } - else - return false; -} - -// ----------------------------------------------------------------------- - -// some convenience functions regarding the yield mutex, aka solar mutex - -sal_Bool ImplSalYieldMutexTryToAcquire() -{ - AquaSalInstance* pInst = (AquaSalInstance*) GetSalData()->mpFirstInstance; - if ( pInst ) - return pInst->mpSalYieldMutex->tryToAcquire(); - else - return FALSE; -} - -void ImplSalYieldMutexAcquire() -{ - AquaSalInstance* pInst = (AquaSalInstance*) GetSalData()->mpFirstInstance; - if ( pInst ) - pInst->mpSalYieldMutex->acquire(); -} - -void ImplSalYieldMutexRelease() -{ - AquaSalInstance* pInst = (AquaSalInstance*) GetSalData()->mpFirstInstance; - if ( pInst ) - pInst->mpSalYieldMutex->release(); -} - -// ======================================================================= - -SalInstance* CreateSalInstance() -{ - // this is the case for not using SVMain - // not so good - if( bNoSVMain ) - initNSApp(); - - SalData* pSalData = GetSalData(); - DBG_ASSERT( pSalData->mpFirstInstance == NULL, "more than one instance created" ); - AquaSalInstance* pInst = new AquaSalInstance; - - // init instance (only one instance in this version !!!) - pSalData->mpFirstInstance = pInst; - // this one is for outside AquaSalInstance::Yield - SalData::ensureThreadAutoreleasePool(); - // no focus rects on NWF aqua - ImplGetSVData()->maNWFData.mbNoFocusRects = true; - ImplGetSVData()->maNWFData.mbNoActiveTabTextRaise = true; - ImplGetSVData()->maNWFData.mbCenteredTabs = true; - ImplGetSVData()->maNWFData.mbProgressNeedsErase = true; - ImplGetSVData()->maNWFData.mbCheckBoxNeedsErase = true; - ImplGetSVData()->maNWFData.mnStatusBarLowerRightOffset = 10; - ImplGetSVData()->maGDIData.mbNoXORClipping = true; - ImplGetSVData()->maWinData.mbNoSaveBackground = true; - - return pInst; -} - -// ----------------------------------------------------------------------- - -void DestroySalInstance( SalInstance* pInst ) -{ - delete pInst; -} - -// ----------------------------------------------------------------------- - -AquaSalInstance::AquaSalInstance() -{ - mpSalYieldMutex = new SalYieldMutex; - mpSalYieldMutex->acquire(); - ::tools::SolarMutex::SetSolarMutex( mpSalYieldMutex ); - maMainThread = osl::Thread::getCurrentIdentifier(); - mbWaitingYield = false; - maUserEventListMutex = osl_createMutex(); - mnActivePrintJobs = 0; - maWaitingYieldCond = osl_createCondition(); -} - -// ----------------------------------------------------------------------- - -AquaSalInstance::~AquaSalInstance() -{ - ::tools::SolarMutex::SetSolarMutex( 0 ); - mpSalYieldMutex->release(); - delete mpSalYieldMutex; - osl_destroyMutex( maUserEventListMutex ); - osl_destroyCondition( maWaitingYieldCond ); -} - -// ----------------------------------------------------------------------- - -void AquaSalInstance::wakeupYield() -{ - // wakeup :Yield - if( mbWaitingYield ) - { - SalData::ensureThreadAutoreleasePool(); - NSPoint aPt = { 0, 0 }; - NSEvent* pEvent = [NSEvent otherEventWithType: NSApplicationDefined - location: aPt - modifierFlags: 0 - timestamp: 0 - windowNumber: 0 - context: nil - subtype: AquaSalInstance::YieldWakeupEvent - data1: 0 - data2: 0 ]; - if( pEvent ) - [NSApp postEvent: pEvent atStart: NO]; - } -} - -// ----------------------------------------------------------------------- - -void AquaSalInstance::PostUserEvent( AquaSalFrame* pFrame, sal_uInt16 nType, void* pData ) -{ - osl_acquireMutex( maUserEventListMutex ); - maUserEvents.push_back( SalUserEvent( pFrame, pData, nType ) ); - osl_releaseMutex( maUserEventListMutex ); - - // notify main loop that an event has arrived - wakeupYield(); -} - -// ----------------------------------------------------------------------- - -comphelper::SolarMutex* AquaSalInstance::GetYieldMutex() -{ - return mpSalYieldMutex; -} - -// ----------------------------------------------------------------------- - -sal_uLong AquaSalInstance::ReleaseYieldMutex() -{ - SalYieldMutex* pYieldMutex = mpSalYieldMutex; - if ( pYieldMutex->GetThreadId() == - osl::Thread::getCurrentIdentifier() ) - { - sal_uLong nCount = pYieldMutex->GetAcquireCount(); - sal_uLong n = nCount; - while ( n ) - { - pYieldMutex->release(); - n--; - } - - return nCount; - } - else - return 0; -} - -// ----------------------------------------------------------------------- - -void AquaSalInstance::AcquireYieldMutex( sal_uLong nCount ) -{ - SalYieldMutex* pYieldMutex = mpSalYieldMutex; - while ( nCount ) - { - pYieldMutex->acquire(); - nCount--; - } -} - -// ----------------------------------------------------------------------- - -bool AquaSalInstance::CheckYieldMutex() -{ - bool bRet = true; - - SalYieldMutex* pYieldMutex = mpSalYieldMutex; - if ( pYieldMutex->GetThreadId() != osl::Thread::getCurrentIdentifier()) - { - bRet = false; - } - - return bRet; -} - -// ----------------------------------------------------------------------- - -bool AquaSalInstance::isNSAppThread() const -{ - return osl::Thread::getCurrentIdentifier() == maMainThread; -} - -// ----------------------------------------------------------------------- - -void AquaSalInstance::handleAppDefinedEvent( NSEvent* pEvent ) -{ - switch( [pEvent subtype] ) - { - case AppStartTimerEvent: - AquaSalTimer::handleStartTimerEvent( pEvent ); - break; - case AppEndLoopEvent: - [NSApp stop: NSApp]; - break; - case AppExecuteSVMain: - { - int nResult = ImplSVMain(); - if( gpnInit ) - *gpnInit = nResult; - [NSApp stop: NSApp]; - bLeftMain = true; - if( pDockMenu ) - { - [pDockMenu release]; - pDockMenu = nil; - } - } - break; - case AppleRemoteEvent: - { - sal_Int16 nCommand = 0; - SalData* pSalData = GetSalData(); - bool bIsFullScreenMode = false; - - std::list::iterator it = pSalData->maFrames.begin(); - while( it != pSalData->maFrames.end() ) - { - if ( (*it) && ((*it)->mbFullScreen == true) ) - bIsFullScreenMode = true; - ++it; - } - - switch ([pEvent data1]) - { - case kRemoteButtonPlay: - nCommand = ( bIsFullScreenMode == true ) ? MEDIA_COMMAND_PLAY_PAUSE : MEDIA_COMMAND_PLAY; - break; - - // kept for experimentation purpose (scheduled for future implementation) - // case kRemoteButtonMenu: nCommand = MEDIA_COMMAND_MENU; break; - - case kRemoteButtonPlus: nCommand = MEDIA_COMMAND_VOLUME_UP; break; - - case kRemoteButtonMinus: nCommand = MEDIA_COMMAND_VOLUME_DOWN; break; - - case kRemoteButtonRight: nCommand = MEDIA_COMMAND_NEXTTRACK; break; - - case kRemoteButtonRight_Hold: nCommand = MEDIA_COMMAND_NEXTTRACK_HOLD; break; - - case kRemoteButtonLeft: nCommand = MEDIA_COMMAND_PREVIOUSTRACK; break; - - case kRemoteButtonLeft_Hold: nCommand = MEDIA_COMMAND_REWIND; break; - - case kRemoteButtonPlay_Hold: nCommand = MEDIA_COMMAND_PLAY_HOLD; break; - - case kRemoteButtonMenu_Hold: nCommand = MEDIA_COMMAND_STOP; break; - - // FIXME : not detected - case kRemoteButtonPlus_Hold: - case kRemoteButtonMinus_Hold: - break; - - default: - break; - } - AquaSalFrame* pFrame = pSalData->maFrames.front(); - Window * pWindow = pFrame->GetWindow() ? pSalData->maFrames.front()->GetWindow() : NULL; - - if( pWindow ) - { - const Point aPoint; - CommandEvent aCEvt( aPoint, COMMAND_MEDIA, FALSE, &nCommand ); - NotifyEvent aNCmdEvt( EVENT_COMMAND, pWindow, &aCEvt ); - - if ( !ImplCallPreNotify( aNCmdEvt ) ) - pWindow->Command( aCEvt ); - } - - } - break; - - case YieldWakeupEvent: - // do nothing, fall out of Yield - break; - - default: - OSL_FAIL( "unhandled NSApplicationDefined event" ); - break; - }; -} - -// ----------------------------------------------------------------------- - -class ReleasePoolHolder -{ - NSAutoreleasePool* mpPool; - public: - ReleasePoolHolder() : mpPool( [[NSAutoreleasePool alloc] init] ) {} - ~ReleasePoolHolder() { [mpPool release]; } -}; - -void AquaSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents ) -{ - // ensure that the per thread autorelease pool is top level and - // will therefore not be destroyed by cocoa implicitly - SalData::ensureThreadAutoreleasePool(); - - // NSAutoreleasePool documentation suggests we should have - // an own pool for each yield level - ReleasePoolHolder aReleasePool; - - // Release all locks so that we don't deadlock when we pull pending - // events from the event queue - bool bDispatchUser = true; - while( bDispatchUser ) - { - sal_uLong nCount = ReleaseYieldMutex(); - - // get one user event - osl_acquireMutex( maUserEventListMutex ); - SalUserEvent aEvent( NULL, NULL, 0 ); - if( ! maUserEvents.empty() ) - { - aEvent = maUserEvents.front(); - maUserEvents.pop_front(); - } - else - bDispatchUser = false; - osl_releaseMutex( maUserEventListMutex ); - - AcquireYieldMutex( nCount ); - - // dispatch it - if( aEvent.mpFrame && AquaSalFrame::isAlive( aEvent.mpFrame ) ) - { - aEvent.mpFrame->CallCallback( aEvent.mnType, aEvent.mpData ); - osl_setCondition( maWaitingYieldCond ); - // return if only one event is asked for - if( ! bHandleAllCurrentEvents ) - return; - } - } - - // handle cocoa event queue - // cocoa events mye be only handled in the thread the NSApp was created - if( isNSAppThread() && mnActivePrintJobs == 0 ) - { - // we need to be woken up by a cocoa-event - // if a user event should be posted by the event handling below - bool bOldWaitingYield = mbWaitingYield; - mbWaitingYield = bWait; - - // handle available events - NSEvent* pEvent = nil; - bool bHadEvent = false; - do - { - sal_uLong nCount = ReleaseYieldMutex(); - - pEvent = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: nil - inMode: NSDefaultRunLoopMode dequeue: YES]; - if( pEvent ) - { - [NSApp sendEvent: pEvent]; - bHadEvent = true; - } - [NSApp updateWindows]; - - AcquireYieldMutex( nCount ); - } while( bHandleAllCurrentEvents && pEvent ); - - // if we had no event yet, wait for one if requested - if( bWait && ! bHadEvent ) - { - sal_uLong nCount = ReleaseYieldMutex(); - - NSDate* pDt = AquaSalTimer::pRunningTimer ? [AquaSalTimer::pRunningTimer fireDate] : [NSDate distantFuture]; - pEvent = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: pDt - inMode: NSDefaultRunLoopMode dequeue: YES]; - if( pEvent ) - [NSApp sendEvent: pEvent]; - [NSApp updateWindows]; - - AcquireYieldMutex( nCount ); - - // #i86581# - // FIXME: sometimes the NSTimer will never fire. Firing it by hand then - // fixes the problem even seems to set the correct next firing date - // Why oh why ? - if( ! pEvent && AquaSalTimer::pRunningTimer ) - { - // this cause crashes on MacOSX 10.4 - // [AquaSalTimer::pRunningTimer fire]; - ImplGetSVData()->mpSalTimer->CallCallback(); - } - } - - mbWaitingYield = bOldWaitingYield; - - // collect update rectangles - const std::list< AquaSalFrame* > rFrames( GetSalData()->maFrames ); - for( std::list< AquaSalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it ) - { - if( (*it)->mbShown && ! (*it)->maInvalidRect.IsEmpty() ) - { - (*it)->Flush( (*it)->maInvalidRect ); - (*it)->maInvalidRect.SetEmpty(); - } - } - osl_setCondition( maWaitingYieldCond ); - } - else if( bWait ) - { - // #i103162# - // wait until any thread (most likely the main thread) - // has dispatched an event, cop out at 200 ms - osl_resetCondition( maWaitingYieldCond ); - TimeValue aVal = { 0, 200000000 }; - sal_uLong nCount = ReleaseYieldMutex(); - osl_waitCondition( maWaitingYieldCond, &aVal ); - AcquireYieldMutex( nCount ); - } - - // we get some apple events way too early - // before the application is ready to handle them, - // so their corresponding application events need to be delayed - // now is a good time to handle at least one of them - if( bWait && !aAppEventList.empty() && ImplGetSVData()->maAppData.mbInAppExecute ) - { - // make sure that only one application event is active at a time - static bool bInAppEvent = false; - if( !bInAppEvent ) - { - bInAppEvent = true; - // get the next delayed application event - const ApplicationEvent* pAppEvent = aAppEventList.front(); - aAppEventList.pop_front(); - // handle one application event (no recursion) - const ImplSVData* pSVData = ImplGetSVData(); - pSVData->mpApp->AppEvent( *pAppEvent ); - delete pAppEvent; - // allow the next delayed application event - bInAppEvent = false; - } - } -} - -// ----------------------------------------------------------------------- - -bool AquaSalInstance::AnyInput( sal_uInt16 nType ) -{ - if( nType & VCL_INPUT_APPEVENT ) - { - if( ! aAppEventList.empty() ) - return true; - if( nType == VCL_INPUT_APPEVENT ) - return false; - } - - if( nType & VCL_INPUT_TIMER ) - { - if( AquaSalTimer::pRunningTimer ) - { - NSDate* pDt = [AquaSalTimer::pRunningTimer fireDate]; - if( pDt && [pDt timeIntervalSinceNow] < 0 ) - { - return true; - } - } - } - - unsigned/*NSUInteger*/ nEventMask = 0; - if( nType & VCL_INPUT_MOUSE) - nEventMask |= - NSLeftMouseDownMask | NSRightMouseDownMask | NSOtherMouseDownMask | - NSLeftMouseUpMask | NSRightMouseUpMask | NSOtherMouseUpMask | - NSLeftMouseDraggedMask | NSRightMouseDraggedMask | NSOtherMouseDraggedMask | - NSScrollWheelMask | - // NSMouseMovedMask | - NSMouseEnteredMask | NSMouseExitedMask; - if( nType & VCL_INPUT_KEYBOARD) - nEventMask |= NSKeyDownMask | NSKeyUpMask | NSFlagsChangedMask; - if( nType & VCL_INPUT_OTHER) - nEventMask |= NSTabletPoint; - // TODO: VCL_INPUT_PAINT / more VCL_INPUT_OTHER - if( !nType) - return false; - - NSEvent* pEvent = [NSApp nextEventMatchingMask: nEventMask untilDate: nil - inMode: NSDefaultRunLoopMode dequeue: NO]; - return (pEvent != NULL); -} - -// ----------------------------------------------------------------------- - -SalFrame* AquaSalInstance::CreateChildFrame( SystemParentData*, sal_uLong /*nSalFrameStyle*/ ) -{ - return NULL; -} - -// ----------------------------------------------------------------------- - -SalFrame* AquaSalInstance::CreateFrame( SalFrame* pParent, sal_uLong nSalFrameStyle ) -{ - SalData::ensureThreadAutoreleasePool(); - - SalFrame* pFrame = new AquaSalFrame( pParent, nSalFrameStyle ); - return pFrame; -} - -// ----------------------------------------------------------------------- - -void AquaSalInstance::DestroyFrame( SalFrame* pFrame ) -{ - delete pFrame; -} - -// ----------------------------------------------------------------------- - -SalObject* AquaSalInstance::CreateObject( SalFrame* pParent, SystemWindowData* /* pWindowData */, sal_Bool /* bShow */ ) -{ - // SystemWindowData is meaningless on Mac OS X - AquaSalObject *pObject = NULL; - - if ( pParent ) - pObject = new AquaSalObject( static_cast(pParent) ); - - return pObject; -} - -// ----------------------------------------------------------------------- - -void AquaSalInstance::DestroyObject( SalObject* pObject ) -{ - delete ( pObject ); -} - -// ----------------------------------------------------------------------- - -SalPrinter* AquaSalInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter ) -{ - return new AquaSalPrinter( dynamic_cast(pInfoPrinter) ); -} - -// ----------------------------------------------------------------------- - -void AquaSalInstance::DestroyPrinter( SalPrinter* pPrinter ) -{ - delete pPrinter; -} - -// ----------------------------------------------------------------------- - -void AquaSalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList ) -{ - NSArray* pNames = [NSPrinter printerNames]; - NSArray* pTypes = [NSPrinter printerTypes]; - unsigned int nNameCount = pNames ? [pNames count] : 0; - unsigned int nTypeCount = pTypes ? [pTypes count] : 0; - DBG_ASSERT( nTypeCount == nNameCount, "type count not equal to printer count" ); - for( unsigned int i = 0; i < nNameCount; i++ ) - { - NSString* pName = [pNames objectAtIndex: i]; - NSString* pType = i < nTypeCount ? [pTypes objectAtIndex: i] : nil; - if( pName ) - { - SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo; - pInfo->maPrinterName = GetOUString( pName ); - if( pType ) - pInfo->maDriver = GetOUString( pType ); - pInfo->mnStatus = 0; - pInfo->mnJobs = 0; - pInfo->mpSysData = NULL; - - pList->Add( pInfo ); - } - } -} - -// ----------------------------------------------------------------------- - -void AquaSalInstance::GetPrinterQueueState( SalPrinterQueueInfo* ) -{ -} - -// ----------------------------------------------------------------------- - -void AquaSalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo ) -{ - delete pInfo; -} - -// ----------------------------------------------------------------------- - -OUString AquaSalInstance::GetDefaultPrinter() -{ - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - if( maDefaultPrinter.isEmpty() ) - { - NSPrintInfo* pPI = [NSPrintInfo sharedPrintInfo]; - DBG_ASSERT( pPI, "no print info" ); - if( pPI ) - { - NSPrinter* pPr = [pPI printer]; - DBG_ASSERT( pPr, "no printer in default info" ); - if( pPr ) - { - NSString* pDefName = [pPr name]; - DBG_ASSERT( pDefName, "printer has no name" ); - maDefaultPrinter = GetOUString( pDefName ); - } - } - } - return maDefaultPrinter; -} - -// ----------------------------------------------------------------------- - -SalInfoPrinter* AquaSalInstance::CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo, - ImplJobSetup* pSetupData ) -{ - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - SalInfoPrinter* pNewInfoPrinter = NULL; - if( pQueueInfo ) - { - pNewInfoPrinter = new AquaSalInfoPrinter( *pQueueInfo ); - if( pSetupData ) - pNewInfoPrinter->SetPrinterData( pSetupData ); - } - - return pNewInfoPrinter; -} - -// ----------------------------------------------------------------------- - -void AquaSalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter ) -{ - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - delete pPrinter; -} - -// ----------------------------------------------------------------------- - -SalSystem* AquaSalInstance::CreateSystem() -{ - return new AquaSalSystem(); -} - -// ----------------------------------------------------------------------- - -void AquaSalInstance::DestroySystem( SalSystem* pSystem ) -{ - delete pSystem; -} - -// ----------------------------------------------------------------------- - -void AquaSalInstance::SetEventCallback( void*, bool(*)(void*,void*,int) ) -{ -} - -// ----------------------------------------------------------------------- - -void AquaSalInstance::SetErrorEventCallback( void*, bool(*)(void*,void*,int) ) -{ -} - -// ----------------------------------------------------------------------- - -void* AquaSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes ) -{ - rReturnedBytes = 1; - rReturnedType = AsciiCString; - return (void*)""; -} - -// We need to re-encode file urls because osl_getFileURLFromSystemPath converts -// to UTF-8 before encoding non ascii characters, which is not what other apps expect. -static OUString translateToExternalUrl(const OUString& internalUrl) -{ - uno::Reference< uno::XComponentContext > context( - comphelper::getProcessComponentContext()); - return uri::ExternalUriReferenceTranslator::create(context)->translateToExternal(internalUrl); -} - -// #i104525# many versions of OSX have problems with some URLs: -// when an app requests OSX to add one of these URLs to the "Recent Items" list -// then this app gets killed (TextEdit, Preview, etc. and also OOo) -static bool isDangerousUrl( const OUString& rUrl ) -{ - // use a heuristic that detects all known cases since there is no official comment - // on the exact impact and root cause of the OSX bug - const int nLen = rUrl.getLength(); - const sal_Unicode* p = rUrl.getStr(); - for( int i = 0; i < nLen-3; ++i, ++p ) { - if( p[0] != '%' ) - continue; - // escaped percent? - if( (p[1] == '2') && (p[2] == '5') ) - return true; - // escapes are considered to be UTF-8 encoded - // => check for invalid UTF-8 leading byte - if( (p[1] != 'f') && (p[1] != 'F') ) - continue; - int cLowNibble = p[2]; - if( (cLowNibble >= '0' ) && (cLowNibble <= '9')) - return false; - if( cLowNibble >= 'a' ) - cLowNibble -= 'a' - 'A'; - if( (cLowNibble < 'A') || (cLowNibble >= 'C')) - return true; - } - - return false; -} - -void AquaSalInstance::AddToRecentDocumentList(const OUString& rFileUrl, const OUString& /*rMimeType*/, const OUString& /*rDocumentService*/) -{ - // Convert file URL for external use (see above) - OUString externalUrl = translateToExternalUrl(rFileUrl); - if( externalUrl.isEmpty() ) - externalUrl = rFileUrl; - - if( !externalUrl.isEmpty() && !isDangerousUrl( externalUrl ) ) - { - NSString* pString = CreateNSString( externalUrl ); - NSURL* pURL = [NSURL URLWithString: pString]; - - if( pURL ) - { - NSDocumentController* pCtrl = [NSDocumentController sharedDocumentController]; - [pCtrl noteNewRecentDocumentURL: pURL]; - } - if( pString ) - [pString release]; - } -} - - -// ----------------------------------------------------------------------- - -SalTimer* AquaSalInstance::CreateSalTimer() -{ - return new AquaSalTimer(); -} - -// ----------------------------------------------------------------------- - -SalSystem* AquaSalInstance::CreateSalSystem() -{ - return new AquaSalSystem(); -} - -// ----------------------------------------------------------------------- - -SalBitmap* AquaSalInstance::CreateSalBitmap() -{ - return new QuartzSalBitmap(); -} - -// ----------------------------------------------------------------------- - -SalSession* AquaSalInstance::CreateSalSession() -{ - return NULL; -} - -// ----------------------------------------------------------------------- - -class MacImeStatus : public SalI18NImeStatus -{ -public: - MacImeStatus() {} - virtual ~MacImeStatus() {} - - // asks whether there is a status window available - // to toggle into menubar - virtual bool canToggle() { return false; } - virtual void toggle() {} -}; - -// ----------------------------------------------------------------------- - -SalI18NImeStatus* AquaSalInstance::CreateI18NImeStatus() -{ - return new MacImeStatus(); -} - -// YieldMutexReleaser -YieldMutexReleaser::YieldMutexReleaser() : mnCount( 0 ) -{ - SalData* pSalData = GetSalData(); - if( ! pSalData->mpFirstInstance->isNSAppThread() ) - { - SalData::ensureThreadAutoreleasePool(); - mnCount = pSalData->mpFirstInstance->ReleaseYieldMutex(); - } -} - -YieldMutexReleaser::~YieldMutexReleaser() -{ - if( mnCount != 0 ) - GetSalData()->mpFirstInstance->AcquireYieldMutex( mnCount ); -} - -CGImageRef CreateCGImage( const Image& rImage ) -{ - BitmapEx aBmpEx( rImage.GetBitmapEx() ); - Bitmap aBmp( aBmpEx.GetBitmap() ); - - if( ! aBmp || ! aBmp.ImplGetImpBitmap() ) - return NULL; - - // simple case, no transparency - QuartzSalBitmap* pSalBmp = static_cast(aBmp.ImplGetImpBitmap()->ImplGetSalBitmap()); - - if( ! pSalBmp ) - return NULL; - - CGImageRef xImage = NULL; - if( ! (aBmpEx.IsAlpha() || aBmpEx.IsTransparent() ) ) - xImage = pSalBmp->CreateCroppedImage( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight ); - else if( aBmpEx.IsAlpha() ) - { - AlphaMask aAlphaMask( aBmpEx.GetAlpha() ); - Bitmap aMask( aAlphaMask.GetBitmap() ); - QuartzSalBitmap* pMaskBmp = static_cast(aMask.ImplGetImpBitmap()->ImplGetSalBitmap()); - if( pMaskBmp ) - xImage = pSalBmp->CreateWithMask( *pMaskBmp, 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight ); - else - xImage = pSalBmp->CreateCroppedImage( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight ); - } - else if( aBmpEx.GetTransparentType() == TRANSPARENT_BITMAP ) - { - Bitmap aMask( aBmpEx.GetMask() ); - QuartzSalBitmap* pMaskBmp = static_cast(aMask.ImplGetImpBitmap()->ImplGetSalBitmap()); - if( pMaskBmp ) - xImage = pSalBmp->CreateWithMask( *pMaskBmp, 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight ); - else - xImage = pSalBmp->CreateCroppedImage( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight ); - } - else if( aBmpEx.GetTransparentType() == TRANSPARENT_COLOR ) - { - Color aTransColor( aBmpEx.GetTransparentColor() ); - SalColor nTransColor = MAKE_SALCOLOR( aTransColor.GetRed(), aTransColor.GetGreen(), aTransColor.GetBlue() ); - xImage = pSalBmp->CreateColorMask( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight, nTransColor ); - } - - return xImage; -} - -NSImage* CreateNSImage( const Image& rImage ) -{ - CGImageRef xImage = CreateCGImage( rImage ); - - if( ! xImage ) - return nil; - - Size aSize( rImage.GetSizePixel() ); - NSImage* pImage = [[NSImage alloc] initWithSize: NSMakeSize( aSize.Width(), aSize.Height() )]; - if( pImage ) - { - [pImage setFlipped: YES]; - [pImage lockFocus]; - - NSGraphicsContext* pContext = [NSGraphicsContext currentContext]; - CGContextRef rCGContext = reinterpret_cast([pContext graphicsPort]); - - const CGRect aDstRect = { {0, 0}, { static_cast(aSize.Width()), static_cast(aSize.Height()) } }; - CGContextDrawImage( rCGContext, aDstRect, xImage ); - - [pImage unlockFocus]; - } - - CGImageRelease( xImage ); - - return pImage; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/app/salnstimer.mm b/vcl/aqua/source/app/salnstimer.mm deleted file mode 100644 index 610c38212624..000000000000 --- a/vcl/aqua/source/app/salnstimer.mm +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/saltimer.h" -#include "aqua/salnstimer.h" -#include "aqua/salinst.h" -#include "aqua/saldata.hxx" - -#include "svdata.hxx" - -@implementation TimerCallbackCaller --(void)timerElapsed:(NSTimer*)pTimer -{ - (void)pTimer; - ImplSVData* pSVData = ImplGetSVData(); - if( AquaSalTimer::bDispatchTimer ) - { - if( pSVData->mpSalTimer ) - { - YIELD_GUARD; - pSVData->mpSalTimer->CallCallback(); - - // NSTimer does not end nextEventMatchingMask of NSApplication - // so we need to wakeup a waiting Yield to inform it something happened - GetSalData()->mpFirstInstance->wakeupYield(); - } - } -} -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/app/salsys.cxx b/vcl/aqua/source/app/salsys.cxx deleted file mode 100644 index 3cfcb3c1fe94..000000000000 --- a/vcl/aqua/source/app/salsys.cxx +++ /dev/null @@ -1,190 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "rtl/ustrbuf.hxx" - -#include "vcl/button.hxx" - -#include "aqua/salsys.h" -#include "aqua/saldata.hxx" -#include "aqua/salinst.h" -#include "quartz/utils.h" - -#include "svids.hrc" - - -// ======================================================================= - -AquaSalSystem::~AquaSalSystem() -{ -} - -unsigned int AquaSalSystem::GetDisplayScreenCount() -{ - NSArray* pScreens = [NSScreen screens]; - return pScreens ? [pScreens count] : 1; -} - -Rectangle AquaSalSystem::GetDisplayScreenPosSizePixel( unsigned int nScreen ) -{ - NSArray* pScreens = [NSScreen screens]; - Rectangle aRet; - NSScreen* pScreen = nil; - if( pScreens && nScreen < [pScreens count] ) - pScreen = [pScreens objectAtIndex: nScreen]; - else - pScreen = [NSScreen mainScreen]; - - if( pScreen ) - { - NSRect aFrame = [pScreen frame]; - aRet = Rectangle( Point( static_cast(aFrame.origin.x), static_cast(aFrame.origin.y) ), - Size( static_cast(aFrame.size.width), static_cast(aFrame.size.height) ) ); - } - return aRet; -} - -OUString AquaSalSystem::GetDisplayScreenName( unsigned int nScreen ) -{ - NSArray* pScreens = [NSScreen screens]; - OUString aRet; - if( nScreen < [pScreens count] ) - { - ResMgr* pMgr = ImplGetResMgr(); - if( pMgr ) - { - OUString aScreenName(ResId(SV_MAC_SCREENNNAME, *pMgr).toString()); - aRet = aScreenName.replaceAll("%d", OUString::number(nScreen)); - } - } - return aRet; -} - -static NSString* getStandardString( int nButtonId, bool bUseResources ) -{ - OUString aText; - if( bUseResources ) - { - aText = Button::GetStandardText( nButtonId ); - } - if( aText.isEmpty() ) // this is for bad cases, we might be missing the vcl resource - { - switch( nButtonId ) - { - case BUTTON_OK: aText = "OK";break; - case BUTTON_ABORT: aText = "Abort";break; - case BUTTON_CANCEL: aText = "Cancel";break; - case BUTTON_RETRY: aText = "Retry";break; - case BUTTON_YES: aText = "Yes";break; - case BUTTON_NO : aText = "No";break; - } - } - return aText.isEmpty() ? nil : CreateNSString( aText); -} - -int AquaSalSystem::ShowNativeMessageBox( const OUString& rTitle, - const OUString& rMessage, - int nButtonCombination, - int nDefaultButton, bool bUseResources) -{ - NSString* pTitle = CreateNSString( rTitle ); - NSString* pMessage = CreateNSString( rMessage ); - - struct id_entry - { - int nCombination; - int nDefaultButton; - int nTextIds[3]; - } aButtonIds[] = - { - { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK, { BUTTON_OK, -1, -1 } }, - { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK, { BUTTON_OK, BUTTON_CANCEL, -1 } }, - { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL, { BUTTON_CANCEL, BUTTON_OK, -1 } }, - { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_ABORT_RETRY_IGNORE, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_ABORT, { BUTTON_ABORT, BUTTON_IGNORE, BUTTON_RETRY } }, - { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_ABORT_RETRY_IGNORE, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_RETRY, { BUTTON_RETRY, BUTTON_IGNORE, BUTTON_ABORT } }, - { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_ABORT_RETRY_IGNORE, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_IGNORE, { BUTTON_IGNORE, BUTTON_IGNORE, BUTTON_ABORT } }, - { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_YES_NO_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_YES, { BUTTON_YES, BUTTON_NO, BUTTON_CANCEL } }, - { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_YES_NO_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO, { BUTTON_NO, BUTTON_YES, BUTTON_CANCEL } }, - { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_YES_NO_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL, { BUTTON_CANCEL, BUTTON_YES, BUTTON_NO } }, - { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_YES_NO, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_YES, { BUTTON_YES, BUTTON_NO, -1 } }, - { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_YES_NO, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO, { BUTTON_NO, BUTTON_YES, -1 } }, - { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_RETRY, { BUTTON_RETRY, BUTTON_CANCEL, -1 } }, - { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL, { BUTTON_CANCEL, BUTTON_RETRY, -1 } } - }; - - NSString* pDefText = nil; - NSString* pAltText = nil; - NSString* pOthText = nil; - - unsigned int nC; - for( nC = 0; nC < sizeof(aButtonIds)/sizeof(aButtonIds[0]); nC++ ) - { - if( aButtonIds[nC].nCombination == nButtonCombination ) - { - if( aButtonIds[nC].nDefaultButton == nDefaultButton ) - { - if( aButtonIds[nC].nTextIds[0] != -1 ) - pDefText = getStandardString( - aButtonIds[nC].nTextIds[0], bUseResources ); - if( aButtonIds[nC].nTextIds[1] != -1 ) - pAltText = getStandardString( - aButtonIds[nC].nTextIds[1], bUseResources ); - if( aButtonIds[nC].nTextIds[2] != -1 ) - pOthText = getStandardString( - aButtonIds[nC].nTextIds[2], bUseResources ); - break; - } - } - } - - - int nResult = NSRunAlertPanel( pTitle, pMessage, pDefText, pAltText, pOthText ); - - if( pTitle ) - [pTitle release]; - if( pMessage ) - [pMessage release]; - if( pDefText ) - [pDefText release]; - if( pAltText ) - [pAltText release]; - if( pOthText ) - [pOthText release]; - - int nRet = 0; - if( nC < sizeof(aButtonIds)/sizeof(aButtonIds[0]) && nResult >= 1 && nResult <= 3 ) - { - int nPressed = aButtonIds[nC].nTextIds[nResult-1]; - switch( nPressed ) - { - case BUTTON_NO: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO; break; - case BUTTON_YES: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_YES; break; - case BUTTON_OK: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK; break; - case BUTTON_CANCEL: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL; break; - case BUTTON_ABORT: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_ABORT; break; - case BUTTON_RETRY: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_RETRY; break; - case BUTTON_IGNORE: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_IGNORE; break; - } - } - - return nRet; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/app/saltimer.cxx b/vcl/aqua/source/app/saltimer.cxx deleted file mode 100644 index 40ff26e7967c..000000000000 --- a/vcl/aqua/source/app/saltimer.cxx +++ /dev/null @@ -1,126 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/saltimer.h" -#include "aqua/salnstimer.h" -#include "aqua/saldata.hxx" -#include "aqua/salframe.h" -#include "aqua/salinst.h" - -// ======================================================================= - -NSTimer* AquaSalTimer::pRunningTimer = nil; -bool AquaSalTimer::bDispatchTimer = false; - - -void ImplSalStartTimer( sal_uLong nMS ) -{ - SalData* pSalData = GetSalData(); - if( pSalData->mpFirstInstance->isNSAppThread() ) - { - AquaSalTimer::bDispatchTimer = true; - NSTimeInterval aTI = double(nMS)/1000.0; - if( AquaSalTimer::pRunningTimer != nil ) - { - if( [AquaSalTimer::pRunningTimer timeInterval] == aTI ) - // set new fire date - [AquaSalTimer::pRunningTimer setFireDate: [NSDate dateWithTimeIntervalSinceNow: aTI]]; - else - { - [AquaSalTimer::pRunningTimer invalidate]; - AquaSalTimer::pRunningTimer = nil; - } - } - if( AquaSalTimer::pRunningTimer == nil ) - { - AquaSalTimer::pRunningTimer = [NSTimer scheduledTimerWithTimeInterval: aTI - target: [[[TimerCallbackCaller alloc] init] autorelease] - selector: @selector(timerElapsed:) - userInfo: nil - repeats: YES]; - /* #i84055# add timer to tracking run loop mode, - so they also elapse while e.g. life resize - */ - [[NSRunLoop currentRunLoop] addTimer: AquaSalTimer::pRunningTimer forMode: NSEventTrackingRunLoopMode]; - } - } - else - { - SalData::ensureThreadAutoreleasePool(); - // post an event so we can get into the main thread - NSPoint aPt = { 0, 0 }; - NSEvent* pEvent = [NSEvent otherEventWithType: NSApplicationDefined - location: aPt - modifierFlags: 0 - timestamp: [NSDate timeIntervalSinceReferenceDate] - windowNumber: 0 - context: nil - subtype: AquaSalInstance::AppStartTimerEvent - data1: (int)nMS - data2: 0 ]; - if( pEvent ) - [NSApp postEvent: pEvent atStart: YES]; - } -} - -void ImplSalStopTimer() -{ - AquaSalTimer::bDispatchTimer = false; -} - -void AquaSalTimer::handleStartTimerEvent( NSEvent* pEvent ) -{ - ImplSVData* pSVData = ImplGetSVData(); - if( pSVData->mpSalTimer ) - { - NSTimeInterval posted = [pEvent timestamp] + NSTimeInterval([pEvent data1])/1000.0; - NSTimeInterval current = [NSDate timeIntervalSinceReferenceDate]; - if( (posted - current) <= 0.0 ) - { - YIELD_GUARD; - // timer already elapsed since event posted - pSVData->mpSalTimer->CallCallback(); - } - ImplSalStartTimer( sal_uLong( [pEvent data1] ) ); - } - -} - -AquaSalTimer::AquaSalTimer( ) -{ -} - -AquaSalTimer::~AquaSalTimer() -{ - ImplSalStopTimer(); -} - -void AquaSalTimer::Start( sal_uLong nMS ) -{ - ImplSalStartTimer( nMS ); -} - -void AquaSalTimer::Stop() -{ - ImplSalStopTimer(); -} - - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/app/vclnsapp.mm b/vcl/aqua/source/app/vclnsapp.mm deleted file mode 100644 index 7c55f8e6c318..000000000000 --- a/vcl/aqua/source/app/vclnsapp.mm +++ /dev/null @@ -1,517 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include - -#include "sal/config.h" - -#include - -#include "vcl/window.hxx" -#include "vcl/svapp.hxx" -#include "vcl/cmdevt.hxx" - -#include "aqua/vclnsapp.h" -#include "aqua/salinst.h" -#include "aqua/saldata.hxx" -#include "aqua/salframe.h" -#include "aqua/salframeview.h" -#include "quartz/utils.h" - -#include "impimagetree.hxx" - -#include "premac.h" -#include -#import "Carbon/Carbon.h" -#import "apple_remote/RemoteControl.h" -#include "postmac.h" - - -@implementation CocoaThreadEnabler --(void)enableCocoaThreads:(id)param -{ - // do nothing, this is just to start an NSThread and therefore put - // Cocoa into multithread mode - (void)param; -} -@end - -// If you wonder how this VCL_NSApplication stuff works, one thing you -// might have missed is that the NSPrincipalClass property in -// desktop/macosx/Info.plist has the value VCL_NSApplication. - -@implementation VCL_NSApplication --(void)sendEvent:(NSEvent*)pEvent -{ - NSEventType eType = [pEvent type]; - if( eType == NSApplicationDefined ) - GetSalData()->mpFirstInstance->handleAppDefinedEvent( pEvent ); - else if( eType == NSKeyDown && ([pEvent modifierFlags] & NSCommandKeyMask) != 0 ) - { - NSWindow* pKeyWin = [NSApp keyWindow]; - if( pKeyWin && [pKeyWin isKindOfClass: [SalFrameWindow class]] ) - { - AquaSalFrame* pFrame = [(SalFrameWindow*)pKeyWin getSalFrame]; - // handle Cmd-W - // FIXME: the correct solution would be to handle this in framework - // in the menu code - // however that is currently being revised, so let's use a preliminary solution here - // this hack is based on assumption - // a) Cmd-W is the same in all languages in OOo's menu conig - // b) Cmd-W is the same in all languages in on MacOS - // for now this seems to be true - unsigned int nModMask = ([pEvent modifierFlags] & (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask)); - if( (pFrame->mnStyleMask & NSClosableWindowMask) != 0 ) - { - if( nModMask == NSCommandKeyMask - && [[pEvent charactersIgnoringModifiers] isEqualToString: @"w"] ) - { - // Note: gcc 4.2.1 (in the 10.6 SDK) tells us - // 'NSWindow' may not respond to - // '-windowShouldClose:' . Is that a bogus - // warning, or is this code bogus? No idea. - // Anyway, so that we can compile also against - // this SDK with -Werror, use objc_msgSend - // instead. - - // Instead of: - // [pFrame->getNSWindow() windowShouldClose: nil]; - // do: - objc_msgSend(pFrame->getNSWindow(), @selector(windowShouldClose:), nil); - - return; - } - } - - /* - * #i98949# - Cmd-M miniaturize window, Cmd-Option-M miniaturize all windows - */ - if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"m"] ) - { - if ( nModMask == NSCommandKeyMask && ([pFrame->getNSWindow() styleMask] & NSMiniaturizableWindowMask) ) - { - [pFrame->getNSWindow() performMiniaturize: nil]; - return; - } - - if ( nModMask == ( NSCommandKeyMask | NSAlternateKeyMask ) ) - { - [NSApp miniaturizeAll: nil]; - return; - } - } - - // #i90083# handle frame switching - // FIXME: lousy workaround - if( (nModMask & (NSControlKeyMask|NSAlternateKeyMask)) == 0 ) - { - if( [[pEvent characters] isEqualToString: @"<"] || - [[pEvent characters] isEqualToString: @"~"] ) - { - [self cycleFrameForward: pFrame]; - return; - } - else if( [[pEvent characters] isEqualToString: @">"] || - [[pEvent characters] isEqualToString: @"`"] ) - { - [self cycleFrameBackward: pFrame]; - return; - } - } - - // get information whether the event was handled; keyDown returns nothing - GetSalData()->maKeyEventAnswer[ pEvent ] = false; - bool bHandled = false; - - // dispatch to view directly to avoid the key event being consumed by the menubar - // popup windows do not get the focus, so they don't get these either - // simplest would be dispatch this to the key window always if it is without parent - // however e.g. in document we want the menu shortcut if e.g. the stylist has focus - if( pFrame->mpParent && (pFrame->mnStyle & SAL_FRAME_STYLE_FLOAT) == 0 ) - { - [[pKeyWin contentView] keyDown: pEvent]; - bHandled = GetSalData()->maKeyEventAnswer[ pEvent ]; - } - - // see whether the main menu consumes this event - // if not, we want to dispatch it ourselves. Unless we do this "trick" - // the main menu just beeps for an unknown or disabled key equivalent - // and swallows the event wholesale - NSMenu* pMainMenu = [NSApp mainMenu]; - if( ! bHandled && (pMainMenu == 0 || ! [pMainMenu performKeyEquivalent: pEvent]) ) - { - [[pKeyWin contentView] keyDown: pEvent]; - bHandled = GetSalData()->maKeyEventAnswer[ pEvent ]; - } - else - bHandled = true; // event handled already or main menu just handled it - - GetSalData()->maKeyEventAnswer.erase( pEvent ); - if( bHandled ) - return; - } - else if( pKeyWin ) - { - // #i94601# a window not of vcl's making has the focus. - // Since our menus do not invoke the usual commands - // try to play nice with native windows like the file dialog - // and emulate them - // precondition: this ONLY works because CMD-V (paste), CMD-C (copy) and CMD-X (cut) are - // NOT localized, that is the same in all locales. Should this be - // different in any locale, this hack will fail. - unsigned int nModMask = ([pEvent modifierFlags] & (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask)); - if( nModMask == NSCommandKeyMask ) - { - - if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"v"] ) - { - if( [NSApp sendAction: @selector(paste:) to: nil from: nil] ) - return; - } - else if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"c"] ) - { - if( [NSApp sendAction: @selector(copy:) to: nil from: nil] ) - return; - } - else if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"x"] ) - { - if( [NSApp sendAction: @selector(cut:) to: nil from: nil] ) - return; - } - } - } - } - [super sendEvent: pEvent]; -} - --(void)sendSuperEvent:(NSEvent*)pEvent -{ - [super sendEvent: pEvent]; -} - --(void)cycleFrameForward: (AquaSalFrame*)pCurFrame -{ - // find current frame in list - std::list< AquaSalFrame* >& rFrames( GetSalData()->maFrames ); - std::list< AquaSalFrame* >::iterator it = rFrames.begin(); - for( ; it != rFrames.end() && *it != pCurFrame; ++it ) - ; - if( it != rFrames.end() ) - { - // now find the next frame (or end) - do - { - ++it; - if( it != rFrames.end() ) - { - if( (*it)->mpDockMenuEntry != NULL && - (*it)->mbShown ) - { - [(*it)->getNSWindow() makeKeyAndOrderFront: NSApp]; - return; - } - } - } while( it != rFrames.end() ); - // cycle around, find the next up to pCurFrame - it = rFrames.begin(); - while( *it != pCurFrame ) - { - if( (*it)->mpDockMenuEntry != NULL && - (*it)->mbShown ) - { - [(*it)->getNSWindow() makeKeyAndOrderFront: NSApp]; - return; - } - ++it; - } - } -} - --(void)cycleFrameBackward: (AquaSalFrame*)pCurFrame -{ - // do the same as cycleFrameForward only with a reverse iterator - - // find current frame in list - std::list< AquaSalFrame* >& rFrames( GetSalData()->maFrames ); - std::list< AquaSalFrame* >::reverse_iterator it = rFrames.rbegin(); - for( ; it != rFrames.rend() && *it != pCurFrame; ++it ) - ; - if( it != rFrames.rend() ) - { - // now find the next frame (or end) - do - { - ++it; - if( it != rFrames.rend() ) - { - if( (*it)->mpDockMenuEntry != NULL && - (*it)->mbShown ) - { - [(*it)->getNSWindow() makeKeyAndOrderFront: NSApp]; - return; - } - } - } while( it != rFrames.rend() ); - // cycle around, find the next up to pCurFrame - it = rFrames.rbegin(); - while( *it != pCurFrame ) - { - if( (*it)->mpDockMenuEntry != NULL && - (*it)->mbShown ) - { - [(*it)->getNSWindow() makeKeyAndOrderFront: NSApp]; - return; - } - ++it; - } - } -} - --(NSMenu*)applicationDockMenu:(NSApplication *)sender -{ - (void)sender; - return AquaSalInstance::GetDynamicDockMenu(); -} - --(BOOL)application: (NSApplication*)app openFile: (NSString*)pFile -{ - (void)app; - std::vector aFile; - aFile.push_back( GetOUString( pFile ) ); - if( ! AquaSalInstance::isOnCommandLine( aFile[0] ) ) - { - const ApplicationEvent* pAppEvent = new ApplicationEvent(ApplicationEvent::TYPE_OPEN, aFile); - AquaSalInstance::aAppEventList.push_back( pAppEvent ); - } - return YES; -} - --(void)application: (NSApplication*) app openFiles: (NSArray*)files -{ - (void)app; - std::vector aFileList; - - NSEnumerator* it = [files objectEnumerator]; - NSString* pFile = nil; - - while( (pFile = [it nextObject]) != nil ) - { - const rtl::OUString aFile( GetOUString( pFile ) ); - if( ! AquaSalInstance::isOnCommandLine( aFile ) ) - { - aFileList.push_back( aFile ); - } - } - - if( !aFileList.empty() ) - { - // we have no back channel here, we have to assume success, in which case - // replyToOpenOrPrint does not need to be called according to documentation - // [app replyToOpenOrPrint: NSApplicationDelegateReplySuccess]; - const ApplicationEvent* pAppEvent = new ApplicationEvent(ApplicationEvent::TYPE_OPEN, aFileList); - AquaSalInstance::aAppEventList.push_back( pAppEvent ); - } -} - --(BOOL)application: (NSApplication*)app printFile: (NSString*)pFile -{ - (void)app; - std::vector aFile; - aFile.push_back( GetOUString( pFile ) ); - const ApplicationEvent* pAppEvent = new ApplicationEvent(ApplicationEvent::TYPE_PRINT, aFile); - AquaSalInstance::aAppEventList.push_back( pAppEvent ); - return YES; -} --(NSApplicationPrintReply)application: (NSApplication *) app printFiles:(NSArray *)files withSettings: (NSDictionary *)printSettings showPrintPanels:(BOOL)bShowPrintPanels -{ - (void)app; - (void)printSettings; - (void)bShowPrintPanels; - // currently ignores print settings an bShowPrintPanels - std::vector aFileList; - - NSEnumerator* it = [files objectEnumerator]; - NSString* pFile = nil; - - while( (pFile = [it nextObject]) != nil ) - { - aFileList.push_back( GetOUString( pFile ) ); - } - const ApplicationEvent* pAppEvent = new ApplicationEvent(ApplicationEvent::TYPE_PRINT, aFileList); - AquaSalInstance::aAppEventList.push_back( pAppEvent ); - // we have no back channel here, we have to assume success - // correct handling would be NSPrintingReplyLater and then send [app replyToOpenOrPrint] - return NSPrintingSuccess; -} - --(NSApplicationTerminateReply)applicationShouldTerminate: (NSApplication *) app -{ - (void)app; - NSApplicationTerminateReply aReply = NSTerminateNow; - { - YIELD_GUARD; - - SalData* pSalData = GetSalData(); - if( ! pSalData->maFrames.empty() ) - { - // the following QueryExit will likely present a message box, activate application - [NSApp activateIgnoringOtherApps: YES]; - aReply = pSalData->maFrames.front()->CallCallback( SALEVENT_SHUTDOWN, NULL ) ? NSTerminateCancel : NSTerminateNow; - } - - if( aReply == NSTerminateNow ) - { - ApplicationEvent aEv(ApplicationEvent::TYPE_PRIVATE_DOSHUTDOWN); - GetpApp()->AppEvent( aEv ); - ImplImageTreeSingletonRef()->shutDown(); - // DeInitVCL should be called in ImplSVMain - unless someon _exits first which - // can occur in Desktop::doShutdown for example - } - } - - return aReply; -} - --(void)systemColorsChanged: (NSNotification*) pNotification -{ - (void)pNotification; - YIELD_GUARD; - - const SalData* pSalData = GetSalData(); - if( !pSalData->maFrames.empty() ) - pSalData->maFrames.front()->CallCallback( SALEVENT_SETTINGSCHANGED, NULL ); -} - --(void)screenParametersChanged: (NSNotification*) pNotification -{ - (void)pNotification; - YIELD_GUARD; - - SalData* pSalData = GetSalData(); - std::list< AquaSalFrame* >::iterator it; - for( it = pSalData->maFrames.begin(); it != pSalData->maFrames.end(); ++it ) - { - (*it)->screenParametersChanged(); - } -} - --(void)scrollbarVariantChanged: (NSNotification*) pNotification -{ - (void)pNotification; - GetSalData()->mpFirstInstance->delayedSettingsChanged( true ); -} - --(void)scrollbarSettingsChanged: (NSNotification*) pNotification -{ - (void)pNotification; - GetSalData()->mpFirstInstance->delayedSettingsChanged( false ); -} - --(void)addFallbackMenuItem: (NSMenuItem*)pNewItem -{ - AquaSalMenu::addFallbackMenuItem( pNewItem ); -} - --(void)removeFallbackMenuItem: (NSMenuItem*)pItem -{ - AquaSalMenu::removeFallbackMenuItem( pItem ); -} - --(void)addDockMenuItem: (NSMenuItem*)pNewItem -{ - NSMenu* pDock = AquaSalInstance::GetDynamicDockMenu(); - [pDock insertItem: pNewItem atIndex: [pDock numberOfItems]]; -} - -// for Apple Remote implementation - -#if !HAVE_FEATURE_MACOSX_SANDBOX -- (void)applicationWillBecomeActive:(NSNotification *)pNotification -{ - (void)pNotification; - SalData* pSalData = GetSalData(); - if( pSalData->mpMainController && pSalData->mpMainController->remoteControl) - { - // [remoteControl startListening: self]; - // does crash because the right thing to do is - // [GetSalData()->mpMainController->remoteControl startListening: self]; - // but the instance variable 'remoteControl' is declared protected - // workaround : declare remoteControl instance variable as public in RemoteMainController.m - - [pSalData->mpMainController->remoteControl startListening: self]; -#ifdef DEBUG - NSLog(@"Apple Remote will become active - Using remote controls"); -#endif - } - for( std::list< AquaSalFrame* >::const_iterator it = pSalData->maPresentationFrames.begin(); - it != pSalData->maPresentationFrames.end(); ++it ) - { - NSWindow* pNSWindow = (*it)->getNSWindow(); - [pNSWindow setLevel: NSPopUpMenuWindowLevel]; - if( [pNSWindow isVisible] ) - [pNSWindow orderFront: NSApp]; - } -} - -- (void)applicationWillResignActive:(NSNotification *)pNotification -{ - (void)pNotification; - SalData* pSalData = GetSalData(); - if( pSalData->mpMainController && pSalData->mpMainController->remoteControl) - { - // [remoteControl stopListening: self]; - // does crash because the right thing to do is - // [GetSalData()->mpMainController->remoteControl stopListening: self]; - // but the instance variable 'remoteControl' is declared protected - // workaround : declare remoteControl instance variable as public in RemoteMainController.m - - [pSalData->mpMainController->remoteControl stopListening: self]; -#ifdef DEBUG - NSLog(@"Apple Remote will resign active - Releasing remote controls"); -#endif - } - for( std::list< AquaSalFrame* >::const_iterator it = pSalData->maPresentationFrames.begin(); - it != pSalData->maPresentationFrames.end(); ++it ) - { - [(*it)->getNSWindow() setLevel: NSNormalWindowLevel]; - } -} -#endif - -- (BOOL)applicationShouldHandleReopen: (NSApplication*)pApp hasVisibleWindows: (BOOL) bWinVisible -{ - (void)pApp; - (void)bWinVisible; - NSObject* pHdl = GetSalData()->mpDockIconClickHandler; - if( pHdl && [pHdl respondsToSelector: @selector(dockIconClicked:)] ) - { - [pHdl performSelector:@selector(dockIconClicked:) withObject: self]; - } - return YES; -} - --(void)setDockIconClickHandler: (NSObject*)pHandler -{ - GetSalData()->mpDockIconClickHandler = pHandler; -} - - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/DataFlavorMapping.cxx b/vcl/aqua/source/dtrans/DataFlavorMapping.cxx deleted file mode 100644 index c5a79b368990..000000000000 --- a/vcl/aqua/source/dtrans/DataFlavorMapping.cxx +++ /dev/null @@ -1,741 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include "sal/config.h" - -#include -#include "HtmlFmtFlt.hxx" -#include "PictToBmpFlt.hxx" -#include "com/sun/star/datatransfer/UnsupportedFlavorException.hpp" -#include "com/sun/star/datatransfer/XMimeContentType.hpp" -#include "com/sun/star/datatransfer/MimeContentTypeFactory.hpp" -#include "com/sun/star/uno/Sequence.hxx" -#include "comphelper/processfactory.hxx" - -#include -#include - -#include -#include - -#include -#include -#include - -using namespace ::com::sun::star::datatransfer; -using namespace ::com::sun::star::uno; -using namespace com::sun::star::lang; -using namespace cppu; -using namespace std; - - -namespace // private -{ - /* Determine whether or not a DataFlavor is valid. - */ - bool isValidFlavor(const DataFlavor& aFlavor) - { - size_t len = aFlavor.MimeType.getLength(); - Type dtype = aFlavor.DataType; - return ((len > 0) && ((dtype == getCppuType((Sequence*)0)) || (dtype == getCppuType( (OUString*)0 )))); - } - - OUString NSStringToOUString(NSString* cfString) - { - BOOST_ASSERT(cfString && "Invalid parameter"); - - const char* utf8Str = [cfString UTF8String]; - unsigned int len = rtl_str_getLength(utf8Str); - - return OUString(utf8Str, len, RTL_TEXTENCODING_UTF8); - } - - NSString* OUStringToNSString(const OUString& ustring) - { - OString utf8Str = OUStringToOString(ustring, RTL_TEXTENCODING_UTF8); - return [NSString stringWithCString: utf8Str.getStr() encoding: NSUTF8StringEncoding]; - } - - NSString* PBTYPE_SODX = @"application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\""; - NSString* PBTYPE_SESX = @"application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\""; - NSString* PBTYPE_SLSDX = @"application/x-openoffice-linksrcdescriptor-xml;windows_formatname=\"Star Link Source Descriptor (XML)\""; - NSString* PBTYPE_ESX = @"application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\""; - NSString* PBTYPE_LSX = @"application/x-openoffice-link-source-xml;windows_formatname=\"Star Link Source (XML)\""; - NSString* PBTYPE_EOX = @"application/x-openoffice-embedded-obj-xml;windows_formatname=\"Star Embedded Object (XML)\""; - NSString* PBTYPE_SVXB = @"application/x-openoffice-svbx;windows_formatname=\"SVXB (StarView Bitmap/Animation)\""; - NSString* PBTYPE_GDIMF = @"application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""; - NSString* PBTYPE_WMF = @"application/x-openoffice-wmf;windows_formatname=\"Image WMF\""; - NSString* PBTYPE_EMF = @"application/x-openoffice-emf;windows_formatname=\"Image EMF\""; - - NSString* PBTYPE_DUMMY_INTERNAL = @"application/x-openoffice-internal"; - - const char* FLAVOR_SODX = "application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\""; - const char* FLAVOR_SESX = "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\""; - const char* FLAVOR_SLSDX = "application/x-openoffice-linksrcdescriptor-xml;windows_formatname=\"Star Link Source Descriptor (XML)\""; - const char* FLAVOR_ESX = "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\""; - const char* FLAVOR_LSX = "application/x-openoffice-link-source-xml;windows_formatname=\"Star Link Source (XML)\""; - const char* FLAVOR_EOX = "application/x-openoffice-embedded-obj-xml;windows_formatname=\"Star Embedded Object (XML)\""; - const char* FLAVOR_SVXB = "application/x-openoffice-svbx;windows_formatname=\"SVXB (StarView Bitmap/Animation)\""; - const char* FLAVOR_GDIMF = "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""; - const char* FLAVOR_WMF = "application/x-openoffice-wmf;windows_formatname=\"Image WMF\""; - const char* FLAVOR_EMF = "application/x-openoffice-emf;windows_formatname=\"Image EMF\""; - - const char* FLAVOR_DUMMY_INTERNAL = "application/x-openoffice-internal"; - - - struct FlavorMap - { - NSString* SystemFlavor; - const char* OOoFlavor; - const char* HumanPresentableName; - bool DataTypeOUString; // sequence otherwise - }; - - /* At the moment it appears as if only MS Office pastes "public.html" to the clipboard. - */ - FlavorMap flavorMap[] = - { - { NSStringPboardType, "text/plain;charset=utf-16", "Unicode Text (UTF-16)", true }, - { NSRTFPboardType, "text/richtext", "Rich Text Format", false }, - { NSTIFFPboardType, "image/png", "Portable Network Graphics", false }, - { NSHTMLPboardType, "text/html", "Plain Html", false }, - { NSFilenamesPboardType, "application/x-openoffice-filelist;windows_formatname=\"FileList\"", "FileList", false }, - { PBTYPE_SESX, FLAVOR_SESX, "Star Embed Source (XML)", false }, - { PBTYPE_SLSDX, FLAVOR_SLSDX, "Star Link Source Descriptor (XML)", false }, - { PBTYPE_ESX, FLAVOR_ESX, "Star Embed Source (XML)", false }, - { PBTYPE_LSX, FLAVOR_LSX, "Star Link Source (XML)", false }, - { PBTYPE_EOX, FLAVOR_EOX, "Star Embedded Object (XML)", false }, - { PBTYPE_SVXB, FLAVOR_SVXB, "SVXB (StarView Bitmap/Animation", false }, - { PBTYPE_GDIMF, FLAVOR_GDIMF, "GDIMetaFile", false }, - { PBTYPE_WMF, FLAVOR_WMF, "Windows MetaFile", false }, - { PBTYPE_EMF, FLAVOR_EMF, "Windows Enhanced MetaFile", false }, - { PBTYPE_SODX, FLAVOR_SODX, "Star Object Descriptor (XML)", false }, - { PBTYPE_DUMMY_INTERNAL, FLAVOR_DUMMY_INTERNAL, "internal data",false } - }; - - - #define SIZE_FLAVOR_MAP (sizeof(flavorMap)/sizeof(FlavorMap)) - - - inline bool isByteSequenceType(const Type& theType) - { - return (theType == getCppuType((Sequence*)0)); - } - - inline bool isOUStringType(const Type& theType) - { - return (theType == getCppuType( (OUString*)0 )); - } - -} // namespace private - - -//########################### - -/* A base class for other data provider. - */ -class DataProviderBaseImpl : public DataProvider -{ -public: - DataProviderBaseImpl(const Any& data); - DataProviderBaseImpl(id data); - virtual ~DataProviderBaseImpl(); - -protected: - Any mData; - //NSData* mSystemData; - id mSystemData; -}; - -DataProviderBaseImpl::DataProviderBaseImpl(const Any& data) : - mData(data), - mSystemData(nil) -{ -} - -DataProviderBaseImpl::DataProviderBaseImpl(id data) : - mSystemData(data) -{ - [mSystemData retain]; -} - - -DataProviderBaseImpl::~DataProviderBaseImpl() -{ - if (mSystemData) - { - [mSystemData release]; - } -} - -//################################# - -class UniDataProvider : public DataProviderBaseImpl -{ -public: - UniDataProvider(const Any& data); - - UniDataProvider(NSData* data); - - virtual NSData* getSystemData(); - - virtual Any getOOoData(); -}; - -UniDataProvider::UniDataProvider(const Any& data) : - DataProviderBaseImpl(data) -{ -} - -UniDataProvider::UniDataProvider(NSData* data) : - DataProviderBaseImpl(data) -{ -} - -NSData* UniDataProvider::getSystemData() -{ - OUString ustr; - mData >>= ustr; - - OString strUtf8; - ustr.convertToString(&strUtf8, RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS); - - return [NSData dataWithBytes: strUtf8.getStr() length: strUtf8.getLength()]; -} - -Any UniDataProvider::getOOoData() -{ - Any oOOData; - - if (mSystemData) - { - oOOData = makeAny(OUString(reinterpret_cast([mSystemData bytes]), - [mSystemData length], - RTL_TEXTENCODING_UTF8)); - } - else - { - oOOData = mData; - } - - return oOOData; -} - -//########################### - -class ByteSequenceDataProvider : public DataProviderBaseImpl -{ -public: - ByteSequenceDataProvider(const Any& data); - - ByteSequenceDataProvider(NSData* data); - - virtual NSData* getSystemData(); - - virtual Any getOOoData(); -}; - -ByteSequenceDataProvider::ByteSequenceDataProvider(const Any& data) : - DataProviderBaseImpl(data) -{ -} - -ByteSequenceDataProvider::ByteSequenceDataProvider(NSData* data) : - DataProviderBaseImpl(data) -{ -} - - -NSData* ByteSequenceDataProvider::getSystemData() -{ - Sequence rawData; - mData >>= rawData; - - return [NSData dataWithBytes: rawData.getArray() length: rawData.getLength()]; -} - -Any ByteSequenceDataProvider::getOOoData() -{ - Any oOOData; - - if (mSystemData) - { - unsigned int flavorDataLength = [mSystemData length]; - Sequence byteSequence; - byteSequence.realloc(flavorDataLength); - memcpy(byteSequence.getArray(), [mSystemData bytes], flavorDataLength); - oOOData = makeAny(byteSequence); - } - else - { - oOOData = mData; - } - - return oOOData; -} - - -//########################### - -class HTMLFormatDataProvider : public DataProviderBaseImpl -{ -public: - HTMLFormatDataProvider(const Any& data); - - HTMLFormatDataProvider(NSData* data); - - virtual NSData* getSystemData(); - - virtual Any getOOoData(); -}; - -HTMLFormatDataProvider::HTMLFormatDataProvider(const Any& data) : - DataProviderBaseImpl(data) -{ -} - -HTMLFormatDataProvider::HTMLFormatDataProvider(NSData* data) : - DataProviderBaseImpl(data) -{ -} - -NSData* HTMLFormatDataProvider::getSystemData() -{ - Sequence textHtmlData; - mData >>= textHtmlData; - - Sequence htmlFormatData = TextHtmlToHTMLFormat(textHtmlData); - - return [NSData dataWithBytes: htmlFormatData.getArray() length: htmlFormatData.getLength()]; -} - -Any HTMLFormatDataProvider::getOOoData() -{ - Any oOOData; - - if (mSystemData) - { - unsigned int flavorDataLength = [mSystemData length]; - Sequence unkHtmlData; - - unkHtmlData.realloc(flavorDataLength); - memcpy(unkHtmlData.getArray(), [mSystemData bytes], flavorDataLength); - - Sequence* pPlainHtml = &unkHtmlData; - Sequence plainHtml; - - if (isHTMLFormat(unkHtmlData)) - { - plainHtml = HTMLFormatToTextHtml(unkHtmlData); - pPlainHtml = &plainHtml; - } - - oOOData = makeAny(*pPlainHtml); - } - else - { - oOOData = mData; - } - - return oOOData; -} - -//########################### - -class PNGDataProvider : public DataProviderBaseImpl -{ - NSBitmapImageFileType meImageType; -public: - PNGDataProvider( const Any&, NSBitmapImageFileType); - - PNGDataProvider( NSData*, NSBitmapImageFileType); - - virtual NSData* getSystemData(); - - virtual Any getOOoData(); -}; - -PNGDataProvider::PNGDataProvider( const Any& data, NSBitmapImageFileType eImageType) : - DataProviderBaseImpl(data), - meImageType( eImageType ) -{ -} - -PNGDataProvider::PNGDataProvider( NSData* data, NSBitmapImageFileType eImageType) : - DataProviderBaseImpl(data), - meImageType( eImageType ) -{ -} - -NSData* PNGDataProvider::getSystemData() -{ - Sequence pngData; - mData >>= pngData; - - Sequence imgData; - NSData* sysData = NULL; - if( PNGToImage( pngData, imgData, meImageType)) - sysData = [NSData dataWithBytes: imgData.getArray() length: imgData.getLength()]; - - return sysData; -} - -/* The AOO 'PCT' filter is not yet good enough to be used - and there is no flavor defined for exchanging 'PCT' with AOO - so we convert 'PCT' to a PNG and provide this to AOO -*/ -Any PNGDataProvider::getOOoData() -{ - Any oOOData; - - if( mSystemData) - { - const unsigned int flavorDataLength = [mSystemData length]; - Sequence imgData( flavorDataLength); - memcpy( imgData.getArray(), [mSystemData bytes], flavorDataLength); - - Sequence pngData; - if( ImageToPNG( imgData, pngData, meImageType)) - oOOData = makeAny( pngData); - } - else - { - oOOData = mData; - } - - return oOOData; -} - -//###################### - -class FileListDataProvider : public DataProviderBaseImpl -{ -public: - FileListDataProvider(const Any& data); - FileListDataProvider(NSArray* data); - - virtual NSData* getSystemData(); - virtual Any getOOoData(); -}; - -FileListDataProvider::FileListDataProvider(const Any& data) : - DataProviderBaseImpl(data) -{ -} - -FileListDataProvider::FileListDataProvider(NSArray* data) : - DataProviderBaseImpl(data) -{ -} - -NSData* FileListDataProvider::getSystemData() -{ - return [NSData data]; -} - -Any FileListDataProvider::getOOoData() -{ - Any oOOData; - - if (mSystemData) - { - size_t length = [mSystemData count]; - size_t lenSeqRequired = 0; - - for (size_t i = 0; i < length; i++) - { - NSString* fname = [mSystemData objectAtIndex: i]; - lenSeqRequired += [fname maximumLengthOfBytesUsingEncoding: NSUnicodeStringEncoding] + sizeof(unichar); - } - - Sequence oOOFileList(lenSeqRequired); - unichar* pBuffer = reinterpret_cast(oOOFileList.getArray()); - memset(pBuffer, 0, lenSeqRequired); - - for (size_t i = 0; i < length; i++) - { - NSString* fname = [mSystemData objectAtIndex: i]; - [fname getCharacters: pBuffer]; - size_t l = [fname length]; - pBuffer += l + 1; - } - - oOOData = makeAny(oOOFileList); - } - else - { - oOOData = mData; - } - - return oOOData; -} - -//########################### - -DataFlavorMapper::DataFlavorMapper() -{ - Reference xContext = comphelper::getProcessComponentContext(); - mrXMimeCntFactory = MimeContentTypeFactory::create( xContext ); -} - -DataFlavorMapper::~DataFlavorMapper() -{ - // release potential NSStrings - for( OfficeOnlyTypes::iterator it = maOfficeOnlyTypes.begin(); it != maOfficeOnlyTypes.end(); ++it ) - { - [it->second release]; - it->second = nil; - } -} - -DataFlavor DataFlavorMapper::systemToOpenOfficeFlavor(NSString* systemDataFlavor) const -{ - DataFlavor oOOFlavor; - - for (size_t i = 0; i < SIZE_FLAVOR_MAP; i++) - { - if ([systemDataFlavor caseInsensitiveCompare: flavorMap[i].SystemFlavor] == NSOrderedSame) - { - oOOFlavor.MimeType = OUString::createFromAscii(flavorMap[i].OOoFlavor); - oOOFlavor.HumanPresentableName = OUString::createFromAscii(flavorMap[i].HumanPresentableName); - oOOFlavor.DataType = flavorMap[i].DataTypeOUString ? getCppuType( (OUString*)0 ) : getCppuType((Sequence*)0); - return oOOFlavor; - } - } // for - - // look if this might be an internal type; if it comes in here it must have - // been through openOfficeToSystemFlavor before, so it should then be in the map - OUString aTryFlavor( NSStringToOUString( systemDataFlavor ) ); - if( maOfficeOnlyTypes.find( aTryFlavor ) != maOfficeOnlyTypes.end() ) - { - oOOFlavor.MimeType = aTryFlavor; - oOOFlavor.HumanPresentableName = OUString(); - oOOFlavor.DataType = getCppuType((Sequence*)0); - } - - return oOOFlavor; -} - -NSString* DataFlavorMapper::openOfficeToSystemFlavor(const DataFlavor& oOOFlavor, bool& rbInternal) const -{ - NSString* sysFlavor = NULL; - rbInternal = false; - - for( size_t i = 0; i < SIZE_FLAVOR_MAP; ++i ) - { - if (oOOFlavor.MimeType.startsWith(OUString::createFromAscii(flavorMap[i].OOoFlavor))) - { - sysFlavor = flavorMap[i].SystemFlavor; - } - } - - if(!sysFlavor) - { - rbInternal = true; - OfficeOnlyTypes::const_iterator it = maOfficeOnlyTypes.find( oOOFlavor.MimeType ); - - if( it == maOfficeOnlyTypes.end() ) - sysFlavor = maOfficeOnlyTypes[ oOOFlavor.MimeType ] = OUStringToNSString( oOOFlavor.MimeType ); - else - sysFlavor = it->second; - } - - return sysFlavor; -} - -NSString* DataFlavorMapper::openOfficeImageToSystemFlavor(NSPasteboard* pPasteboard) const -{ - NSArray *supportedTypes = [NSArray arrayWithObjects: NSTIFFPboardType, nil]; - NSString *sysFlavor = [pPasteboard availableTypeFromArray:supportedTypes]; - return sysFlavor; -} - -DataProviderPtr_t DataFlavorMapper::getDataProvider(NSString* systemFlavor, Reference rTransferable) const -{ - DataProviderPtr_t dp; - - try - { - DataFlavor oOOFlavor = systemToOpenOfficeFlavor(systemFlavor); - - Any data = rTransferable->getTransferData(oOOFlavor); - - if (isByteSequenceType(data.getValueType())) - { - /* - the HTMLFormatDataProvider prepends segment information to HTML - this is useful for exchange with MS Word (which brings this stuff from Windows) - but annoying for other applications. Since this extension is not a standard datatype - on the Mac, let us not provide but provide normal HTML - - if ([systemFlavor caseInsensitiveCompare: NSHTMLPboardType] == NSOrderedSame) - { - dp = DataProviderPtr_t(new HTMLFormatDataProvider(data)); - } - else - */ - if ([systemFlavor caseInsensitiveCompare: NSTIFFPboardType] == NSOrderedSame) - { - dp = DataProviderPtr_t( new PNGDataProvider( data, NSTIFFFileType)); - } - else if ([systemFlavor caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame) - { - dp = DataProviderPtr_t(new FileListDataProvider(data)); - } - else - { - dp = DataProviderPtr_t(new ByteSequenceDataProvider(data)); - } - } - else // Must be OUString type - { - SAL_WARN_IF( - !isOUStringType(data.getValueType()), "vcl", - "must be OUString type"); - dp = DataProviderPtr_t(new UniDataProvider(data)); - } - } - catch(UnsupportedFlavorException&) - { - // Somebody violates the contract of the clipboard - // interface @see XTransferable - } - - return dp; -} - -DataProviderPtr_t DataFlavorMapper::getDataProvider(const NSString* /*systemFlavor*/, NSArray* systemData) const -{ - return DataProviderPtr_t(new FileListDataProvider(systemData)); -} - -DataProviderPtr_t DataFlavorMapper::getDataProvider(const NSString* systemFlavor, NSData* systemData) const -{ - DataProviderPtr_t dp; - - if ([systemFlavor caseInsensitiveCompare: NSStringPboardType] == NSOrderedSame) - { - dp = DataProviderPtr_t(new UniDataProvider(systemData)); - } - else if ([systemFlavor caseInsensitiveCompare: NSHTMLPboardType] == NSOrderedSame) - { - dp = DataProviderPtr_t(new HTMLFormatDataProvider(systemData)); - } - else if ([systemFlavor caseInsensitiveCompare: NSTIFFPboardType] == NSOrderedSame) - { - dp = DataProviderPtr_t( new PNGDataProvider(systemData, NSTIFFFileType)); - } - else if ([systemFlavor caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame) - { - //dp = DataProviderPtr_t(new FileListDataProvider(systemData)); - } - else - { - dp = DataProviderPtr_t(new ByteSequenceDataProvider(systemData)); - } - - return dp; -} - -bool DataFlavorMapper::isValidMimeContentType(const OUString& contentType) const -{ - bool result = true; - - try - { - Reference xCntType(mrXMimeCntFactory->createMimeContentType(contentType)); - } - catch( IllegalArgumentException& ) - { - result = false; - } - - return result; -} - -NSArray* DataFlavorMapper::flavorSequenceToTypesArray(const com::sun::star::uno::Sequence& flavors) const -{ - sal_uInt32 nFlavors = flavors.getLength(); - NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity: 1]; - - bool bNeedDummyInternalFlavor(false); - - for (sal_uInt32 i = 0; i < nFlavors; i++) - { - if( flavors[i].MimeType.startsWith("image/bmp") ) - { - [array addObject: NSTIFFPboardType]; - } - else - { - NSString* str = openOfficeToSystemFlavor(flavors[i], bNeedDummyInternalFlavor); - - if (str != NULL) - { - [str retain]; - [array addObject: str]; - } - } - } - - // #i89462# #i90747# - // in case no system flavor was found to report - // report at least one so D&D between OOo targets works - if( [array count] == 0 || bNeedDummyInternalFlavor) - { - [array addObject: PBTYPE_DUMMY_INTERNAL]; - } - - return [array autorelease]; -} - -com::sun::star::uno::Sequence DataFlavorMapper::typesArrayToFlavorSequence(NSArray* types) const -{ - int nFormats = [types count]; - Sequence flavors; - - for (int i = 0; i < nFormats; i++) - { - NSString* sysFormat = [types objectAtIndex: i]; - DataFlavor oOOFlavor = systemToOpenOfficeFlavor(sysFormat); - - if (isValidFlavor(oOOFlavor)) - { - flavors.realloc(flavors.getLength() + 1); - flavors[flavors.getLength() - 1] = oOOFlavor; - } - } - - return flavors; -} - - -NSArray* DataFlavorMapper::getAllSupportedPboardTypes() const -{ - NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity: SIZE_FLAVOR_MAP]; - - for (sal_uInt32 i = 0; i < SIZE_FLAVOR_MAP; i++) - { - [array addObject: flavorMap[i].SystemFlavor]; - } - - return [array autorelease]; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/DataFlavorMapping.hxx b/vcl/aqua/source/dtrans/DataFlavorMapping.hxx deleted file mode 100644 index f5c579ef8965..000000000000 --- a/vcl/aqua/source/dtrans/DataFlavorMapping.hxx +++ /dev/null @@ -1,141 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_DTRANS_DATAFLAVORMAPPING_HXX -#define INCLUDED_VCL_AQUA_SOURCE_DTRANS_DATAFLAVORMAPPING_HXX - -#include -#include -#include -#include - -#include -#import -#include - -#include -#include -#include - - -/* An interface to get the clipboard data in either - system or OOo format. - */ -class DataProvider -{ -public: - virtual ~DataProvider() {}; - - /* Get the clipboard data in the system format. - The caller has to retain/release the returned - CFDataRef on demand. - */ - virtual NSData* getSystemData() = 0; - - /* Get the clipboard data in OOo format. - */ - virtual com::sun::star::uno::Any getOOoData() = 0; -}; - -typedef std::auto_ptr DataProviderPtr_t; - - -//################################ - - -class DataFlavorMapper -{ -public: - /* Initialialize a DataFavorMapper instance. Throws a RuntimeException in case the XMimeContentTypeFactory service - cannot be created. - */ - DataFlavorMapper(); - ~DataFlavorMapper(); - - - /* Map a system data flavor to an OpenOffice data flavor. - Return an empty string if there is not suiteable - mapping from a system data flavor to a OpenOffice data - flavor. - */ - com::sun::star::datatransfer::DataFlavor systemToOpenOfficeFlavor(NSString* systemDataFlavor) const; - - - /* Map an OpenOffice data flavor to a system data flavor. - If there is no suiteable mapping available NULL will - be returned. - */ - NSString* openOfficeToSystemFlavor(const com::sun::star::datatransfer::DataFlavor& oooDataFlavor, bool& rbInternal) const; - - /* Select the best available image data type - If there is no suiteable mapping available NULL will - be returned. - */ - NSString* openOfficeImageToSystemFlavor(NSPasteboard* pPasteboard) const; - - /* Get a data provider which is able to provide the data 'rTransferable' offers in a format that can - be put on to the system clipboard. - */ - DataProviderPtr_t getDataProvider(NSString* systemFlavor, - const com::sun::star::uno::Reference< com::sun::star::datatransfer::XTransferable > rTransferable) const; - - - - /* Get a data provider which is able to provide 'systemData' in the OOo expected format. - */ - DataProviderPtr_t getDataProvider(const NSString* systemFlavor, NSArray* systemData) const; - - - /* Get a data provider which is able to provide 'systemData' in the OOo expected format. - */ - DataProviderPtr_t getDataProvider(const NSString* systemFlavor, NSData* systemData) const; - - - /* Translate a sequence of DataFlavors into a NSArray of system types. - Only those DataFlavors for which a suitable mapping to a system - type exist will be contained in the returned types array. - */ - NSArray* flavorSequenceToTypesArray(const com::sun::star::uno::Sequence& flavors) const; - - /* Translate a NSArray of system types into a sequence of DataFlavors. - Only those types for which a suitable mapping to a DataFlavor - exist will be contained in the new DataFlavor Sequence. - */ - com::sun::star::uno::Sequence typesArrayToFlavorSequence(NSArray* types) const; - - /* Returns an NSArray containing all pasteboard types supported by OOo - */ - NSArray* getAllSupportedPboardTypes() const; - -private: - /* Determines if the provided Mime content type is valid. - */ - bool isValidMimeContentType(const OUString& contentType) const; - -private: - ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XMimeContentTypeFactory> mrXMimeCntFactory; - typedef boost::unordered_map< OUString, NSString*, OUStringHash > OfficeOnlyTypes; - mutable OfficeOnlyTypes maOfficeOnlyTypes; -}; - -typedef boost::shared_ptr DataFlavorMapperPtr_t; - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/DragActionConversion.cxx b/vcl/aqua/source/dtrans/DragActionConversion.cxx deleted file mode 100644 index d4bb9e5c3c86..000000000000 --- a/vcl/aqua/source/dtrans/DragActionConversion.cxx +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include "DragActionConversion.hxx" -#include - - -using namespace com::sun::star::datatransfer::dnd; - - -/* Convert office drag actions as defined in - com::sun::star::datatransfer::dnd::DNDConstants - into system conform drag actions. - */ -unsigned int OfficeToSystemDragActions(sal_Int8 dragActions) -{ - unsigned int actions = NSDragOperationNone; - - if (dragActions & DNDConstants::ACTION_COPY) - { - actions |= NSDragOperationCopy; - } - - if (dragActions & DNDConstants::ACTION_MOVE) - { - actions |= NSDragOperationMove; - } - - if (dragActions & DNDConstants::ACTION_LINK) - { - actions |= NSDragOperationLink; - } - - return actions; -} - -/* Convert system conform drag actions into office conform - drag actions as defined in - com::sun::star::datatransfer::dnd::DNDConstants. - */ -sal_Int8 SystemToOfficeDragActions(unsigned int dragActions) -{ - sal_Int8 actions = DNDConstants::ACTION_NONE; - - if (dragActions & NSDragOperationCopy) - { - actions |= DNDConstants::ACTION_COPY; - } - - if (dragActions & NSDragOperationMove) - { - actions |= DNDConstants::ACTION_MOVE; - } - - if (dragActions & NSDragOperationLink) - { - actions |= DNDConstants::ACTION_LINK; - } - - // We map NSDragOperationGeneric to ACTION_DEFAULT to - // signal that we have to decide for a drag action - if (dragActions & NSDragOperationGeneric) - { - actions |= DNDConstants::ACTION_DEFAULT; - } - - return actions; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/DragActionConversion.hxx b/vcl/aqua/source/dtrans/DragActionConversion.hxx deleted file mode 100644 index 8c9b057bff0f..000000000000 --- a/vcl/aqua/source/dtrans/DragActionConversion.hxx +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include - -#include -#import -#include - - -/* Convert office drag actions as defined in - com::sun::star::datatransfer::dnd::DNDConstants - into system conform drag actions. - */ -unsigned int OfficeToSystemDragActions(sal_Int8 dragActions); - -/* Convert system conform drag actions into office conform - drag actions as defined in - com::sun::star::datatransfer::dnd::DNDConstants. - */ -sal_Int8 SystemToOfficeDragActions(unsigned int dragActions); - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/DragSource.cxx b/vcl/aqua/source/dtrans/DragSource.cxx deleted file mode 100644 index 57862241ce21..000000000000 --- a/vcl/aqua/source/dtrans/DragSource.cxx +++ /dev/null @@ -1,372 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include -#include -#include - -#include "rtl/ustring.hxx" - -#include "comphelper/makesequence.hxx" - -#include "DragSource.hxx" -#include "DragSourceContext.hxx" -#include "aqua_clipboard.hxx" -#include "DragActionConversion.hxx" - -#include "aqua/salframe.h" - -#include - - -using namespace cppu; -using namespace osl; -using namespace com::sun::star; -using namespace com::sun::star::datatransfer; -using namespace com::sun::star::datatransfer::clipboard; -using namespace com::sun::star::datatransfer::dnd; -using namespace com::sun::star::datatransfer::dnd::DNDConstants; -using namespace com::sun::star::uno; -using namespace com::sun::star::awt::MouseButton; -using namespace com::sun::star::awt; -using namespace com::sun::star::lang; -using namespace comphelper; -using namespace std; - - -// For OOo internal D&D we provide the Transferable without NSDragPboard -// interference as a shortcut -uno::Reference DragSource::g_XTransferable; -NSView* DragSource::g_DragSourceView = nil; -bool DragSource::g_DropSuccessSet = false; -bool DragSource::g_DropSuccess = false; - - -OUString dragSource_getImplementationName() -{ - return OUString("com.sun.star.comp.datatransfer.dnd.OleDragSource_V1"); -} - -Sequence dragSource_getSupportedServiceNames() -{ - return makeSequence(OUString("com.sun.star.datatransfer.dnd.OleDragSource")); -} - - -@implementation DragSourceHelper; - --(DragSourceHelper*)initWithDragSource: (DragSource*) pds -{ - self = [super init]; - - if (self) - { - mDragSource = pds; - } - - return self; -} - - --(void)mouseDown: (NSEvent*)theEvent -{ - mDragSource->saveMouseEvent(theEvent); -} - - --(void)mouseDragged: (NSEvent*)theEvent -{ - mDragSource->saveMouseEvent(theEvent); -} - - --(unsigned int)draggingSourceOperationMaskForLocal: (BOOL)isLocal -{ - return mDragSource->getSupportedDragOperations(isLocal); -} - - --(void)draggedImage:(NSImage*)anImage beganAt:(NSPoint)aPoint -{ - (void)anImage; - (void)aPoint; - DragSourceDragEvent dsde(static_cast(mDragSource), - new DragSourceContext, - mDragSource, - DNDConstants::ACTION_COPY, - DNDConstants::ACTION_COPY); - - mDragSource->mXDragSrcListener->dragEnter(dsde); -} - - --(void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation -{ - (void)anImage; - (void)aPoint; - // an internal drop can accept the drop but fail with dropComplete( false ) - // this is different than the Cocoa API - bool bDropSuccess = operation != NSDragOperationNone; - if( DragSource::g_DropSuccessSet ) - bDropSuccess = DragSource::g_DropSuccess; - - DragSourceDropEvent dsde(static_cast(mDragSource), - new DragSourceContext, - static_cast< XDragSource* >(mDragSource), - SystemToOfficeDragActions(operation), - bDropSuccess ); - - mDragSource->mXDragSrcListener->dragDropEnd(dsde); - mDragSource->mXDragSrcListener = uno::Reference(); -} - - --(void)draggedImage:(NSImage *)draggedImage movedTo:(NSPoint)screenPoint -{ - (void)draggedImage; - (void)screenPoint; - DragSourceDragEvent dsde(static_cast(mDragSource), - new DragSourceContext, - mDragSource, - DNDConstants::ACTION_COPY, - DNDConstants::ACTION_COPY); - - mDragSource->mXDragSrcListener->dragOver(dsde); -} - -@end - - -DragSource::DragSource(): - WeakComponentImplHelper3(m_aMutex), - mView(NULL), - mpFrame(NULL), - mLastMouseEventBeforeStartDrag(nil), - m_MouseButton(0) -{ -} - - -DragSource::~DragSource() -{ - if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) - [(id )mView unregisterMouseEventListener: mDragSourceHelper]; - [mDragSourceHelper release]; -} - - -void SAL_CALL DragSource::initialize(const Sequence< Any >& aArguments) - throw(Exception) -{ - if (aArguments.getLength() < 2) - { - throw Exception("DragSource::initialize: Not enough parameter.", - static_cast(this)); - } - - Any pNSView = aArguments[1]; - sal_uInt64 tmp = 0; - pNSView >>= tmp; - mView = (NSView*)tmp; - - /* All SalFrameView the base class for all VCL system views inherits from - NSView in order to get mouse and other events. This is the only way to - get these events. In order to start a drag operation we need to provide - the mouse event which was the trigger. SalFrameView therefor implements - a hook mechanism so that we can get mouse events for our purpose. - */ - if (![mView respondsToSelector: @selector(registerMouseEventListener:)] || - ![mView respondsToSelector: @selector(unregisterMouseEventListener:)]) - { - throw Exception("DragSource::initialize: Provided view doesn't support mouse listener", - static_cast(this)); - } - NSWindow* pWin = [mView window]; - if( ! pWin || ![pWin respondsToSelector: @selector(getSalFrame)] ) - { - throw Exception("DragSource::initialize: Provided view is not attached to a vcl frame", - static_cast(this)); - } - mpFrame = (AquaSalFrame*)[pWin performSelector: @selector(getSalFrame)]; - - mDragSourceHelper = [[DragSourceHelper alloc] initWithDragSource: this]; - - if (mDragSourceHelper == nil) - { - throw Exception("DragSource::initialize: Cannot initialize DragSource", - static_cast(this)); - } - - [(id )mView registerMouseEventListener: mDragSourceHelper]; -} - - -//---------------------------------------------------- -// XDragSource -//---------------------------------------------------- - -sal_Bool SAL_CALL DragSource::isDragImageSupported( ) - throw(RuntimeException) -{ - return true; -} - - -sal_Int32 SAL_CALL DragSource::getDefaultCursor( sal_Int8 /*dragAction*/ ) - throw( IllegalArgumentException, RuntimeException) -{ - return 0; -} - - -void SAL_CALL DragSource::startDrag(const DragGestureEvent& trigger, - sal_Int8 sourceActions, - sal_Int32 /*cursor*/, - sal_Int32 /*image*/, - const uno::Reference& transferable, - const uno::Reference& listener ) - throw( RuntimeException) -{ - MutexGuard guard(m_aMutex); - - OSL_ASSERT(listener.is() && "DragSource::startDrag: No XDragSourceListener provided\n"); - OSL_ASSERT(transferable.is() && "DragSource::startDrag: No transferable provided\n"); - - trigger.Event >>= mMouseEvent; - m_MouseButton= mMouseEvent.Buttons; - mXDragSrcListener = listener; - mXCurrentContext = static_cast(new DragSourceContext); - auto_ptr clipb(new AquaClipboard(NULL, false)); - g_XTransferable = transferable; - clipb->setContents(g_XTransferable, uno::Reference()); - mDragSourceActions = sourceActions; - g_DragSourceView = mView; - - NSSize sz; - sz.width = 5; - sz.height = 5; - - NSImage* dragImage; - dragImage = [[NSImage alloc] initWithSize: sz]; - - NSRect bounds; - bounds.origin = NSMakePoint(0,0); - bounds.size = sz; - - [dragImage lockFocus]; - [[NSColor blackColor] set]; - [NSBezierPath fillRect: bounds]; - [dragImage unlockFocus]; - - NSPoint pInWnd = [mLastMouseEventBeforeStartDrag locationInWindow]; - NSPoint p; - p = [mView convertPoint: pInWnd fromView: nil]; - p.x = p.x - sz.width/2; - p.y = p.y - sz.height/2; - - // reset drop success flags - g_DropSuccessSet = false; - g_DropSuccess = false; - - [mView dragImage: dragImage - at: p - offset: NSMakeSize(0,0) - event: mLastMouseEventBeforeStartDrag - pasteboard: clipb->getPasteboard() - source: mDragSourceHelper - slideBack: 1]; - - [dragImage release]; - - g_XTransferable = uno::Reference(); - g_DragSourceView = nil; - - // reset drop success flags - g_DropSuccessSet = false; - g_DropSuccess = false; -} - - -// In order to initiate a D&D operation we need to -// provide the triggering mouse event which we get -// from the SalFrameView that is associated with -// this DragSource -void DragSource::saveMouseEvent(NSEvent* theEvent) -{ - if (mLastMouseEventBeforeStartDrag != nil) - { - [mLastMouseEventBeforeStartDrag release]; - } - - mLastMouseEventBeforeStartDrag = theEvent; -} - - -/* isLocal indicates whether or not the DnD operation is OOo - internal. - */ -unsigned int DragSource::getSupportedDragOperations(bool isLocal) const -{ - unsigned int srcActions = OfficeToSystemDragActions(mDragSourceActions); - - if (isLocal) - { - // Support NSDragOperation generic which means we can - // decide which D&D operation to choose. We map - // NSDragOperationGenric to DNDConstants::ACTION_DEFAULT - // in SystemToOfficeDragActions to signal this and - // use it in DropTarget::determineDropAction - srcActions |= NSDragOperationGeneric; - } - else - { - // Mask out link and move operations on external DnD - srcActions &= ~(NSDragOperationMove | NSDragOperationLink); - } - - return srcActions; -} - - -//################################ -// XServiceInfo -//################################ - -OUString SAL_CALL DragSource::getImplementationName( ) throw (RuntimeException) -{ - return dragSource_getImplementationName(); -} - - -sal_Bool SAL_CALL DragSource::supportsService( const OUString& ServiceName ) throw (RuntimeException) -{ - return ServiceName == "com.sun.star.datatransfer.dnd.OleDragSource"; -} - - -Sequence< OUString > SAL_CALL DragSource::getSupportedServiceNames() throw (RuntimeException) -{ - return dragSource_getSupportedServiceNames(); -} - - - - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/DragSource.hxx b/vcl/aqua/source/dtrans/DragSource.hxx deleted file mode 100644 index be4443a5e191..000000000000 --- a/vcl/aqua/source/dtrans/DragSource.hxx +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_DTRANS_DRAGSOURCE_HXX -#define INCLUDED_VCL_AQUA_SOURCE_DTRANS_DRAGSOURCE_HXX - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#import -#include - - -class DragSource; -class AquaSalFrame; - -/* The functions declared in this protocol are actually - declared in vcl/aqua/inc/salframe.h. Because we want - to avoid importing VCL headers in UNO services and - on the other hand want to avoid warnings caused by - gcc complaining about unknowness of these functions - we declare them in a protocol here and cast at the - appropriate places. -*/ -@protocol MouseEventListener --(void)registerMouseEventListener:(id)theHandler; --(void)unregisterMouseEventListener:(id)theHandler; -@end - - -@interface DragSourceHelper : NSObject -{ - DragSource* mDragSource; -} - --(DragSourceHelper*)initWithDragSource: (DragSource*) pds; - --(void)mouseDown: (NSEvent*)theEvent; --(void)mouseDragged: (NSEvent*)theEvent; - --(unsigned int)draggingSourceOperationMaskForLocal:(BOOL)isLocal; --(void)draggedImage:(NSImage*)anImage beganAt:(NSPoint)aPoint; --(void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation; --(void)draggedImage:(NSImage *)draggedImage movedTo:(NSPoint)screenPoint; - -@end - - -class DragSource : public ::cppu::BaseMutex, - public ::cppu::WeakComponentImplHelper3< com::sun::star::datatransfer::dnd::XDragSource, - com::sun::star::lang::XInitialization, - com::sun::star::lang::XServiceInfo >, - private ::boost::noncopyable -{ -public: - DragSource(); - virtual ~DragSource(); - - // XInitialization - virtual void SAL_CALL initialize( const com::sun::star::uno::Sequence< com::sun::star::uno::Any >& aArguments ) - throw(com::sun::star::uno::Exception/*, com::sun::star::uno::RuntimeException*/); - - // XDragSource - virtual sal_Bool SAL_CALL isDragImageSupported( ) throw(com::sun::star::uno::RuntimeException); - - virtual sal_Int32 SAL_CALL getDefaultCursor(sal_Int8 dragAction) - throw(com::sun::star::lang::IllegalArgumentException, com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL startDrag( const com::sun::star::datatransfer::dnd::DragGestureEvent& trigger, - sal_Int8 sourceActions, - sal_Int32 cursor, - sal_Int32 image, - const com::sun::star::uno::Reference< com::sun::star::datatransfer::XTransferable >& transferable, - const com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDragSourceListener >& listener ) - throw(com::sun::star::uno::RuntimeException); - - // XServiceInfo - virtual OUString SAL_CALL getImplementationName() throw (com::sun::star::uno::RuntimeException); - virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw (com::sun::star::uno::RuntimeException); - virtual com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() throw (com::sun::star::uno::RuntimeException); - - virtual void saveMouseEvent(NSEvent* theEvent); - virtual unsigned int getSupportedDragOperations(bool isLocal) const; - -public: - // The context notifies the XDragSourceListeners - com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDragSourceContext > mXCurrentContext; - - id mView; - AquaSalFrame* mpFrame; - NSEvent* mLastMouseEventBeforeStartDrag; - DragSourceHelper* mDragSourceHelper; - com::sun::star::awt::MouseEvent mMouseEvent; - com::sun::star::uno::Reference< com::sun::star::datatransfer::XTransferable > mXTransferable; - com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDragSourceListener > mXDragSrcListener; - // The mouse button that set off the drag and drop operation - short m_MouseButton; - sal_Int8 mDragSourceActions; - - static com::sun::star::uno::Reference< com::sun::star::datatransfer::XTransferable > g_XTransferable; - static NSView* g_DragSourceView; - static bool g_DropSuccessSet; - static bool g_DropSuccess; - -}; - - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/DragSourceContext.cxx b/vcl/aqua/source/dtrans/DragSourceContext.cxx deleted file mode 100644 index 1eb4fe3ac78e..000000000000 --- a/vcl/aqua/source/dtrans/DragSourceContext.cxx +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include - -#include "DragSourceContext.hxx" - - -using namespace com::sun::star::datatransfer::dnd; -using namespace com::sun::star::datatransfer::dnd::DNDConstants; -using namespace com::sun::star::uno; -using namespace cppu; - -DragSourceContext::DragSourceContext() : - WeakComponentImplHelper1(m_aMutex) -{ -} - -DragSourceContext::~DragSourceContext() -{ -} - -sal_Int32 SAL_CALL DragSourceContext::getCurrentCursor( ) - throw( RuntimeException) -{ - return 0; -} - -void SAL_CALL DragSourceContext::setCursor( sal_Int32 /*cursorId*/ ) - throw( RuntimeException) -{ -} - -void SAL_CALL DragSourceContext::setImage( sal_Int32 /*imageId*/ ) - throw( RuntimeException) -{ -} - -void SAL_CALL DragSourceContext::transferablesFlavorsChanged( ) - throw( RuntimeException) -{ -} - - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/DragSourceContext.hxx b/vcl/aqua/source/dtrans/DragSourceContext.hxx deleted file mode 100644 index 6d8d0d9bac18..000000000000 --- a/vcl/aqua/source/dtrans/DragSourceContext.hxx +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_DTRANS_DRAGSOURCECONTEXT_HXX -#define INCLUDED_VCL_AQUA_SOURCE_DTRANS_DRAGSOURCECONTEXT_HXX - -#include -#include -#include -#include - -#include - -// This class fires events to XDragSourceListener implementations. -// Of that interface only dragDropEnd and dropActionChanged are called. -// The functions dragEnter, dragExit and dragOver are not supported -// currently. -// An instance of SourceContext only lives as long as the drag and drop -// operation lasts. -class DragSourceContext: public cppu::BaseMutex, - public cppu::WeakComponentImplHelper1, - private ::boost::noncopyable -{ -public: - DragSourceContext(); - ~DragSourceContext(); - - virtual sal_Int32 SAL_CALL getCurrentCursor( ) - throw( com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL setCursor( sal_Int32 cursorId ) - throw( com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL setImage( sal_Int32 imageId ) - throw( com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL transferablesFlavorsChanged( ) - throw( com::sun::star::uno::RuntimeException); -}; - - - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/DropTarget.cxx b/vcl/aqua/source/dtrans/DropTarget.cxx deleted file mode 100644 index fd762a9744c0..000000000000 --- a/vcl/aqua/source/dtrans/DropTarget.cxx +++ /dev/null @@ -1,596 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include -#include -#include - -#include "comphelper/makesequence.hxx" -#include - -#include "aqua_clipboard.hxx" -#include "DropTarget.hxx" -#include "DragActionConversion.hxx" - -#include "DragSource.hxx" - -#include -#include - -#include -#include -#include - -#include -#include - -using namespace cppu; -using namespace osl; -using namespace com::sun::star::datatransfer; -using namespace com::sun::star::datatransfer::dnd; -using namespace com::sun::star::datatransfer::dnd::DNDConstants; -using namespace com::sun::star::datatransfer::clipboard; -using namespace com::sun::star::lang; -using namespace com::sun::star::uno; -using namespace com::sun::star; -using namespace comphelper; - - -OUString dropTarget_getImplementationName() -{ - return OUString("com.sun.star.comp.datatransfer.dnd.OleDropTarget_V1"); -} - - -Sequence dropTarget_getSupportedServiceNames() -{ - return makeSequence(OUString("com.sun.star.datatransfer.dnd.OleDropTarget")); -} - - -namespace /* private */ -{ - // Cocoa's coordinate system has its origin lower-left, VCL's - // coordinate system upper-left hence we need to transform - // coordinates - - inline void CocoaToVCL(NSPoint& rPoint, const NSRect& bounds) - { - rPoint.y = bounds.size.height - rPoint.y; - } -} - - -@implementation DropTargetHelper - - --(DropTargetHelper*)initWithDropTarget:(DropTarget*)pdt -{ - self = [super init]; - - if (self) - { - mDropTarget = pdt; - } - - return self; -} - - --(NSDragOperation)draggingEntered:(id )sender -{ - return mDropTarget->draggingEntered(sender); -} - - --(NSDragOperation)draggingUpdated:(id )sender -{ - return mDropTarget->draggingUpdated(sender); -} - - --(void)draggingExited:(id )sender -{ - mDropTarget->draggingExited(sender); -} - - --(BOOL)prepareForDragOperation:(id )sender -{ - return mDropTarget->prepareForDragOperation(sender); -} - - --(BOOL)performDragOperation:(id )sender -{ - return mDropTarget->performDragOperation(sender); -} - - --(void)concludeDragOperation:(id )sender -{ - mDropTarget->concludeDragOperation(sender); -} - - -@end - - -DropTarget::DropTarget() : - WeakComponentImplHelper5(m_aMutex), - mView(nil), - mpFrame(NULL), - mDropTargetHelper(nil), - mbActive(false), - mDragSourceSupportedActions(DNDConstants::ACTION_NONE), - mSelectedDropAction(DNDConstants::ACTION_NONE), - mDefaultActions(DNDConstants::ACTION_COPY_OR_MOVE | DNDConstants::ACTION_LINK | DNDConstants::ACTION_DEFAULT) -{ - mDataFlavorMapper = DataFlavorMapperPtr_t(new DataFlavorMapper()); -} - - -DropTarget::~DropTarget() -{ - if( AquaSalFrame::isAlive( mpFrame ) ) - [(id )mView unregisterDraggingDestinationHandler:mDropTargetHelper]; - [mDropTargetHelper release]; -} - - -sal_Int8 DropTarget::determineDropAction(sal_Int8 dropActions, id sender) const -{ - sal_Int8 dropAct = dropActions; - bool srcAndDestEqual = false; - - if ([sender draggingSource] != nil) - { - // Internal DnD - NSView* destView = [[sender draggingDestinationWindow] contentView]; - srcAndDestEqual = (DragSource::g_DragSourceView == destView); - } - - // If ACTION_DEFAULT is set this means NSDragOperationGeneric - // has been set and we map this to ACTION_MOVE or ACTION_COPY - // depending on whether or not source and dest are equal, - // this hopefully satisfies all parties - if( (dropActions == DNDConstants::ACTION_DEFAULT) - || ((dropActions == mDragSourceSupportedActions) - && !(~mDragSourceSupportedActions & DNDConstants::ACTION_COPY_OR_MOVE ) ) ) - { - dropAct = srcAndDestEqual ? DNDConstants::ACTION_MOVE : - DNDConstants::ACTION_COPY; - } - // if more than one drop actions have been specified - // set ACTION_DEFAULT in order to let the drop target - // decide which one to use - else if (dropActions != DNDConstants::ACTION_NONE && - dropActions != DNDConstants::ACTION_MOVE && - dropActions != DNDConstants::ACTION_COPY && - dropActions != DNDConstants::ACTION_LINK) - { - if (srcAndDestEqual) - { - dropAct = dropActions; - } - else // source and destination are different - { - if (dropActions & DNDConstants::ACTION_COPY) - dropAct = DNDConstants::ACTION_COPY; - else if (dropActions & DNDConstants::ACTION_MOVE) - dropAct = DNDConstants::ACTION_MOVE; - else if (dropActions & DNDConstants::ACTION_LINK) - dropAct = DNDConstants::ACTION_LINK; - } - - dropAct |= DNDConstants::ACTION_DEFAULT; - } - - return dropAct; -} - - -NSDragOperation DropTarget::draggingEntered(id sender) -{ - // Initially when DnD will be started no modifier key can be pressed yet - // thus we are getting all actions that the drag source supports, we save - // this value because later the system masks the drag source actions if - // a modifier key will be pressed - mDragSourceSupportedActions = SystemToOfficeDragActions([sender draggingSourceOperationMask]); - - // Only if the drop target is really interessted in the drag actions - // supported by the source - if (mDragSourceSupportedActions & mDefaultActions) - { - sal_Int8 currentAction = determineDropAction(mDragSourceSupportedActions, sender); - - NSRect bounds = [mView bounds]; - NSPoint dragLocation = [sender draggedImageLocation]; - - CocoaToVCL(dragLocation, bounds); - - sal_Int32 posX = static_cast(dragLocation.x); - sal_Int32 posY = static_cast(dragLocation.y); - - NSPasteboard* dragPboard = [sender draggingPasteboard]; - mXCurrentDragClipboard = new AquaClipboard(dragPboard, false); - - uno::Reference xTransferable = DragSource::g_XTransferable.is() ? - DragSource::g_XTransferable : mXCurrentDragClipboard->getContents(); - - DropTargetDragEnterEvent dtdee(static_cast(this), - 0, - this, - currentAction, - posX, - posY, - mDragSourceSupportedActions, - xTransferable->getTransferDataFlavors()); - - fire_dragEnter(dtdee); - } - - return OfficeToSystemDragActions(mSelectedDropAction); -} - - -NSDragOperation DropTarget::draggingUpdated(id sender) -{ - sal_Int8 currentDragSourceActions = - SystemToOfficeDragActions([sender draggingSourceOperationMask]); - NSDragOperation dragOp = NSDragOperationNone; - - if (currentDragSourceActions & mDefaultActions) - { - sal_Int8 currentAction = determineDropAction(currentDragSourceActions, sender); - NSRect bounds = [mView bounds]; - NSPoint dragLocation = [sender draggedImageLocation]; - - CocoaToVCL(dragLocation, bounds); - - sal_Int32 posX = static_cast(dragLocation.x); - sal_Int32 posY = static_cast(dragLocation.y); - - DropTargetDragEvent dtde(static_cast(this), - 0, - this, - currentAction, - posX, - posY, - mDragSourceSupportedActions); - - fire_dragOver(dtde); - - // drag over callbacks likely have rendered something - [mView setNeedsDisplay: TRUE]; - - dragOp = OfficeToSystemDragActions(mSelectedDropAction); - - //NSLog(@"Drag update: Source actions: %x proposed action %x selected action %x", mDragSourceSupportedActions, currentAction, mSelectedDropAction); - } - -#ifndef __LP64__ - // Weird but it appears as if there is no method in Cocoa - // to create a kThemeCopyArrowCursor hence we have to use - // Carbon to do it - if (dragOp == NSDragOperationNone) - SetThemeCursor(kThemeNotAllowedCursor); - else if (dragOp == NSDragOperationCopy) - SetThemeCursor(kThemeCopyArrowCursor); - else - SetThemeCursor(kThemeArrowCursor); -#else - // FIXME: SetThemeCursor replacement? -#endif - return dragOp; -} - - -void DropTarget::draggingExited(id /*sender*/) -{ - DropTargetEvent dte(static_cast(this), 0); - fire_dragExit(dte); - mDragSourceSupportedActions = DNDConstants::ACTION_NONE; - mSelectedDropAction = DNDConstants::ACTION_NONE; -#ifndef __LP64__ - SetThemeCursor(kThemeArrowCursor); -#endif -} - - -BOOL DropTarget::prepareForDragOperation(id /*sender*/) -{ - return 1; -} - - -BOOL DropTarget::performDragOperation(id sender) -{ - bool bSuccess = false; - - if (mSelectedDropAction != DNDConstants::ACTION_NONE) - { - uno::Reference xTransferable = DragSource::g_XTransferable; - - if (!DragSource::g_XTransferable.is()) - { - xTransferable = mXCurrentDragClipboard->getContents(); - } - - NSRect bounds = [mView bounds]; - NSPoint dragLocation = [sender draggedImageLocation]; - - CocoaToVCL(dragLocation, bounds); - - sal_Int32 posX = static_cast(dragLocation.x); - sal_Int32 posY = static_cast(dragLocation.y); - - DropTargetDropEvent dtde(static_cast(this), - 0, - this, - mSelectedDropAction, - posX, - posY, - mDragSourceSupportedActions, - xTransferable); - - fire_drop(dtde); - - bSuccess = true; - } - - return bSuccess; -} - - -void DropTarget::concludeDragOperation(id /*sender*/) -{ - mDragSourceSupportedActions = DNDConstants::ACTION_NONE; - mSelectedDropAction = DNDConstants::ACTION_NONE; - mXCurrentDragClipboard = uno::Reference(); -#ifndef __LP64__ - SetThemeCursor(kThemeArrowCursor); -#endif -} - - - // called from WeakComponentImplHelperX::dispose - // WeakComponentImplHelper calls disposing before it destroys - // itself. - void SAL_CALL DropTarget::disposing() - { - } - - - void SAL_CALL DropTarget::initialize(const Sequence< Any >& aArguments) - throw(Exception) - { - if (aArguments.getLength() < 2) - { - throw RuntimeException("DropTarget::initialize: Cannot install window event handler", - static_cast(this)); - } - - Any pNSView = aArguments[0]; - sal_uInt64 tmp = 0; - pNSView >>= tmp; - mView = (id)tmp; - mpFrame = [(SalFrameView*)mView getSalFrame]; - - mDropTargetHelper = [[DropTargetHelper alloc] initWithDropTarget: this]; - - [(id )mView registerDraggingDestinationHandler:mDropTargetHelper]; - [mView registerForDraggedTypes: mDataFlavorMapper->getAllSupportedPboardTypes()]; - - id wnd = [mView window]; - NSWindow* parentWnd = [wnd parentWindow]; - unsigned int topWndStyle = (NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask); - unsigned int wndStyles = [wnd styleMask] & topWndStyle; - - if (parentWnd == nil && (wndStyles == topWndStyle)) - { - [wnd registerDraggingDestinationHandler:mDropTargetHelper]; - [wnd registerForDraggedTypes: [NSArray arrayWithObjects: NSFilenamesPboardType, nil]]; - } - } - - - void SAL_CALL DropTarget::addDropTargetListener(const uno::Reference& dtl) - throw(RuntimeException) - { - rBHelper.addListener(::getCppuType(&dtl), dtl); - } - - - void SAL_CALL DropTarget::removeDropTargetListener(const uno::Reference& dtl) - throw(RuntimeException) - { - rBHelper.removeListener(::getCppuType(&dtl), dtl); - } - - - sal_Bool SAL_CALL DropTarget::isActive( ) throw(RuntimeException) - { - return mbActive; - } - - - void SAL_CALL DropTarget::setActive(sal_Bool active) throw(RuntimeException) - { - mbActive = active; - } - - - sal_Int8 SAL_CALL DropTarget::getDefaultActions() throw(RuntimeException) - { - return mDefaultActions; - } - - - void SAL_CALL DropTarget::setDefaultActions(sal_Int8 actions) throw(RuntimeException) - { - OSL_ENSURE( actions < 8, "No valid default actions"); - mDefaultActions= actions; - } - - - // XDropTargetDragContext - - void SAL_CALL DropTarget::acceptDrag(sal_Int8 dragOperation) throw (RuntimeException) - { - mSelectedDropAction = dragOperation; - } - - - void SAL_CALL DropTarget::rejectDrag() throw (RuntimeException) - { - mSelectedDropAction = DNDConstants::ACTION_NONE; - } - - - //XDropTargetDropContext - - void SAL_CALL DropTarget::acceptDrop(sal_Int8 dropOperation) throw( RuntimeException) - { - mSelectedDropAction = dropOperation; - } - - - void SAL_CALL DropTarget::rejectDrop() throw (RuntimeException) - { - mSelectedDropAction = DNDConstants::ACTION_NONE; - } - - - void SAL_CALL DropTarget::dropComplete(sal_Bool success) throw (RuntimeException) - { - // Reset the internal transferable used as shortcut in case this is - // an internal D&D operation - DragSource::g_XTransferable = uno::Reference(); - DragSource::g_DropSuccessSet = true; - DragSource::g_DropSuccess = success; - } - - - void DropTarget::fire_drop( const DropTargetDropEvent& dte) - { - OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference* )0 ) ); - if( pContainer) - { - OInterfaceIteratorHelper iter( *pContainer); - while( iter.hasMoreElements()) - { - uno::Reference listener( static_cast( iter.next())); - - try { listener->drop( dte); } - catch(RuntimeException&) {} - } - } - } - - - void DropTarget::fire_dragEnter(const DropTargetDragEnterEvent& e) - { - OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference* )0 ) ); - if( pContainer) - { - OInterfaceIteratorHelper iter( *pContainer); - while( iter.hasMoreElements()) - { - uno::Reference listener( static_cast( iter.next())); - - try { listener->dragEnter( e); } - catch (RuntimeException&) {} - } - } - } - - - void DropTarget::fire_dragExit(const DropTargetEvent& dte) - { - OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference* )0 ) ); - - if( pContainer) - { - OInterfaceIteratorHelper iter( *pContainer); - while( iter.hasMoreElements()) - { - uno::Reference listener( static_cast( iter.next())); - - try { listener->dragExit( dte); } - catch (RuntimeException&) {} - } - } - } - - - void DropTarget::fire_dragOver(const DropTargetDragEvent& dtde) - { - OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference* )0 ) ); - if( pContainer) - { - OInterfaceIteratorHelper iter( *pContainer ); - while( iter.hasMoreElements()) - { - uno::Reference listener( static_cast( iter.next())); - - try { listener->dragOver( dtde); } - catch (RuntimeException&) {} - } - } - } - - - void DropTarget::fire_dropActionChanged(const DropTargetDragEvent& dtde) - { - OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference* )0 ) ); - if( pContainer) - { - OInterfaceIteratorHelper iter( *pContainer); - while( iter.hasMoreElements()) - { - uno::Reference listener( static_cast( iter.next())); - - try { listener->dropActionChanged( dtde); } - catch (RuntimeException&) {} - } - } - } - - - // XServiceInfo - - OUString SAL_CALL DropTarget::getImplementationName() throw (RuntimeException) - { - return dropTarget_getImplementationName(); - } - - - sal_Bool SAL_CALL DropTarget::supportsService( const OUString& ServiceName ) throw (RuntimeException) - { - return ServiceName == "com.sun.star.datatransfer.dnd.OleDropTarget"; - } - - - Sequence< OUString > SAL_CALL DropTarget::getSupportedServiceNames( ) throw (RuntimeException) - { - return dropTarget_getSupportedServiceNames(); - } - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/DropTarget.hxx b/vcl/aqua/source/dtrans/DropTarget.hxx deleted file mode 100644 index 9318d80b9b46..000000000000 --- a/vcl/aqua/source/dtrans/DropTarget.hxx +++ /dev/null @@ -1,163 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_DTRANS_DROPTARGET_HXX -#define INCLUDED_VCL_AQUA_SOURCE_DTRANS_DROPTARGET_HXX - -#include "DataFlavorMapping.hxx" -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#import -#include - -class DropTarget; -class AquaSalFrame; - -/* The functions declared in this protocol are actually - declared in vcl/aqua/inc/salframe.h. Because we want - to avoid importing VCL headers in UNO services and - on the other hand want to avoid warnings caused by - gcc complaining about unknowness of these functions - we declare them in a protocol here and cast at the - appropriate places. -*/ -@protocol DraggingDestinationHandler --(void)registerDraggingDestinationHandler:(id)theHandler; --(void)unregisterDraggingDestinationHandler:(id)theHandler; -@end - - -@interface DropTargetHelper : NSObject -{ - DropTarget* mDropTarget; -} - --(DropTargetHelper*)initWithDropTarget:(DropTarget*)pdt; - --(NSDragOperation)draggingEntered:(id )sender; --(NSDragOperation)draggingUpdated:(id )sender; --(void)draggingExited:(id )sender; --(BOOL)prepareForDragOperation:(id )sender; --(BOOL)performDragOperation:(id )sender; --(void)concludeDragOperation:(id )sender; - -@end - - -class DropTarget: public cppu::BaseMutex, - public cppu::WeakComponentImplHelper5< com::sun::star::lang::XInitialization, - com::sun::star::datatransfer::dnd::XDropTarget, - com::sun::star::datatransfer::dnd::XDropTargetDragContext, - com::sun::star::datatransfer::dnd::XDropTargetDropContext, - com::sun::star::lang::XServiceInfo >, - private boost::noncopyable -{ -public: - DropTarget(); - virtual ~DropTarget(); - - // Overrides WeakComponentImplHelper::disposing which is called by - // WeakComponentImplHelper::dispose - // Must be called. - virtual void SAL_CALL disposing(); - - // XInitialization - virtual void SAL_CALL initialize( const com::sun::star::uno::Sequence< com::sun::star::uno::Any >& aArguments ) - throw(com::sun::star::uno::Exception); - - // XDropTarget - virtual void SAL_CALL addDropTargetListener( const com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDropTargetListener >& dtl ) - throw(com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL removeDropTargetListener( const com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDropTargetListener >& dtl ) - throw(com::sun::star::uno::RuntimeException); - - // Default is not active - virtual sal_Bool SAL_CALL isActive() throw(com::sun::star::uno::RuntimeException); - virtual void SAL_CALL setActive(sal_Bool isActive) throw(com::sun::star::uno::RuntimeException); - virtual sal_Int8 SAL_CALL getDefaultActions() throw(com::sun::star::uno::RuntimeException); - virtual void SAL_CALL setDefaultActions(sal_Int8 actions) throw(com::sun::star::uno::RuntimeException); - - // XDropTargetDragContext - virtual void SAL_CALL acceptDrag(sal_Int8 dragOperation) throw(com::sun::star::uno::RuntimeException); - virtual void SAL_CALL rejectDrag() throw(com::sun::star::uno::RuntimeException); - - // XDropTargetDragContext - virtual void SAL_CALL acceptDrop(sal_Int8 dropOperation) throw (com::sun::star::uno::RuntimeException); - virtual void SAL_CALL rejectDrop() throw (com::sun::star::uno::RuntimeException); - virtual void SAL_CALL dropComplete(sal_Bool success) throw (com::sun::star::uno::RuntimeException); - - // XServiceInfo - virtual OUString SAL_CALL getImplementationName() throw (com::sun::star::uno::RuntimeException); - virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw (com::sun::star::uno::RuntimeException); - virtual com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() throw (com::sun::star::uno::RuntimeException); - - // NSDraggingDestination protocol functions - virtual NSDragOperation draggingEntered(id sender); - virtual NSDragOperation draggingUpdated(id sender); - virtual void draggingExited(id sender); - virtual BOOL prepareForDragOperation(id sender); - virtual BOOL performDragOperation(id sender); - virtual void concludeDragOperation(id sender); - - /* If multiple actions are supported by the drag source and - the user did not choose a specific action by pressing a - modifier key choose a default action to be proposed to - the application. - */ - sal_Int8 determineDropAction(sal_Int8 dropActions, id sender) const; - -private: - void fire_drop(const com::sun::star::datatransfer::dnd::DropTargetDropEvent& dte); - void fire_dragEnter(const com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& dtdee); - void fire_dragExit(const com::sun::star::datatransfer::dnd::DropTargetEvent& dte); - void fire_dragOver(const com::sun::star::datatransfer::dnd::DropTargetDragEvent& dtde); - void fire_dropActionChanged(const com::sun::star::datatransfer::dnd::DropTargetDragEvent& dtde); - -private: - com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDropTargetDragContext > mXCurrentDragContext; - com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDropTargetDropContext > mXCurrentDropContext; - com::sun::star::uno::Reference< com::sun::star::datatransfer::clipboard::XClipboard > mXCurrentDragClipboard; - DataFlavorMapperPtr_t mDataFlavorMapper; - id mView; - AquaSalFrame* mpFrame; - DropTargetHelper* mDropTargetHelper; - bool mbActive; - sal_Int8 mDragSourceSupportedActions; - sal_Int8 mSelectedDropAction; - sal_Int8 mDefaultActions; -}; - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/HtmlFmtFlt.cxx b/vcl/aqua/source/dtrans/HtmlFmtFlt.cxx deleted file mode 100644 index e629f11e982e..000000000000 --- a/vcl/aqua/source/dtrans/HtmlFmtFlt.cxx +++ /dev/null @@ -1,168 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include "HtmlFmtFlt.hxx" - -#include - -#include -#include -#include -#include - -#include - -using namespace com::sun::star::uno; - -//------------------------------------------------------------------------------ -// converts the openoffice text/html clipboard format to the HTML Format -// well known under MS Windows -// the MS HTML Format has a header before the real html data -// -// Version:1.0 Version number of the clipboard. Staring is 0.9 -// StartHTML: Byte count from the beginning of the clipboard to the start -// of the context, or -1 if no context -// EndHTML: Byte count from the beginning of the clipboard to the end -// of the context, or -1 if no context -// StartFragment: Byte count from the beginning of the clipboard to the -// start of the fragment -// EndFragment: Byte count from the beginning of the clipboard to the -// end of the fragment -// StartSelection: Byte count from the beginning of the clipboard to the -// start of the selection -// EndSelection: Byte count from the beginning of the clipboard to the -// end of the selection -// -// StartSelection and EndSelection are optional -// The fragment should be preceded and followed by the HTML comments -// and (no space between !-- and the -// text -//------------------------------------------------------------------------------ - -namespace // private -{ -std::string GetHtmlFormatHeader(size_t startHtml, size_t endHtml, size_t startFragment, size_t endFragment) -{ - std::ostringstream htmlHeader; - htmlHeader << "Version:1.0" << '\r' << '\n'; - htmlHeader << "StartHTML:" << std::setw(10) << std::setfill('0') << std::dec << startHtml << '\r' << '\n'; - htmlHeader << "EndHTML:" << std::setw(10) << std::setfill('0') << std::dec << endHtml << '\r' << '\n'; - htmlHeader << "StartFragment:" << std::setw(10) << std::setfill('0') << std::dec << startFragment << '\r' << '\n'; - htmlHeader << "EndFragment:" << std::setw(10) << std::setfill('0') << std::dec << endFragment << '\r' << '\n'; - return htmlHeader.str(); -} - -} // namespace private - - -// the office always writes the start and end html tag in upper cases and -// without spaces both tags don't allow parameters -const std::string TAG_HTML = std::string(""); -const std::string TAG_END_HTML = std::string(""); - -// The body tag may have parameters so we need to search for the -// closing '>' manually e.g. #92840# -const std::string TAG_BODY = std::string(" SAL_CALL TextHtmlToHTMLFormat(Sequence& aTextHtml) -{ - OSL_ASSERT(aTextHtml.getLength() > 0); - - if (!(aTextHtml.getLength() > 0)) - return Sequence(); - - // fill the buffer with dummy values to calc the exact length - std::string dummyHtmlHeader = GetHtmlFormatHeader(0, 0, 0, 0); - size_t lHtmlFormatHeader = dummyHtmlHeader.length(); - - std::string textHtml( - reinterpret_cast(aTextHtml.getConstArray()), - reinterpret_cast(aTextHtml.getConstArray()) + aTextHtml.getLength()); - - std::string::size_type nStartHtml = textHtml.find(TAG_HTML) + lHtmlFormatHeader - 1; // we start one before '' Word 2000 does also so - std::string::size_type nEndHtml = textHtml.find(TAG_END_HTML) + lHtmlFormatHeader + TAG_END_HTML.length() + 1; // our SOffice 5.2 wants 2 behind ? - - // The body tag may have parameters so we need to search for the - // closing '>' manually e.g. #92840# - std::string::size_type nStartFragment = textHtml.find(">", textHtml.find(TAG_BODY)) + lHtmlFormatHeader + 1; - std::string::size_type nEndFragment = textHtml.find(TAG_END_BODY) + lHtmlFormatHeader; - - std::string htmlFormat = GetHtmlFormatHeader(nStartHtml, nEndHtml, nStartFragment, nEndFragment); - htmlFormat += textHtml; - - Sequence byteSequence(htmlFormat.length() + 1); // space the trailing '\0' - memset(byteSequence.getArray(), 0, byteSequence.getLength()); - - memcpy( - static_cast(byteSequence.getArray()), - static_cast(htmlFormat.c_str()), - htmlFormat.length()); - - return byteSequence; -} - -const char* HtmlStartTag = " HTMLFormatToTextHtml(const Sequence& aHTMLFormat) -{ - BOOST_ASSERT(isHTMLFormat(aHTMLFormat) && "No HTML Format provided"); - - Sequence& nonconstHTMLFormatRef = const_cast< Sequence& >(aHTMLFormat); - sal_Char* dataStart = reinterpret_cast(nonconstHTMLFormatRef.getArray()); - sal_Char* dataEnd = dataStart + nonconstHTMLFormatRef.getLength() - 1; - const sal_Char* htmlStartTag = strcasestr(dataStart, HtmlStartTag); - - BOOST_ASSERT(htmlStartTag && "Seems to be no HTML at all"); - - // It doesn't seem to be HTML? Well then simply return what has been - // provided in non-debug builds - if (htmlStartTag == NULL) - { - return aHTMLFormat; - } - - sal_Int32 len = dataEnd - htmlStartTag; - Sequence plainHtmlData(len); - - memcpy(static_cast(plainHtmlData.getArray()), htmlStartTag, len); - - return plainHtmlData; -} - -/* A simple format detection. We are just comparing the first few bytes - of the provided byte sequence to see whether or not it is the MS - Office Html format. If it shows that this is not reliable enough we - can improve this -*/ -const char HtmlFormatStart[] = "Version:"; -int HtmlFormatStartLen = (sizeof(HtmlFormatStart) - 1); - -bool isHTMLFormat(const Sequence& aHtmlSequence) -{ - if (aHtmlSequence.getLength() < HtmlFormatStartLen) - return false; - - return rtl_str_compareIgnoreAsciiCase_WithLength(HtmlFormatStart, - HtmlFormatStartLen, - reinterpret_cast(aHtmlSequence.getConstArray()), - HtmlFormatStartLen) == 0; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/HtmlFmtFlt.hxx b/vcl/aqua/source/dtrans/HtmlFmtFlt.hxx deleted file mode 100644 index 393aed89fb72..000000000000 --- a/vcl/aqua/source/dtrans/HtmlFmtFlt.hxx +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_DTRANS_HTMLFMTFLT_HXX -#define INCLUDED_VCL_AQUA_SOURCE_DTRANS_HTMLFMTFLT_HXX - -#include - -/* Transform plain HTML into the format expected by MS Office. - */ -com::sun::star::uno::Sequence TextHtmlToHTMLFormat(com::sun::star::uno::Sequence& aTextHtml); - -/* Transform the MS Office HTML format into plain HTML. - */ -com::sun::star::uno::Sequence HTMLFormatToTextHtml(const com::sun::star::uno::Sequence& aHTMLFormat); - -/* Detects whether the given byte sequence contains the MS Office Html format. - - @returns True if the MS Office Html format will be detected False otherwise. - */ -bool isHTMLFormat (const com::sun::star::uno::Sequence& aHtmlSequence); - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/OSXTransferable.cxx b/vcl/aqua/source/dtrans/OSXTransferable.cxx deleted file mode 100644 index 7cfffcd4d7c5..000000000000 --- a/vcl/aqua/source/dtrans/OSXTransferable.cxx +++ /dev/null @@ -1,203 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include - -#include "OSXTransferable.hxx" - -#include "DataFlavorMapping.hxx" - -using namespace std; -using namespace osl; -using namespace cppu; -using namespace com::sun::star::uno; -using namespace com::sun::star::datatransfer; -using namespace com::sun::star::io; -using namespace com::sun::star::lang; -using namespace com::sun::star::container; - - -namespace // private -{ - bool isValidFlavor( const DataFlavor& aFlavor ) - { - size_t len = aFlavor.MimeType.getLength(); - Type dtype = aFlavor.DataType; - return ((len > 0) && ((dtype == getCppuType((Sequence*)0)) || (dtype == getCppuType((OUString*)0)))); - } - -} // namespace private - - -OSXTransferable::OSXTransferable(const Reference rXMimeCntFactory, - DataFlavorMapperPtr_t pDataFlavorMapper, - NSPasteboard* pasteboard) : - mrXMimeCntFactory(rXMimeCntFactory), - mDataFlavorMapper(pDataFlavorMapper), - mPasteboard(pasteboard) -{ - [mPasteboard retain]; - - initClipboardItemList(); -} - - -OSXTransferable::~OSXTransferable() -{ - [mPasteboard release]; -} - - -Any SAL_CALL OSXTransferable::getTransferData( const DataFlavor& aFlavor ) - throw( UnsupportedFlavorException, IOException, RuntimeException ) -{ - if (!isValidFlavor(aFlavor) || !isDataFlavorSupported(aFlavor)) - { - throw UnsupportedFlavorException("AquaClipboard: Unsupported data flavor", - static_cast(this)); - } - - bool bInternal(false); - NSString* sysFormat = - (aFlavor.MimeType.startsWith("image/png")) - ? mDataFlavorMapper->openOfficeImageToSystemFlavor( mPasteboard ) - : mDataFlavorMapper->openOfficeToSystemFlavor(aFlavor, bInternal); - DataProviderPtr_t dp; - - if ([sysFormat caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame) - { - NSArray* sysData = [mPasteboard propertyListForType: sysFormat]; - dp = mDataFlavorMapper->getDataProvider(sysFormat, sysData); - } - else - { - NSData* sysData = [mPasteboard dataForType: sysFormat]; - dp = mDataFlavorMapper->getDataProvider(sysFormat, sysData); - } - - if (dp.get() == NULL) - { - throw UnsupportedFlavorException("AquaClipboard: Unsupported data flavor", - static_cast(this)); - } - - return dp->getOOoData(); -} - - -bool OSXTransferable::isUnicodeText(const DataFlavor& flavor) -{ - return (flavor.DataType == getCppuType((OUString*)0)); -} - - -Sequence< DataFlavor > SAL_CALL OSXTransferable::getTransferDataFlavors( ) - throw( RuntimeException ) -{ - return mFlavorList; -} - - -sal_Bool SAL_CALL OSXTransferable::isDataFlavorSupported(const DataFlavor& aFlavor) - throw( RuntimeException ) -{ - for (sal_Int32 i = 0; i < mFlavorList.getLength(); i++) - if (compareDataFlavors(aFlavor, mFlavorList[i])) - return sal_True; - - return sal_False; -} - - -void OSXTransferable::initClipboardItemList() -{ - NSArray* pboardFormats = [mPasteboard types]; - - if (pboardFormats == NULL) - { - throw RuntimeException("AquaClipboard: Cannot get clipboard data", - static_cast(this)); - } - - mFlavorList = mDataFlavorMapper->typesArrayToFlavorSequence(pboardFormats); -} - - -/* Compares two DataFlavors. Returns true if both DataFlavor have the same media type - and the number of parameter and all parameter values do match otherwise false - is returned. - */ -bool OSXTransferable::compareDataFlavors(const DataFlavor& lhs, const DataFlavor& rhs ) -{ - try - { - Reference xLhs(mrXMimeCntFactory->createMimeContentType(lhs.MimeType)); - Reference xRhs(mrXMimeCntFactory->createMimeContentType(rhs.MimeType)); - - if (!xLhs->getFullMediaType().equalsIgnoreAsciiCase(xRhs->getFullMediaType()) || - !cmpAllContentTypeParameter(xLhs, xRhs)) - { - return false; - } - } - catch( IllegalArgumentException& ) - { - OSL_FAIL( "Invalid content type detected" ); - return false; - } - - return true; -} - - -bool OSXTransferable::cmpAllContentTypeParameter(const Reference xLhs, - const Reference xRhs) const -{ - Sequence xLhsFlavors = xLhs->getParameters(); - Sequence xRhsFlavors = xRhs->getParameters(); - - // Stop here if the number of parameters is different already - if (xLhsFlavors.getLength() != xRhsFlavors.getLength()) - return false; - - try - { - OUString pLhs; - OUString pRhs; - - for (sal_Int32 i = 0; i < xLhsFlavors.getLength(); i++) - { - pLhs = xLhs->getParameterValue(xLhsFlavors[i]); - pRhs = xRhs->getParameterValue(xLhsFlavors[i]); - - if (!pLhs.equalsIgnoreAsciiCase(pRhs)) - { - return false; - } - } - } - catch(IllegalArgumentException&) - { - return false; - } - - return true; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/OSXTransferable.hxx b/vcl/aqua/source/dtrans/OSXTransferable.hxx deleted file mode 100644 index 27885effd03f..000000000000 --- a/vcl/aqua/source/dtrans/OSXTransferable.hxx +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#ifndef _TRANSFERABLE_HXX_ -#define _TRANSFERABLE_HXX_ - -#include -#include -#include -#include - -#include "DataFlavorMapping.hxx" - -#include -#import -#include - -#include -#include -#include - - -class OSXTransferable : public ::cppu::WeakImplHelper1, - private ::boost::noncopyable -{ -public: - typedef com::sun::star::uno::Sequence< sal_Int8 > ByteSequence_t; - - explicit OSXTransferable(com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XMimeContentTypeFactory> rXMimeCntFactory, - DataFlavorMapperPtr_t pDataFlavorMapper, - NSPasteboard* pasteboard); - - virtual ~OSXTransferable(); - - //------------------------------------------------------------------------ - // XTransferable - //------------------------------------------------------------------------ - - virtual ::com::sun::star::uno::Any SAL_CALL getTransferData( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) - throw( ::com::sun::star::datatransfer::UnsupportedFlavorException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException ); - - virtual ::com::sun::star::uno::Sequence< ::com::sun::star::datatransfer::DataFlavor > SAL_CALL getTransferDataFlavors( ) - throw( ::com::sun::star::uno::RuntimeException ); - - virtual sal_Bool SAL_CALL isDataFlavorSupported( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) - throw( ::com::sun::star::uno::RuntimeException ); - - //------------------------------------------------------------------------ - // Helper functions not part of the XTransferable interface - //------------------------------------------------------------------------ - - void initClipboardItemList(); - - //com::sun::star::uno::Any getClipboardItemData(ClipboardItemPtr_t clipboardItem); - - bool isUnicodeText(const com::sun::star::datatransfer::DataFlavor& flavor); - - bool compareDataFlavors( const com::sun::star::datatransfer::DataFlavor& lhs, - const com::sun::star::datatransfer::DataFlavor& rhs ); - - bool cmpAllContentTypeParameter( const com::sun::star::uno::Reference< com::sun::star::datatransfer::XMimeContentType > xLhs, - const com::sun::star::uno::Reference< com::sun::star::datatransfer::XMimeContentType > xRhs ) const; - -private: - com::sun::star::uno::Sequence< com::sun::star::datatransfer::DataFlavor > mFlavorList; - ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XMimeContentTypeFactory> mrXMimeCntFactory; - DataFlavorMapperPtr_t mDataFlavorMapper; - NSPasteboard* mPasteboard; -}; - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/PictToBmpFlt.cxx b/vcl/aqua/source/dtrans/PictToBmpFlt.cxx deleted file mode 100644 index 91ed2bc5f177..000000000000 --- a/vcl/aqua/source/dtrans/PictToBmpFlt.cxx +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include -#include -#include -#include - -#include - -#include "PictToBmpFlt.hxx" - -bool ImageToPNG( com::sun::star::uno::Sequence& rImgData, - com::sun::star::uno::Sequence& rPngData, - NSBitmapImageFileType eInFormat) -{ - (void) eInFormat; // Really not needed? Weird. - - NSData* pData = [NSData dataWithBytesNoCopy: (void*)rImgData.getConstArray() length: rImgData.getLength() freeWhenDone: 0]; - if( !pData) - return false; - - NSBitmapImageRep* pRep =[NSBitmapImageRep imageRepWithData: pData]; - if( !pRep) - return false; - - NSData* pOut = [pRep representationUsingType: NSPNGFileType properties: nil]; - if( !pOut) - return false; - - const size_t nPngSize = [pOut length]; - rPngData.realloc( nPngSize); - [pOut getBytes: rPngData.getArray() length: nPngSize]; - return (nPngSize > 0); -} - -bool PNGToImage( com::sun::star::uno::Sequence& rPngData, - com::sun::star::uno::Sequence& rImgData, - NSBitmapImageFileType eOutFormat - ) -{ - NSData* pData = [NSData dataWithBytesNoCopy: const_cast(rPngData.getConstArray()) length: rPngData.getLength() freeWhenDone: 0]; - if( !pData) - return false; - - NSBitmapImageRep* pRep = [NSBitmapImageRep imageRepWithData: pData]; - if( !pRep) - return false; - - NSData* pOut = [pRep representationUsingType: eOutFormat properties: nil]; - if( !pOut) - return false; - - const size_t nImgSize = [pOut length]; - rImgData.realloc( nImgSize); - [pOut getBytes: rImgData.getArray() length: nImgSize]; - return (nImgSize > 0); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/PictToBmpFlt.hxx b/vcl/aqua/source/dtrans/PictToBmpFlt.hxx deleted file mode 100644 index 65a7771caf1d..000000000000 --- a/vcl/aqua/source/dtrans/PictToBmpFlt.hxx +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_DTRANS_PICTTOBMPFLT_HXX -#define INCLUDED_VCL_AQUA_SOURCE_DTRANS_PICTTOBMPFLT_HXX - -#include - -#include -#include -#include - -bool ImageToPNG( com::sun::star::uno::Sequence& rImgData, - com::sun::star::uno::Sequence& rPngData, - NSBitmapImageFileType eInFormat); - -bool PNGToImage( com::sun::star::uno::Sequence& rPngData, - com::sun::star::uno::Sequence& rImgData, - NSBitmapImageFileType eOutFormat); - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/aqua_clipboard.cxx b/vcl/aqua/source/dtrans/aqua_clipboard.cxx deleted file mode 100644 index ac3bcaee1d60..000000000000 --- a/vcl/aqua/source/dtrans/aqua_clipboard.cxx +++ /dev/null @@ -1,372 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include "aqua_clipboard.hxx" - -#include "DataFlavorMapping.hxx" -#include "OSXTransferable.hxx" -#include -#include "comphelper/makesequence.hxx" -#include "comphelper/processfactory.hxx" - -#include - -using namespace com::sun::star::datatransfer; -using namespace com::sun::star::datatransfer::clipboard; -using namespace com::sun::star::lang; -using namespace com::sun::star::uno; -using namespace cppu; -using namespace osl; -using namespace std; -using namespace comphelper; - - -@implementation EventListener; - --(EventListener*)initWithAquaClipboard: (AquaClipboard*) pcb -{ - self = [super init]; - - if (self) - pAquaClipboard = pcb; - - return self; -} - --(void)pasteboard:(NSPasteboard*)sender provideDataForType:(NSString*)type -{ - if( pAquaClipboard ) - pAquaClipboard->provideDataForType(sender, type); -} - --(void)applicationDidBecomeActive:(NSNotification*)aNotification -{ - if( pAquaClipboard ) - pAquaClipboard->applicationDidBecomeActive(aNotification); -} - --(void)disposing -{ - pAquaClipboard = NULL; -} - -@end - - -OUString clipboard_getImplementationName() -{ - return OUString("com.sun.star.datatransfer.clipboard.AquaClipboard"); -} - -Sequence clipboard_getSupportedServiceNames() -{ - return makeSequence(OUString("com.sun.star.datatransfer.clipboard.SystemClipboard")); -} - - -AquaClipboard::AquaClipboard(NSPasteboard* pasteboard, bool bUseSystemPasteboard) : - WeakComponentImplHelper3(m_aMutex), - mIsSystemPasteboard(bUseSystemPasteboard) -{ - Reference xContext = comphelper::getProcessComponentContext(); - - mrXMimeCntFactory = MimeContentTypeFactory::create(xContext); - - mpDataFlavorMapper = DataFlavorMapperPtr_t(new DataFlavorMapper()); - - if (pasteboard != NULL) - { - mPasteboard = pasteboard; - mIsSystemPasteboard = false; - } - else - { - mPasteboard = bUseSystemPasteboard ? [NSPasteboard generalPasteboard] : - [NSPasteboard pasteboardWithName: NSDragPboard]; - - if (mPasteboard == nil) - { - throw RuntimeException("AquaClipboard: Cannot create Cocoa pasteboard", - static_cast(this)); - } - } - - [mPasteboard retain]; - - mEventListener = [[EventListener alloc] initWithAquaClipboard: this]; - - if (mEventListener == nil) - { - [mPasteboard release]; - - throw RuntimeException( - OUString("AquaClipboard: Cannot create pasteboard change listener"), - static_cast(this)); - } - - if (mIsSystemPasteboard) - { - NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter]; - - [notificationCenter addObserver: mEventListener - selector: @selector(applicationDidBecomeActive:) - name: @"NSApplicationDidBecomeActiveNotification" - object: [NSApplication sharedApplication]]; - } - - mPasteboardChangeCount = [mPasteboard changeCount]; -} - - -AquaClipboard::~AquaClipboard() -{ - if (mIsSystemPasteboard) - { - [[NSNotificationCenter defaultCenter] removeObserver: mEventListener]; - } - - [mEventListener disposing]; - [mEventListener release]; - [mPasteboard release]; -} - - -Reference SAL_CALL AquaClipboard::getContents() throw(RuntimeException) -{ - MutexGuard aGuard(m_aMutex); - - // Shortcut: If we are clipboard owner already we don't need - // to drag the data through the system clipboard - if (mXClipboardContent.is()) - { - return mXClipboardContent; - } - - return Reference(new OSXTransferable(mrXMimeCntFactory, - mpDataFlavorMapper, - mPasteboard)); -} - - -void SAL_CALL AquaClipboard::setContents(const Reference& xTransferable, - const Reference& xClipboardOwner) - throw( RuntimeException ) -{ - NSArray* types = xTransferable.is() ? - mpDataFlavorMapper->flavorSequenceToTypesArray(xTransferable->getTransferDataFlavors()) : - [NSArray array]; - - ClearableMutexGuard aGuard(m_aMutex); - - Reference oldOwner(mXClipboardOwner); - mXClipboardOwner = xClipboardOwner; - - Reference oldContent(mXClipboardContent); - mXClipboardContent = xTransferable; - - mPasteboardChangeCount = [mPasteboard declareTypes: types owner: mEventListener]; - - aGuard.clear(); - - // if we are already the owner of the clipboard - // then fire lost ownership event - if (oldOwner.is()) - { - fireLostClipboardOwnershipEvent(oldOwner, oldContent); - } - - fireClipboardChangedEvent(); -} - - -OUString SAL_CALL AquaClipboard::getName() throw( RuntimeException ) -{ - return OUString(); -} - - -sal_Int8 SAL_CALL AquaClipboard::getRenderingCapabilities() throw( RuntimeException ) -{ - return 0; -} - - -void SAL_CALL AquaClipboard::addClipboardListener(const Reference< XClipboardListener >& listener) - throw( RuntimeException ) -{ - MutexGuard aGuard(m_aMutex); - - if (!listener.is()) - throw IllegalArgumentException("empty reference", - static_cast(this), 1); - - mClipboardListeners.push_back(listener); -} - - -void SAL_CALL AquaClipboard::removeClipboardListener(const Reference< XClipboardListener >& listener) - throw( RuntimeException ) -{ - MutexGuard aGuard(m_aMutex); - - if (!listener.is()) - throw IllegalArgumentException("empty reference", - static_cast(this), 1); - - mClipboardListeners.remove(listener); -} - - -void AquaClipboard::applicationDidBecomeActive(NSNotification*) -{ - ClearableMutexGuard aGuard(m_aMutex); - - int currentPboardChgCount = [mPasteboard changeCount]; - - if (currentPboardChgCount != mPasteboardChangeCount) - { - mPasteboardChangeCount = currentPboardChgCount; - - // Clear clipboard content and owner and send lostOwnership - // notification to the old clipboard owner as well as - // ClipboardChanged notification to any clipboard listener - Reference oldOwner(mXClipboardOwner); - mXClipboardOwner.clear(); - - Reference oldContent(mXClipboardContent); - mXClipboardContent.clear(); - - aGuard.clear(); - - if (oldOwner.is()) - { - fireLostClipboardOwnershipEvent(oldOwner, oldContent); - } - - fireClipboardChangedEvent(); - } -} - - -void AquaClipboard::fireClipboardChangedEvent() -{ - ClearableMutexGuard aGuard(m_aMutex); - - list > listeners(mClipboardListeners); - ClipboardEvent aEvent; - - if (listeners.begin() != listeners.end()) - { - aEvent = ClipboardEvent(static_cast(this), getContents()); - } - - aGuard.clear(); - - while (listeners.begin() != listeners.end()) - { - if (listeners.front().is()) - { - try { listeners.front()->changedContents(aEvent); } - catch (RuntimeException&) { } - } - listeners.pop_front(); - } -} - - -void AquaClipboard::fireLostClipboardOwnershipEvent(Reference oldOwner, Reference oldContent) -{ - BOOST_ASSERT(oldOwner.is()); - - try { oldOwner->lostOwnership(static_cast(this), oldContent); } - catch(RuntimeException&) { } -} - - -void AquaClipboard::provideDataForType(NSPasteboard* sender, NSString* type) -{ - if( mXClipboardContent.is() ) - { - DataProviderPtr_t dp = mpDataFlavorMapper->getDataProvider(type, mXClipboardContent); - NSData* pBoardData = NULL; - - if (dp.get() != NULL) - { - pBoardData = (NSData*)dp->getSystemData(); - [sender setData: pBoardData forType: type]; - } - } -} - - -//------------------------------------------------ -// XFlushableClipboard -//------------------------------------------------ - -void SAL_CALL AquaClipboard::flushClipboard() - throw(RuntimeException) -{ - if (mXClipboardContent.is()) - { - Sequence flavorList = mXClipboardContent->getTransferDataFlavors(); - sal_uInt32 nFlavors = flavorList.getLength(); - bool bInternal(false); - - for (sal_uInt32 i = 0; i < nFlavors; i++) - { - NSString* sysType = mpDataFlavorMapper->openOfficeToSystemFlavor(flavorList[i], bInternal); - - if (sysType != NULL) - { - provideDataForType(mPasteboard, sysType); - } - } - mXClipboardContent.clear(); - } -} - - -NSPasteboard* AquaClipboard::getPasteboard() const -{ - return mPasteboard; -} - - -//------------------------------------------------- -// XServiceInfo -//------------------------------------------------- - -OUString SAL_CALL AquaClipboard::getImplementationName() throw( RuntimeException ) -{ - return clipboard_getImplementationName(); -} - - -sal_Bool SAL_CALL AquaClipboard::supportsService( const OUString& /*ServiceName*/ ) throw( RuntimeException ) -{ - return sal_False; -} - - -Sequence< OUString > SAL_CALL AquaClipboard::getSupportedServiceNames() throw( RuntimeException ) -{ - return clipboard_getSupportedServiceNames(); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/aqua_clipboard.hxx b/vcl/aqua/source/dtrans/aqua_clipboard.hxx deleted file mode 100644 index ba0aecd9f172..000000000000 --- a/vcl/aqua/source/dtrans/aqua_clipboard.hxx +++ /dev/null @@ -1,175 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_AQUA_SOURCE_DTRANS_AQUA_CLIPBOARD_HXX -#define INCLUDED_VCL_AQUA_SOURCE_DTRANS_AQUA_CLIPBOARD_HXX - -#include "DataFlavorMapping.hxx" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#import -#include - -class AquaClipboard; - -@interface EventListener : NSObject -{ - AquaClipboard* pAquaClipboard; -} - -// Init the pasteboard change listener with a reference to the OfficeClipboard -// instance -- (EventListener*)initWithAquaClipboard: (AquaClipboard*) pcb; - -// Promiss resolver function -- (void)pasteboard:(NSPasteboard*)sender provideDataForType:(NSString *)type; - --(void)applicationDidBecomeActive:(NSNotification*)aNotification; - --(void)disposing; -@end - - -class AquaClipboard : public ::cppu::BaseMutex, - public ::cppu::WeakComponentImplHelper3< com::sun::star::datatransfer::clipboard::XSystemClipboard, - com::sun::star::datatransfer::clipboard::XFlushableClipboard, - com::sun::star::lang::XServiceInfo >, - private ::boost::noncopyable -{ -public: - /* Create a clipboard instance. - - @param pasteboard - If not equal NULL the instance will be instantiated with the provided - pasteboard reference and 'bUseSystemClipboard' will be ignored - - @param bUseSystemClipboard - If 'pasteboard' is NULL 'bUseSystemClipboard' determines whether the - system clipboard will be created (bUseSystemClipboard == true) or if - the DragPasteboard if bUseSystemClipboard == false - */ - AquaClipboard(NSPasteboard* pasteboard = NULL, - bool bUseSystemClipboard = true); - - ~AquaClipboard(); - - //------------------------------------------------ - // XClipboard - //------------------------------------------------ - - virtual ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > SAL_CALL getContents() - throw( ::com::sun::star::uno::RuntimeException ); - - virtual void SAL_CALL setContents( const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable >& xTransferable, - const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardOwner >& xClipboardOwner ) - throw( ::com::sun::star::uno::RuntimeException ); - - virtual OUString SAL_CALL getName() - throw( ::com::sun::star::uno::RuntimeException ); - - //------------------------------------------------ - // XClipboardEx - //------------------------------------------------ - - virtual sal_Int8 SAL_CALL getRenderingCapabilities() - throw( ::com::sun::star::uno::RuntimeException ); - - //------------------------------------------------ - // XClipboardNotifier - //------------------------------------------------ - - virtual void SAL_CALL addClipboardListener( const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardListener >& listener ) - throw( ::com::sun::star::uno::RuntimeException ); - - virtual void SAL_CALL removeClipboardListener( const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardListener >& listener ) - throw( ::com::sun::star::uno::RuntimeException ); - - //------------------------------------------------ - // XFlushableClipboard - //------------------------------------------------ - - virtual void SAL_CALL flushClipboard( ) throw( com::sun::star::uno::RuntimeException ); - - //------------------------------------------------ - // XServiceInfo - //------------------------------------------------ - - virtual OUString SAL_CALL getImplementationName() - throw(::com::sun::star::uno::RuntimeException); - - virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) - throw(::com::sun::star::uno::RuntimeException); - - virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() - throw(::com::sun::star::uno::RuntimeException); - - /* Get a reference to the used pastboard. - */ - NSPasteboard* getPasteboard() const; - - /* Notify the current clipboard owner that he is no longer the clipboard owner. - */ - void fireLostClipboardOwnershipEvent(::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardOwner> oldOwner, - ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > oldContent); - - void pasteboardChangedOwner(); - - void provideDataForType(NSPasteboard* sender, NSString* type); - - void applicationDidBecomeActive(NSNotification* aNotification); - -private: - - /* Notify all registered XClipboardListener that the clipboard content - has changed. - */ - void fireClipboardChangedEvent(); - -private: - ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XMimeContentTypeFactory > mrXMimeCntFactory; - ::std::list< ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardListener > > mClipboardListeners; - ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > mXClipboardContent; - com::sun::star::uno::Reference< com::sun::star::datatransfer::clipboard::XClipboardOwner > mXClipboardOwner; - DataFlavorMapperPtr_t mpDataFlavorMapper; - bool mIsSystemPasteboard; - NSPasteboard* mPasteboard; - int mPasteboardChangeCount; - EventListener* mEventListener; -}; - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/dtrans/service_entry.cxx b/vcl/aqua/source/dtrans/service_entry.cxx deleted file mode 100644 index 07103bfe9547..000000000000 --- a/vcl/aqua/source/dtrans/service_entry.cxx +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "osl/diagnose.h" - -#include "vcl/svapp.hxx" - -#include "aqua/saldata.hxx" -#include "aqua/salinst.h" - -#include "DragSource.hxx" -#include "DropTarget.hxx" -#include "aqua_clipboard.hxx" - -using namespace ::osl; -using namespace ::rtl; -using namespace ::com::sun::star; -using namespace ::com::sun::star::uno; -using namespace ::cppu; -using namespace ::com::sun::star::lang; -using namespace ::com::sun::star::datatransfer::clipboard; - - -uno::Reference< XInterface > AquaSalInstance::CreateClipboard( const Sequence< Any >& i_rArguments ) -{ - if ( Application::IsHeadlessModeEnabled() ) - return SalInstance::CreateClipboard( i_rArguments ); - - SalData* pSalData = GetSalData(); - if( ! pSalData->mxClipboard.is() ) - pSalData->mxClipboard = uno::Reference(static_cast< XClipboard* >(new AquaClipboard()), UNO_QUERY); - return pSalData->mxClipboard; -} - -uno::Reference AquaSalInstance::CreateDragSource() -{ - if ( Application::IsHeadlessModeEnabled() ) - return SalInstance::CreateDragSource(); - - return uno::Reference(static_cast< XInitialization* >(new DragSource()), UNO_QUERY); -} - -uno::Reference AquaSalInstance::CreateDropTarget() -{ - if ( Application::IsHeadlessModeEnabled() ) - return SalInstance::CreateDropTarget(); - - return uno::Reference(static_cast< XInitialization* >(new DropTarget()), UNO_QUERY); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/gdi/aquaprintaccessoryview.mm b/vcl/aqua/source/gdi/aquaprintaccessoryview.mm deleted file mode 100644 index 5c6ea0e0162c..000000000000 --- a/vcl/aqua/source/gdi/aquaprintaccessoryview.mm +++ /dev/null @@ -1,1381 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include "sal/config.h" - -#include "tools/resary.hxx" - -#include "vcl/print.hxx" -#include "vcl/image.hxx" -#include "vcl/virdev.hxx" -#include "vcl/svapp.hxx" -#include "vcl/unohelp.hxx" - -#include "aqua/aquaprintview.h" -#include "aqua/salinst.h" -#include "quartz/utils.h" - -#include "svdata.hxx" -#include "svids.hrc" - -#include "com/sun/star/i18n/XBreakIterator.hpp" -#include "com/sun/star/i18n/WordType.hpp" - -#include - -using namespace vcl; -using namespace com::sun::star; -using namespace com::sun::star::beans; -using namespace com::sun::star::uno; - -/* Note: the accesory view as implemented here is already deprecated in Leopard. Unfortunately - as long as our baseline is Tiger we cannot gain the advantages over multiple accessory views - as well havs having accessory views AND a preview (as long as you are linked vs. 10.4 libraries - the preview insists on not being present. This is unfortunate. -*/ - -class ControllerProperties; - -@interface ControlTarget : NSObject -{ - ControllerProperties* mpController; -} --(id)initWithControllerMap: (ControllerProperties*)pController; --(void)triggered:(id)pSender; --(void)triggeredNumeric:(id)pSender; --(void)triggeredPreview:(id)pSender; --(void)dealloc; -@end - - -class ControllerProperties -{ - vcl::PrinterController* mpController; - std::map< int, rtl::OUString > maTagToPropertyName; - std::map< int, sal_Int32 > maTagToValueInt; - std::map< NSView*, NSView* > maViewPairMap; - std::vector< NSObject* > maViews; - int mnNextTag; - sal_Int32 mnLastPageCount; - PrintAccessoryViewState* mpState; - NSPrintOperation* mpOp; - NSView* mpAccessoryView; - NSTabView* mpTabView; - NSBox* mpPreviewBox; - NSImageView* mpPreview; - NSTextField* mpPageEdit; - NSStepper* mpStepper; - NSTextView* mpPagesLabel; - ResStringArray maLocalizedStrings; - - public: - ControllerProperties( vcl::PrinterController* i_pController, - NSPrintOperation* i_pOp, - NSView* i_pAccessoryView, - NSTabView* i_pTabView, - PrintAccessoryViewState* i_pState ) - : mpController( i_pController ), - mnNextTag( 0 ), - mnLastPageCount( i_pController->getFilteredPageCount() ), - mpState( i_pState ), - mpOp( i_pOp ), - mpAccessoryView( i_pAccessoryView ), - mpTabView( i_pTabView ), - mpPreviewBox( nil ), - mpPreview( nil ), - mpPageEdit( nil ), - mpStepper( nil ), - mpPagesLabel( nil ), - maLocalizedStrings( VclResId( SV_PRINT_NATIVE_STRINGS ) ) - { - mpState->bNeedRestart = false; - DBG_ASSERT( maLocalizedStrings.Count() >= 5, "resources not found !" ); - } - - rtl::OUString getMoreString() - { - return maLocalizedStrings.Count() >= 4 - ? OUString( maLocalizedStrings.GetString( 3 ) ) - : OUString( "More" ); - } - - rtl::OUString getPrintSelectionString() - { - return maLocalizedStrings.Count() >= 5 - ? OUString( maLocalizedStrings.GetString( 4 ) ) - : OUString( "Print selection only" ); - } - - void updatePrintJob() - { - // TODO: refresh page count etc from mpController - - // page range may have changed depending on options - sal_Int32 nPages = mpController->getFilteredPageCount(); - #if OSL_DEBUG_LEVEL > 1 - if( nPages != mnLastPageCount ) - fprintf( stderr, "trouble: number of pages changed from %ld to %ld !\n", mnLastPageCount, nPages ); - #endif - mpState->bNeedRestart = (nPages != mnLastPageCount); - NSTabViewItem* pItem = [mpTabView selectedTabViewItem]; - if( pItem ) - mpState->nLastPage = [mpTabView indexOfTabViewItem: pItem]; - else - mpState->nLastPage = 0; - mnLastPageCount = nPages; - if( mpState->bNeedRestart ) - { - // Warning: bad hack ahead - // Apple does not give us a chance of changing the page count, - // and they don't let us cancel the dialog either - // hack: send a cancel message to the window displaying our views. - // this is ugly. - NSWindow* pNSWindow = [NSApp modalWindow]; - if( pNSWindow ) - [pNSWindow cancelOperation: nil]; - [[mpOp printInfo] setJobDisposition: NSPrintCancelJob]; - } - else - { - sal_Int32 nPage = [mpStepper intValue]; - updatePreviewImage( nPage-1 ); - } - } - - int addNameTag( const rtl::OUString& i_rPropertyName ) - { - int nNewTag = mnNextTag++; - maTagToPropertyName[ nNewTag ] = i_rPropertyName; - return nNewTag; - } - - int addNameAndValueTag( const rtl::OUString& i_rPropertyName, sal_Int32 i_nValue ) - { - int nNewTag = mnNextTag++; - maTagToPropertyName[ nNewTag ] = i_rPropertyName; - maTagToValueInt[ nNewTag ] = i_nValue; - return nNewTag; - } - - void addObservedControl( NSObject* i_pView ) - { - maViews.push_back( i_pView ); - } - - void addViewPair( NSView* i_pLeft, NSView* i_pRight ) - { - maViewPairMap[ i_pLeft ] = i_pRight; - maViewPairMap[ i_pRight ] = i_pLeft; - } - - NSView* getPair( NSView* i_pLeft ) const - { - NSView* pRight = nil; - std::map< NSView*, NSView* >::const_iterator it = maViewPairMap.find( i_pLeft ); - if( it != maViewPairMap.end() ) - pRight = it->second; - return pRight; - } - - void changePropertyWithIntValue( int i_nTag ) - { - std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); - std::map< int, sal_Int32 >::const_iterator value_it = maTagToValueInt.find( i_nTag ); - if( name_it != maTagToPropertyName.end() && value_it != maTagToValueInt.end() ) - { - PropertyValue* pVal = mpController->getValue( name_it->second ); - if( pVal ) - { - pVal->Value <<= value_it->second; - updatePrintJob(); - } - } - } - - void changePropertyWithIntValue( int i_nTag, sal_Int64 i_nValue ) - { - std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); - if( name_it != maTagToPropertyName.end() ) - { - PropertyValue* pVal = mpController->getValue( name_it->second ); - if( pVal ) - { - pVal->Value <<= i_nValue; - updatePrintJob(); - } - } - } - - void changePropertyWithBoolValue( int i_nTag, sal_Bool i_bValue ) - { - std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); - if( name_it != maTagToPropertyName.end() ) - { - PropertyValue* pVal = mpController->getValue( name_it->second ); - if( pVal ) - { - // ugly - if( name_it->second.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrintContent")) ) - pVal->Value <<= i_bValue ? sal_Int32(2) : sal_Int32(0); - else - pVal->Value <<= i_bValue; - updatePrintJob(); - } - } - } - - void changePropertyWithStringValue( int i_nTag, const rtl::OUString& i_rValue ) - { - std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); - if( name_it != maTagToPropertyName.end() ) - { - PropertyValue* pVal = mpController->getValue( name_it->second ); - if( pVal ) - { - pVal->Value <<= i_rValue; - updatePrintJob(); - } - } - } - - void updateEnableState() - { - for( std::vector< NSObject* >::iterator it = maViews.begin(); it != maViews.end(); ++it ) - { - NSObject* pObj = *it; - NSControl* pCtrl = nil; - NSCell* pCell = nil; - if( [pObj isKindOfClass: [NSControl class]] ) - pCtrl = (NSControl*)pObj; - else if( [pObj isKindOfClass: [NSCell class]] ) - pCell = (NSCell*)pObj; - - int nTag = pCtrl ? [pCtrl tag] : - pCell ? [pCell tag] : - -1; - - std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( nTag ); - if( name_it != maTagToPropertyName.end() && ! name_it->second.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrintContent")) ) - { - BOOL bEnabled = mpController->isUIOptionEnabled( name_it->second ) ? YES : NO; - if( pCtrl ) - { - [pCtrl setEnabled: bEnabled]; - NSView* pOther = getPair( pCtrl ); - if( pOther && [pOther isKindOfClass: [NSControl class]] ) - [(NSControl*)pOther setEnabled: bEnabled]; - } - else if( pCell ) - [pCell setEnabled: bEnabled]; - - } - } - } - - void updatePreviewImage( sal_Int32 i_nPage ) - { - sal_Int32 nPages = mpController->getFilteredPageCount(); - NSRect aViewFrame = [mpPreview frame]; - Size aPixelSize( static_cast(aViewFrame.size.width), - static_cast(aViewFrame.size.height) ); - if( i_nPage >= 0 && nPages > i_nPage ) - { - GDIMetaFile aMtf; - PrinterController::PageSize aPageSize( mpController->getFilteredPageFile( i_nPage, aMtf, false ) ); - VirtualDevice aDev; - if( mpController->getPrinter()->GetPrinterOptions().IsConvertToGreyscales() ) - aDev.SetDrawMode( aDev.GetDrawMode() | ( DRAWMODE_GRAYLINE | DRAWMODE_GRAYFILL | DRAWMODE_GRAYTEXT | - DRAWMODE_GRAYBITMAP | DRAWMODE_GRAYGRADIENT ) ); - // see salprn.cxx, currently we pretend to be a 720dpi device on printers - aDev.SetReferenceDevice( 720, 720 ); - aDev.EnableOutput( TRUE ); - Size aLogicSize( aDev.PixelToLogic( aPixelSize, MapMode( MAP_100TH_MM ) ) ); - double fScaleX = double(aLogicSize.Width())/double(aPageSize.aSize.Width()); - double fScaleY = double(aLogicSize.Height())/double(aPageSize.aSize.Height()); - double fScale = (fScaleX < fScaleY) ? fScaleX : fScaleY; - // #i104784# if we render the page too small then rounding issues result in - // layout artifacts looking really bad. So scale the page unto a device that is not - // full page size but not too small either. This also results in much better visual - // quality of the preview, e.g. when its height approaches the number of text lines - if( fScale < 0.1 ) - fScale = 0.1; - aMtf.WindStart(); - aMtf.Scale( fScale, fScale ); - aMtf.WindStart(); - aLogicSize.Width() = long(double(aPageSize.aSize.Width()) * fScale); - aLogicSize.Height() = long(double(aPageSize.aSize.Height()) * fScale); - aPixelSize = aDev.LogicToPixel( aLogicSize, MapMode( MAP_100TH_MM ) ); - aDev.SetOutputSizePixel( aPixelSize ); - aMtf.WindStart(); - aDev.SetMapMode( MapMode( MAP_100TH_MM ) ); - aMtf.Play( &aDev, Point( 0, 0 ), aLogicSize ); - aDev.EnableMapMode( FALSE ); - Image aImage( aDev.GetBitmap( Point( 0, 0 ), aPixelSize ) ); - NSImage* pImage = CreateNSImage( aImage ); - [mpPreview setImage: [pImage autorelease]]; - } - else - [mpPreview setImage: nil]; - } - - void setupPreview( ControlTarget* i_pCtrlTarget ) - { - if( maLocalizedStrings.Count() < 3 ) - return; - - // get the preview control - NSRect aPreviewFrame = [mpAccessoryView frame]; - aPreviewFrame.origin.x = 0; - aPreviewFrame.origin.y = 5; - aPreviewFrame.size.width = 190; - aPreviewFrame.size.height -= 7; - - // create a box to put the preview controls in - mpPreviewBox = [[NSBox alloc] initWithFrame: aPreviewFrame]; - [mpPreviewBox setTitle: [CreateNSString( maLocalizedStrings.GetString( 0 ) ) autorelease]]; - [mpAccessoryView addSubview: [mpPreviewBox autorelease]]; - - // now create the image view of the preview - NSSize aMargins = [mpPreviewBox contentViewMargins]; - aPreviewFrame.origin.x = 0; - aPreviewFrame.origin.y = 34; - aPreviewFrame.size.width -= 2*(aMargins.width+1); - aPreviewFrame.size.height -= 61; - mpPreview = [[NSImageView alloc] initWithFrame: aPreviewFrame]; - [mpPreview setImageScaling: NSScaleProportionally]; - [mpPreview setImageAlignment: NSImageAlignCenter]; - [mpPreview setImageFrameStyle: NSImageFrameNone]; - [mpPreviewBox addSubview: [mpPreview autorelease]]; - - // add a label - sal_Int32 nPages = mpController->getFilteredPageCount(); - rtl::OUStringBuffer aBuf( 16 ); - aBuf.appendAscii( "/ " ); - aBuf.append( rtl::OUString::number( nPages ) ); - - NSString* pText = CreateNSString( aBuf.makeStringAndClear() ); - NSRect aTextRect = { { 100, 5 }, { 100, 22 } }; - mpPagesLabel = [[NSTextView alloc] initWithFrame: aTextRect]; - [mpPagesLabel setFont: [NSFont controlContentFontOfSize: 0]]; - [mpPagesLabel setEditable: NO]; - [mpPagesLabel setSelectable: NO]; - [mpPagesLabel setDrawsBackground: NO]; - [mpPagesLabel setString: [pText autorelease]]; - [mpPagesLabel setToolTip: [CreateNSString( maLocalizedStrings.GetString( 2 ) ) autorelease]]; - [mpPreviewBox addSubview: [mpPagesLabel autorelease]]; - - NSRect aFieldRect = { { 45, 5 }, { 35, 25 } }; - mpPageEdit = [[NSTextField alloc] initWithFrame: aFieldRect]; - [mpPageEdit setEditable: YES]; - [mpPageEdit setSelectable: YES]; - [mpPageEdit setDrawsBackground: YES]; - [mpPageEdit setToolTip: [CreateNSString( maLocalizedStrings.GetString( 1 ) ) autorelease]]; - [mpPreviewBox addSubview: [mpPageEdit autorelease]]; - - // add a stepper control - NSRect aStepFrame = { { 85, 5 }, { 15, 25 } }; - mpStepper = [[NSStepper alloc] initWithFrame: aStepFrame]; - [mpStepper setIncrement: 1]; - [mpStepper setValueWraps: NO]; - [mpPreviewBox addSubview: [mpStepper autorelease]]; - - // constrain the text field to decimal numbers - NSNumberFormatter* pFormatter = [[NSNumberFormatter alloc] init]; - [pFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4]; - [pFormatter setMinimum: [[NSNumber numberWithInt: 1] autorelease]]; - [pFormatter setMaximum: [[NSNumber numberWithInt: nPages] autorelease]]; - [pFormatter setNumberStyle: NSNumberFormatterDecimalStyle]; - [pFormatter setAllowsFloats: NO]; - [pFormatter setMaximumFractionDigits: 0]; - [mpPageEdit setFormatter: pFormatter]; - [mpStepper setMinValue: 1]; - [mpStepper setMaxValue: nPages]; - - [mpPageEdit setIntValue: 1]; - [mpStepper setIntValue: 1]; - - // connect target and action - [mpStepper setTarget: i_pCtrlTarget]; - [mpStepper setAction: @selector(triggeredPreview:)]; - [mpPageEdit setTarget: i_pCtrlTarget]; - [mpPageEdit setAction: @selector(triggeredPreview:)]; - - // set first preview image - updatePreviewImage( 0 ); - } - - void changePreview( NSObject* i_pSender ) - { - if( [i_pSender isMemberOfClass: [NSTextField class]] ) - { - NSTextField* pField = (NSTextField*)i_pSender; - if( pField == mpPageEdit ) // sanity check - { - sal_Int32 nPage = [pField intValue]; - [mpStepper setIntValue: nPage]; - updatePreviewImage( nPage-1 ); - } - } - else if( [i_pSender isMemberOfClass: [NSStepper class]] ) - { - NSStepper* pStepper = (NSStepper*)i_pSender; - if( pStepper == mpStepper ) // sanity check - { - sal_Int32 nPage = [pStepper intValue]; - [mpPageEdit setIntValue: nPage]; - updatePreviewImage( nPage-1 ); - } - } - } -}; - -static void filterAccelerator( rtl::OUString& io_rText ) -{ - rtl::OUStringBuffer aBuf( io_rText.getLength() ); - for( sal_Int32 nIndex = 0; nIndex != -1; ) - aBuf.append( io_rText.getToken( 0, '~', nIndex ) ); - io_rText = aBuf.makeStringAndClear(); -} - -@implementation ControlTarget --(id)initWithControllerMap: (ControllerProperties*)pController -{ - if( (self = [super init]) ) - { - mpController = pController; - } - return self; -} --(void)triggered:(id)pSender -{ - if( [pSender isMemberOfClass: [NSPopUpButton class]] ) - { - NSPopUpButton* pBtn = (NSPopUpButton*)pSender; - NSMenuItem* pSelected = [pBtn selectedItem]; - if( pSelected ) - { - int nTag = [pSelected tag]; - mpController->changePropertyWithIntValue( nTag ); - } - } - else if( [pSender isMemberOfClass: [NSButton class]] ) - { - NSButton* pBtn = (NSButton*)pSender; - int nTag = [pBtn tag]; - mpController->changePropertyWithBoolValue( nTag, [pBtn state] == NSOnState ); - } - else if( [pSender isMemberOfClass: [NSMatrix class]] ) - { - NSObject* pObj = [(NSMatrix*)pSender selectedCell]; - if( [pObj isMemberOfClass: [NSButtonCell class]] ) - { - NSButtonCell* pCell = (NSButtonCell*)pObj; - int nTag = [pCell tag]; - mpController->changePropertyWithIntValue( nTag ); - } - } - else if( [pSender isMemberOfClass: [NSTextField class]] ) - { - NSTextField* pField = (NSTextField*)pSender; - int nTag = [pField tag]; - rtl::OUString aValue = GetOUString( [pSender stringValue] ); - mpController->changePropertyWithStringValue( nTag, aValue ); - } - else - { - SAL_INFO( "vcl.aqua.print", "Unsupported class" << ([pSender class] ? [NSStringFromClass([pSender class]) UTF8String] : "nil")); - } - mpController->updateEnableState(); -} --(void)triggeredNumeric:(id)pSender -{ - if( [pSender isMemberOfClass: [NSTextField class]] ) - { - NSTextField* pField = (NSTextField*)pSender; - int nTag = [pField tag]; - sal_Int64 nValue = [pField intValue]; - - NSView* pOther = mpController->getPair( pField ); - if( pOther ) - [(NSControl*)pOther setIntValue: nValue]; - - mpController->changePropertyWithIntValue( nTag, nValue ); - } - else if( [pSender isMemberOfClass: [NSStepper class]] ) - { - NSStepper* pStep = (NSStepper*)pSender; - int nTag = [pStep tag]; - sal_Int64 nValue = [pStep intValue]; - - NSView* pOther = mpController->getPair( pStep ); - if( pOther ) - [(NSControl*)pOther setIntValue: nValue]; - - mpController->changePropertyWithIntValue( nTag, nValue ); - } - else - { - SAL_INFO( "vcl.aqua.print", "Unsupported class" << ([pSender class] ? [NSStringFromClass([pSender class]) UTF8String] : "nil")); - } - mpController->updateEnableState(); -} --(void)triggeredPreview:(id)pSender -{ - mpController->changePreview( pSender ); -} --(void)dealloc -{ - delete mpController; - [super dealloc]; -} -@end - -struct ColumnItem -{ - NSControl* pControl; - long nOffset; - NSControl* pSubControl; - - ColumnItem( NSControl* i_pControl = nil, long i_nOffset = 0, NSControl* i_pSub = nil ) - : pControl( i_pControl ) - , nOffset( i_nOffset ) - , pSubControl( i_pSub ) - {} - - long getWidth() const - { - long nWidth = 0; - if( pControl ) - { - NSRect aCtrlRect = [pControl frame]; - nWidth = aCtrlRect.size.width; - nWidth += nOffset; - if( pSubControl ) - { - NSRect aSubRect = [pSubControl frame]; - nWidth += aSubRect.size.width; - nWidth += aSubRect.origin.x - (aCtrlRect.origin.x + aCtrlRect.size.width); - } - } - return nWidth; - } -}; - -static void adjustViewAndChildren( NSView* pNSView, NSSize& rMaxSize, - std::vector< ColumnItem >& rLeftColumn, - std::vector< ColumnItem >& rRightColumn - ) -{ - // balance columns - - // first get overall column widths - long nLeftWidth = 0; - long nRightWidth = 0; - for( size_t i = 0; i < rLeftColumn.size(); i++ ) - { - long nW = rLeftColumn[i].getWidth(); - if( nW > nLeftWidth ) - nLeftWidth = nW; - } - for( size_t i = 0; i < rRightColumn.size(); i++ ) - { - long nW = rRightColumn[i].getWidth(); - if( nW > nRightWidth ) - nRightWidth = nW; - } - - // right align left column - for( size_t i = 0; i < rLeftColumn.size(); i++ ) - { - if( rLeftColumn[i].pControl ) - { - NSRect aCtrlRect = [rLeftColumn[i].pControl frame]; - long nX = nLeftWidth - aCtrlRect.size.width; - if( rLeftColumn[i].pSubControl ) - { - NSRect aSubRect = [rLeftColumn[i].pSubControl frame]; - nX -= aSubRect.size.width + (aSubRect.origin.x - (aCtrlRect.origin.x + aCtrlRect.size.width)); - aSubRect.origin.x = nLeftWidth - aSubRect.size.width; - [rLeftColumn[i].pSubControl setFrame: aSubRect]; - } - aCtrlRect.origin.x = nX; - [rLeftColumn[i].pControl setFrame: aCtrlRect]; - } - } - - // left align right column - for( size_t i = 0; i < rRightColumn.size(); i++ ) - { - if( rRightColumn[i].pControl ) - { - NSRect aCtrlRect = [rRightColumn[i].pControl frame]; - long nX = nLeftWidth + 3; - if( rRightColumn[i].pSubControl ) - { - NSRect aSubRect = [rRightColumn[i].pSubControl frame]; - aSubRect.origin.x = nX + aSubRect.origin.x - aCtrlRect.origin.x; - [rRightColumn[i].pSubControl setFrame: aSubRect]; - } - aCtrlRect.origin.x = nX; - [rRightColumn[i].pControl setFrame: aCtrlRect]; - } - } - - NSArray* pSubViews = [pNSView subviews]; - unsigned int nViews = [pSubViews count]; - NSRect aUnion = { { 0, 0 }, { 0, 0 } }; - - // get the combined frame of all subviews - for( unsigned int n = 0; n < nViews; n++ ) - { - aUnion = NSUnionRect( aUnion, [[pSubViews objectAtIndex: n] frame] ); - } - - // move everything so it will fit - for( unsigned int n = 0; n < nViews; n++ ) - { - NSView* pCurSubView = [pSubViews objectAtIndex: n]; - NSRect aFrame = [pCurSubView frame]; - aFrame.origin.x -= aUnion.origin.x - 5; - aFrame.origin.y -= aUnion.origin.y - 5; - [pCurSubView setFrame: aFrame]; - } - - // resize the view itself - aUnion.size.height += 10; - aUnion.size.width += 20; - [pNSView setFrameSize: aUnion.size]; - - if( aUnion.size.width > rMaxSize.width ) - rMaxSize.width = aUnion.size.width; - if( aUnion.size.height > rMaxSize.height ) - rMaxSize.height = aUnion.size.height; -} - -static void adjustTabViews( NSTabView* pTabView, NSSize aTabSize ) -{ - // loop over all contained tab pages - NSArray* pTabbedViews = [pTabView tabViewItems]; - int nViews = [pTabbedViews count]; - for( int i = 0; i < nViews; i++ ) - { - NSTabViewItem* pItem = (NSTabViewItem*)[pTabbedViews objectAtIndex: i]; - NSView* pNSView = [pItem view]; - if( pNSView ) - { - NSRect aRect = [pNSView frame]; - double nDiff = aTabSize.height - aRect.size.height; - aRect.size = aTabSize; - [pNSView setFrame: aRect]; - - NSArray* pSubViews = [pNSView subviews]; - unsigned int nSubViews = [pSubViews count]; - - // move everything up - for( unsigned int n = 0; n < nSubViews; n++ ) - { - NSView* pCurSubView = [pSubViews objectAtIndex: n]; - NSRect aFrame = [pCurSubView frame]; - aFrame.origin.y += nDiff; - // give separators the correct width - // separators are currently the only NSBoxes we use - if( [pCurSubView isMemberOfClass: [NSBox class]] ) - { - aFrame.size.width = aTabSize.width - aFrame.origin.x - 10; - } - [pCurSubView setFrame: aFrame]; - } - } - } -} - -static NSControl* createLabel( const rtl::OUString& i_rText ) -{ - NSString* pText = CreateNSString( i_rText ); - NSRect aTextRect = { { 0, 0 }, {20, 15} }; - NSTextField* pTextView = [[NSTextField alloc] initWithFrame: aTextRect]; - [pTextView setFont: [NSFont controlContentFontOfSize: 0]]; - [pTextView setEditable: NO]; - [pTextView setSelectable: NO]; - [pTextView setDrawsBackground: NO]; - [pTextView setBordered: NO]; - [pTextView setStringValue: pText]; - [pTextView sizeToFit]; - [pText release]; - return pTextView; -} - -static sal_Int32 findBreak( const rtl::OUString& i_rText, sal_Int32 i_nPos ) -{ - sal_Int32 nRet = i_rText.getLength(); - Reference< i18n::XBreakIterator > xBI( vcl::unohelper::CreateBreakIterator() ); - if( xBI.is() ) - { - i18n::Boundary aBoundary = xBI->getWordBoundary( i_rText, i_nPos, - Application::GetSettings().GetLanguageTag().getLocale(), - i18n::WordType::ANYWORD_IGNOREWHITESPACES, - sal_True ); - nRet = aBoundary.endPos; - } - return nRet; -} - -static void linebreakCell( NSCell* pBtn, const rtl::OUString& i_rText ) -{ - NSString* pText = CreateNSString( i_rText ); - [pBtn setTitle: pText]; - [pText release]; - NSSize aSize = [pBtn cellSize]; - if( aSize.width > 280 ) - { - // need two lines - sal_Int32 nLen = i_rText.getLength(); - sal_Int32 nIndex = nLen / 2; - nIndex = findBreak( i_rText, nIndex ); - if( nIndex < nLen ) - { - rtl::OUStringBuffer aBuf( i_rText ); - aBuf[nIndex] = '\n'; - pText = CreateNSString( aBuf.makeStringAndClear() ); - [pBtn setTitle: pText]; - [pText release]; - } - } -} - -static void addSubgroup( NSView* pCurParent, long& rCurY, const rtl::OUString& rText ) -{ - NSControl* pTextView = createLabel( rText ); - [pCurParent addSubview: [pTextView autorelease]]; - NSRect aTextRect = [pTextView frame]; - // move to nCurY - aTextRect.origin.y = rCurY - aTextRect.size.height; - [pTextView setFrame: aTextRect]; - - NSRect aSepRect = { { aTextRect.size.width + 1, aTextRect.origin.y }, { 100, 6 } }; - NSBox* pBox = [[NSBox alloc] initWithFrame: aSepRect]; - [pBox setBoxType: NSBoxSeparator]; - [pCurParent addSubview: [pBox autorelease]]; - - // update nCurY - rCurY = aTextRect.origin.y - 5; -} - -static void addBool( NSView* pCurParent, long& rCurX, long& rCurY, long nAttachOffset, - const rtl::OUString& rText, sal_Bool bEnabled, - const rtl::OUString& rProperty, sal_Bool bValue, - std::vector& rRightColumn, - ControllerProperties* pControllerProperties, - ControlTarget* pCtrlTarget - ) -{ - NSRect aCheckRect = { { static_cast(rCurX + nAttachOffset), 0 }, { 0, 15 } }; - NSButton* pBtn = [[NSButton alloc] initWithFrame: aCheckRect]; - [pBtn setButtonType: NSSwitchButton]; - [pBtn setState: bValue ? NSOnState : NSOffState]; - if( ! bEnabled ) - [pBtn setEnabled: NO]; - linebreakCell( [pBtn cell], rText ); - [pBtn sizeToFit]; - - rRightColumn.push_back( ColumnItem( pBtn ) ); - - // connect target - [pBtn setTarget: pCtrlTarget]; - [pBtn setAction: @selector(triggered:)]; - int nTag = pControllerProperties->addNameTag( rProperty ); - pControllerProperties->addObservedControl( pBtn ); - [pBtn setTag: nTag]; - - aCheckRect = [pBtn frame]; - // #i115837# add a murphy factor; it can apparently occasionally happen - // that sizeToFit does not a perfect job and that the button linebreaks again - // if - and only if - there is already a '\n' contained in the text and the width - // is minimally of - aCheckRect.size.width += 1; - - // move to rCurY - aCheckRect.origin.y = rCurY - aCheckRect.size.height; - [pBtn setFrame: aCheckRect]; - - [pCurParent addSubview: [pBtn autorelease]]; - - // update rCurY - rCurY = aCheckRect.origin.y - 5; -} - -static void addRadio( NSView* pCurParent, long& rCurX, long& rCurY, long nAttachOffset, - const rtl::OUString& rText, - const rtl::OUString& rProperty, Sequence< rtl::OUString > rChoices, sal_Int32 nSelectValue, - std::vector& rLeftColumn, - std::vector& rRightColumn, - ControllerProperties* pControllerProperties, - ControlTarget* pCtrlTarget - ) -{ - sal_Int32 nOff = 0; - if( rText.getLength() ) - { - // add a label - NSControl* pTextView = createLabel( rText ); - NSRect aTextRect = [pTextView frame]; - aTextRect.origin.x = rCurX + nAttachOffset; - [pCurParent addSubview: [pTextView autorelease]]; - - rLeftColumn.push_back( ColumnItem( pTextView ) ); - - // move to nCurY - aTextRect.origin.y = rCurY - aTextRect.size.height; - [pTextView setFrame: aTextRect]; - - // update nCurY - rCurY = aTextRect.origin.y - 5; - - // indent the radio group relative to the text - // nOff = 20; - } - - // setup radio matrix - NSButtonCell* pProto = [[NSButtonCell alloc] init]; - - NSRect aRadioRect = { { static_cast(rCurX + nOff), 0 }, { static_cast(280 - rCurX), static_cast(5*rChoices.getLength()) } }; - [pProto setTitle: @"RadioButtonGroup"]; - [pProto setButtonType: NSRadioButton]; - NSMatrix* pMatrix = [[NSMatrix alloc] initWithFrame: aRadioRect - mode: NSRadioModeMatrix - prototype: (NSCell*)pProto - numberOfRows: rChoices.getLength() - numberOfColumns: 1]; - // set individual titles - NSArray* pCells = [pMatrix cells]; - for( sal_Int32 m = 0; m < rChoices.getLength(); m++ ) - { - NSCell* pCell = [pCells objectAtIndex: m]; - filterAccelerator( rChoices[m] ); - linebreakCell( pCell, rChoices[m] ); - // connect target and action - [pCell setTarget: pCtrlTarget]; - [pCell setAction: @selector(triggered:)]; - int nTag = pControllerProperties->addNameAndValueTag( rProperty, m ); - pControllerProperties->addObservedControl( pCell ); - [pCell setTag: nTag]; - // set current selection - if( nSelectValue == m ) - [pMatrix selectCellAtRow: m column: 0]; - } - [pMatrix sizeToFit]; - aRadioRect = [pMatrix frame]; - - // move it down, so it comes to the correct position - aRadioRect.origin.y = rCurY - aRadioRect.size.height; - [pMatrix setFrame: aRadioRect]; - [pCurParent addSubview: [pMatrix autorelease]]; - - rRightColumn.push_back( ColumnItem( pMatrix ) ); - - // update nCurY - rCurY = aRadioRect.origin.y - 5; - - [pProto release]; -} - -static void addList( NSView* pCurParent, long& rCurX, long& rCurY, long /*nAttachOffset*/, - const rtl::OUString& rText, - const rtl::OUString& rProperty, const Sequence< rtl::OUString > rChoices, sal_Int32 nSelectValue, - std::vector& rLeftColumn, - std::vector& rRightColumn, - ControllerProperties* pControllerProperties, - ControlTarget* pCtrlTarget - ) -{ - // don't indent attached lists, looks bad in the existing cases - NSControl* pTextView = createLabel( rText ); - [pCurParent addSubview: [pTextView autorelease]]; - rLeftColumn.push_back( ColumnItem( pTextView ) ); - NSRect aTextRect = [pTextView frame]; - aTextRect.origin.x = rCurX /* + nAttachOffset*/; - - // don't indent attached lists, looks bad in the existing cases - NSRect aBtnRect = { { rCurX /*+ nAttachOffset*/ + aTextRect.size.width, 0 }, { 0, 15 } }; - NSPopUpButton* pBtn = [[NSPopUpButton alloc] initWithFrame: aBtnRect pullsDown: NO]; - - // iterate options - for( sal_Int32 m = 0; m < rChoices.getLength(); m++ ) - { - NSString* pItemText = CreateNSString( rChoices[m] ); - [pBtn addItemWithTitle: pItemText]; - NSMenuItem* pItem = [pBtn itemWithTitle: pItemText]; - int nTag = pControllerProperties->addNameAndValueTag( rProperty, m ); - [pItem setTag: nTag]; - [pItemText release]; - } - - [pBtn selectItemAtIndex: nSelectValue]; - - // add the button to observed controls for enabled state changes - // also add a tag just for this purpose - pControllerProperties->addObservedControl( pBtn ); - [pBtn setTag: pControllerProperties->addNameTag( rProperty )]; - - [pBtn sizeToFit]; - [pCurParent addSubview: [pBtn autorelease]]; - - rRightColumn.push_back( ColumnItem( pBtn ) ); - - // connect target and action - [pBtn setTarget: pCtrlTarget]; - [pBtn setAction: @selector(triggered:)]; - - // move to nCurY - aBtnRect = [pBtn frame]; - aBtnRect.origin.y = rCurY - aBtnRect.size.height; - [pBtn setFrame: aBtnRect]; - - // align label - aTextRect.origin.y = aBtnRect.origin.y + (aBtnRect.size.height - aTextRect.size.height)/2; - [pTextView setFrame: aTextRect]; - - // update rCurY - rCurY = aBtnRect.origin.y - 5; -} - -static void addEdit( NSView* pCurParent, long& rCurX, long& rCurY, long nAttachOffset, - const rtl::OUString rCtrlType, - const rtl::OUString& rText, - const rtl::OUString& rProperty, const PropertyValue* pValue, - sal_Int64 nMinValue, sal_Int64 nMaxValue, - std::vector& rLeftColumn, - std::vector& rRightColumn, - ControllerProperties* pControllerProperties, - ControlTarget* pCtrlTarget - ) -{ - sal_Int32 nOff = 0; - if( rText.getLength() ) - { - // add a label - NSControl* pTextView = createLabel( rText ); - [pCurParent addSubview: [pTextView autorelease]]; - - rLeftColumn.push_back( ColumnItem( pTextView ) ); - - // move to nCurY - NSRect aTextRect = [pTextView frame]; - aTextRect.origin.x = rCurX + nAttachOffset; - aTextRect.origin.y = rCurY - aTextRect.size.height; - [pTextView setFrame: aTextRect]; - - // update nCurY - rCurY = aTextRect.origin.y - 5; - - // and set the offset for the real edit field - nOff = aTextRect.size.width + 5; - } - - NSRect aFieldRect = { { static_cast(rCurX + nOff + nAttachOffset), 0 }, { 100, 25 } }; - NSTextField* pFieldView = [[NSTextField alloc] initWithFrame: aFieldRect]; - [pFieldView setEditable: YES]; - [pFieldView setSelectable: YES]; - [pFieldView setDrawsBackground: YES]; - [pFieldView sizeToFit]; // FIXME: this does nothing - [pCurParent addSubview: [pFieldView autorelease]]; - - rRightColumn.push_back( ColumnItem( pFieldView ) ); - - // add the field to observed controls for enabled state changes - // also add a tag just for this purpose - pControllerProperties->addObservedControl( pFieldView ); - int nTag = pControllerProperties->addNameTag( rProperty ); - [pFieldView setTag: nTag]; - // pControllerProperties->addNamedView( pFieldView, aPropertyName ); - - // move to nCurY - aFieldRect.origin.y = rCurY - aFieldRect.size.height; - [pFieldView setFrame: aFieldRect]; - - if( rCtrlType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Range" ) ) ) - { - // add a stepper control - NSRect aStepFrame = { { aFieldRect.origin.x + aFieldRect.size.width + 5, - aFieldRect.origin.y }, - { 15, aFieldRect.size.height } }; - NSStepper* pStep = [[NSStepper alloc] initWithFrame: aStepFrame]; - [pStep setIncrement: 1]; - [pStep setValueWraps: NO]; - [pStep setTag: nTag]; - [pCurParent addSubview: [pStep autorelease]]; - - rRightColumn.back().pSubControl = pStep; - - pControllerProperties->addObservedControl( pStep ); - [pStep setTarget: pCtrlTarget]; - [pStep setAction: @selector(triggered:)]; - - // constrain the text field to decimal numbers - NSNumberFormatter* pFormatter = [[NSNumberFormatter alloc] init]; - [pFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4]; - [pFormatter setNumberStyle: NSNumberFormatterDecimalStyle]; - [pFormatter setAllowsFloats: NO]; - [pFormatter setMaximumFractionDigits: 0]; - if( nMinValue != nMaxValue ) - { - [pFormatter setMinimum: [[NSNumber numberWithInt: nMinValue] autorelease]]; - [pStep setMinValue: nMinValue]; - [pFormatter setMaximum: [[NSNumber numberWithInt: nMaxValue] autorelease]]; - [pStep setMaxValue: nMaxValue]; - } - [pFieldView setFormatter: pFormatter]; - - sal_Int64 nSelectVal = 0; - if( pValue && pValue->Value.hasValue() ) - pValue->Value >>= nSelectVal; - - [pFieldView setIntValue: nSelectVal]; - [pStep setIntValue: nSelectVal]; - - pControllerProperties->addViewPair( pFieldView, pStep ); - // connect target and action - [pFieldView setTarget: pCtrlTarget]; - [pFieldView setAction: @selector(triggeredNumeric:)]; - [pStep setTarget: pCtrlTarget]; - [pStep setAction: @selector(triggeredNumeric:)]; - } - else - { - // connect target and action - [pFieldView setTarget: pCtrlTarget]; - [pFieldView setAction: @selector(triggered:)]; - - if( pValue && pValue->Value.hasValue() ) - { - rtl::OUString aValue; - pValue->Value >>= aValue; - if( aValue.getLength() ) - { - NSString* pText = CreateNSString( aValue ); - [pFieldView setStringValue: pText]; - [pText release]; - } - } - } - - // update nCurY - rCurY = aFieldRect.origin.y - 5; -} - -// In 10.5 and later: -// 'setAccessoryView:' is deprecated - -// Make deprecation warnings just warnings in a -Werror compilation. - -#if HAVE_GCC_PRAGMA_DIAGNOSTIC_MODIFY -// #pragma GCC diagnostic push -#pragma GCC diagnostic warning "-Wdeprecated-declarations" -#endif - -@implementation AquaPrintAccessoryView -+(NSObject*)setupPrinterPanel: (NSPrintOperation*)pOp withController: (vcl::PrinterController*)pController withState: (PrintAccessoryViewState*)pState -{ - const Sequence< PropertyValue >& rOptions( pController->getUIOptions() ); - if( rOptions.getLength() == 0 ) - return nil; - - NSView* pCurParent = 0; - long nCurY = 0; - long nCurX = 0; - NSRect aViewFrame = { { 0, 0 }, {600, 400 } }; - NSRect aTabViewFrame = { { 190, 0 }, {410, 400 } }; - NSSize aMaxTabSize = { 0, 0 }; - NSView* pAccessoryView = [[NSView alloc] initWithFrame: aViewFrame]; - NSTabView* pTabView = [[NSTabView alloc] initWithFrame: aTabViewFrame]; - [pAccessoryView addSubview: [pTabView autorelease]]; - - sal_Bool bIgnoreSubgroup = sal_False; - - ControllerProperties* pControllerProperties = new ControllerProperties( pController, pOp, pAccessoryView, pTabView, pState ); - ControlTarget* pCtrlTarget = [[ControlTarget alloc] initWithControllerMap: pControllerProperties]; - - std::vector< ColumnItem > aLeftColumn, aRightColumn; - - // ugly: - // prepend a "selection" checkbox if the properties have such a selection in PrintContent - bool bAddSelectionCheckBox = false, bSelectionBoxEnabled = false, bSelectionBoxChecked = false; - for( int i = 0; i < rOptions.getLength(); i++ ) - { - Sequence< beans::PropertyValue > aOptProp; - rOptions[i].Value >>= aOptProp; - - rtl::OUString aCtrlType; - rtl::OUString aPropertyName; - Sequence< rtl::OUString > aChoices; - Sequence< sal_Bool > aChoicesDisabled; - sal_Int32 aSelectionChecked = 0; - for( int n = 0; n < aOptProp.getLength(); n++ ) - { - const beans::PropertyValue& rEntry( aOptProp[ n ] ); - if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ControlType")) ) - { - rEntry.Value >>= aCtrlType; - } - else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Choices")) ) - { - rEntry.Value >>= aChoices; - } - else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ChoicesDisabled")) ) - { - rEntry.Value >>= aChoicesDisabled; - } - else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Property")) ) - { - PropertyValue aVal; - rEntry.Value >>= aVal; - aPropertyName = aVal.Name; - if( aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrintContent")) ) - aVal.Value >>= aSelectionChecked; - } - } - if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Radio")) && - aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrintContent")) && - aChoices.getLength() > 2 ) - { - bAddSelectionCheckBox = true; - bSelectionBoxEnabled = aChoicesDisabled.getLength() < 2 || ! aChoicesDisabled[2]; - bSelectionBoxChecked = (aSelectionChecked==2); - break; - } - } - - for( int i = 0; i < rOptions.getLength(); i++ ) - { - Sequence< beans::PropertyValue > aOptProp; - rOptions[i].Value >>= aOptProp; - - // extract ui element - bool bEnabled = true; - rtl::OUString aCtrlType; - rtl::OUString aText; - rtl::OUString aPropertyName; - rtl::OUString aGroupHint; - Sequence< rtl::OUString > aChoices; - sal_Int64 nMinValue = 0, nMaxValue = 0; - long nAttachOffset = 0; - sal_Bool bIgnore = sal_False; - - for( int n = 0; n < aOptProp.getLength(); n++ ) - { - const beans::PropertyValue& rEntry( aOptProp[ n ] ); - if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Text")) ) - { - rEntry.Value >>= aText; - filterAccelerator( aText ); - } - else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ControlType")) ) - { - rEntry.Value >>= aCtrlType; - } - else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Choices")) ) - { - rEntry.Value >>= aChoices; - } - else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Property")) ) - { - PropertyValue aVal; - rEntry.Value >>= aVal; - aPropertyName = aVal.Name; - } - else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Enabled")) ) - { - sal_Bool bValue = sal_True; - rEntry.Value >>= bValue; - bEnabled = bValue; - } - else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("MinValue")) ) - { - rEntry.Value >>= nMinValue; - } - else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("MaxValue")) ) - { - rEntry.Value >>= nMaxValue; - } - else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("AttachToDependency")) ) - { - nAttachOffset = 20; - } - else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("InternalUIOnly")) ) - { - rEntry.Value >>= bIgnore; - } - else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("GroupingHint")) ) - { - rEntry.Value >>= aGroupHint; - } - } - - if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Group")) || - aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Subgroup")) || - aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Radio")) || - aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("List")) || - aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Edit")) || - aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Range")) || - aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Bool")) ) - { - // since our build target is MacOSX 10.4 we can have only one accessory view - // so we have a single accessory view that is tabbed for grouping - if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Group")) - || ! pCurParent - || ( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Subgroup")) && nCurY < -250 && ! bIgnore ) - ) - { - rtl::OUString aGroupTitle( aText ); - if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Subgroup")) ) - aGroupTitle = pControllerProperties->getMoreString(); - // set size of current parent - if( pCurParent ) - adjustViewAndChildren( pCurParent, aMaxTabSize, aLeftColumn, aRightColumn ); - - // new tab item - if( ! aText.getLength() ) - aText = OUString( "OOo" ); - NSString* pLabel = CreateNSString( aGroupTitle ); - NSTabViewItem* pItem = [[NSTabViewItem alloc] initWithIdentifier: pLabel ]; - [pItem setLabel: pLabel]; - [pTabView addTabViewItem: pItem]; - pCurParent = [[NSView alloc] initWithFrame: aTabViewFrame]; - [pItem setView: pCurParent]; - [pLabel release]; - - // reset indent - nCurX = 20; - // reset Y - nCurY = 0; - // clear columns - aLeftColumn.clear(); - aRightColumn.clear(); - - if( bAddSelectionCheckBox ) - { - addBool( pCurParent, nCurX, nCurY, 0, - pControllerProperties->getPrintSelectionString(), bSelectionBoxEnabled, - OUString( "PrintContent" ), bSelectionBoxChecked, - aRightColumn, pControllerProperties, pCtrlTarget ); - bAddSelectionCheckBox = false; - } - } - - if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Subgroup")) && pCurParent ) - { - bIgnoreSubgroup = bIgnore; - if( bIgnore ) - continue; - - addSubgroup( pCurParent, nCurY, aText ); - } - else if( bIgnoreSubgroup || bIgnore ) - { - continue; - } - else if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Bool")) && pCurParent ) - { - sal_Bool bVal = sal_False; - PropertyValue* pVal = pController->getValue( aPropertyName ); - if( pVal ) - pVal->Value >>= bVal; - addBool( pCurParent, nCurX, nCurY, nAttachOffset, - aText, true, aPropertyName, bVal, - aRightColumn, pControllerProperties, pCtrlTarget ); - } - else if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Radio")) && pCurParent ) - { - // get currently selected value - sal_Int32 nSelectVal = 0; - PropertyValue* pVal = pController->getValue( aPropertyName ); - if( pVal && pVal->Value.hasValue() ) - pVal->Value >>= nSelectVal; - - addRadio( pCurParent, nCurX, nCurY, nAttachOffset, - aText, aPropertyName, aChoices, nSelectVal, - aLeftColumn, aRightColumn, - pControllerProperties, pCtrlTarget ); - } - else if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("List")) && pCurParent ) - { - PropertyValue* pVal = pController->getValue( aPropertyName ); - sal_Int32 aSelectVal = 0; - if( pVal && pVal->Value.hasValue() ) - pVal->Value >>= aSelectVal; - - addList( pCurParent, nCurX, nCurY, nAttachOffset, - aText, aPropertyName, aChoices, aSelectVal, - aLeftColumn, aRightColumn, - pControllerProperties, pCtrlTarget ); - } - else if( (aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Edit")) || aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Range"))) && pCurParent ) - { - // current value - PropertyValue* pVal = pController->getValue( aPropertyName ); - addEdit( pCurParent, nCurX, nCurY, nAttachOffset, - aCtrlType, aText, aPropertyName, pVal, - nMinValue, nMaxValue, - aLeftColumn, aRightColumn, - pControllerProperties, pCtrlTarget ); - } - } - else - { - SAL_INFO( "vcl.aqua.print", "Unsupported UI option \"" << aCtrlType << "\""); - } - } - - pControllerProperties->updateEnableState(); - adjustViewAndChildren( pCurParent, aMaxTabSize, aLeftColumn, aRightColumn ); - - // leave some space for the preview - if( aMaxTabSize.height < 200 ) - aMaxTabSize.height = 200; - - // now reposition everything again so it is upper bound - adjustTabViews( pTabView, aMaxTabSize ); - - // find the minimum needed tab size - NSSize aTabCtrlSize = [pTabView minimumSize]; - aTabCtrlSize.height += aMaxTabSize.height + 10; - if( aTabCtrlSize.width < aMaxTabSize.width + 10 ) - aTabCtrlSize.width = aMaxTabSize.width + 10; - [pTabView setFrameSize: aTabCtrlSize]; - aViewFrame.size.width = aTabCtrlSize.width + aTabViewFrame.origin.x; - aViewFrame.size.height = aTabCtrlSize.height + aTabViewFrame.origin.y; - [pAccessoryView setFrameSize: aViewFrame.size]; - - pControllerProperties->setupPreview( pCtrlTarget ); - - // set the accessory view - [pOp setAccessoryView: [pAccessoryView autorelease]]; - - // set the current selecte tab item - if( pState->nLastPage >= 0 && pState->nLastPage < [pTabView numberOfTabViewItems] ) - [pTabView selectTabViewItemAtIndex: pState->nLastPage]; - - return pCtrlTarget; -} - -// #pragma GCC diagnostic pop - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/gdi/aquaprintview.mm b/vcl/aqua/source/gdi/aquaprintview.mm deleted file mode 100644 index d7957eecb5e2..000000000000 --- a/vcl/aqua/source/gdi/aquaprintview.mm +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "vcl/print.hxx" - -#include "aqua/aquaprintview.h" -#include "aqua/salprn.h" - -@implementation AquaPrintView --(id)initWithController: (vcl::PrinterController*)pController withInfoPrinter: (AquaSalInfoPrinter*)pInfoPrinter -{ - NSRect aRect = { { 0, 0 }, [pInfoPrinter->getPrintInfo() paperSize] }; - if( (self = [super initWithFrame: aRect]) != nil ) - { - mpController = pController; - mpInfoPrinter = pInfoPrinter; - } - return self; -} - --(BOOL)knowsPageRange: (NSRangePointer)range -{ - range->location = 1; - range->length = mpInfoPrinter->getCurPageRangeCount(); - return YES; -} - --(NSRect)rectForPage: (int)page -{ - NSSize aPaperSize = [mpInfoPrinter->getPrintInfo() paperSize]; - int nWidth = (int)aPaperSize.width; - // #i101108# sanity check - if( nWidth < 1 ) - nWidth = 1; - NSRect aRect = { { static_cast(page % nWidth), static_cast(page / nWidth) }, aPaperSize }; - return aRect; -} - --(NSPoint)locationOfPrintRect: (NSRect)aRect -{ - (void)aRect; - NSPoint aPoint = { 0, 0 }; - return aPoint; -} - --(void)drawRect: (NSRect)rect -{ - mpInfoPrinter->setStartPageOffset( static_cast(rect.origin.x), static_cast(rect.origin.y) ); - NSSize aPaperSize = [mpInfoPrinter->getPrintInfo() paperSize]; - int nPage = (int)(aPaperSize.width * rect.origin.y + rect.origin.x); - - // page count is 1 based - if( nPage - 1 < (mpInfoPrinter->getCurPageRangeStart() + mpInfoPrinter->getCurPageRangeCount() ) ) - mpController->printFilteredPage( nPage-1 ); -} -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/gdi/salgdicommon.cxx b/vcl/aqua/source/gdi/salgdicommon.cxx deleted file mode 100644 index f49ce9f65776..000000000000 --- a/vcl/aqua/source/gdi/salgdicommon.cxx +++ /dev/null @@ -1,1755 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include "sal/config.h" - -#include - -#include -#include -#include - -#include "basegfx/polygon/b2dpolygon.hxx" - -#include "quartz/salbmp.h" -#include "coretext/salgdi.h" - -#include "fontsubset.hxx" -#include "sft.hxx" - -using namespace vcl; - - -//typedef unsigned char Boolean; // copied from MacTypes.h, should be properly included -typedef std::vector ByteVector; - -static const basegfx::B2DPoint aHalfPointOfs ( 0.5, 0.5 ); - -static void AddPolygonToPath( CGMutablePathRef xPath, - const ::basegfx::B2DPolygon& rPolygon, - bool bClosePath, bool bPixelSnap, bool bLineDraw ) -{ - // short circuit if there is nothing to do - const int nPointCount = rPolygon.count(); - if( nPointCount <= 0 ) - { - return; - } - (void)bPixelSnap; // TODO - const CGAffineTransform* pTransform = NULL; - - const bool bHasCurves = rPolygon.areControlPointsUsed(); - for( int nPointIdx = 0, nPrevIdx = 0;; nPrevIdx = nPointIdx++ ) - { - int nClosedIdx = nPointIdx; - if( nPointIdx >= nPointCount ) - { - // prepare to close last curve segment if needed - if( bClosePath && (nPointIdx == nPointCount) ) - { - nClosedIdx = 0; - } - else - { - break; - } - } - - ::basegfx::B2DPoint aPoint = rPolygon.getB2DPoint( nClosedIdx ); - - if( bPixelSnap) - { - // snap device coordinates to full pixels - aPoint.setX( basegfx::fround( aPoint.getX() ) ); - aPoint.setY( basegfx::fround( aPoint.getY() ) ); - } - - if( bLineDraw ) - { - aPoint += aHalfPointOfs; - } - if( !nPointIdx ) - { - // first point => just move there - CGPathMoveToPoint( xPath, pTransform, aPoint.getX(), aPoint.getY() ); - continue; - } - - bool bPendingCurve = false; - if( bHasCurves ) - { - bPendingCurve = rPolygon.isNextControlPointUsed( nPrevIdx ); - bPendingCurve |= rPolygon.isPrevControlPointUsed( nClosedIdx ); - } - - if( !bPendingCurve ) // line segment - { - CGPathAddLineToPoint( xPath, pTransform, aPoint.getX(), aPoint.getY() ); - } - else // cubic bezier segment - { - basegfx::B2DPoint aCP1 = rPolygon.getNextControlPoint( nPrevIdx ); - basegfx::B2DPoint aCP2 = rPolygon.getPrevControlPoint( nClosedIdx ); - if( bLineDraw ) - { - aCP1 += aHalfPointOfs; - aCP2 += aHalfPointOfs; - } - CGPathAddCurveToPoint( xPath, pTransform, aCP1.getX(), aCP1.getY(), - aCP2.getX(), aCP2.getY(), aPoint.getX(), aPoint.getY() ); - } - } - - if( bClosePath ) - { - CGPathCloseSubpath( xPath ); - } -} - -static void AddPolyPolygonToPath( CGMutablePathRef xPath, - const ::basegfx::B2DPolyPolygon& rPolyPoly, - bool bPixelSnap, bool bLineDraw ) -{ - // short circuit if there is nothing to do - const int nPolyCount = rPolyPoly.count(); - if( nPolyCount <= 0 ) - { - return; - } - for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx ) - { - const ::basegfx::B2DPolygon rPolygon = rPolyPoly.getB2DPolygon( nPolyIdx ); - AddPolygonToPath( xPath, rPolygon, true, bPixelSnap, bLineDraw ); - } -} - -sal_Bool AquaSalGraphics::CreateFontSubset( const OUString& rToFile, - const PhysicalFontFace* pFontData, - sal_Int32* pGlyphIDs, sal_uInt8* pEncoding, - sal_Int32* pGlyphWidths, int nGlyphCount, - FontSubsetInfo& rInfo ) -{ - // TODO: move more of the functionality here into the generic subsetter code - - // prepare the requested file name for writing the font-subset file - OUString aSysPath; - if( osl_File_E_None != osl_getSystemPathFromFileURL( rToFile.pData, &aSysPath.pData ) ) - return sal_False; - const rtl_TextEncoding aThreadEncoding = osl_getThreadTextEncoding(); - const OString aToFile( OUStringToOString( aSysPath, aThreadEncoding ) ); - - // get the raw-bytes from the font to be subset - ByteVector aBuffer; - bool bCffOnly = false; - if( !GetRawFontData( pFontData, aBuffer, &bCffOnly ) ) - return sal_False; - - // handle CFF-subsetting - if( bCffOnly ) - { - // provide the raw-CFF data to the subsetter - ByteCount nCffLen = aBuffer.size(); - rInfo.LoadFont( FontSubsetInfo::CFF_FONT, &aBuffer[0], nCffLen ); - - // NOTE: assuming that all glyphids requested on Aqua are fully translated - - // make the subsetter provide the requested subset - FILE* pOutFile = fopen( aToFile.getStr(), "wb" ); -#ifdef __LP64__ - long *pLongGlyphIDs = (long*)alloca(nGlyphCount * sizeof(long)); - for (int i = 0; i < nGlyphCount; i++) - pLongGlyphIDs[i] = pGlyphIDs[i]; - bool bRC = rInfo.CreateFontSubset( FontSubsetInfo::TYPE1_PFB, pOutFile, NULL, - pLongGlyphIDs, pEncoding, nGlyphCount, pGlyphWidths ); -#else - bool bRC = rInfo.CreateFontSubset( FontSubsetInfo::TYPE1_PFB, pOutFile, NULL, - pGlyphIDs, pEncoding, nGlyphCount, pGlyphWidths ); -#endif - fclose( pOutFile ); - return bRC; - } - - // TODO: modernize psprint's horrible fontsubset C-API - // this probably only makes sense after the switch to another SCM - // that can preserve change history after file renames - - // prepare data for psprint's font subsetter - TrueTypeFont* pSftFont = NULL; - int nRC = ::OpenTTFontBuffer( (void*)&aBuffer[0], aBuffer.size(), 0, &pSftFont); - if( nRC != SF_OK ) - return sal_False; - - // get details about the subsetted font - TTGlobalFontInfo aTTInfo; - ::GetTTGlobalFontInfo( pSftFont, &aTTInfo ); - rInfo.m_nFontType = FontSubsetInfo::SFNT_TTF; - rInfo.m_aPSName = OUString( - aTTInfo.psname, std::strlen(aTTInfo.psname), RTL_TEXTENCODING_UTF8 ); - rInfo.m_aFontBBox = Rectangle( Point( aTTInfo.xMin, aTTInfo.yMin ), - Point( aTTInfo.xMax, aTTInfo.yMax ) ); - rInfo.m_nCapHeight = aTTInfo.yMax; // Well ... - rInfo.m_nAscent = aTTInfo.winAscent; - rInfo.m_nDescent = aTTInfo.winDescent; - // mac fonts usually do not have an OS2-table - // => get valid ascent/descent values from other tables - if( !rInfo.m_nAscent ) - rInfo.m_nAscent = +aTTInfo.typoAscender; - if( !rInfo.m_nAscent ) - rInfo.m_nAscent = +aTTInfo.ascender; - if( !rInfo.m_nDescent ) - rInfo.m_nDescent = +aTTInfo.typoDescender; - if( !rInfo.m_nDescent ) - rInfo.m_nDescent = -aTTInfo.descender; - - // subset glyphs and get their properties - // take care that subset fonts require the NotDef glyph in pos 0 - int nOrigCount = nGlyphCount; - sal_uInt16 aShortIDs[ 256 ]; - sal_uInt8 aTempEncs[ 256 ]; - - int nNotDef = -1; - for( int i = 0; i < nGlyphCount; ++i ) - { - aTempEncs[i] = pEncoding[i]; - sal_uInt32 nGlyphIdx = pGlyphIDs[i] & GF_IDXMASK; - if( pGlyphIDs[i] & GF_ISCHAR ) - { - bool bVertical = (pGlyphIDs[i] & GF_ROTMASK) != 0; - nGlyphIdx = ::MapChar( pSftFont, static_cast(nGlyphIdx), bVertical ); - if( nGlyphIdx == 0 && pFontData->IsSymbolFont() ) - { - // #i12824# emulate symbol aliasing U+FXXX <-> U+0XXX - nGlyphIdx = pGlyphIDs[i] & GF_IDXMASK; - nGlyphIdx = (nGlyphIdx & 0xF000) ? (nGlyphIdx & 0x00FF) : (nGlyphIdx | 0xF000 ); - nGlyphIdx = ::MapChar( pSftFont, static_cast(nGlyphIdx), bVertical ); - } - } - aShortIDs[i] = static_cast( nGlyphIdx ); - if( !nGlyphIdx ) - if( nNotDef < 0 ) - nNotDef = i; // first NotDef glyph found - } - - if( nNotDef != 0 ) - { - // add fake NotDef glyph if needed - if( nNotDef < 0 ) - nNotDef = nGlyphCount++; - - // NotDef glyph must be in pos 0 => swap glyphids - aShortIDs[ nNotDef ] = aShortIDs[0]; - aTempEncs[ nNotDef ] = aTempEncs[0]; - aShortIDs[0] = 0; - aTempEncs[0] = 0; - } - DBG_ASSERT( nGlyphCount < 257, "too many glyphs for subsetting" ); - - // TODO: where to get bVertical? - const bool bVertical = false; - - // fill the pGlyphWidths array - // while making sure that the NotDef glyph is at index==0 - TTSimpleGlyphMetrics* pGlyphMetrics = - ::GetTTSimpleGlyphMetrics( pSftFont, aShortIDs, nGlyphCount, bVertical ); - if( !pGlyphMetrics ) - return sal_False; - sal_uInt16 nNotDefAdv = pGlyphMetrics[0].adv; - pGlyphMetrics[0].adv = pGlyphMetrics[nNotDef].adv; - pGlyphMetrics[nNotDef].adv = nNotDefAdv; - for( int i = 0; i < nOrigCount; ++i ) - pGlyphWidths[i] = pGlyphMetrics[i].adv; - free( pGlyphMetrics ); - - // write subset into destination file - nRC = ::CreateTTFromTTGlyphs( pSftFont, aToFile.getStr(), aShortIDs, - aTempEncs, nGlyphCount, 0, NULL, 0 ); - ::CloseTTFont(pSftFont); - return (nRC == SF_OK); -} - -static inline void alignLinePoint( const SalPoint* i_pIn, float& o_fX, float& o_fY ) -{ - o_fX = static_cast(i_pIn->mnX ) + 0.5; - o_fY = static_cast(i_pIn->mnY ) + 0.5; -} - -void AquaSalGraphics::copyBits( const SalTwoRect& rPosAry, SalGraphics *pSrcGraphics ) -{ - if( !pSrcGraphics ) - { - pSrcGraphics = this; - } - //from unix salgdi2.cxx - //[FIXME] find a better way to prevent calc from crashing when width and height are negative - if( rPosAry.mnSrcWidth <= 0 - || rPosAry.mnSrcHeight <= 0 - || rPosAry.mnDestWidth <= 0 - || rPosAry.mnDestHeight <= 0 ) - { - return; - } - - // accelerate trivial operations - /*const*/ AquaSalGraphics* pSrc = static_cast(pSrcGraphics); - const bool bSameGraphics = (this == pSrc) || - (mbWindow && mpFrame && pSrc->mbWindow && (mpFrame == pSrc->mpFrame)); - if( bSameGraphics - && (rPosAry.mnSrcWidth == rPosAry.mnDestWidth) - && (rPosAry.mnSrcHeight == rPosAry.mnDestHeight)) - { - // short circuit if there is nothing to do - if( (rPosAry.mnSrcX == rPosAry.mnDestX) - && (rPosAry.mnSrcY == rPosAry.mnDestY)) - return; - // use copyArea() if source and destination context are identical - copyArea( rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnSrcX, rPosAry.mnSrcY, - rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, 0 ); - return; - } - - ApplyXorContext(); - pSrc->ApplyXorContext(); - - DBG_ASSERT( pSrc->mxLayer!=NULL, "AquaSalGraphics::copyBits() from non-layered graphics" ); - - const CGPoint aDstPoint = { static_cast(+rPosAry.mnDestX - rPosAry.mnSrcX), static_cast(rPosAry.mnDestY - rPosAry.mnSrcY) }; - if( (rPosAry.mnSrcWidth == rPosAry.mnDestWidth && - rPosAry.mnSrcHeight == rPosAry.mnDestHeight) && - (!mnBitmapDepth || (aDstPoint.x + pSrc->mnWidth) <= mnWidth) ) // workaround a Quartz crasher - { - // in XOR mode the drawing context is redirected to the XOR mask - // if source and target are identical then copyBits() paints onto the target context though - CGContextRef xCopyContext = mrContext; - if( mpXorEmulation && mpXorEmulation->IsEnabled() ) - { - if( pSrcGraphics == this ) - { - xCopyContext = mpXorEmulation->GetTargetContext(); - } - } - CGContextSaveGState( xCopyContext ); - const CGRect aDstRect = { { static_cast(rPosAry.mnDestX), static_cast(rPosAry.mnDestY) }, { static_cast(rPosAry.mnDestWidth), static_cast(rPosAry.mnDestHeight) } }; - CGContextClipToRect( xCopyContext, aDstRect ); - - // draw at new destination - // NOTE: flipped drawing gets disabled for this, else the subimage would be drawn upside down - if( pSrc->IsFlipped() ) - { - CGContextTranslateCTM( xCopyContext, 0, +mnHeight ); CGContextScaleCTM( xCopyContext, +1, -1 ); - } - // TODO: pSrc->size() != this->size() - ::CGContextDrawLayerAtPoint( xCopyContext, aDstPoint, pSrc->mxLayer ); - CGContextRestoreGState( xCopyContext ); - // mark the destination rectangle as updated - RefreshRect( aDstRect ); - } - else - { - SalBitmap* pBitmap = pSrc->getBitmap( rPosAry.mnSrcX, rPosAry.mnSrcY, - rPosAry.mnSrcWidth, rPosAry.mnSrcHeight ); - - if( pBitmap ) - { - SalTwoRect aPosAry( rPosAry ); - aPosAry.mnSrcX = 0; - aPosAry.mnSrcY = 0; - drawBitmap( aPosAry, *pBitmap ); - delete pBitmap; - } - } -} - -static void DrawPattern50( void*, CGContextRef rContext ) -{ - static const CGRect aRects[2] = { { {0,0}, { 2, 2 } }, { { 2, 2 }, { 2, 2 } } }; - CGContextAddRects( rContext, aRects, 2 ); - CGContextFillPath( rContext ); -} - -static void getBoundRect( sal_uLong nPoints, const SalPoint *pPtAry, long &rX, long& rY, long& rWidth, long& rHeight ) -{ - long nX1 = pPtAry->mnX; - long nX2 = nX1; - long nY1 = pPtAry->mnY; - long nY2 = nY1; - for( sal_uLong n = 1; n < nPoints; n++ ) - { - if( pPtAry[n].mnX < nX1 ) - { - nX1 = pPtAry[n].mnX; - } - else if( pPtAry[n].mnX > nX2 ) - { - nX2 = pPtAry[n].mnX; - } - if( pPtAry[n].mnY < nY1 ) - { - nY1 = pPtAry[n].mnY; - } - else if( pPtAry[n].mnY > nY2 ) - { - nY2 = pPtAry[n].mnY; - } - } - rX = nX1; - rY = nY1; - rWidth = nX2 - nX1 + 1; - rHeight = nY2 - nY1 + 1; -} - -static SalColor ImplGetROPSalColor( SalROPColor nROPColor ) -{ - SalColor nSalColor; - if ( nROPColor == SAL_ROP_0 ) - { - nSalColor = MAKE_SALCOLOR( 0, 0, 0 ); - } - else - { - nSalColor = MAKE_SALCOLOR( 255, 255, 255 ); - } - return nSalColor; -} - -// apply the XOR mask to the target context if active and dirty -void AquaSalGraphics::ApplyXorContext() -{ - if( !mpXorEmulation ) - { - return; - } - if( mpXorEmulation->UpdateTarget() ) - { - RefreshRect( 0, 0, mnWidth, mnHeight ); // TODO: refresh minimal changerect - } -} - -void AquaSalGraphics::copyArea( long nDstX, long nDstY,long nSrcX, long nSrcY, - long nSrcWidth, long nSrcHeight, sal_uInt16 /*nFlags*/ ) -{ - ApplyXorContext(); - - DBG_ASSERT( mxLayer!=NULL, "AquaSalGraphics::copyArea() for non-layered graphics" ); - - // in XOR mode the drawing context is redirected to the XOR mask - // copyArea() always works on the target context though - CGContextRef xCopyContext = mrContext; - if( mpXorEmulation && mpXorEmulation->IsEnabled() ) - { - xCopyContext = mpXorEmulation->GetTargetContext(); - } - // drawing a layer onto its own context causes trouble on OSX => copy it first - // TODO: is it possible to get rid of this unneeded copy more often? - // e.g. on OSX>=10.5 only this situation causes problems: - // mnBitmapDepth && (aDstPoint.x + pSrc->mnWidth) > mnWidth - CGLayerRef xSrcLayer = mxLayer; - // TODO: if( mnBitmapDepth > 0 ) - { - const CGSize aSrcSize = { static_cast(nSrcWidth), static_cast(nSrcHeight) }; - xSrcLayer = ::CGLayerCreateWithContext( xCopyContext, aSrcSize, NULL ); - const CGContextRef xSrcContext = CGLayerGetContext( xSrcLayer ); - CGPoint aSrcPoint = { static_cast(-nSrcX), static_cast(-nSrcY) }; - if( IsFlipped() ) - { - ::CGContextTranslateCTM( xSrcContext, 0, +nSrcHeight ); - ::CGContextScaleCTM( xSrcContext, +1, -1 ); - aSrcPoint.y = (nSrcY + nSrcHeight) - mnHeight; - } - ::CGContextDrawLayerAtPoint( xSrcContext, aSrcPoint, mxLayer ); - } - - // draw at new destination - const CGPoint aDstPoint = { static_cast(+nDstX), static_cast(+nDstY) }; - ::CGContextDrawLayerAtPoint( xCopyContext, aDstPoint, xSrcLayer ); - - // cleanup - if( xSrcLayer != mxLayer ) - { - CGLayerRelease( xSrcLayer ); - } - // mark the destination rectangle as updated - RefreshRect( nDstX, nDstY, nSrcWidth, nSrcHeight ); - -} - -void AquaSalGraphics::copyResolution( AquaSalGraphics& rGraphics ) -{ - if( !rGraphics.mnRealDPIY && rGraphics.mbWindow && rGraphics.mpFrame ) - { - rGraphics.initResolution( rGraphics.mpFrame->getNSWindow() ); - } - mnRealDPIX = rGraphics.mnRealDPIX; - mnRealDPIY = rGraphics.mnRealDPIY; - mfFakeDPIScale = rGraphics.mfFakeDPIScale; -} - -bool AquaSalGraphics::drawAlphaBitmap( const SalTwoRect& rTR, - const SalBitmap& rSrcBitmap, - const SalBitmap& rAlphaBmp ) -{ - // An image mask can't have a depth > 8 bits (should be 1 to 8 bits) - if( rAlphaBmp.GetBitCount() > 8 ) - { - return false; - } - // are these two tests really necessary? (see vcl/unx/source/gdi/salgdi2.cxx) - // horizontal/vertical mirroring not implemented yet - if( rTR.mnDestWidth < 0 || rTR.mnDestHeight < 0 ) - { - return false; - } - - const QuartzSalBitmap& rSrcSalBmp = static_cast(rSrcBitmap); - const QuartzSalBitmap& rMaskSalBmp = static_cast(rAlphaBmp); - CGImageRef xMaskedImage = rSrcSalBmp.CreateWithMask( rMaskSalBmp, rTR.mnSrcX, - rTR.mnSrcY, rTR.mnSrcWidth, - rTR.mnSrcHeight ); - if( !xMaskedImage ) - { - return false; - } - if ( CheckContext() ) - { - const CGRect aDstRect = { { static_cast(rTR.mnDestX), static_cast(rTR.mnDestY) }, { static_cast(rTR.mnDestWidth), static_cast(rTR.mnDestHeight) } }; - CGContextDrawImage( mrContext, aDstRect, xMaskedImage ); - RefreshRect( aDstRect ); - } - - CGImageRelease(xMaskedImage); - return true; -} - -bool AquaSalGraphics::drawTransformedBitmap( - const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX, const basegfx::B2DPoint& rY, - const SalBitmap& rSrcBitmap, const SalBitmap* pAlphaBmp ) -{ - if( !CheckContext() ) - return true; - - // get the Quartz image - CGImageRef xImage = NULL; - const Size aSize = rSrcBitmap.GetSize(); - const QuartzSalBitmap& rSrcSalBmp = static_cast(rSrcBitmap); - const QuartzSalBitmap* pMaskSalBmp = static_cast(pAlphaBmp); - if( !pMaskSalBmp) - xImage = rSrcSalBmp.CreateCroppedImage( 0, 0, (int)aSize.Width(), (int)aSize.Height() ); - else - xImage = rSrcSalBmp.CreateWithMask( *pMaskSalBmp, 0, 0, (int)aSize.Width(), (int)aSize.Height() ); - if( !xImage ) - return false; - - // setup the image transformation - // using the rNull,rX,rY points as destinations for the (0,0),(0,Width),(Height,0) source points - CGContextSaveGState( mrContext ); - const basegfx::B2DVector aXRel = rX - rNull; - const basegfx::B2DVector aYRel = rY - rNull; - const CGAffineTransform aCGMat = CGAffineTransformMake( - aXRel.getX()/aSize.Width(), aXRel.getY()/aSize.Width(), - aYRel.getX()/aSize.Height(), aYRel.getY()/aSize.Height(), - rNull.getX(), rNull.getY()); - CGContextConcatCTM( mrContext, aCGMat ); - - // draw the transformed image - const CGRect aSrcRect = {{0,0}, {static_cast(aSize.Width()), static_cast(aSize.Height())}}; - CGContextDrawImage( mrContext, aSrcRect, xImage ); - CGImageRelease( xImage ); - // restore the Quartz graphics state - CGContextRestoreGState(mrContext); - - // mark the destination as painted - const CGRect aDstRect = CGRectApplyAffineTransform( aSrcRect, aCGMat ); - RefreshRect( aDstRect ); - return true; -} - - -bool AquaSalGraphics::drawAlphaRect( long nX, long nY, long nWidth, - long nHeight, sal_uInt8 nTransparency ) -{ - if( !CheckContext() ) - { - return true; - } - // save the current state - CGContextSaveGState( mrContext ); - CGContextSetAlpha( mrContext, (100-nTransparency) * (1.0/100) ); - - CGRect aRect = { { static_cast(nX), static_cast(nY) }, { static_cast(nWidth-1), static_cast(nHeight-1) } }; - if( IsPenVisible() ) - { - aRect.origin.x += 0.5; - aRect.origin.y += 0.5; - } - - CGContextBeginPath( mrContext ); - CGContextAddRect( mrContext, aRect ); - CGContextDrawPath( mrContext, kCGPathFill ); - - // restore state - CGContextRestoreGState(mrContext); - RefreshRect( aRect ); - return true; -} - -void AquaSalGraphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap ) -{ - if( !CheckContext() ) - { - return; - } - const QuartzSalBitmap& rBitmap = static_cast(rSalBitmap); - CGImageRef xImage = rBitmap.CreateCroppedImage( (int)rPosAry.mnSrcX, (int)rPosAry.mnSrcY, - (int)rPosAry.mnSrcWidth, (int)rPosAry.mnSrcHeight ); - if( !xImage ) - { - return; - } - const CGRect aDstRect = { { static_cast(rPosAry.mnDestX), static_cast(rPosAry.mnDestY) }, - { static_cast(rPosAry.mnDestWidth), static_cast(rPosAry.mnDestHeight) } }; - CGContextDrawImage( mrContext, aDstRect, xImage ); - CGImageRelease( xImage ); - RefreshRect( aDstRect ); -} - -void AquaSalGraphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap,SalColor ) -{ - OSL_FAIL("not implemented for color masking!"); - drawBitmap( rPosAry, rSalBitmap ); -} - -void AquaSalGraphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap, - const SalBitmap& rTransparentBitmap ) -{ - if( !CheckContext() ) - { - return; - } - const QuartzSalBitmap& rBitmap = static_cast(rSalBitmap); - const QuartzSalBitmap& rMask = static_cast(rTransparentBitmap); - CGImageRef xMaskedImage( rBitmap.CreateWithMask( rMask, rPosAry.mnSrcX, rPosAry.mnSrcY, - rPosAry.mnSrcWidth, rPosAry.mnSrcHeight ) ); - if( !xMaskedImage ) - { - return; - } - const CGRect aDstRect = { { static_cast(rPosAry.mnDestX), static_cast(rPosAry.mnDestY)}, - { static_cast(rPosAry.mnDestWidth), static_cast(rPosAry.mnDestHeight) } }; - CGContextDrawImage( mrContext, aDstRect, xMaskedImage ); - CGImageRelease( xMaskedImage ); - RefreshRect( aDstRect ); -} - -sal_Bool AquaSalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight, - void* pEpsData, sal_uLong nByteCount ) -{ - // convert the raw data to an NSImageRef - NSData* xNSData = [NSData dataWithBytes:(void*)pEpsData length:(int)nByteCount]; - NSImageRep* xEpsImage = [NSEPSImageRep imageRepWithData: xNSData]; - if( !xEpsImage ) - { - return false; - } - // get the target context - if( !CheckContext() ) - { - return false; - } - // NOTE: flip drawing, else the nsimage would be drawn upside down - CGContextSaveGState( mrContext ); -// CGContextTranslateCTM( mrContext, 0, +mnHeight ); - CGContextScaleCTM( mrContext, +1, -1 ); - nY = /*mnHeight*/ - (nY + nHeight); - - // prepare the target context - NSGraphicsContext* pOrigNSCtx = [NSGraphicsContext currentContext]; - [pOrigNSCtx retain]; - - // create new context - NSGraphicsContext* pDrawNSCtx = [NSGraphicsContext graphicsContextWithGraphicsPort: mrContext flipped: IsFlipped()]; - // set it, setCurrentContext also releases the prviously set one - [NSGraphicsContext setCurrentContext: pDrawNSCtx]; - - // draw the EPS - const NSRect aDstRect = { { static_cast(nX), static_cast(nY) }, { static_cast(nWidth), static_cast(nHeight) } }; - const BOOL bOK = [xEpsImage drawInRect: aDstRect]; - - // restore the NSGraphicsContext - [NSGraphicsContext setCurrentContext: pOrigNSCtx]; - [pOrigNSCtx release]; // restore the original retain count - - CGContextRestoreGState( mrContext ); - // mark the destination rectangle as updated - RefreshRect( aDstRect ); - - return bOK; -} - -void AquaSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 ) -{ - if( nX1 == nX2 && nY1 == nY2 ) - { - // #i109453# platform independent code expects at least one pixel to be drawn - drawPixel( nX1, nY1 ); - return; - } - - if( !CheckContext() ) - { - return; - } - CGContextBeginPath( mrContext ); - CGContextMoveToPoint( mrContext, static_cast(nX1)+0.5, static_cast(nY1)+0.5 ); - CGContextAddLineToPoint( mrContext, static_cast(nX2)+0.5, static_cast(nY2)+0.5 ); - CGContextDrawPath( mrContext, kCGPathStroke ); - - Rectangle aRefreshRect( nX1, nY1, nX2, nY2 ); - // Is a call to RefreshRect( aRefreshRect ) missing here? -} - -void AquaSalGraphics::drawMask( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap, SalColor nMaskColor ) -{ - if( !CheckContext() ) - { - return; - } - const QuartzSalBitmap& rBitmap = static_cast(rSalBitmap); - CGImageRef xImage = rBitmap.CreateColorMask( rPosAry.mnSrcX, rPosAry.mnSrcY, - rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, - nMaskColor ); - if( !xImage ) - { - return; - } - const CGRect aDstRect = { { static_cast(rPosAry.mnDestX), static_cast(rPosAry.mnDestY) }, - { static_cast(rPosAry.mnDestWidth), static_cast(rPosAry.mnDestHeight) } }; - CGContextDrawImage( mrContext, aDstRect, xImage ); - CGImageRelease( xImage ); - RefreshRect( aDstRect ); -} - -void AquaSalGraphics::drawPixel( long nX, long nY ) -{ - // draw pixel with current line color - ImplDrawPixel( nX, nY, maLineColor ); -} - -void AquaSalGraphics::drawPixel( long nX, long nY, SalColor nSalColor ) -{ - const RGBAColor aPixelColor( nSalColor ); - ImplDrawPixel( nX, nY, aPixelColor ); -} - -bool AquaSalGraphics::drawPolyLine( - const ::basegfx::B2DPolygon& rPolyLine, - double fTransparency, - const ::basegfx::B2DVector& rLineWidths, - basegfx::B2DLineJoin eLineJoin, - com::sun::star::drawing::LineCap eLineCap) -{ - // short circuit if there is nothing to do - const int nPointCount = rPolyLine.count(); - if( nPointCount <= 0 ) - { - return true; - } - // reject requests that cannot be handled yet - if( rLineWidths.getX() != rLineWidths.getY() ) - { - return false; - } - // #i101491# Aqua does not support B2DLINEJOIN_NONE; return false to use - // the fallback (own geometry preparation) - // #i104886# linejoin-mode and thus the above only applies to "fat" lines - if( (basegfx::B2DLINEJOIN_NONE == eLineJoin) && - (rLineWidths.getX() > 1.3) ) - { - return false; - } - // setup line attributes - CGLineJoin aCGLineJoin = kCGLineJoinMiter; - switch( eLineJoin ) - { - case ::basegfx::B2DLINEJOIN_NONE: aCGLineJoin = /*TODO?*/kCGLineJoinMiter; break; - case ::basegfx::B2DLINEJOIN_MIDDLE: aCGLineJoin = /*TODO?*/kCGLineJoinMiter; break; - case ::basegfx::B2DLINEJOIN_BEVEL: aCGLineJoin = kCGLineJoinBevel; break; - case ::basegfx::B2DLINEJOIN_MITER: aCGLineJoin = kCGLineJoinMiter; break; - case ::basegfx::B2DLINEJOIN_ROUND: aCGLineJoin = kCGLineJoinRound; break; - } - - // setup cap attribute - CGLineCap aCGLineCap(kCGLineCapButt); - - switch(eLineCap) - { - default: // com::sun::star::drawing::LineCap_BUTT: - { - aCGLineCap = kCGLineCapButt; - break; - } - case com::sun::star::drawing::LineCap_ROUND: - { - aCGLineCap = kCGLineCapRound; - break; - } - case com::sun::star::drawing::LineCap_SQUARE: - { - aCGLineCap = kCGLineCapSquare; - break; - } - } - - // setup poly-polygon path - CGMutablePathRef xPath = CGPathCreateMutable(); - AddPolygonToPath( xPath, rPolyLine, rPolyLine.isClosed(), !getAntiAliasB2DDraw(), true ); - - const CGRect aRefreshRect = CGPathGetBoundingBox( xPath ); - // #i97317# workaround for Quartz having problems with drawing small polygons - if( ! ((aRefreshRect.size.width <= 0.125) && (aRefreshRect.size.height <= 0.125)) ) - { - // use the path to prepare the graphics context - CGContextSaveGState( mrContext ); - CGContextAddPath( mrContext, xPath ); - // draw path with antialiased line - CGContextSetShouldAntialias( mrContext, true ); - CGContextSetAlpha( mrContext, 1.0 - fTransparency ); - CGContextSetLineJoin( mrContext, aCGLineJoin ); - CGContextSetLineCap( mrContext, aCGLineCap ); - CGContextSetLineWidth( mrContext, rLineWidths.getX() ); - CGContextDrawPath( mrContext, kCGPathStroke ); - CGContextRestoreGState( mrContext ); - - // mark modified rectangle as updated - RefreshRect( aRefreshRect ); - } - - CGPathRelease( xPath ); - - return true; -} - -sal_Bool AquaSalGraphics::drawPolyLineBezier( sal_uLong, const SalPoint*, const sal_uInt8* ) -{ - return sal_False; -} - -bool AquaSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly, - double fTransparency ) -{ - // short circuit if there is nothing to do - const int nPolyCount = rPolyPoly.count(); - if( nPolyCount <= 0 ) - { - return true; - } - // ignore invisible polygons - if( (fTransparency >= 1.0) || (fTransparency < 0) ) - { - return true; - } - // setup poly-polygon path - CGMutablePathRef xPath = CGPathCreateMutable(); - for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx ) - { - const ::basegfx::B2DPolygon rPolygon = rPolyPoly.getB2DPolygon( nPolyIdx ); - AddPolygonToPath( xPath, rPolygon, true, !getAntiAliasB2DDraw(), IsPenVisible() ); - } - - const CGRect aRefreshRect = CGPathGetBoundingBox( xPath ); - // #i97317# workaround for Quartz having problems with drawing small polygons - if( ! ((aRefreshRect.size.width <= 0.125) && (aRefreshRect.size.height <= 0.125)) ) - { - // use the path to prepare the graphics context - CGContextSaveGState( mrContext ); - CGContextBeginPath( mrContext ); - CGContextAddPath( mrContext, xPath ); - - // draw path with antialiased polygon - CGContextSetShouldAntialias( mrContext, true ); - CGContextSetAlpha( mrContext, 1.0 - fTransparency ); - CGContextDrawPath( mrContext, kCGPathEOFillStroke ); - CGContextRestoreGState( mrContext ); - - // mark modified rectangle as updated - RefreshRect( aRefreshRect ); - } - - CGPathRelease( xPath ); - - return true; -} - -void AquaSalGraphics::drawPolyPolygon( sal_uInt32 nPolyCount, const sal_uInt32 *pPoints, PCONSTSALPOINT *ppPtAry ) -{ - if( nPolyCount <= 0 ) - return; - if( !CheckContext() ) - return; - - // find bound rect - long leftX = 0, topY = 0, maxWidth = 0, maxHeight = 0; - getBoundRect( pPoints[0], ppPtAry[0], leftX, topY, maxWidth, maxHeight ); - for( sal_uLong n = 1; n < nPolyCount; n++ ) - { - long nX = leftX, nY = topY, nW = maxWidth, nH = maxHeight; - getBoundRect( pPoints[n], ppPtAry[n], nX, nY, nW, nH ); - if( nX < leftX ) - { - maxWidth += leftX - nX; - leftX = nX; - } - if( nY < topY ) - { - maxHeight += topY - nY; - topY = nY; - } - if( nX + nW > leftX + maxWidth ) - { - maxWidth = nX + nW - leftX; - } - if( nY + nH > topY + maxHeight ) - { - maxHeight = nY + nH - topY; - } - } - - // prepare drawing mode - CGPathDrawingMode eMode; - if( IsBrushVisible() && IsPenVisible() ) - { - eMode = kCGPathEOFillStroke; - } - else if( IsPenVisible() ) - { - eMode = kCGPathStroke; - } - else if( IsBrushVisible() ) - { - eMode = kCGPathEOFill; - } - else - { - return; - } - // convert to CGPath - CGContextBeginPath( mrContext ); - if( IsPenVisible() ) - { - for( sal_uLong nPoly = 0; nPoly < nPolyCount; nPoly++ ) - { - const sal_uLong nPoints = pPoints[nPoly]; - if( nPoints > 1 ) - { - const SalPoint *pPtAry = ppPtAry[nPoly]; - float fX, fY; - alignLinePoint( pPtAry, fX, fY ); - CGContextMoveToPoint( mrContext, fX, fY ); - pPtAry++; - for( sal_uLong nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++ ) - { - alignLinePoint( pPtAry, fX, fY ); - CGContextAddLineToPoint( mrContext, fX, fY ); - } - CGContextClosePath(mrContext); - } - } - } - else - { - for( sal_uLong nPoly = 0; nPoly < nPolyCount; nPoly++ ) - { - const sal_uLong nPoints = pPoints[nPoly]; - if( nPoints > 1 ) - { - const SalPoint *pPtAry = ppPtAry[nPoly]; - CGContextMoveToPoint( mrContext, pPtAry->mnX, pPtAry->mnY ); - pPtAry++; - for( sal_uLong nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++ ) - { - CGContextAddLineToPoint( mrContext, pPtAry->mnX, pPtAry->mnY ); - } - CGContextClosePath(mrContext); - } - } - } - - CGContextDrawPath( mrContext, eMode ); - - RefreshRect( leftX, topY, maxWidth, maxHeight ); -} - -void AquaSalGraphics::drawPolygon( sal_uLong nPoints, const SalPoint *pPtAry ) -{ - if( nPoints <= 1 ) - return; - if( !CheckContext() ) - return; - - long nX = 0, nY = 0, nWidth = 0, nHeight = 0; - getBoundRect( nPoints, pPtAry, nX, nY, nWidth, nHeight ); - - CGPathDrawingMode eMode; - if( IsBrushVisible() && IsPenVisible() ) - { - eMode = kCGPathEOFillStroke; - } - else if( IsPenVisible() ) - { - eMode = kCGPathStroke; - } - else if( IsBrushVisible() ) - { - eMode = kCGPathEOFill; - } - else - { - return; - } - CGContextBeginPath( mrContext ); - - if( IsPenVisible() ) - { - float fX, fY; - alignLinePoint( pPtAry, fX, fY ); - CGContextMoveToPoint( mrContext, fX, fY ); - pPtAry++; - for( sal_uLong nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++ ) - { - alignLinePoint( pPtAry, fX, fY ); - CGContextAddLineToPoint( mrContext, fX, fY ); - } - } - else - { - CGContextMoveToPoint( mrContext, pPtAry->mnX, pPtAry->mnY ); - pPtAry++; - for( sal_uLong nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++ ) - { - CGContextAddLineToPoint( mrContext, pPtAry->mnX, pPtAry->mnY ); - } - } - - CGContextClosePath( mrContext ); - CGContextDrawPath( mrContext, eMode ); - RefreshRect( nX, nY, nWidth, nHeight ); -} - -sal_Bool AquaSalGraphics::drawPolygonBezier( sal_uLong, const SalPoint*, const sal_uInt8* ) -{ - return sal_False; -} - -sal_Bool AquaSalGraphics::drawPolyPolygonBezier( sal_uInt32, const sal_uInt32*, - const SalPoint* const*, const sal_uInt8* const* ) -{ - return sal_False; -} - -void AquaSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight ) -{ - if( !CheckContext() ) - { - return; - } - CGRect aRect( CGRectMake(nX, nY, nWidth, nHeight) ); - if( IsPenVisible() ) - { - aRect.origin.x += 0.5; - aRect.origin.y += 0.5; - aRect.size.width -= 1; - aRect.size.height -= 1; - } - - if( IsBrushVisible() ) - { - CGContextFillRect( mrContext, aRect ); - } - if( IsPenVisible() ) - { - CGContextStrokeRect( mrContext, aRect ); - } - RefreshRect( nX, nY, nWidth, nHeight ); -} - - -void AquaSalGraphics::drawPolyLine( sal_uLong nPoints, const SalPoint *pPtAry ) -{ - if( nPoints < 1 ) - { - return; - } - if( !CheckContext() ) - { - return; - } - - long nX = 0, nY = 0, nWidth = 0, nHeight = 0; - getBoundRect( nPoints, pPtAry, nX, nY, nWidth, nHeight ); - - float fX, fY; - CGContextBeginPath( mrContext ); - alignLinePoint( pPtAry, fX, fY ); - CGContextMoveToPoint( mrContext, fX, fY ); - pPtAry++; - for( sal_uLong nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++ ) - { - alignLinePoint( pPtAry, fX, fY ); - CGContextAddLineToPoint( mrContext, fX, fY ); - } - CGContextDrawPath( mrContext, kCGPathStroke ); - - RefreshRect( nX, nY, nWidth, nHeight ); -} - -sal_uInt16 AquaSalGraphics::GetBitCount() const -{ - sal_uInt16 nBits = mnBitmapDepth ? mnBitmapDepth : 32;//24; - return nBits; -} - -SalBitmap* AquaSalGraphics::getBitmap( long nX, long nY, long nDX, long nDY ) -{ - DBG_ASSERT( mxLayer, "AquaSalGraphics::getBitmap() with no layer" ); - - ApplyXorContext(); - - QuartzSalBitmap* pBitmap = new QuartzSalBitmap; - if( !pBitmap->Create( mxLayer, mnBitmapDepth, nX, nY, nDX, nDY, !mbWindow ) ) - { - delete pBitmap; - pBitmap = NULL; - } - - return pBitmap; -} - -SystemGraphicsData AquaSalGraphics::GetGraphicsData() const -{ - SystemGraphicsData aRes; - aRes.nSize = sizeof(aRes); - aRes.rCGContext = mrContext; - return aRes; -} - -long AquaSalGraphics::GetGraphicsWidth() const -{ - long w = 0; - if( mrContext && (mbWindow || mbVirDev) ) - { - w = mnWidth; - } - - if( w == 0 ) - { - if( mbWindow && mpFrame ) - { - w = mpFrame->maGeometry.nWidth; - } - } - return w; -} - -SalColor AquaSalGraphics::getPixel( long nX, long nY ) -{ - // return default value on printers or when out of bounds - if( !mxLayer || (nX < 0) || (nX >= mnWidth) || - (nY < 0) || (nY >= mnHeight)) - { - return COL_BLACK; - } - // prepare creation of matching a CGBitmapContext - CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace; - CGBitmapInfo aCGBmpInfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big; -#if defined OSL_BIGENDIAN - struct{ unsigned char b, g, r, a; } aPixel; -#else - struct{ unsigned char a, r, g, b; } aPixel; -#endif - - // create a one-pixel bitmap context - // TODO: is it worth to cache it? - CGContextRef xOnePixelContext = - ::CGBitmapContextCreate( &aPixel, 1, 1, 8, sizeof(aPixel), - aCGColorSpace, aCGBmpInfo ); - - // update this graphics layer - ApplyXorContext(); - - // copy the requested pixel into the bitmap context - if( IsFlipped() ) - { - nY = mnHeight - nY; - } - const CGPoint aCGPoint = { static_cast(-nX), static_cast(-nY) }; - CGContextDrawLayerAtPoint( xOnePixelContext, aCGPoint, mxLayer ); - CGContextRelease( xOnePixelContext ); - - SalColor nSalColor = MAKE_SALCOLOR( aPixel.r, aPixel.g, aPixel.b ); - return nSalColor; -} - -void AquaSalGraphics::GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY ) -{ - if( !mnRealDPIY ) - { - initResolution( (mbWindow && mpFrame) ? mpFrame->getNSWindow() : nil ); - } - - rDPIX = static_cast(mfFakeDPIScale * mnRealDPIX); - rDPIY = static_cast(mfFakeDPIScale * mnRealDPIY); -} - -void AquaSalGraphics::ImplDrawPixel( long nX, long nY, const RGBAColor& rColor ) -{ - if( !CheckContext() ) - { - return; - } - // overwrite the fill color - CGContextSetFillColor( mrContext, rColor.AsArray() ); - // draw 1x1 rect, there is no pixel drawing in Quartz - CGRect aDstRect = { { static_cast(nX), static_cast(nY) }, {1,1}}; - CGContextFillRect( mrContext, aDstRect ); - RefreshRect( aDstRect ); - // reset the fill color - CGContextSetFillColor( mrContext, maFillColor.AsArray() ); -} - -void AquaSalGraphics::initResolution( NSWindow* ) -{ - // #i100617# read DPI only once; there is some kind of weird caching going on - // if the main screen changes - // FIXME: this is really unfortunate and needs to be investigated - - SalData* pSalData = GetSalData(); - if( pSalData->mnDPIX == 0 || pSalData->mnDPIY == 0 ) - { - NSScreen* pScreen = nil; - - /* #i91301# - many woes went into the try to have different resolutions - on different screens. The result of these trials is that OOo is not ready - for that yet, vcl and applications would need to be adapted. - - Unfortunately this is not possible in the 3.0 timeframe. - So let's stay with one resolution for all Windows and VirtualDevices - which is the resolution of the main screen - - This of course also means that measurements are exact only on the main screen. - For activating different resolutions again just comment out the two lines below. - - if( pWin ) - pScreen = [pWin screen]; - */ - if( pScreen == nil ) - { - NSArray* pScreens = [NSScreen screens]; - if( pScreens ) - pScreen = [pScreens objectAtIndex: 0]; - } - - mnRealDPIX = mnRealDPIY = 96; - if( pScreen ) - { - NSDictionary* pDev = [pScreen deviceDescription]; - if( pDev ) - { - NSNumber* pVal = [pDev objectForKey: @"NSScreenNumber"]; - if( pVal ) - { - // FIXME: casting a long to CGDirectDisplayID is evil, but - // Apple suggest to do it this way - const CGDirectDisplayID nDisplayID = (CGDirectDisplayID)[pVal longValue]; - const CGSize aSize = CGDisplayScreenSize( nDisplayID ); // => result is in millimeters - mnRealDPIX = static_cast((CGDisplayPixelsWide( nDisplayID ) * 25.4) / aSize.width); - mnRealDPIY = static_cast((CGDisplayPixelsHigh( nDisplayID ) * 25.4) / aSize.height); - } - else - { - OSL_FAIL( "no resolution found in device description" ); - } - } - else - { - OSL_FAIL( "no device description" ); - } - } - else - { - OSL_FAIL( "no screen found" ); - } - - // #i107076# maintaining size-WYSIWYG-ness causes many problems for - // low-DPI, high-DPI or for mis-reporting devices - // => it is better to limit the calculation result then - static const int nMinDPI = 72; - if( (mnRealDPIX < nMinDPI) || (mnRealDPIY < nMinDPI) ) - { - mnRealDPIX = mnRealDPIY = nMinDPI; - } - static const int nMaxDPI = 200; - if( (mnRealDPIX > nMaxDPI) || (mnRealDPIY > nMaxDPI) ) - { - mnRealDPIX = mnRealDPIY = nMaxDPI; - } - // for OSX any anisotropy reported for the display resolution is best ignored (e.g. TripleHead2Go) - mnRealDPIX = mnRealDPIY = (mnRealDPIX + mnRealDPIY + 1) / 2; - - pSalData->mnDPIX = mnRealDPIX; - pSalData->mnDPIY = mnRealDPIY; - } - else - { - mnRealDPIX = pSalData->mnDPIX; - mnRealDPIY = pSalData->mnDPIY; - } - - mfFakeDPIScale = 1.0; -} - -void AquaSalGraphics::invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags ) -{ - if ( CheckContext() ) - { - CGRect aCGRect = CGRectMake( nX, nY, nWidth, nHeight); - CGContextSaveGState(mrContext); - - if ( nFlags & SAL_INVERT_TRACKFRAME ) - { - const CGFloat dashLengths[2] = { 4.0, 4.0 }; // for drawing dashed line - CGContextSetBlendMode( mrContext, kCGBlendModeDifference ); - CGContextSetRGBStrokeColor ( mrContext, 1.0, 1.0, 1.0, 1.0 ); - CGContextSetLineDash ( mrContext, 0, dashLengths, 2 ); - CGContextSetLineWidth( mrContext, 2.0); - CGContextStrokeRect ( mrContext, aCGRect ); - } - else if ( nFlags & SAL_INVERT_50 ) - { - //CGContextSetAllowsAntialiasing( mrContext, false ); - CGContextSetBlendMode(mrContext, kCGBlendModeDifference); - CGContextAddRect( mrContext, aCGRect ); - Pattern50Fill(); - } - else // just invert - { - CGContextSetBlendMode(mrContext, kCGBlendModeDifference); - CGContextSetRGBFillColor ( mrContext,1.0, 1.0, 1.0 , 1.0 ); - CGContextFillRect ( mrContext, aCGRect ); - } - CGContextRestoreGState( mrContext); - RefreshRect( aCGRect ); - } -} - -void AquaSalGraphics::invert( sal_uLong nPoints, const SalPoint* pPtAry, SalInvert nSalFlags ) -{ - CGPoint* CGpoints ; - if ( CheckContext() ) - { - CGContextSaveGState(mrContext); - CGpoints = makeCGptArray(nPoints,pPtAry); - CGContextAddLines ( mrContext, CGpoints, nPoints ); - if ( nSalFlags & SAL_INVERT_TRACKFRAME ) - { - const CGFloat dashLengths[2] = { 4.0, 4.0 }; // for drawing dashed line - CGContextSetBlendMode( mrContext, kCGBlendModeDifference ); - CGContextSetRGBStrokeColor ( mrContext, 1.0, 1.0, 1.0, 1.0 ); - CGContextSetLineDash ( mrContext, 0, dashLengths, 2 ); - CGContextSetLineWidth( mrContext, 2.0); - CGContextStrokePath ( mrContext ); - } - else if ( nSalFlags & SAL_INVERT_50 ) - { - CGContextSetBlendMode(mrContext, kCGBlendModeDifference); - Pattern50Fill(); - } - else // just invert - { - CGContextSetBlendMode( mrContext, kCGBlendModeDifference ); - CGContextSetRGBFillColor( mrContext, 1.0, 1.0, 1.0, 1.0 ); - CGContextFillPath( mrContext ); - } - const CGRect aRefreshRect = CGContextGetClipBoundingBox(mrContext); - CGContextRestoreGState( mrContext); - delete [] CGpoints; - RefreshRect( aRefreshRect ); - } -} - -void AquaSalGraphics::Pattern50Fill() -{ - static const CGFloat aFillCol[4] = { 1,1,1,1 }; - static const CGPatternCallbacks aCallback = { 0, &DrawPattern50, NULL }; - if( ! GetSalData()->mxP50Space ) - { - GetSalData()->mxP50Space = CGColorSpaceCreatePattern( GetSalData()->mxRGBSpace ); - } - if( ! GetSalData()->mxP50Pattern ) - { - GetSalData()->mxP50Pattern = CGPatternCreate( NULL, CGRectMake( 0, 0, 4, 4 ), - CGAffineTransformIdentity, 4, 4, - kCGPatternTilingConstantSpacing, - false, &aCallback ); - } - CGContextSetFillColorSpace( mrContext, GetSalData()->mxP50Space ); - CGContextSetFillPattern( mrContext, GetSalData()->mxP50Pattern, aFillCol ); - CGContextFillPath( mrContext ); -} - - -void AquaSalGraphics::ResetClipRegion() -{ - // release old path and indicate no clipping - if( mxClipPath ) - { - CGPathRelease( mxClipPath ); - mxClipPath = NULL; - } - if( CheckContext() ) - { - SetState(); - } -} - -void AquaSalGraphics::SetLineColor() -{ - maLineColor.SetAlpha( 0.0 ); // transparent - if( CheckContext() ) - { - CGContextSetStrokeColor( mrContext, maLineColor.AsArray() ); - } -} - -void AquaSalGraphics::SetLineColor( SalColor nSalColor ) -{ - maLineColor = RGBAColor( nSalColor ); - if( CheckContext() ) - { - CGContextSetStrokeColor( mrContext, maLineColor.AsArray() ); - } -} - -void AquaSalGraphics::SetFillColor() -{ - maFillColor.SetAlpha( 0.0 ); // transparent - if( CheckContext() ) - { - CGContextSetFillColor( mrContext, maFillColor.AsArray() ); - } -} - -void AquaSalGraphics::SetFillColor( SalColor nSalColor ) -{ - maFillColor = RGBAColor( nSalColor ); - if( CheckContext() ) - { - CGContextSetFillColor( mrContext, maFillColor.AsArray() ); - } -} - -bool AquaSalGraphics::supportsOperation( OutDevSupportType eType ) const -{ - bool bRet = false; - switch( eType ) - { - case OutDevSupport_TransparentRect: - case OutDevSupport_B2DClip: - case OutDevSupport_B2DDraw: - bRet = true; - break; - default: break; - } - return bRet; -} - -bool AquaSalGraphics::setClipRegion( const Region& i_rClip ) -{ - // release old clip path - if( mxClipPath ) - { - CGPathRelease( mxClipPath ); - mxClipPath = NULL; - } - mxClipPath = CGPathCreateMutable(); - - // set current path, either as polypolgon or sequence of rectangles - if(i_rClip.HasPolyPolygonOrB2DPolyPolygon()) - { - const basegfx::B2DPolyPolygon aClip(i_rClip.GetAsB2DPolyPolygon()); - - AddPolyPolygonToPath( mxClipPath, aClip, !getAntiAliasB2DDraw(), false ); - } - else - { - RectangleVector aRectangles; - i_rClip.GetRegionRectangles(aRectangles); - - for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++) - { - const long nW(aRectIter->Right() - aRectIter->Left() + 1); // uses +1 logic in original - - if(nW) - { - const long nH(aRectIter->Bottom() - aRectIter->Top() + 1); // uses +1 logic in original - - if(nH) - { - CGRect aRect = {{ (CGFloat) aRectIter->Left(), (CGFloat) aRectIter->Top() }, { (CGFloat) nW, (CGFloat) nH }}; - CGPathAddRect( mxClipPath, NULL, aRect ); - } - } - } - } - // set the current path as clip region - if( CheckContext() ) - { - SetState(); - } - return true; -} - -void AquaSalGraphics::SetROPFillColor( SalROPColor nROPColor ) -{ - if( ! mbPrinter ) - SetFillColor( ImplGetROPSalColor( nROPColor ) ); -} - -void AquaSalGraphics::SetROPLineColor( SalROPColor nROPColor ) -{ - if( ! mbPrinter ) - SetLineColor( ImplGetROPSalColor( nROPColor ) ); -} - -void AquaSalGraphics::SetXORMode( bool bSet, bool bInvertOnly ) -{ - // return early if XOR mode remains unchanged - if( mbPrinter ) - { - return; - } - if( ! bSet && mnXorMode == 2 ) - { - CGContextSetBlendMode( mrContext, kCGBlendModeNormal ); - mnXorMode = 0; - return; - } - else if( bSet && bInvertOnly && mnXorMode == 0) - { - CGContextSetBlendMode( mrContext, kCGBlendModeDifference ); - mnXorMode = 2; - return; - } - - if( (mpXorEmulation == NULL) && !bSet ) - { - return; - } - if( (mpXorEmulation != NULL) && (bSet == mpXorEmulation->IsEnabled()) ) - { - return; - } - if( !CheckContext() ) - { - return; - } - // prepare XOR emulation - if( !mpXorEmulation ) - { - mpXorEmulation = new XorEmulation(); - mpXorEmulation->SetTarget( mnWidth, mnHeight, mnBitmapDepth, mrContext, mxLayer ); - } - - // change the XOR mode - if( bSet ) - { - mpXorEmulation->Enable(); - mrContext = mpXorEmulation->GetMaskContext(); - mnXorMode = 1; - } - else - { - mpXorEmulation->UpdateTarget(); - mpXorEmulation->Disable(); - mrContext = mpXorEmulation->GetTargetContext(); - mnXorMode = 0; - } -} - -void AquaSalGraphics::updateResolution() -{ - DBG_ASSERT( mbWindow, "updateResolution on inappropriate graphics" ); - - initResolution( (mbWindow && mpFrame) ? mpFrame->getNSWindow() : nil ); -} - - -// ----------------------------------------------------------- - -XorEmulation::XorEmulation() -: m_xTargetLayer( NULL ) -, m_xTargetContext( NULL ) -, m_xMaskContext( NULL ) -, m_xTempContext( NULL ) -, m_pMaskBuffer( NULL ) -, m_pTempBuffer( NULL ) -, m_nBufferLongs( 0 ) -, m_bIsEnabled( false ) -{} - -XorEmulation::~XorEmulation() -{ - Disable(); - SetTarget( 0, 0, 0, NULL, NULL ); -} - -void XorEmulation::SetTarget( int nWidth, int nHeight, int nTargetDepth, - CGContextRef xTargetContext, CGLayerRef xTargetLayer ) -{ - // prepare to replace old mask+temp context - if( m_xMaskContext ) - { - // cleanup the mask context - CGContextRelease( m_xMaskContext ); - delete[] m_pMaskBuffer; - m_xMaskContext = NULL; - m_pMaskBuffer = NULL; - - // cleanup the temp context if needed - if( m_xTempContext ) - { - CGContextRelease( m_xTempContext ); - delete[] m_pTempBuffer; - m_xTempContext = NULL; - m_pTempBuffer = NULL; - } - } - - // return early if there is nothing more to do - if( !xTargetContext ) - { - return; - } - // retarget drawing operations to the XOR mask - m_xTargetLayer = xTargetLayer; - m_xTargetContext = xTargetContext; - - // prepare creation of matching CGBitmaps - CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace; - CGBitmapInfo aCGBmpInfo = kCGImageAlphaNoneSkipFirst; - int nBitDepth = nTargetDepth; - if( !nBitDepth ) - { - nBitDepth = 32; - } - int nBytesPerRow = (nBitDepth == 16) ? 2 : 4; - const size_t nBitsPerComponent = (nBitDepth == 16) ? 5 : 8; - if( nBitDepth <= 8 ) - { - aCGColorSpace = GetSalData()->mxGraySpace; - aCGBmpInfo = kCGImageAlphaNone; - nBytesPerRow = 1; - } - nBytesPerRow *= nWidth; - m_nBufferLongs = (nHeight * nBytesPerRow + sizeof(sal_uLong)-1) / sizeof(sal_uLong); - - // create a XorMask context - m_pMaskBuffer = new sal_uLong[ m_nBufferLongs ]; - m_xMaskContext = ::CGBitmapContextCreate( m_pMaskBuffer, - nWidth, nHeight, - nBitsPerComponent, nBytesPerRow, - aCGColorSpace, aCGBmpInfo ); - // reset the XOR mask to black - memset( m_pMaskBuffer, 0, m_nBufferLongs * sizeof(sal_uLong) ); - - // a bitmap context will be needed for manual XORing - // create one unless the target context is a bitmap context - if( nTargetDepth ) - m_pTempBuffer = (sal_uLong*)CGBitmapContextGetData( m_xTargetContext ); - if( !m_pTempBuffer ) - { - // create a bitmap context matching to the target context - m_pTempBuffer = new sal_uLong[ m_nBufferLongs ]; - m_xTempContext = ::CGBitmapContextCreate( m_pTempBuffer, - nWidth, nHeight, - nBitsPerComponent, nBytesPerRow, - aCGColorSpace, aCGBmpInfo ); - } - - // initialize XOR mask context for drawing - CGContextSetFillColorSpace( m_xMaskContext, aCGColorSpace ); - CGContextSetStrokeColorSpace( m_xMaskContext, aCGColorSpace ); - CGContextSetShouldAntialias( m_xMaskContext, false ); - - // improve the XorMask's XOR emulation a litte - // NOTE: currently only enabled for monochrome contexts - if( aCGColorSpace == GetSalData()->mxGraySpace ) - { - CGContextSetBlendMode( m_xMaskContext, kCGBlendModeDifference ); - } - // intialize the transformation matrix to the drawing target - const CGAffineTransform aCTM = CGContextGetCTM( xTargetContext ); - CGContextConcatCTM( m_xMaskContext, aCTM ); - if( m_xTempContext ) - { - CGContextConcatCTM( m_xTempContext, aCTM ); - } - // initialize the default XorMask graphics state - CGContextSaveGState( m_xMaskContext ); -} - -bool XorEmulation::UpdateTarget() -{ - if( !IsEnabled() ) - { - return false; - } - // update the temp bitmap buffer if needed - if( m_xTempContext ) - { - CGContextDrawLayerAtPoint( m_xTempContext, CGPointZero, m_xTargetLayer ); - } - // do a manual XOR with the XorMask - // this approach suffices for simple color manipulations - // and also the complex-clipping-XOR-trick used in metafiles - const sal_uLong* pSrc = m_pMaskBuffer; - sal_uLong* pDst = m_pTempBuffer; - for( int i = m_nBufferLongs; --i >= 0;) - { - *(pDst++) ^= *(pSrc++); - } - // write back the XOR results to the target context - if( m_xTempContext ) - { - CGImageRef xXorImage = CGBitmapContextCreateImage( m_xTempContext ); - const int nWidth = (int)CGImageGetWidth( xXorImage ); - const int nHeight = (int)CGImageGetHeight( xXorImage ); - // TODO: update minimal changerect - const CGRect aFullRect = { {0, 0}, { static_cast(nWidth), static_cast(nHeight) } }; - CGContextDrawImage( m_xTargetContext, aFullRect, xXorImage ); - CGImageRelease( xXorImage ); - } - - // reset the XorMask to black again - // TODO: not needed for last update - memset( m_pMaskBuffer, 0, m_nBufferLongs * sizeof(sal_uLong) ); - - // TODO: return FALSE if target was not changed - return true; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/gdi/salgdiutils.cxx b/vcl/aqua/source/gdi/salgdiutils.cxx deleted file mode 100644 index c0a8d0d7ea6e..000000000000 --- a/vcl/aqua/source/gdi/salgdiutils.cxx +++ /dev/null @@ -1,299 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "basebmp/scanlineformats.hxx" -#include "basebmp/color.hxx" - -#include "basegfx/range/b2drectangle.hxx" -#include "basegfx/range/b2irange.hxx" -#include "basegfx/vector/b2ivector.hxx" -#include "basegfx/polygon/b2dpolygon.hxx" -#include "basegfx/polygon/b2dpolygontools.hxx" - -#include "vcl/svapp.hxx" - -#include "coretext/salgdi.h" -#include "aqua/salframe.h" -#include "aqua/saldata.hxx" - -// ---------------------------------------------------------------------- - -void AquaSalGraphics::SetWindowGraphics( AquaSalFrame* pFrame ) -{ - mpFrame = pFrame; - - mbWindow = true; - mbPrinter = false; - mbVirDev = false; -} - -void AquaSalGraphics::SetPrinterGraphics( CGContextRef xContext, long nDPIX, long nDPIY, double fScale ) -{ - mbWindow = false; - mbPrinter = true; - mbVirDev = false; - - mrContext = xContext; - mfFakeDPIScale = fScale; - mnRealDPIX = nDPIX; - mnRealDPIY = nDPIY; - - // a previously set clip path is now invalid - if( mxClipPath ) - { - CGPathRelease( mxClipPath ); - mxClipPath = NULL; - } - - if( mrContext ) - { - CGContextSetFillColorSpace( mrContext, GetSalData()->mxRGBSpace ); - CGContextSetStrokeColorSpace( mrContext, GetSalData()->mxRGBSpace ); - CGContextSaveGState( mrContext ); - SetState(); - } -} - -void AquaSalGraphics::SetVirDevGraphics( CGLayerRef xLayer, CGContextRef xContext, - int nBitmapDepth ) -{ - mbWindow = false; - mbPrinter = false; - mbVirDev = true; - - // set graphics properties - mxLayer = xLayer; - mrContext = xContext; - mnBitmapDepth = nBitmapDepth; - - // return early if the virdev is being destroyed - if( !xContext ) - return; - - // get new graphics properties - if( !mxLayer ) - { - mnWidth = CGBitmapContextGetWidth( mrContext ); - mnHeight = CGBitmapContextGetHeight( mrContext ); - } - else - { - const CGSize aSize = CGLayerGetSize( mxLayer ); - mnWidth = static_cast(aSize.width); - mnHeight = static_cast(aSize.height); - } - - // prepare graphics for drawing - const CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace; - CGContextSetFillColorSpace( mrContext, aCGColorSpace ); - CGContextSetStrokeColorSpace( mrContext, aCGColorSpace ); - - // re-enable XorEmulation for the new context - if( mpXorEmulation ) - { - mpXorEmulation->SetTarget( mnWidth, mnHeight, mnBitmapDepth, mrContext, mxLayer ); - if( mpXorEmulation->IsEnabled() ) - mrContext = mpXorEmulation->GetMaskContext(); - } - - // initialize stack of CGContext states - CGContextSaveGState( mrContext ); - SetState(); -} - -// ---------------------------------------------------------------------- - -void AquaSalGraphics::InvalidateContext() -{ - UnsetState(); - mrContext = 0; -} - -// ---------------------------------------------------------------------- - -void AquaSalGraphics::UnsetState() -{ - if( mrContext ) - { - CGContextRestoreGState( mrContext ); - mrContext = 0; - } - if( mxClipPath ) - { - CGPathRelease( mxClipPath ); - mxClipPath = NULL; - } -} - -void AquaSalGraphics::SetState() -{ - CGContextRestoreGState( mrContext ); - CGContextSaveGState( mrContext ); - - // setup clipping - if( mxClipPath ) - { - CGContextBeginPath( mrContext ); // discard any existing path - CGContextAddPath( mrContext, mxClipPath ); // set the current path to the clipping path - CGContextClip( mrContext ); // use it for clipping - } - - // set RGB colorspace and line and fill colors - CGContextSetFillColor( mrContext, maFillColor.AsArray() ); - CGContextSetStrokeColor( mrContext, maLineColor.AsArray() ); - CGContextSetShouldAntialias( mrContext, false ); - if( mnXorMode == 2 ) - CGContextSetBlendMode( mrContext, kCGBlendModeDifference ); -} - -// ---------------------------------------------------------------------- - -bool AquaSalGraphics::CheckContext() -{ - if( mbWindow && mpFrame != NULL ) - { - const unsigned int nWidth = mpFrame->maGeometry.nWidth; - const unsigned int nHeight = mpFrame->maGeometry.nHeight; - - CGContextRef rReleaseContext = 0; - CGLayerRef rReleaseLayer = NULL; - - // check if a new drawing context is needed (e.g. after a resize) - if( (unsigned(mnWidth) != nWidth) || (unsigned(mnHeight) != nHeight) ) - { - mnWidth = nWidth; - mnHeight = nHeight; - // prepare to release the corresponding resources - rReleaseContext = mrContext; - rReleaseLayer = mxLayer; - mrContext = NULL; - mxLayer = NULL; - } - - if( !mrContext ) - { - const CGSize aLayerSize = { static_cast(nWidth), static_cast(nHeight) }; - NSGraphicsContext* pNSGContext = [NSGraphicsContext graphicsContextWithWindow: mpFrame->getNSWindow()]; - CGContextRef xCGContext = reinterpret_cast([pNSGContext graphicsPort]); - mxLayer = CGLayerCreateWithContext( xCGContext, aLayerSize, NULL ); - if( mxLayer ) - mrContext = CGLayerGetContext( mxLayer ); - - if( mrContext ) - { - // copy original layer to resized layer - if( rReleaseLayer ) - CGContextDrawLayerAtPoint( mrContext, CGPointZero, rReleaseLayer ); - - CGContextTranslateCTM( mrContext, 0, nHeight ); - CGContextScaleCTM( mrContext, 1.0, -1.0 ); - CGContextSetFillColorSpace( mrContext, GetSalData()->mxRGBSpace ); - CGContextSetStrokeColorSpace( mrContext, GetSalData()->mxRGBSpace ); - CGContextSaveGState( mrContext ); - SetState(); - - // re-enable XOR emulation for the new context - if( mpXorEmulation ) - mpXorEmulation->SetTarget( mnWidth, mnHeight, mnBitmapDepth, mrContext, mxLayer ); - } - } - - if( rReleaseLayer ) - CGLayerRelease( rReleaseLayer ); - else if( rReleaseContext ) - CGContextRelease( rReleaseContext ); - } - - DBG_ASSERT( mrContext || mbPrinter, "<<>> AquaSalGraphics::CheckContext() FAILED!!!!\n" ); - return (mrContext != NULL); -} - -CGContextRef AquaSalGraphics::GetContext() -{ - if(!mrContext) - { - CheckContext(); - } - return mrContext; -} - -void AquaSalGraphics::RefreshRect(float lX, float lY, float lWidth, float lHeight) -{ - if( ! mbWindow ) // view only on Window graphics - return; - - if( mpFrame ) - { - // update a little more around the designated rectangle - // this helps with antialiased rendering - const Rectangle aVclRect(Point(static_cast(lX-1), - static_cast(lY-1) ), - Size( static_cast(lWidth+2), - static_cast(lHeight+2) ) ); - mpFrame->maInvalidRect.Union( aVclRect ); - } -} - -CGPoint* AquaSalGraphics::makeCGptArray(sal_uLong nPoints, const SalPoint* pPtAry) -{ - CGPoint *CGpoints = new CGPoint[nPoints]; - if ( CGpoints ) - { - for(sal_uLong i=0;i([pContext graphicsPort]); - - CGMutablePathRef rClip = mpFrame->getClipPath(); - if( rClip ) - { - CGContextSaveGState( rCGContext ); - CGContextBeginPath( rCGContext ); - CGContextAddPath( rCGContext, rClip ); - CGContextClip( rCGContext ); - } - - ApplyXorContext(); - CGContextDrawLayerAtPoint( rCGContext, CGPointZero, mxLayer ); - if( rClip ) // cleanup clipping - CGContextRestoreGState( rCGContext ); - } - else - DBG_ASSERT( mpFrame->mbInitShow, "UpdateWindow called on uneligible graphics" ); -} - -// ----------------------------------------------------------------------- - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/gdi/salmathutils.cxx b/vcl/aqua/source/gdi/salmathutils.cxx deleted file mode 100644 index ec4850c91c71..000000000000 --- a/vcl/aqua/source/gdi/salmathutils.cxx +++ /dev/null @@ -1,154 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salmathutils.hxx" - -#include - -// ======================================================================= - -// ======================================================================= - -#define Swap( x, y ) { x ^= y; y ^= x; x ^= y; } - -// ======================================================================= - -// ======================================================================= - -// Storage free swapping using XOR - -void CSwap ( char &rX, char &rY ) -{ - Swap( rX, rY ); -} // CSwap - -// ----------------------------------------------------------------------- - -// Storage free swapping using XOR - -void UCSwap ( unsigned char &rX, unsigned char &rY ) -{ - Swap( rX, rY ); -} // UCSwap - -// ----------------------------------------------------------------------- - -// Storage free swapping using XOR - -void SSwap ( short &rX, short &rY ) -{ - Swap( rX, rY ); -} // SSwap - -// ----------------------------------------------------------------------- - -// Storage free swapping using XOR - -void USSwap ( unsigned short &rX, unsigned short &rY ) -{ - Swap( rX, rY ); -} // USSwap - -// ----------------------------------------------------------------------- - -// Storage free swapping using XOR - -void LSwap ( long &rX, long &rY ) -{ - Swap( rX, rY ); -} // LSwap - -// ----------------------------------------------------------------------- - -// Storage free swapping using XOR - -void ULSwap ( unsigned long &rX, unsigned long &rY ) -{ - Swap( rX, rY ); -} // ULSwap - -// ======================================================================= - -// ======================================================================= - -// ----------------------------------------------------------------------- -// -// This way of measuring distance is also called the "Manhattan distance." -// Manhattan distance takes advantage of the fact that the sum of the -// lengths of the three components of a 3D vector is a rough approxima- -// tion of the vector's length. -// -// ----------------------------------------------------------------------- - -unsigned long Euclidian2Norm ( const LRectCoorVector pVec ) -{ - unsigned long ndist = 0; - - if ( pVec ) - { - long nDX = 0; - long nDY = 0; - long nDZ = 0; - unsigned long nMax = 0; - unsigned long nMed = 0; - unsigned long nMin = 0; - - // Find |x'-x|, |y'-y|, and |z'-z| from (x,y,z) and (x',y',z') - - nDX = pVec[1].x - pVec[0].x; - nDY = pVec[1].y - pVec[0].y; - nDZ = pVec[1].z - pVec[0].z; - - nMax = (unsigned long)abs( nDX ); - nMed = (unsigned long)abs( nDY ); - nMin = (unsigned long)abs( nDZ ); - - // Sort them (3 compares, 0-3 swaps) - - if ( nMax < nMed ) - { - Swap( nMax, nMed ); - } // if - - if ( nMax < nMin ) - { - Swap( nMax, nMin ); - } // if - - // Approximate Euclidian distance: - // - // d = max + (11/32)*med + (1/4)*min - // - // with +/- 8% error, where the exact formulae for d is - // - // || (x',y',z') - (x,y,z) || = { |x'-x|^2 + |y'-y|^2 + |z'-z|^2 }^(1/2) - - ndist = nMax + ( nMin >> 2UL ) - + ( ( ( nMed << 3UL ) + ( nMed << 1UL ) + nMed ) >> 5UL ); - } // if - - return ndist; -} // RGBDistance - -// ======================================================================= - -// ======================================================================= - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/gdi/salnativewidgets.cxx b/vcl/aqua/source/gdi/salnativewidgets.cxx deleted file mode 100644 index 18ee1cc3ea2e..000000000000 --- a/vcl/aqua/source/gdi/salnativewidgets.cxx +++ /dev/null @@ -1,1462 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include "vcl/salnativewidgets.hxx" -#include "vcl/decoview.hxx" -#include "vcl/svapp.hxx" -#include "vcl/timer.hxx" - -#include "coretext/salgdi.h" -#include "aqua/salnativewidgets.h" -#include "aqua/saldata.hxx" -#include "aqua/salframe.h" - -#include "premac.h" -#include -#include "postmac.h" - -#ifndef NSAppKitVersionNumber10_7 -#define NSAppKitVersionNumber10_7 1138 -#endif - -class AquaBlinker : public Timer -{ - AquaSalFrame* mpFrame; - Rectangle maInvalidateRect; - - AquaBlinker( AquaSalFrame* pFrame, const Rectangle& rRect ) - : mpFrame( pFrame ), maInvalidateRect( rRect ) - { - mpFrame->maBlinkers.push_back( this ); - } - - public: - - static void Blink( AquaSalFrame*, const Rectangle&, int nTimeout = 80 ); - - virtual void Timeout() - { - Stop(); - if( AquaSalFrame::isAlive( mpFrame ) && mpFrame->mbShown ) - { - mpFrame->maBlinkers.remove( this ); - mpFrame->SendPaintEvent( &maInvalidateRect ); - } - delete this; - } -}; - -void AquaBlinker::Blink( AquaSalFrame* pFrame, const Rectangle& rRect, int nTimeout ) -{ - // prevent repeated paints from triggering themselves all the time - for( std::list< AquaBlinker* >::const_iterator it = pFrame->maBlinkers.begin(); - it != pFrame->maBlinkers.end(); ++it ) - { - if( (*it)->maInvalidateRect == rRect ) - return; - } - AquaBlinker* pNew = new AquaBlinker( pFrame, rRect ); - pNew->SetTimeout( nTimeout ); - pNew->Start(); -} - -// Helper returns an HIRect - -static HIRect ImplGetHIRectFromRectangle(Rectangle aRect) -{ - HIRect aHIRect; - aHIRect.origin.x = static_cast(aRect.Left()); - aHIRect.origin.y = static_cast(aRect.Top()); - aHIRect.size.width = static_cast(aRect.GetWidth()); - aHIRect.size.height = static_cast(aRect.GetHeight()); - return aHIRect; -} - -static ThemeButtonValue ImplGetButtonValue( ButtonValue aButtonValue ) -{ - switch( aButtonValue ) - { - case BUTTONVALUE_ON: - return kThemeButtonOn; - break; - - case BUTTONVALUE_OFF: - return kThemeButtonOff; - break; - - case BUTTONVALUE_MIXED: - case BUTTONVALUE_DONTKNOW: - default: - return kThemeButtonMixed; - break; - } -} - -static bool AquaGetScrollRect( /* TODO: int nScreen, */ ControlPart nPart, - const Rectangle& rControlRect, Rectangle& rResultRect ) -{ - bool bRetVal = true; - rResultRect = rControlRect; - - switch( nPart ) - { - case PART_BUTTON_UP: - if (NSAppKitVersionNumber < NSAppKitVersionNumber10_7) - { - if( GetSalData()->mbIsScrollbarDoubleMax ) - rResultRect.Top() = rControlRect.Bottom() - 2*BUTTON_HEIGHT; - rResultRect.Bottom() = rResultRect.Top() + BUTTON_HEIGHT; - } - else - { - rResultRect.Bottom() = rResultRect.Top(); - } - break; - - case PART_BUTTON_DOWN: - if (NSAppKitVersionNumber < NSAppKitVersionNumber10_7) - { - rResultRect.Top() = rControlRect.Bottom() - BUTTON_HEIGHT; - } - else - { - rResultRect.Top() = rResultRect.Bottom(); - } - break; - - case PART_BUTTON_LEFT: - if (NSAppKitVersionNumber < NSAppKitVersionNumber10_7) - { - if( GetSalData()->mbIsScrollbarDoubleMax ) - rResultRect.Left() = rControlRect.Right() - 2*BUTTON_WIDTH; - rResultRect.Right() = rResultRect.Left() + BUTTON_WIDTH; - } - else - { - rResultRect.Right() = rResultRect.Left(); - } - break; - - case PART_BUTTON_RIGHT: - if (NSAppKitVersionNumber < NSAppKitVersionNumber10_7) - { - rResultRect.Left() = rControlRect.Right() - BUTTON_WIDTH; - } - else - { - rResultRect.Left() = rResultRect.Right(); - } - break; - - case PART_TRACK_HORZ_AREA: - if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) - break; - rResultRect.Right() -= BUTTON_WIDTH + 1; - if( GetSalData()->mbIsScrollbarDoubleMax ) - rResultRect.Right() -= BUTTON_WIDTH; - else - rResultRect.Left() += BUTTON_WIDTH + 1; - break; - - case PART_TRACK_VERT_AREA: - if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) - break; - rResultRect.Bottom() -= BUTTON_HEIGHT + 1; - if( GetSalData()->mbIsScrollbarDoubleMax ) - rResultRect.Bottom() -= BUTTON_HEIGHT; - else - rResultRect.Top() += BUTTON_HEIGHT + 1; - break; - case PART_THUMB_HORZ: - if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) - break; - if( GetSalData()->mbIsScrollbarDoubleMax ) - { - rResultRect.Left() += 8; - rResultRect.Right() += 6; - } - else - { - rResultRect.Left() += 4; - rResultRect.Right() += 4; - } - break; - case PART_THUMB_VERT: - if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) - break; - if( GetSalData()->mbIsScrollbarDoubleMax ) - { - rResultRect.Top() += 8; - rResultRect.Bottom() += 8; - } - else - { - rResultRect.Top() += 4; - rResultRect.Bottom() += 4; - } - break; - case PART_TRACK_HORZ_LEFT: - if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) - break; - if( GetSalData()->mbIsScrollbarDoubleMax ) - rResultRect.Right() += 8; - else - rResultRect.Right() += 4; - break; - case PART_TRACK_HORZ_RIGHT: - if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) - break; - if( GetSalData()->mbIsScrollbarDoubleMax ) - rResultRect.Left() += 6; - else - rResultRect.Left() += 4; - break; - case PART_TRACK_VERT_UPPER: - if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) - break; - if( GetSalData()->mbIsScrollbarDoubleMax ) - rResultRect.Bottom() += 8; - else - rResultRect.Bottom() += 4; - break; - case PART_TRACK_VERT_LOWER: - if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) - break; - if( GetSalData()->mbIsScrollbarDoubleMax ) - rResultRect.Top() += 8; - else - rResultRect.Top() += 4; - break; - default: - bRetVal = false; - } - - return bRetVal; -} - -/* - * IsNativeControlSupported() - * -------------------------- - * Returns sal_True if the platform supports native - * drawing of the control defined by nPart. - * - */ -sal_Bool AquaSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart ) -{ - bool bOk = sal_False; - - // Native controls are now defaults - // If you want to disable experimental native controls code, - // just set the environment variable SAL_NO_NWF to something - // and vcl controls will be used as default again. - - switch( nType ) - { - case CTRL_PUSHBUTTON: - case CTRL_RADIOBUTTON: - case CTRL_CHECKBOX: - case CTRL_LISTNODE: - if( nPart == PART_ENTIRE_CONTROL ) - return true; - break; - - case CTRL_SCROLLBAR: - if( nPart == PART_DRAW_BACKGROUND_HORZ || - nPart == PART_DRAW_BACKGROUND_VERT || - nPart == PART_ENTIRE_CONTROL || - nPart == HAS_THREE_BUTTONS ) - return true; - break; - - case CTRL_SLIDER: - if( nPart == PART_TRACK_HORZ_AREA || nPart == PART_TRACK_VERT_AREA ) - return true; - break; - - case CTRL_EDITBOX: - if( nPart == PART_ENTIRE_CONTROL || - nPart == HAS_BACKGROUND_TEXTURE ) - return true; - break; - - case CTRL_MULTILINE_EDITBOX: - if( nPart == PART_ENTIRE_CONTROL || - nPart == HAS_BACKGROUND_TEXTURE ) - return true; - break; - - case CTRL_SPINBOX: - if( nPart == PART_ENTIRE_CONTROL || - nPart == PART_ALL_BUTTONS || - nPart == HAS_BACKGROUND_TEXTURE ) - return true; - break; - - case CTRL_SPINBUTTONS: - return false; - break; - - case CTRL_COMBOBOX: - if( nPart == PART_ENTIRE_CONTROL || - nPart == HAS_BACKGROUND_TEXTURE ) - return true; - break; - - case CTRL_LISTBOX: - if( nPart == PART_ENTIRE_CONTROL || - nPart == PART_WINDOW || - nPart == HAS_BACKGROUND_TEXTURE || - nPart == PART_SUB_EDIT - ) - return true; - break; - - case CTRL_TAB_ITEM: - case CTRL_TAB_PANE: - case CTRL_TAB_BODY: // see vcl/source/window/tabpage.cxx - if( nPart == PART_ENTIRE_CONTROL || - nPart == PART_TABS_DRAW_RTL || - nPart == HAS_BACKGROUND_TEXTURE ) - return true; - break; - - // when PART_BUTTON is used, toolbar icons are not highlighted when mouse rolls over. - // More Aqua compliant - case CTRL_TOOLBAR: - if( nPart == PART_ENTIRE_CONTROL || - nPart == PART_DRAW_BACKGROUND_HORZ || - nPart == PART_DRAW_BACKGROUND_VERT) - return true; - break; - - case CTRL_WINDOW_BACKGROUND: - if ( nPart == PART_BACKGROUND_WINDOW || - nPart == PART_BACKGROUND_DIALOG ) - return true; - break; - - case CTRL_MENUBAR: - if( nPart == PART_ENTIRE_CONTROL ) - return true; - break; - - case CTRL_TOOLTIP: // ** TO DO - break; - - case CTRL_MENU_POPUP: - if( nPart == PART_ENTIRE_CONTROL || - nPart == PART_MENU_ITEM || - nPart == PART_MENU_ITEM_CHECK_MARK || - nPart == PART_MENU_ITEM_RADIO_MARK) - return true; - break; - case CTRL_PROGRESS: - case CTRL_INTROPROGRESS: - if( nPart == PART_ENTIRE_CONTROL ) - return true; - break; - case CTRL_FRAME: - if( nPart == PART_BORDER ) - return true; - break; - case CTRL_LISTNET: - if( nPart == PART_ENTIRE_CONTROL ) - return true; - break; - } - - return bOk; -} - -/* - * HitTestNativeControl() - * - * If the return value is sal_True, bIsInside contains information whether - * aPos was or was not inside the native widget specified by the - * nType/nPart combination. - */ -sal_Bool AquaSalGraphics::hitTestNativeControl( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, - const Point& rPos, sal_Bool& rIsInside ) -{ - if ( nType == CTRL_SCROLLBAR ) - { - Rectangle aRect; - bool bValid = AquaGetScrollRect( /* TODO: m_nScreen */ nPart, rControlRegion, aRect ); - rIsInside = bValid ? aRect.IsInside( rPos ) : sal_False; - if( NSAppKitVersionNumber < NSAppKitVersionNumber10_7 && - GetSalData()->mbIsScrollbarDoubleMax ) - { - // in double max mode the actual trough is a little smaller than the track - // there is some visual filler that is not sensitive - if( bValid && rIsInside ) - { - if( nPart == PART_TRACK_HORZ_AREA ) - { - // the left 4 pixels are not hit sensitive - if( rPos.X() - aRect.Left() < 4 ) - rIsInside = sal_False; - } - else if( nPart == PART_TRACK_VERT_AREA ) - { - // the top 4 pixels are not hit sensitive - if( rPos.Y() - aRect.Top() < 4 ) - rIsInside = sal_False; - } - } - } - return bValid; - } // CTRL_SCROLLBAR - - return sal_False; -} - -/* - kThemeStateInactive = 0, - kThemeStateActive = 1, - kThemeStatePressed = 2, - kThemeStateRollover = 6, - kThemeStateUnavailable = 7, - kThemeStateUnavailableInactive = 8 - kThemeStatePressedUp = 2, - kThemeStatePressedDown = 3 - -#define CTRL_STATE_ENABLED 0x0001 -#define CTRL_STATE_FOCUSED 0x0002 -#define CTRL_STATE_PRESSED 0x0004 -#define CTRL_STATE_ROLLOVER 0x0008 -#define CTRL_STATE_HIDDEN 0x0010 -#define CTRL_STATE_DEFAULT 0x0020 -#define CTRL_STATE_SELECTED 0x0040 -#define CTRL_CACHING_ALLOWED 0x8000 // set when the control is completely visible (i.e. not clipped) -*/ -UInt32 AquaSalGraphics::getState( ControlState nState ) -{ - const bool bDrawActive = mpFrame ? ([mpFrame->getNSWindow() isKeyWindow] ? true : false) : true; - if( (nState & CTRL_STATE_ENABLED) == 0 || ! bDrawActive ) - { - if( (nState & CTRL_STATE_HIDDEN) == 0 ) - return kThemeStateInactive; - else - return kThemeStateUnavailableInactive; - } - - if( (nState & CTRL_STATE_HIDDEN) != 0 ) - return kThemeStateUnavailable; - - if( (nState & CTRL_STATE_PRESSED) != 0 ) - return kThemeStatePressed; - - return kThemeStateActive; -} - -UInt32 AquaSalGraphics::getTrackState( ControlState nState ) -{ - const bool bDrawActive = mpFrame ? ([mpFrame->getNSWindow() isKeyWindow] ? true : false) : true; - if( (nState & CTRL_STATE_ENABLED) == 0 || ! bDrawActive ) - return kThemeTrackInactive; - - return kThemeTrackActive; -} - -/* - * DrawNativeControl() - * - * Draws the requested control described by nPart/nState. - * - * rControlRegion: The bounding region of the complete control in VCL frame coordinates. - * aValue: An optional value (tristate/numerical/string) - * aCaption: A caption or title string (like button text etc) - */ -sal_Bool AquaSalGraphics::drawNativeControl(ControlType nType, - ControlPart nPart, - const Rectangle& rControlRegion, - ControlState nState, - const ImplControlValue& aValue, - const OUString& ) -{ - sal_Bool bOK = sal_False; - - if( ! CheckContext() ) - return false; - - CGContextSaveGState( mrContext ); - - Rectangle buttonRect = rControlRegion; - HIRect rc = ImplGetHIRectFromRectangle(buttonRect); - - switch( nType ) - { - - case CTRL_COMBOBOX: - if ( nPart == HAS_BACKGROUND_TEXTURE || - nPart == PART_ENTIRE_CONTROL ) - { - HIThemeButtonDrawInfo aComboInfo; - aComboInfo.version = 0; - aComboInfo.kind = kThemeComboBox; - aComboInfo.state = getState( nState ); - aComboInfo.value = kThemeButtonOn; - aComboInfo.adornment = kThemeAdornmentNone; - - if( (nState & CTRL_STATE_FOCUSED) != 0 ) - aComboInfo.adornment |= kThemeAdornmentFocus; - - HIThemeDrawButton(&rc, &aComboInfo, mrContext, kHIThemeOrientationNormal,&rc); - bOK = true; - } - break; - - case CTRL_TOOLBAR: - { - HIThemeMenuItemDrawInfo aMenuItemDrawInfo; - aMenuItemDrawInfo.version = 0; - aMenuItemDrawInfo.state = kThemeMenuActive; - aMenuItemDrawInfo.itemType = kThemeMenuItemHierBackground; - HIThemeDrawMenuItem(&rc,&rc,&aMenuItemDrawInfo,mrContext,kHIThemeOrientationNormal,NULL); - bOK = true; - } - break; - - case CTRL_WINDOW_BACKGROUND: - { - HIThemeBackgroundDrawInfo aThemeBackgroundInfo; - aThemeBackgroundInfo.version = 0; - aThemeBackgroundInfo.state = getState( nState ); - aThemeBackgroundInfo.kind = kThemeBrushDialogBackgroundActive; - // FIXME: without this magical offset there is a 2 pixel black border on the right and bottom - rc.size.width += 2; - rc.size.height += 2; - - HIThemeApplyBackground( &rc, &aThemeBackgroundInfo, mrContext, kHIThemeOrientationNormal); - CGContextFillRect( mrContext, rc ); - bOK = true; - } - break; - - case CTRL_MENUBAR: - case CTRL_MENU_POPUP: - { - if ((nPart == PART_ENTIRE_CONTROL) || (nPart == PART_MENU_ITEM )|| (nPart == HAS_BACKGROUND_TEXTURE )) - { - // FIXME: without this magical offset there is a 2 pixel black border on the right - rc.size.width += 2; - - HIThemeMenuDrawInfo aMenuInfo; - aMenuInfo.version = 0; - aMenuInfo.menuType = kThemeMenuTypePullDown; - - HIThemeMenuItemDrawInfo aMenuItemDrawInfo; - // the Aqua grey theme when the item is selected is drawn here. - aMenuItemDrawInfo.itemType = kThemeMenuItemPlain; - - if ((nPart == PART_MENU_ITEM ) && (nState & CTRL_STATE_SELECTED)) - { - // the blue theme when the item is selected is drawn here. - aMenuItemDrawInfo.state = kThemeMenuSelected; - } - else - { - // normal color for non selected item - aMenuItemDrawInfo.state = kThemeMenuActive; - } - - // repaints the background of the pull down menu - HIThemeDrawMenuBackground(&rc,&aMenuInfo,mrContext,kHIThemeOrientationNormal); - - // repaints the item either blue (selected) and/or Aqua grey (active only) - HIThemeDrawMenuItem(&rc,&rc,&aMenuItemDrawInfo,mrContext,kHIThemeOrientationNormal,&rc); - - bOK = true; - } - else if(( nPart == PART_MENU_ITEM_CHECK_MARK )||( nPart == PART_MENU_ITEM_RADIO_MARK )) { - if( nState & CTRL_STATE_PRESSED ) {//checked, else it is not displayed (see vcl/source/window/menu.cxx) - HIThemeTextInfo aTextInfo; - aTextInfo.version = 0; - aTextInfo.state = ((nState & CTRL_STATE_ENABLED)==0) ? kThemeStateInactive: kThemeStateActive; - aTextInfo.fontID = kThemeMenuItemMarkFont; - aTextInfo.horizontalFlushness=kHIThemeTextHorizontalFlushCenter; - aTextInfo.verticalFlushness=kHIThemeTextVerticalFlushTop; - aTextInfo.options=kHIThemeTextBoxOptionNone; - aTextInfo.truncationPosition=kHIThemeTextTruncationNone; - //aTextInfo.truncationMaxLines unused because of kHIThemeTextTruncationNone - - if( nState & CTRL_STATE_SELECTED) aTextInfo.state = kThemeStatePressed; //item highlighted - - UniChar mark=( nPart == PART_MENU_ITEM_CHECK_MARK ) ? kCheckUnicode: kBulletUnicode;//0x2713; - CFStringRef cfString = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, &mark, 1, kCFAllocatorNull); - HIThemeDrawTextBox(cfString, &rc, &aTextInfo, mrContext, kHIThemeOrientationNormal); - if (cfString) - CFRelease(cfString); - - bOK = true; - } - } - } - break; - - case CTRL_PUSHBUTTON: - { - // [ FIXME] : instead of use a value, vcl can retrieve corect values on the fly (to be implemented) - const int PB_Mini_Height = 15; - const int PB_Norm_Height = 21; - - HIThemeButtonDrawInfo aPushInfo; - aPushInfo.version = 0; - - // no animation - aPushInfo.animation.time.start = 0; - aPushInfo.animation.time.current = 0; - PushButtonValue* pPBVal = aValue.getType() == CTRL_PUSHBUTTON ? (PushButtonValue*)&aValue : NULL; - int nPaintHeight = static_cast(rc.size.height); - - if( pPBVal && pPBVal->mbBevelButton ) - { - aPushInfo.kind = kThemeRoundedBevelButton; - } - else if( rc.size.height <= PB_Norm_Height ) - { - aPushInfo.kind = kThemePushButtonMini; - nPaintHeight = PB_Mini_Height; - } - else if( pPBVal->mbSingleLine || rc.size.height < (PB_Norm_Height + PB_Norm_Height/2) ) - { - aPushInfo.kind = kThemePushButtonNormal; - nPaintHeight = PB_Norm_Height; - - // avoid clipping when focused - rc.origin.x += FOCUS_RING_WIDTH/2; - rc.size.width -= FOCUS_RING_WIDTH; - - if( (nState & CTRL_STATE_DEFAULT) != 0 ) - { - AquaBlinker::Blink( mpFrame, buttonRect ); - // show correct animation phase - aPushInfo.animation.time.current = CFAbsoluteTimeGetCurrent(); - } - } - else - aPushInfo.kind = kThemeBevelButton; - - // translate the origin for controls with fixed paint height - // so content ends up somewhere sensible - int delta_y = static_cast(rc.size.height) - nPaintHeight; - rc.origin.y += delta_y/2; - - aPushInfo.state = getState( nState ); - aPushInfo.value = ImplGetButtonValue( aValue.getTristateVal() ); - - aPushInfo.adornment = (( nState & CTRL_STATE_DEFAULT ) != 0) ? - kThemeAdornmentDefault : - kThemeAdornmentNone; - if( (nState & CTRL_STATE_FOCUSED) != 0 ) - aPushInfo.adornment |= kThemeAdornmentFocus; - - HIThemeDrawButton( &rc, &aPushInfo, mrContext, kHIThemeOrientationNormal, NULL ); - bOK = true; - } - break; - - case CTRL_RADIOBUTTON: - case CTRL_CHECKBOX: - { - HIThemeButtonDrawInfo aInfo; - aInfo.version = 0; - switch( nType ) - { - case CTRL_RADIOBUTTON: if(rc.size.width >= BUTTON_HEIGHT) aInfo.kind = kThemeRadioButton; - else aInfo.kind = kThemeSmallRadioButton; - break; - case CTRL_CHECKBOX: if(rc.size.width >= BUTTON_HEIGHT) aInfo.kind = kThemeCheckBox; - else aInfo.kind = kThemeSmallCheckBox; - break; - } - - aInfo.state = getState( nState ); - - ButtonValue aButtonValue = aValue.getTristateVal(); - aInfo.value = ImplGetButtonValue( aButtonValue ); - - aInfo.adornment = (( nState & CTRL_STATE_DEFAULT ) != 0) ? - kThemeAdornmentDefault : - kThemeAdornmentNone; - if( (nState & CTRL_STATE_FOCUSED) != 0 ) - aInfo.adornment |= kThemeAdornmentFocus; - HIThemeDrawButton( &rc, &aInfo, mrContext, kHIThemeOrientationNormal, NULL ); - bOK = true; - } - break; - - case CTRL_LISTNODE: - { - ButtonValue aButtonValue = aValue.getTristateVal(); - - if( Application::GetSettings().GetLayoutRTL() && aButtonValue == BUTTONVALUE_OFF ) - { - // FIXME: a value of kThemeDisclosureLeft - // should draw a theme compliant left disclosure triangle - // sadly this does not seem to work, so we'll draw a left - // grey equilateral triangle here ourselves. - // Perhaps some other HIThemeButtonDrawInfo setting would do the trick ? - - CGContextSetShouldAntialias( mrContext, true ); - CGFloat aGrey[] = { 0.45, 0.45, 0.45, 1.0 }; - CGContextSetFillColor( mrContext, aGrey ); - CGContextBeginPath( mrContext ); - float x = rc.origin.x + rc.size.width; - float y = rc.origin.y; - CGContextMoveToPoint( mrContext, x, y ); - y += rc.size.height; - CGContextAddLineToPoint( mrContext, x, y ); - x -= rc.size.height * 0.866; // cos( 30 degree ) is approx. 0.866 - y -= rc.size.height/2; - CGContextAddLineToPoint( mrContext, x, y ); - CGContextDrawPath( mrContext, kCGPathEOFill ); - } - else - { - HIThemeButtonDrawInfo aInfo; - aInfo.version = 0; - aInfo.kind = kThemeDisclosureTriangle; - aInfo.value = kThemeDisclosureRight; - aInfo.state = getState( nState ); - - aInfo.adornment = kThemeAdornmentNone; - - switch( aButtonValue ) { - case BUTTONVALUE_ON: aInfo.value = kThemeDisclosureDown;//expanded - break; - case BUTTONVALUE_OFF: - // FIXME: this should have drawn a theme compliant disclosure triangle - // (see above) - if( Application::GetSettings().GetLayoutRTL() ) - { - aInfo.value = kThemeDisclosureLeft;//collapsed, RTL - } - break; - case BUTTONVALUE_DONTKNOW: //what to do? - default: - break; - } - - HIThemeDrawButton( &rc, &aInfo, mrContext, kHIThemeOrientationNormal, NULL ); - } - bOK = true; - } - break; - - case CTRL_PROGRESS: - case CTRL_INTROPROGRESS: - { - long nProgressWidth = aValue.getNumericVal(); - HIThemeTrackDrawInfo aTrackInfo; - aTrackInfo.version = 0; - aTrackInfo.kind = (rc.size.height > 10) ? kThemeProgressBarLarge : kThemeProgressBarMedium; - aTrackInfo.bounds = rc; - aTrackInfo.min = 0; - aTrackInfo.max = static_cast(rc.size.width); - aTrackInfo.value = nProgressWidth; - aTrackInfo.reserved = 0; - aTrackInfo.bounds.origin.y -= 2; // FIXME: magic for shadow - aTrackInfo.bounds.size.width -= 2; // FIXME: magic for shadow - aTrackInfo.attributes = kThemeTrackHorizontal; - if( Application::GetSettings().GetLayoutRTL() ) - aTrackInfo.attributes |= kThemeTrackRightToLeft; - aTrackInfo.enableState = getTrackState( nState ); - // the intro bitmap never gets key anyway; we want to draw that enabled - if( nType == CTRL_INTROPROGRESS ) - aTrackInfo.enableState = kThemeTrackActive; - aTrackInfo.filler1 = 0; - aTrackInfo.trackInfo.progress.phase = static_cast(CFAbsoluteTimeGetCurrent()*10.0); - - HIThemeDrawTrack( &aTrackInfo, NULL, mrContext, kHIThemeOrientationNormal ); - bOK = true; - } - break; - - case CTRL_SLIDER: - { - SliderValue* pSLVal = (SliderValue*)&aValue; - - HIThemeTrackDrawInfo aTrackDraw; - aTrackDraw.kind = kThemeSliderMedium; - if( nPart == PART_TRACK_HORZ_AREA || nPart == PART_TRACK_VERT_AREA ) - { - aTrackDraw.bounds = rc; - aTrackDraw.min = pSLVal->mnMin; - aTrackDraw.max = pSLVal->mnMax; - aTrackDraw.value = pSLVal->mnCur; - aTrackDraw.reserved = 0; - aTrackDraw.attributes = kThemeTrackShowThumb; - if( nPart == PART_TRACK_HORZ_AREA ) - aTrackDraw.attributes |= kThemeTrackHorizontal; - aTrackDraw.enableState = (nState & CTRL_STATE_ENABLED) - ? kThemeTrackActive : kThemeTrackInactive; - - SliderTrackInfo aSlideInfo; - aSlideInfo.thumbDir = kThemeThumbUpward; - aSlideInfo.pressState = 0; - aTrackDraw.trackInfo.slider = aSlideInfo; - - HIThemeDrawTrack( &aTrackDraw, NULL, mrContext, kHIThemeOrientationNormal ); - bOK = true; - } - } - break; - - case CTRL_SCROLLBAR: - { - const ScrollbarValue* pScrollbarVal = (aValue.getType() == CTRL_SCROLLBAR) ? static_cast(&aValue) : NULL; - - if( nPart == PART_DRAW_BACKGROUND_VERT || - nPart == PART_DRAW_BACKGROUND_HORZ ) - { - HIThemeTrackDrawInfo aTrackDraw; - aTrackDraw.kind = kThemeMediumScrollBar; - // FIXME: the scrollbar length must be adjusted - if (nPart == PART_DRAW_BACKGROUND_VERT) - rc.size.height += 2; - else - rc.size.width += 2; - - aTrackDraw.bounds = rc; - aTrackDraw.min = pScrollbarVal->mnMin; - aTrackDraw.max = pScrollbarVal->mnMax - pScrollbarVal->mnVisibleSize; - aTrackDraw.value = pScrollbarVal->mnCur; - aTrackDraw.reserved = 0; - aTrackDraw.attributes = kThemeTrackShowThumb; - if( nPart == PART_DRAW_BACKGROUND_HORZ ) - aTrackDraw.attributes |= kThemeTrackHorizontal; - aTrackDraw.enableState = getTrackState( nState ); - - ScrollBarTrackInfo aScrollInfo; - aScrollInfo.viewsize = pScrollbarVal->mnVisibleSize; - aScrollInfo.pressState = 0; - - if ( pScrollbarVal->mnButton1State & CTRL_STATE_ENABLED ) - { - if ( pScrollbarVal->mnButton1State & CTRL_STATE_PRESSED ) - aScrollInfo.pressState = kThemeTopOutsideArrowPressed; - } - - if ( pScrollbarVal->mnButton2State & CTRL_STATE_ENABLED ) - { - if ( pScrollbarVal->mnButton2State & CTRL_STATE_PRESSED ) - aScrollInfo.pressState = kThemeBottomOutsideArrowPressed; - } - - if ( pScrollbarVal->mnThumbState & CTRL_STATE_ENABLED ) - { - if ( pScrollbarVal->mnThumbState & CTRL_STATE_PRESSED ) - aScrollInfo.pressState = kThemeThumbPressed; - } - - aTrackDraw.trackInfo.scrollbar = aScrollInfo; - - HIThemeDrawTrack( &aTrackDraw, NULL, mrContext, kHIThemeOrientationNormal ); - bOK = true; - } - } - break; - - case CTRL_TAB_PANE: - { - HIThemeTabPaneDrawInfo aTabPaneDrawInfo; - aTabPaneDrawInfo.version = 1; - aTabPaneDrawInfo.state = kThemeStateActive; - aTabPaneDrawInfo.direction=kThemeTabNorth; - aTabPaneDrawInfo.size=kHIThemeTabSizeNormal; - aTabPaneDrawInfo.kind=kHIThemeTabKindNormal; - - //the border is outside the rect rc for Carbon - //but for VCL it should be inside - rc.origin.x+=1; - rc.origin.y-=TAB_HEIGHT_NORMAL/2; - rc.size.height+=TAB_HEIGHT_NORMAL/2; - rc.size.width-=2; - - HIThemeDrawTabPane(&rc, &aTabPaneDrawInfo, mrContext, kHIThemeOrientationNormal); - - bOK = true; - } - break; - - case CTRL_TAB_ITEM: - { - HIThemeTabDrawInfo aTabItemDrawInfo; - aTabItemDrawInfo.version=1; - aTabItemDrawInfo.style=kThemeTabNonFront; - aTabItemDrawInfo.direction=kThemeTabNorth; - aTabItemDrawInfo.size=kHIThemeTabSizeNormal; - aTabItemDrawInfo.adornment=kHIThemeTabAdornmentTrailingSeparator; - //State - if(nState & CTRL_STATE_SELECTED) { - aTabItemDrawInfo.style=kThemeTabFront; - } - if(nState & CTRL_STATE_FOCUSED) { - aTabItemDrawInfo.adornment|=kHIThemeTabAdornmentFocus; - } - - //first, last or middle tab - aTabItemDrawInfo.position=kHIThemeTabPositionMiddle; - - TabitemValue* pTabValue = (TabitemValue *) &aValue; - unsigned int nAlignment = pTabValue->mnAlignment; - //TABITEM_LEFTALIGNED (and TABITEM_RIGHTALIGNED) for the leftmost (or rightmost) tab - //when there are several lines of tabs because there is only one first tab and one - //last tab and TABITEM_FIRST_IN_GROUP (and TABITEM_LAST_IN_GROUP) because when the - //line width is different from window width, there may not be TABITEM_RIGHTALIGNED - if( ( (nAlignment & TABITEM_LEFTALIGNED)&&(nAlignment & TABITEM_RIGHTALIGNED) ) || - ( (nAlignment & TABITEM_FIRST_IN_GROUP)&&(nAlignment & TABITEM_LAST_IN_GROUP) ) - ) //tab alone - aTabItemDrawInfo.position=kHIThemeTabPositionOnly; - else if((nAlignment & TABITEM_LEFTALIGNED)||(nAlignment & TABITEM_FIRST_IN_GROUP)) - aTabItemDrawInfo.position=kHIThemeTabPositionFirst; - else if((nAlignment & TABITEM_RIGHTALIGNED)||(nAlignment & TABITEM_LAST_IN_GROUP)) - aTabItemDrawInfo.position=kHIThemeTabPositionLast; - - //support for RTL - //see issue 79748 - if( Application::GetSettings().GetLayoutRTL() ) { - if( aTabItemDrawInfo.position == kHIThemeTabPositionFirst ) - aTabItemDrawInfo.position = kHIThemeTabPositionLast; - else if( aTabItemDrawInfo.position == kHIThemeTabPositionLast ) - aTabItemDrawInfo.position = kHIThemeTabPositionFirst; - } - - rc.size.width+=2;//because VCL has 2 empty pixels between 2 tabs - rc.origin.x-=1; - - HIThemeDrawTab(&rc, &aTabItemDrawInfo, mrContext, kHIThemeOrientationNormal, &rc ); - - bOK=true; - } - break; - - case CTRL_LISTBOX: - switch( nPart) - { - case PART_ENTIRE_CONTROL: - case PART_BUTTON_DOWN: - { - HIThemeButtonDrawInfo aListInfo; - aListInfo.version = 0; - aListInfo.kind = kThemePopupButton; - aListInfo.state = getState( nState );//kThemeStateInactive -> greyed - aListInfo.value = kThemeButtonOn; - - aListInfo.adornment = kThemeAdornmentDefault; - if( (nState & CTRL_STATE_FOCUSED) != 0 ) - aListInfo.adornment |= kThemeAdornmentFocus; - - HIThemeDrawButton(&rc, &aListInfo, mrContext, kHIThemeOrientationNormal,&rc); - bOK = true; - break; - } - case PART_WINDOW: - { - HIThemeFrameDrawInfo aTextDrawInfo; - aTextDrawInfo.version=0; - aTextDrawInfo.kind=kHIThemeFrameTextFieldSquare; - aTextDrawInfo.state=getState( nState ); - aTextDrawInfo.isFocused=false; - - rc.size.width+=1;//else there's a white space because aqua theme hasn't a 3D border - rc.size.height+=1; - HIThemeDrawFrame(&rc, &aTextDrawInfo, mrContext, kHIThemeOrientationNormal); - - if(nState & CTRL_STATE_FOCUSED) HIThemeDrawFocusRect(&rc, true, mrContext, kHIThemeOrientationNormal); - - bOK=true; - break; - } - } - break; - - case CTRL_EDITBOX: - case CTRL_MULTILINE_EDITBOX: - { - HIThemeFrameDrawInfo aTextDrawInfo; - aTextDrawInfo.version=0; - aTextDrawInfo.kind=kHIThemeFrameTextFieldSquare; - aTextDrawInfo.state=getState( nState ); - aTextDrawInfo.isFocused=false; - - rc.size.width += 1; // else there may be a white space because aqua theme hasn't a 3D border - // change rc so that the frame will encompass only the content region - // see counterpart in GetNativeControlRegion - rc.size.width += 2; - rc.size.height += 2; - - //CGContextSetFillColorWithColor - CGContextFillRect (mrContext, CGRectMake(rc.origin.x, rc.origin.y, rc.size.width, rc.size.height)); - //fill a white background, because drawFrame only draws the border - - HIThemeDrawFrame(&rc, &aTextDrawInfo, mrContext, kHIThemeOrientationNormal); - - if(nState & CTRL_STATE_FOCUSED) HIThemeDrawFocusRect(&rc, true, mrContext, kHIThemeOrientationNormal); - - bOK=true; - } - break; - - case CTRL_SPINBOX: - { - if(nPart == PART_ENTIRE_CONTROL) - { - //text field: - HIThemeFrameDrawInfo aTextDrawInfo; - aTextDrawInfo.version=0; - aTextDrawInfo.kind=kHIThemeFrameTextFieldSquare; - aTextDrawInfo.state=getState( nState ); - aTextDrawInfo.isFocused=false; - - //rc.size.width contains the full size of the spinbox ie textfield + button - //so we remove the button width and the space between the button and the textfield - rc.size.width -= SPIN_BUTTON_SPACE + SPIN_BUTTON_WIDTH + 2*FOCUS_RING_WIDTH; - rc.origin.x += FOCUS_RING_WIDTH; - rc.origin.y += FOCUS_RING_WIDTH; - - //CGContextSetFillColorWithColor - CGContextFillRect (mrContext, CGRectMake(rc.origin.x, rc.origin.y, rc.size.width, rc.size.height)); - //fill a white background, because drawFrame only draws the border - - HIThemeDrawFrame(&rc, &aTextDrawInfo, mrContext, kHIThemeOrientationNormal); - - if(nState & CTRL_STATE_FOCUSED) HIThemeDrawFocusRect(&rc, true, mrContext, kHIThemeOrientationNormal); - - //buttons: - const SpinbuttonValue* pSpinButtonVal = (aValue.getType() == CTRL_SPINBUTTONS) ? static_cast(&aValue) : NULL; - ControlState nUpperState = CTRL_STATE_ENABLED;//state of the upper button - ControlState nLowerState = CTRL_STATE_ENABLED;//and of the lower button - if(pSpinButtonVal) {//pSpinButtonVal is sometimes null - nUpperState = (ControlState) pSpinButtonVal->mnUpperState; - nLowerState = (ControlState) pSpinButtonVal->mnLowerState; - - HIThemeButtonDrawInfo aSpinInfo; - aSpinInfo.kind = kThemeIncDecButton; - aSpinInfo.state = kThemeStateActive; - if(nUpperState & CTRL_STATE_PRESSED) - aSpinInfo.state = kThemeStatePressedUp; - else if(nLowerState & CTRL_STATE_PRESSED) - aSpinInfo.state = kThemeStatePressedDown; - else if((nUpperState & ~CTRL_STATE_ENABLED)||(nLowerState & ~CTRL_STATE_ENABLED)) - aSpinInfo.state = kThemeStateInactive; - else if((nUpperState & CTRL_STATE_ROLLOVER)||(nLowerState & CTRL_STATE_ROLLOVER)) - aSpinInfo.state = kThemeStateRollover; - - Rectangle aSpinRect( pSpinButtonVal->maUpperRect ); - aSpinRect.Union( pSpinButtonVal->maLowerRect ); - HIRect buttonRc = ImplGetHIRectFromRectangle(aSpinRect); - - // FIXME: without this fuzz factor there is some unwanted clipping - if( Application::GetSettings().GetLayoutRTL() ) - buttonRc.origin.x -= FOCUS_RING_WIDTH - CLIP_FUZZ; - else - buttonRc.origin.x += FOCUS_RING_WIDTH + CLIP_FUZZ; - - switch( aValue.getTristateVal() ) - { - case BUTTONVALUE_ON: aSpinInfo.value = kThemeButtonOn; - break; - case BUTTONVALUE_OFF: aSpinInfo.value = kThemeButtonOff; - break; - case BUTTONVALUE_MIXED: - case BUTTONVALUE_DONTKNOW: - default: aSpinInfo.value = kThemeButtonMixed; - break; - } - - aSpinInfo.adornment = ( ((nUpperState & CTRL_STATE_DEFAULT) != 0 ) || - ((nLowerState & CTRL_STATE_DEFAULT) != 0 )) ? - kThemeAdornmentDefault : - kThemeAdornmentNone; - if( ((nUpperState & CTRL_STATE_FOCUSED) != 0 ) || ((nLowerState & CTRL_STATE_FOCUSED) != 0 )) - aSpinInfo.adornment |= kThemeAdornmentFocus; - - HIThemeDrawButton( &buttonRc, &aSpinInfo, mrContext, kHIThemeOrientationNormal, NULL ); - } - - bOK=true; - } - - } - break; - - case CTRL_FRAME: - { - sal_uInt16 nStyle = aValue.getNumericVal(); - if( nPart == PART_BORDER ) { - if(!( nStyle & FRAME_DRAW_MENU ) && !(nStyle & FRAME_DRAW_WINDOWBORDER) ) - { - // #i84756# strange effects start to happen when HIThemeDrawFrame - // meets the border of the window. These can be avoided by clipping - // to the boundary of the frame - if( rc.origin.y + rc.size.height >= mpFrame->maGeometry.nHeight-3 ) - { - CGMutablePathRef rPath = CGPathCreateMutable(); - CGPathAddRect( rPath, NULL, CGRectMake( 0, 0, mpFrame->maGeometry.nWidth-1, mpFrame->maGeometry.nHeight-1 ) ); - - CGContextBeginPath( mrContext ); - CGContextAddPath( mrContext, rPath ); - CGContextClip( mrContext ); - CGPathRelease( rPath ); - } - - HIThemeFrameDrawInfo aTextDrawInfo; - aTextDrawInfo.version=0; - aTextDrawInfo.kind=kHIThemeFrameListBox; - aTextDrawInfo.state=kThemeStateActive; - aTextDrawInfo.isFocused=false; - - HIThemeDrawFrame(&rc, &aTextDrawInfo, mrContext, kHIThemeOrientationNormal); - - bOK=true; - } - } - } - break; - - case CTRL_LISTNET: - { - //do nothing as there isn't net for listviews on macos - bOK=true; - } - break; - - } - - CGContextRestoreGState( mrContext ); - - /* #i90291# in most cases invalidating the whole control region instead - of just the unclipped part of it is sufficient (and probably faster). - However for the window background we should not unnecessarily enlarge - the really changed rectangle since the difference is usually quite high - (the background is always drawn as a whole since we don't know anything - about its possible contents) - */ - if( nType == CTRL_WINDOW_BACKGROUND ) - { - CGRect aRect = { { 0, 0 }, { 0, 0 } }; - if( mxClipPath ) - aRect = CGPathGetBoundingBox( mxClipPath ); - if( aRect.size.width != 0 && aRect.size.height != 0 ) - buttonRect.Intersection( Rectangle( Point( static_cast(aRect.origin.x), - static_cast(aRect.origin.y) ), - Size( static_cast(aRect.size.width), - static_cast(aRect.size.height) ) ) ); - } - - RefreshRect( buttonRect.Left(), buttonRect.Top(), buttonRect.GetWidth(), buttonRect.GetHeight() ); - - return bOK; -} - -/* - * GetNativeControlRegion() - * - * If the return value is sal_True, rNativeBoundingRegion - * contains the true bounding region covered by the control - * including any adornment, while rNativeContentRegion contains the area - * within the control that can be safely drawn into without drawing over - * the borders of the control. - * - * rControlRegion: The bounding region of the control in VCL frame coordinates. - * aValue: An optional value (tristate/numerical/string) - * aCaption: A caption or title string (like button text etc) - */ -sal_Bool AquaSalGraphics::getNativeControlRegion( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, ControlState /*nState*/, - const ImplControlValue& aValue, const OUString&, - Rectangle &rNativeBoundingRegion, Rectangle &rNativeContentRegion ) - -{ - sal_Bool toReturn = sal_False; - - Rectangle aCtrlBoundRect( rControlRegion ); - short x = aCtrlBoundRect.Left(); - short y = aCtrlBoundRect.Top(); - short w, h; - - sal_uInt8 nBorderCleanup = 0; - - switch (nType) - { - case CTRL_SLIDER: - { - if( nPart == PART_THUMB_HORZ ) - { - w = 19; // taken from HIG - h = aCtrlBoundRect.GetHeight(); - rNativeBoundingRegion = rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h ) ); - toReturn = true; - } - else if( nPart == PART_THUMB_VERT ) - { - w = aCtrlBoundRect.GetWidth(); - h = 18; // taken from HIG - rNativeBoundingRegion = rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h ) ); - toReturn = true; - } - } - break; - - case CTRL_SCROLLBAR: - { - Rectangle aRect; - if( AquaGetScrollRect( /* m_nScreen */ nPart, aCtrlBoundRect, aRect ) ) - { - toReturn = sal_True; - rNativeBoundingRegion = aRect; - rNativeContentRegion = aRect; - } - } - break; - - case CTRL_PUSHBUTTON: - case CTRL_RADIOBUTTON: - case CTRL_CHECKBOX: - { - if ( nType == CTRL_PUSHBUTTON ) - { - w = aCtrlBoundRect.GetWidth(); - h = aCtrlBoundRect.GetHeight(); - } - else - { - // checkbox and radio borders need cleanup after unchecking them - nBorderCleanup = 4; - - // TEXT_SEPARATOR to respect Aqua HIG - w = BUTTON_WIDTH + TEXT_SEPARATOR; - h = BUTTON_HEIGHT; - - } - - rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h + nBorderCleanup) ); - rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h ) ); - - toReturn = sal_True; - } - break; - case CTRL_PROGRESS: - { - Rectangle aRect( aCtrlBoundRect ); - if( aRect.GetHeight() < 16 ) - aRect.Bottom() = aRect.Top() + 9; // values taken from HIG for medium progress - else - aRect.Bottom() = aRect.Top() + 15; // values taken from HIG for large progress - rNativeBoundingRegion = aRect; - rNativeContentRegion = aRect; - toReturn = sal_True; - } - break; - - case CTRL_INTROPROGRESS: - { - Rectangle aRect( aCtrlBoundRect ); - aRect.Bottom() = aRect.Top() + INTRO_PROGRESS_HEIGHT; // values taken from HIG for medium progress - rNativeBoundingRegion = aRect; - rNativeContentRegion = aRect; - toReturn = sal_True; - } - break; - - case CTRL_TAB_ITEM: - - w = aCtrlBoundRect.GetWidth() + 2*TAB_TEXT_OFFSET - 2*VCL_TAB_TEXT_OFFSET; - -#ifdef OLD_TAB_STYLE - h = TAB_HEIGHT_NORMAL; -#else - h = TAB_HEIGHT_NORMAL+2; -#endif - rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h ) ); - rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h ) ); - - toReturn = sal_True; - - break; - - case CTRL_EDITBOX: - { - w = aCtrlBoundRect.GetWidth(); - if( w < 3+2*FOCUS_RING_WIDTH ) - w = 3+2*FOCUS_RING_WIDTH; - h = TEXT_EDIT_HEIGHT_NORMAL+2*FOCUS_RING_WIDTH; - if( h < aCtrlBoundRect.GetHeight() ) - h = aCtrlBoundRect.GetHeight(); - - rNativeContentRegion = Rectangle( Point( x+FOCUS_RING_WIDTH, y+FOCUS_RING_WIDTH ), Size( w-2*(FOCUS_RING_WIDTH+1), h-2*(FOCUS_RING_WIDTH+1) ) ); - rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h ) ); - - toReturn = sal_True; - } - break; - case CTRL_LISTBOX: - case CTRL_COMBOBOX: - { - if( nPart == PART_ENTIRE_CONTROL ) - { - w = aCtrlBoundRect.GetWidth(); - h = COMBOBOX_HEIGHT_NORMAL;//listboxes and comboxes have the same height - - rNativeContentRegion = Rectangle( Point( x+FOCUS_RING_WIDTH, y+FOCUS_RING_WIDTH ), Size( w-2*FOCUS_RING_WIDTH, h ) ); - rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h+2*FOCUS_RING_WIDTH ) ); - - toReturn = sal_True; - } - else if( nPart == PART_BUTTON_DOWN ) - { - w = aCtrlBoundRect.GetWidth(); - if( w < 3+2*FOCUS_RING_WIDTH ) - w = 3+2*FOCUS_RING_WIDTH; - h = COMBOBOX_HEIGHT_NORMAL;//listboxes and comboxes have the same height - - x += w-DROPDOWN_BUTTON_WIDTH - FOCUS_RING_WIDTH; - y += FOCUS_RING_WIDTH; - w = DROPDOWN_BUTTON_WIDTH; - - rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h ) ); - rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w+FOCUS_RING_WIDTH, h+2*FOCUS_RING_WIDTH ) ); - - toReturn = true; - } - else if( nPart == PART_SUB_EDIT ) - { - w = aCtrlBoundRect.GetWidth(); - h = COMBOBOX_HEIGHT_NORMAL;//listboxes and comboxes have the same height - - x += FOCUS_RING_WIDTH; - x += 3; // add an offset for rounded borders - y += 2; // don't draw into upper border - y += FOCUS_RING_WIDTH; - w -= 3 + DROPDOWN_BUTTON_WIDTH + 2*FOCUS_RING_WIDTH; - if( nType == CTRL_LISTBOX ) - w -= 9; // HIG specifies 9 units distance between dropdown button area and content - h -= 4; // don't draw into lower border - - rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h ) ); - rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w+FOCUS_RING_WIDTH, h+2*FOCUS_RING_WIDTH ) ); - - toReturn = true; - } - } - break; - case CTRL_SPINBOX: - if( nPart == PART_ENTIRE_CONTROL ) { - w = aCtrlBoundRect.GetWidth(); - if( w < 3+2*FOCUS_RING_WIDTH+SPIN_BUTTON_SPACE+SPIN_BUTTON_WIDTH ) - w = 3+2*FOCUS_RING_WIDTH+SPIN_BUTTON_SPACE+SPIN_BUTTON_WIDTH; - h = TEXT_EDIT_HEIGHT_NORMAL; - - rNativeContentRegion = Rectangle( Point( x+FOCUS_RING_WIDTH, y ), Size( w-2*FOCUS_RING_WIDTH, h ) ); - rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h+2*FOCUS_RING_WIDTH ) ); - - toReturn = sal_True; - } - else if( nPart == PART_SUB_EDIT ) { - w = aCtrlBoundRect.GetWidth() - SPIN_BUTTON_SPACE - SPIN_BUTTON_WIDTH; - h = TEXT_EDIT_HEIGHT_NORMAL; - x += 4; // add an offset for rounded borders - y += 2; // don't draw into upper border - w -= 8; // offset for left and right rounded border - h -= 4; // don't draw into upper or ower border - - rNativeContentRegion = Rectangle( Point( x + FOCUS_RING_WIDTH, y + FOCUS_RING_WIDTH ), Size( w - 2* FOCUS_RING_WIDTH, h ) ); - rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h+2*FOCUS_RING_WIDTH ) ); - - toReturn = sal_True; - } - else if( nPart == PART_BUTTON_UP ) { - //aCtrlBoundRect.GetWidth() contains the width of the full control - //ie the width of the textfield + button - //x is the position of the left corner of the full control - x += aCtrlBoundRect.GetWidth() - SPIN_BUTTON_WIDTH - SPIN_BUTTON_SPACE - CLIP_FUZZ; - y += FOCUS_RING_WIDTH - CLIP_FUZZ; - w = SPIN_BUTTON_WIDTH + 2*CLIP_FUZZ; - h = SPIN_UPPER_BUTTON_HEIGHT + 2*CLIP_FUZZ; - - rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h ) ); - rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h ) ); - - toReturn = sal_True; - } - else if( nPart == PART_BUTTON_DOWN ) { - x += aCtrlBoundRect.GetWidth() - SPIN_BUTTON_WIDTH - SPIN_BUTTON_SPACE - CLIP_FUZZ; - y += SPIN_UPPER_BUTTON_HEIGHT + FOCUS_RING_WIDTH - CLIP_FUZZ; - w = SPIN_BUTTON_WIDTH + 2*CLIP_FUZZ; - h = SPIN_LOWER_BUTTON_HEIGHT + 2*CLIP_FUZZ; - - rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h ) ); - rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h ) ); - - toReturn = sal_True; - } - break; - case CTRL_FRAME: - { - sal_uInt16 nStyle = aValue.getNumericVal(); - if( ( nPart == PART_BORDER ) && - !( nStyle & (FRAME_DRAW_MENU | FRAME_DRAW_WINDOWBORDER | FRAME_DRAW_BORDERWINDOWBORDER) ) ) - { - Rectangle aRect(aCtrlBoundRect); - if( nStyle & FRAME_DRAW_DOUBLEIN ) - { - aRect.Left() += 1; - aRect.Top() += 1; - //rRect.Right() -= 1; - //rRect.Bottom() -= 1; - } - else - { - aRect.Left() += 1; - aRect.Top() += 1; - aRect.Right() -= 1; - aRect.Bottom() -= 1; - } - - rNativeContentRegion = aRect; - rNativeBoundingRegion = aRect; - - toReturn = sal_True; - } - } - break; - - case CTRL_MENUBAR: - case CTRL_MENU_POPUP: - { - if(( nPart == PART_MENU_ITEM_CHECK_MARK )||( nPart == PART_MENU_ITEM_RADIO_MARK )) { - - w=10; - h=10;//dimensions of the mark (10px font) - - rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h ) ); - rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h ) ); - - toReturn = sal_True; - } - } - break; - - } - - return toReturn; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/gdi/salprn.cxx b/vcl/aqua/source/gdi/salprn.cxx deleted file mode 100644 index b64d039a5c04..000000000000 --- a/vcl/aqua/source/gdi/salprn.cxx +++ /dev/null @@ -1,755 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include - -#include "officecfg/Office/Common.hxx" - -#include "vcl/print.hxx" -#include - -#include "aqua/salinst.h" -#include "aqua/salprn.h" -#include "aqua/aquaprintview.h" -#include "coretext/salgdi.h" -#include "aqua/saldata.hxx" -#include "quartz/utils.h" - -#include "jobset.h" -#include "salptype.hxx" - -#include "com/sun/star/beans/PropertyValue.hpp" -#include "com/sun/star/awt/Size.hpp" -#include "com/sun/star/uno/Sequence.hxx" - -#include - -using namespace vcl; -using namespace com::sun::star; -using namespace com::sun::star::beans; - - -// ======================================================================= - -AquaSalInfoPrinter::AquaSalInfoPrinter( const SalPrinterQueueInfo& i_rQueue ) : - mpGraphics( 0 ), - mbGraphics( false ), - mbJob( false ), - mpPrinter( nil ), - mpPrintInfo( nil ), - mePageOrientation( ORIENTATION_PORTRAIT ), - mnStartPageOffsetX( 0 ), - mnStartPageOffsetY( 0 ), - mnCurPageRangeStart( 0 ), - mnCurPageRangeCount( 0 ) -{ - NSString* pStr = CreateNSString( i_rQueue.maPrinterName ); - mpPrinter = [NSPrinter printerWithName: pStr]; - [pStr release]; - - NSPrintInfo* pShared = [NSPrintInfo sharedPrintInfo]; - if( pShared ) - { - mpPrintInfo = [pShared copy]; - [mpPrintInfo setPrinter: mpPrinter]; - mePageOrientation = ([mpPrintInfo orientation] == NSLandscapeOrientation) ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT; -#if MACOSX_SDK_VERSION >= 1090 - [mpPrintInfo setOrientation: NSPaperOrientationPortrait]; -#else - [mpPrintInfo setOrientation: NSPortraitOrientation]; -#endif - } - - mpGraphics = new AquaSalGraphics(); - - const int nWidth = 100, nHeight = 100; - maContextMemory.reset( reinterpret_cast( rtl_allocateMemory( nWidth * 4 * nHeight ) ), - boost::bind( rtl_freeMemory, _1 ) ); - - if( maContextMemory ) - { - mrContext = CGBitmapContextCreate( maContextMemory.get(), nWidth, nHeight, 8, nWidth * 4, GetSalData()->mxRGBSpace, kCGImageAlphaNoneSkipFirst ); - if( mrContext ) - SetupPrinterGraphics( mrContext ); - } -} - -// ----------------------------------------------------------------------- - -AquaSalInfoPrinter::~AquaSalInfoPrinter() -{ - delete mpGraphics; - if( mpPrintInfo ) - [mpPrintInfo release]; - if( mrContext ) - CFRelease( mrContext ); -} - -// ----------------------------------------------------------------------- - -void AquaSalInfoPrinter::SetupPrinterGraphics( CGContextRef i_rContext ) const -{ - if( mpGraphics ) - { - if( mpPrintInfo ) - { - // FIXME: get printer resolution - long nDPIX = 720, nDPIY = 720; - NSSize aPaperSize = [mpPrintInfo paperSize]; - - NSRect aImageRect = [mpPrintInfo imageablePageBounds]; - if( mePageOrientation == ORIENTATION_PORTRAIT ) - { - // move mirrored CTM back into paper - double dX = 0, dY = aPaperSize.height; - // move CTM to reflect imageable area - dX += aImageRect.origin.x; - dY -= aPaperSize.height - aImageRect.size.height - aImageRect.origin.y; - CGContextTranslateCTM( i_rContext, dX + mnStartPageOffsetX, dY - mnStartPageOffsetY ); - // scale to be top/down and reflect our "virtual" DPI - CGContextScaleCTM( i_rContext, 72.0/double(nDPIX), -(72.0/double(nDPIY)) ); - } - else - { - // move CTM to reflect imageable area - double dX = aImageRect.origin.x, dY = aPaperSize.height - aImageRect.size.height - aImageRect.origin.y; - CGContextTranslateCTM( i_rContext, -dX, -dY ); - // turn by 90 degree - CGContextRotateCTM( i_rContext, M_PI/2 ); - // move turned CTM back into paper - dX = aPaperSize.height; - dY = -aPaperSize.width; - CGContextTranslateCTM( i_rContext, dX + mnStartPageOffsetY, dY - mnStartPageOffsetX ); - // scale to be top/down and reflect our "virtual" DPI - CGContextScaleCTM( i_rContext, -(72.0/double(nDPIY)), (72.0/double(nDPIX)) ); - } - mpGraphics->SetPrinterGraphics( i_rContext, nDPIX, nDPIY, 1.0 ); - } - else - OSL_FAIL( "no print info in SetupPrinterGraphics" ); - } -} - -// ----------------------------------------------------------------------- - -SalGraphics* AquaSalInfoPrinter::GetGraphics() -{ - SalGraphics* pGraphics = mbGraphics ? NULL : mpGraphics; - mbGraphics = true; - return pGraphics; -} - -// ----------------------------------------------------------------------- - -void AquaSalInfoPrinter::ReleaseGraphics( SalGraphics* ) -{ - mbGraphics = false; -} - -// ----------------------------------------------------------------------- - -sal_Bool AquaSalInfoPrinter::Setup( SalFrame*, ImplJobSetup* ) -{ - return sal_False; -} - -// ----------------------------------------------------------------------- - -sal_Bool AquaSalInfoPrinter::SetPrinterData( ImplJobSetup* io_pSetupData ) -{ - // FIXME: implement driver data - if( io_pSetupData && io_pSetupData->mpDriverData ) - return SetData( ~0, io_pSetupData ); - - - sal_Bool bSuccess = sal_True; - - // set system type - io_pSetupData->mnSystem = JOBSETUP_SYSTEM_MAC; - - // get paper format - if( mpPrintInfo ) - { - NSSize aPaperSize = [mpPrintInfo paperSize]; - double width = aPaperSize.width, height = aPaperSize.height; - // set paper - PaperInfo aInfo( PtTo10Mu( width ), PtTo10Mu( height ) ); - aInfo.doSloppyFit(); - io_pSetupData->mePaperFormat = aInfo.getPaper(); - if( io_pSetupData->mePaperFormat == PAPER_USER ) - { - io_pSetupData->mnPaperWidth = PtTo10Mu( width ); - io_pSetupData->mnPaperHeight = PtTo10Mu( height ); - } - else - { - io_pSetupData->mnPaperWidth = 0; - io_pSetupData->mnPaperHeight = 0; - } - - // set orientation - io_pSetupData->meOrientation = mePageOrientation; - - io_pSetupData->mnPaperBin = 0; - io_pSetupData->mpDriverData = reinterpret_cast(rtl_allocateMemory( 4 )); - io_pSetupData->mnDriverDataLen = 4; - } - else - bSuccess = sal_False; - - - return bSuccess; -} - -// ----------------------------------------------------------------------- - -void AquaSalInfoPrinter::setPaperSize( long i_nWidth, long i_nHeight, Orientation i_eSetOrientation ) -{ - - Orientation ePaperOrientation = ORIENTATION_PORTRAIT; - const PaperInfo* pPaper = matchPaper( i_nWidth, i_nHeight, ePaperOrientation ); - - if( pPaper ) - { - NSString* pPaperName = [CreateNSString( OStringToOUString(PaperInfo::toPSName(pPaper->getPaper()), RTL_TEXTENCODING_ASCII_US) ) autorelease]; - [mpPrintInfo setPaperName: pPaperName]; - } - else if( i_nWidth > 0 && i_nHeight > 0 ) - { - NSSize aPaperSize = { static_cast(TenMuToPt(i_nWidth)), static_cast(TenMuToPt(i_nHeight)) }; - [mpPrintInfo setPaperSize: aPaperSize]; - } - // this seems counterintuitive - mePageOrientation = i_eSetOrientation; -} - -// ----------------------------------------------------------------------- - -sal_Bool AquaSalInfoPrinter::SetData( sal_uLong i_nFlags, ImplJobSetup* io_pSetupData ) -{ - if( ! io_pSetupData || io_pSetupData->mnSystem != JOBSETUP_SYSTEM_MAC ) - return sal_False; - - - if( mpPrintInfo ) - { - if( (i_nFlags & SAL_JOBSET_ORIENTATION) != 0 ) - mePageOrientation = io_pSetupData->meOrientation; - - if( (i_nFlags & SAL_JOBSET_PAPERSIZE) != 0) - { - // set paper format - long width = 21000, height = 29700; - if( io_pSetupData->mePaperFormat == PAPER_USER ) - { - // #i101108# sanity check - if( io_pSetupData->mnPaperWidth && io_pSetupData->mnPaperHeight ) - { - width = io_pSetupData->mnPaperWidth; - height = io_pSetupData->mnPaperHeight; - } - } - else - { - PaperInfo aInfo( io_pSetupData->mePaperFormat ); - width = aInfo.getWidth(); - height = aInfo.getHeight(); - } - - setPaperSize( width, height, mePageOrientation ); - } - } - - return mpPrintInfo != nil; -} - -// ----------------------------------------------------------------------- - -sal_uLong AquaSalInfoPrinter::GetPaperBinCount( const ImplJobSetup* ) -{ - return 0; -} - -// ----------------------------------------------------------------------- - -OUString AquaSalInfoPrinter::GetPaperBinName( const ImplJobSetup*, sal_uLong ) -{ - return OUString(); -} - -// ----------------------------------------------------------------------- - -sal_uLong AquaSalInfoPrinter::GetCapabilities( const ImplJobSetup*, sal_uInt16 i_nType ) -{ - switch( i_nType ) - { - case PRINTER_CAPABILITIES_SUPPORTDIALOG: - return 0; - case PRINTER_CAPABILITIES_COPIES: - return 0xffff; - case PRINTER_CAPABILITIES_COLLATECOPIES: - return 0xffff; - case PRINTER_CAPABILITIES_SETORIENTATION: - return 1; - case PRINTER_CAPABILITIES_SETDUPLEX: - return 0; - case PRINTER_CAPABILITIES_SETPAPERBIN: - return 0; - case PRINTER_CAPABILITIES_SETPAPERSIZE: - return 1; - case PRINTER_CAPABILITIES_SETPAPER: - return 1; - case PRINTER_CAPABILITIES_EXTERNALDIALOG: - return officecfg::Office::Common::Misc::UseSystemPrintDialog::get() - ? 1 : 0; - case PRINTER_CAPABILITIES_PDF: - return 1; - case PRINTER_CAPABILITIES_USEPULLMODEL: - return 1; - default: break; - }; - return 0; -} - -// ----------------------------------------------------------------------- - -void AquaSalInfoPrinter::GetPageInfo( const ImplJobSetup*, - long& o_rOutWidth, long& o_rOutHeight, - long& o_rPageOffX, long& o_rPageOffY, - long& o_rPageWidth, long& o_rPageHeight ) -{ - if( mpPrintInfo ) - { - sal_Int32 nDPIX = 72, nDPIY = 72; - mpGraphics->GetResolution( nDPIX, nDPIY ); - const double fXScaling = static_cast(nDPIX)/72.0, - fYScaling = static_cast(nDPIY)/72.0; - - NSSize aPaperSize = [mpPrintInfo paperSize]; - o_rPageWidth = static_cast( double(aPaperSize.width) * fXScaling ); - o_rPageHeight = static_cast( double(aPaperSize.height) * fYScaling ); - - NSRect aImageRect = [mpPrintInfo imageablePageBounds]; - o_rPageOffX = static_cast( aImageRect.origin.x * fXScaling ); - o_rPageOffY = static_cast( (aPaperSize.height - aImageRect.size.height - aImageRect.origin.y) * fYScaling ); - o_rOutWidth = static_cast( aImageRect.size.width * fXScaling ); - o_rOutHeight = static_cast( aImageRect.size.height * fYScaling ); - - if( mePageOrientation == ORIENTATION_LANDSCAPE ) - { - std::swap( o_rOutWidth, o_rOutHeight ); - std::swap( o_rPageWidth, o_rPageHeight ); - std::swap( o_rPageOffX, o_rPageOffY ); - } - } -} - -static Size getPageSize( vcl::PrinterController& i_rController, sal_Int32 i_nPage ) -{ - Size aPageSize; - uno::Sequence< PropertyValue > aPageParms( i_rController.getPageParameters( i_nPage ) ); - for( sal_Int32 nProperty = 0, nPropertyCount = aPageParms.getLength(); nProperty < nPropertyCount; ++nProperty ) - { - if ( aPageParms[ nProperty ].Name == "PageSize" ) - { - awt::Size aSize; - aPageParms[ nProperty].Value >>= aSize; - aPageSize.Width() = aSize.Width; - aPageSize.Height() = aSize.Height; - break; - } - } - return aPageSize; -} - -sal_Bool AquaSalInfoPrinter::StartJob( const OUString* i_pFileName, - const OUString& i_rJobName, - const OUString& /*i_rAppName*/, - ImplJobSetup* i_pSetupData, - vcl::PrinterController& i_rController - ) -{ - if( mbJob ) - return sal_False; - - sal_Bool bSuccess = sal_False; - bool bWasAborted = false; - AquaSalInstance* pInst = GetSalData()->mpFirstInstance; - PrintAccessoryViewState aAccViewState; - sal_Int32 nAllPages = 0; - - // reset IsLastPage - i_rController.setLastPage( sal_False ); - - // update job data - if( i_pSetupData ) - SetData( ~0, i_pSetupData ); - - // do we want a progress panel ? - sal_Bool bShowProgressPanel = sal_True; - beans::PropertyValue* pMonitor = i_rController.getValue( OUString( "MonitorVisible" ) ); - if( pMonitor ) - pMonitor->Value >>= bShowProgressPanel; - if( ! i_rController.isShowDialogs() ) - bShowProgressPanel = sal_False; - - // possibly create one job for collated output - sal_Bool bSinglePrintJobs = sal_False; - beans::PropertyValue* pSingleValue = i_rController.getValue( OUString( "PrintCollateAsSingleJobs" ) ); - if( pSingleValue ) - { - pSingleValue->Value >>= bSinglePrintJobs; - } - - // FIXME: jobStarted() should be done after the print dialog has ended (if there is one) - // how do I know when that might be ? - i_rController.jobStarted(); - - - int nCopies = i_rController.getPrinter()->GetCopyCount(); - int nJobs = 1; - if( bSinglePrintJobs ) - { - nJobs = nCopies; - nCopies = 1; - } - - for( int nCurJob = 0; nCurJob < nJobs; nCurJob++ ) - { - aAccViewState.bNeedRestart = true; - do - { - if( aAccViewState.bNeedRestart ) - { - mnCurPageRangeStart = 0; - mnCurPageRangeCount = 0; - nAllPages = i_rController.getFilteredPageCount(); - } - - aAccViewState.bNeedRestart = false; - - Size aCurSize( 21000, 29700 ); - if( nAllPages > 0 ) - { - mnCurPageRangeCount = 1; - aCurSize = getPageSize( i_rController, mnCurPageRangeStart ); - Size aNextSize( aCurSize ); - - // print pages up to a different size - while( mnCurPageRangeCount + mnCurPageRangeStart < nAllPages ) - { - aNextSize = getPageSize( i_rController, mnCurPageRangeStart + mnCurPageRangeCount ); - if( aCurSize == aNextSize // same page size - || - (aCurSize.Width() == aNextSize.Height() && aCurSize.Height() == aNextSize.Width()) // same size, but different orientation - ) - { - mnCurPageRangeCount++; - } - else - break; - } - } - else - mnCurPageRangeCount = 0; - - // now for the current run - mnStartPageOffsetX = mnStartPageOffsetY = 0; - // setup the paper size and orientation - // do this on our associated Printer object, since that is - // out interface to the applications which occasionally rely on the paper - // information (e.g. brochure printing scales to the found paper size) - // also SetPaperSizeUser has the advantage that we can share a - // platform independent paper matching algorithm - boost::shared_ptr pPrinter( i_rController.getPrinter() ); - pPrinter->SetMapMode( MapMode( MAP_100TH_MM ) ); - pPrinter->SetPaperSizeUser( aCurSize, true ); - - // create view - NSView* pPrintView = [[AquaPrintView alloc] initWithController: &i_rController withInfoPrinter: this]; - - NSMutableDictionary* pPrintDict = [mpPrintInfo dictionary]; - - // set filename - if( i_pFileName ) - { - [mpPrintInfo setJobDisposition: NSPrintSaveJob]; - NSString* pPath = CreateNSString( *i_pFileName ); - [pPrintDict setObject: pPath forKey: NSPrintSavePath]; - [pPath release]; - } - - [pPrintDict setObject: [[NSNumber numberWithInt: nCopies] autorelease] forKey: NSPrintCopies]; - if( nCopies > 1 ) - [pPrintDict setObject: [[NSNumber numberWithBool: pPrinter->IsCollateCopy()] autorelease] forKey: NSPrintMustCollate]; - [pPrintDict setObject: [[NSNumber numberWithBool: YES] autorelease] forKey: NSPrintDetailedErrorReporting]; - [pPrintDict setObject: [[NSNumber numberWithInt: 1] autorelease] forKey: NSPrintFirstPage]; - // #i103253# weird: for some reason, autoreleasing the value below like the others above - // leads do a double free malloc error. Why this value should behave differently from all the others - // is a mystery. - [pPrintDict setObject: [NSNumber numberWithInt: mnCurPageRangeCount] forKey: NSPrintLastPage]; - - - // create print operation - NSPrintOperation* pPrintOperation = [NSPrintOperation printOperationWithView: pPrintView printInfo: mpPrintInfo]; - - if( pPrintOperation ) - { - NSObject* pReleaseAfterUse = nil; - bool bShowPanel = !i_rController.isDirectPrint() - && (officecfg::Office::Common::Misc::UseSystemPrintDialog:: - get()) - && i_rController.isShowDialogs(); - [pPrintOperation setShowsPrintPanel: bShowPanel ? YES : NO ]; - [pPrintOperation setShowsProgressPanel: bShowProgressPanel ? YES : NO]; - - // set job title (since MacOSX 10.5) - if( [pPrintOperation respondsToSelector: @selector(setJobTitle:)] ) - [pPrintOperation performSelector: @selector(setJobTitle:) withObject: [CreateNSString( i_rJobName ) autorelease]]; - - if( bShowPanel && mnCurPageRangeStart == 0 && nCurJob == 0) // only the first range of pages (in the first job) gets the accesory view - pReleaseAfterUse = [AquaPrintAccessoryView setupPrinterPanel: pPrintOperation withController: &i_rController withState: &aAccViewState]; - - bSuccess = sal_True; - mbJob = true; - pInst->startedPrintJob(); - [pPrintOperation runOperation]; - pInst->endedPrintJob(); - bWasAborted = [[[pPrintOperation printInfo] jobDisposition] compare: NSPrintCancelJob] == NSOrderedSame; - mbJob = false; - if( pReleaseAfterUse ) - [pReleaseAfterUse release]; - } - - mnCurPageRangeStart += mnCurPageRangeCount; - mnCurPageRangeCount = 1; - } while( aAccViewState.bNeedRestart || mnCurPageRangeStart + mnCurPageRangeCount < nAllPages ); - } - - // inform application that it can release its data - // this is awkward, but the XRenderable interface has no method for this, - // so we need to call XRenderadble::render one last time with IsLastPage = sal_True - i_rController.setLastPage( sal_True ); - GDIMetaFile aPageFile; - if( mrContext ) - SetupPrinterGraphics( mrContext ); - i_rController.getFilteredPageFile( 0, aPageFile ); - - i_rController.setJobState( bWasAborted - ? view::PrintableState_JOB_ABORTED - : view::PrintableState_JOB_SPOOLED ); - - mnCurPageRangeStart = mnCurPageRangeCount = 0; - - return bSuccess; -} - -// ----------------------------------------------------------------------- - -sal_Bool AquaSalInfoPrinter::EndJob() -{ - mnStartPageOffsetX = mnStartPageOffsetY = 0; - mbJob = false; - return sal_True; -} - -// ----------------------------------------------------------------------- - -sal_Bool AquaSalInfoPrinter::AbortJob() -{ - mbJob = false; - - // FIXME: implementation - return sal_False; -} - -// ----------------------------------------------------------------------- - -SalGraphics* AquaSalInfoPrinter::StartPage( ImplJobSetup* i_pSetupData, sal_Bool i_bNewJobData ) -{ - if( i_bNewJobData && i_pSetupData ) - SetPrinterData( i_pSetupData ); - - CGContextRef rContext = reinterpret_cast([[NSGraphicsContext currentContext] graphicsPort]); - - SetupPrinterGraphics( rContext ); - - return mpGraphics; -} - -// ----------------------------------------------------------------------- - -sal_Bool AquaSalInfoPrinter::EndPage() -{ - mpGraphics->InvalidateContext(); - return sal_True; -} - -// ----------------------------------------------------------------------- - -sal_uLong AquaSalInfoPrinter::GetErrorCode() const -{ - return 0; -} - -// ======================================================================= - -AquaSalPrinter::AquaSalPrinter( AquaSalInfoPrinter* i_pInfoPrinter ) : - mpInfoPrinter( i_pInfoPrinter ) -{ -} - -// ----------------------------------------------------------------------- - -AquaSalPrinter::~AquaSalPrinter() -{ -} - -// ----------------------------------------------------------------------- - -sal_Bool AquaSalPrinter::StartJob( const OUString* i_pFileName, - const OUString& i_rJobName, - const OUString& i_rAppName, - ImplJobSetup* i_pSetupData, - vcl::PrinterController& i_rController ) -{ - return mpInfoPrinter->StartJob( i_pFileName, i_rJobName, i_rAppName, i_pSetupData, i_rController ); -} - -// ----------------------------------------------------------------------- - -sal_Bool AquaSalPrinter::StartJob( const OUString* /*i_pFileName*/, - const OUString& /*i_rJobName*/, - const OUString& /*i_rAppName*/, - sal_uLong /*i_nCopies*/, - bool /*i_bCollate*/, - bool /*i_bDirect*/, - ImplJobSetup* ) -{ - OSL_FAIL( "should never be called" ); - return sal_False; -} - -// ----------------------------------------------------------------------- - -sal_Bool AquaSalPrinter::EndJob() -{ - return mpInfoPrinter->EndJob(); -} - -// ----------------------------------------------------------------------- - -sal_Bool AquaSalPrinter::AbortJob() -{ - return mpInfoPrinter->AbortJob(); -} - -// ----------------------------------------------------------------------- - -SalGraphics* AquaSalPrinter::StartPage( ImplJobSetup* i_pSetupData, sal_Bool i_bNewJobData ) -{ - return mpInfoPrinter->StartPage( i_pSetupData, i_bNewJobData ); -} - -// ----------------------------------------------------------------------- - -sal_Bool AquaSalPrinter::EndPage() -{ - return mpInfoPrinter->EndPage(); -} - -// ----------------------------------------------------------------------- - -sal_uLong AquaSalPrinter::GetErrorCode() -{ - return mpInfoPrinter->GetErrorCode(); -} - -void AquaSalInfoPrinter::InitPaperFormats( const ImplJobSetup* ) -{ - m_aPaperFormats.clear(); - m_bPapersInit = true; - - if( mpPrinter ) - { - if( [mpPrinter statusForTable: @"PPD"] == NSPrinterTableOK ) - { - NSArray* pPaperNames = [mpPrinter stringListForKey: @"PageSize" inTable: @"PPD"]; - if( pPaperNames ) - { - unsigned int nPapers = [pPaperNames count]; - for( unsigned int i = 0; i < nPapers; i++ ) - { - NSString* pPaper = [pPaperNames objectAtIndex: i]; - // first try to match the name - OString aPaperName( [pPaper UTF8String] ); - Paper ePaper = PaperInfo::fromPSName( aPaperName ); - if( ePaper != PAPER_USER ) - { - m_aPaperFormats.push_back( PaperInfo( ePaper ) ); - } - else - { - NSSize aPaperSize = [mpPrinter pageSizeForPaper: pPaper]; - if( aPaperSize.width > 0 && aPaperSize.height > 0 ) - { - PaperInfo aInfo( PtTo10Mu( aPaperSize.width ), - PtTo10Mu( aPaperSize.height ) ); - if( aInfo.getPaper() == PAPER_USER ) - aInfo.doSloppyFit(); - m_aPaperFormats.push_back( aInfo ); - } - } - } - } - } - } -} - -const PaperInfo* AquaSalInfoPrinter::matchPaper( long i_nWidth, long i_nHeight, Orientation& o_rOrientation ) const -{ - if( ! m_bPapersInit ) - const_cast(this)->InitPaperFormats( NULL ); - - const PaperInfo* pMatch = NULL; - o_rOrientation = ORIENTATION_PORTRAIT; - for( int n = 0; n < 2 ; n++ ) - { - for( size_t i = 0; i < m_aPaperFormats.size(); i++ ) - { - if( abs( m_aPaperFormats[i].getWidth() - i_nWidth ) < 50 && - abs( m_aPaperFormats[i].getHeight() - i_nHeight ) < 50 ) - { - pMatch = &m_aPaperFormats[i]; - return pMatch; - } - } - o_rOrientation = ORIENTATION_LANDSCAPE; - std::swap( i_nWidth, i_nHeight ); - } - return pMatch; -} - -int AquaSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* ) -{ - return 900; -} - - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/gdi/salvd.cxx b/vcl/aqua/source/gdi/salvd.cxx deleted file mode 100644 index 2be469c7ae2c..000000000000 --- a/vcl/aqua/source/gdi/salvd.cxx +++ /dev/null @@ -1,261 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "vcl/svapp.hxx" -#include "vcl/sysdata.hxx" - -#include "aqua/salvd.h" -#include "aqua/salinst.h" -#include "coretext/salgdi.h" -#include "aqua/saldata.hxx" -#include "aqua/salframe.h" - -// ----------------------------------------------------------------------- - -SalVirtualDevice* AquaSalInstance::CreateVirtualDevice( SalGraphics* pGraphics, - long nDX, long nDY, sal_uInt16 nBitCount, const SystemGraphicsData *pData ) -{ - // #i92075# can be called first in a thread - SalData::ensureThreadAutoreleasePool(); - - return new AquaSalVirtualDevice( static_cast< AquaSalGraphics* >( pGraphics ), nDX, nDY, nBitCount, pData ); -} - -// ----------------------------------------------------------------------- - -void AquaSalInstance::DestroyVirtualDevice( SalVirtualDevice* pDevice ) -{ - delete pDevice; -} - -// ======================================================================= - -AquaSalVirtualDevice::AquaSalVirtualDevice( AquaSalGraphics* pGraphic, long nDX, long nDY, sal_uInt16 nBitCount, const SystemGraphicsData *pData ) -: mbGraphicsUsed( false ) -, mxBitmapContext( NULL ) -, mnBitmapDepth( 0 ) -, mxLayer( NULL ) -{ - if( pGraphic && pData && pData->rCGContext ) - { - // Create virtual device based on existing SystemGraphicsData - // We ignore nDx and nDY, as the desired size comes from the SystemGraphicsData - mbForeignContext = true; // the mxContext is from pData - mpGraphics = new AquaSalGraphics( /*pGraphic*/ ); - mpGraphics->SetVirDevGraphics( mxLayer, pData->rCGContext ); - } - else - { - // create empty new virtual device - mbForeignContext = false; // the mxContext is created within VCL - mpGraphics = new AquaSalGraphics(); // never fails - mnBitmapDepth = nBitCount; - - // inherit resolution from reference device - if( pGraphic ) - { - AquaSalFrame* pFrame = pGraphic->getGraphicsFrame(); - if( pFrame && AquaSalFrame::isAlive( pFrame ) ) - { - mpGraphics->setGraphicsFrame( pFrame ); - mpGraphics->copyResolution( *pGraphic ); - } - } - - if( nDX && nDY ) - SetSize( nDX, nDY ); - - // NOTE: if SetSize does not succeed, we just ignore the nDX and nDY - } -} - -// ----------------------------------------------------------------------- - -AquaSalVirtualDevice::~AquaSalVirtualDevice() -{ - if( mpGraphics ) - { - mpGraphics->SetVirDevGraphics( NULL, NULL ); - delete mpGraphics; - mpGraphics = 0; - } - Destroy(); -} - -// ----------------------------------------------------------------------- - -void AquaSalVirtualDevice::Destroy() -{ - if( mbForeignContext ) { - // Do not delete mxContext that we have received from outside VCL - mxLayer = NULL; - return; - } - - if( mxLayer ) - { - if( mpGraphics ) - mpGraphics->SetVirDevGraphics( NULL, NULL ); - CGLayerRelease( mxLayer ); - mxLayer = NULL; - } - - if( mxBitmapContext ) - { - void* pRawData = CGBitmapContextGetData( mxBitmapContext ); - rtl_freeMemory( pRawData ); - CGContextRelease( mxBitmapContext ); - mxBitmapContext = NULL; - } -} - -// ----------------------------------------------------------------------- - -SalGraphics* AquaSalVirtualDevice::GetGraphics() -{ - if( mbGraphicsUsed || !mpGraphics ) - return 0; - - mbGraphicsUsed = true; - return mpGraphics; -} - -// ----------------------------------------------------------------------- - -void AquaSalVirtualDevice::ReleaseGraphics( SalGraphics* ) -{ - mbGraphicsUsed = false; -} - -// ----------------------------------------------------------------------- - -sal_Bool AquaSalVirtualDevice::SetSize( long nDX, long nDY ) -{ - if( mbForeignContext ) - { - // Do not delete/resize mxContext that we have received from outside VCL - return true; - } - - if( mxLayer ) - { - const CGSize aSize = CGLayerGetSize( mxLayer ); - if( (nDX == aSize.width) && (nDY == aSize.height) ) - { - // Yay, we do not have to do anything :) - return true; - } - } - - Destroy(); - - // create a Quartz layer matching to the intended virdev usage - CGContextRef xCGContext = NULL; - if( mnBitmapDepth && (mnBitmapDepth < 16) ) - { - mnBitmapDepth = 8; // TODO: are 1bit vdevs worth it? - const CGColorSpaceRef aCGColorSpace = GetSalData()->mxGraySpace; - const CGBitmapInfo aCGBmpInfo = kCGImageAlphaNone; - const int nBytesPerRow = (mnBitmapDepth * nDX + 7) / 8; - - void* pRawData = rtl_allocateMemory( nBytesPerRow * nDY ); - mxBitmapContext = ::CGBitmapContextCreate( pRawData, nDX, nDY, - mnBitmapDepth, nBytesPerRow, aCGColorSpace, aCGBmpInfo ); - xCGContext = mxBitmapContext; - } - else - { - // default to a NSView target context - AquaSalFrame* pSalFrame = mpGraphics->getGraphicsFrame(); - if( !pSalFrame || !AquaSalFrame::isAlive( pSalFrame )) - { - if( !GetSalData()->maFrames.empty() ) - { - // get the first matching frame - pSalFrame = *GetSalData()->maFrames.begin(); - } - else - { - // ensure we don't reuse a dead AquaSalFrame on the very - // unlikely case of no other frame to use - pSalFrame = NULL; - } - // update the frame reference - mpGraphics->setGraphicsFrame( pSalFrame ); - } - if( pSalFrame ) - { - // #i91990# - NSWindow* pNSWindow = pSalFrame->getNSWindow(); - if ( pNSWindow ) - { - NSGraphicsContext* pNSContext = [NSGraphicsContext graphicsContextWithWindow: pNSWindow]; - if( pNSContext ) - xCGContext = reinterpret_cast([pNSContext graphicsPort]); - } - else - { - // fall back to a bitmap context - mnBitmapDepth = 32; - const CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace; - const CGBitmapInfo aCGBmpInfo = kCGImageAlphaNoneSkipFirst; - const int nBytesPerRow = (mnBitmapDepth * nDX) / 8; - - void* pRawData = rtl_allocateMemory( nBytesPerRow * nDY ); - mxBitmapContext = ::CGBitmapContextCreate( pRawData, nDX, nDY, - 8, nBytesPerRow, aCGColorSpace, aCGBmpInfo ); - xCGContext = mxBitmapContext; - } - } - } - - DBG_ASSERT( xCGContext, "no context" ); - - const CGSize aNewSize = { static_cast(nDX), static_cast(nDY) }; - mxLayer = CGLayerCreateWithContext( xCGContext, aNewSize, NULL ); - - if( mxLayer && mpGraphics ) - { - // get the matching Quartz context - CGContextRef xDrawContext = CGLayerGetContext( mxLayer ); - mpGraphics->SetVirDevGraphics( mxLayer, xDrawContext, mnBitmapDepth ); - } - - return (mxLayer != NULL); -} - -// ----------------------------------------------------------------------- - -void AquaSalVirtualDevice::GetSize( long& rWidth, long& rHeight ) -{ - if( mxLayer ) - { - const CGSize aSize = CGLayerGetSize( mxLayer ); - rWidth = static_cast(aSize.width); - rHeight = static_cast(aSize.height); - } - else - { - rWidth = 0; - rHeight = 0; - } -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/res/MainMenu.nib/classes.nib b/vcl/aqua/source/res/MainMenu.nib/classes.nib deleted file mode 100644 index b9b4b09f6b0d..000000000000 --- a/vcl/aqua/source/res/MainMenu.nib/classes.nib +++ /dev/null @@ -1,4 +0,0 @@ -{ - IBClasses = ({CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }); - IBVersion = 1; -} \ No newline at end of file diff --git a/vcl/aqua/source/res/MainMenu.nib/info.nib b/vcl/aqua/source/res/MainMenu.nib/info.nib deleted file mode 100644 index 856429aee5bd..000000000000 --- a/vcl/aqua/source/res/MainMenu.nib/info.nib +++ /dev/null @@ -1,21 +0,0 @@ - - - - - IBDocumentLocation - 135 107 356 240 0 0 1680 1028 - IBEditorPositions - - 29 - 132 352 141 44 0 0 1680 1028 - - IBFramework Version - 446.1 - IBOpenObjects - - 29 - - IBSystem Version - 8R2218 - - diff --git a/vcl/aqua/source/res/MainMenu.nib/keyedobjects.nib b/vcl/aqua/source/res/MainMenu.nib/keyedobjects.nib deleted file mode 100644 index d39d10119c0c..000000000000 Binary files a/vcl/aqua/source/res/MainMenu.nib/keyedobjects.nib and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/airbrush.png b/vcl/aqua/source/res/cursors/airbrush.png deleted file mode 100644 index 7ec780c4f9f9..000000000000 Binary files a/vcl/aqua/source/res/cursors/airbrush.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/ase.png b/vcl/aqua/source/res/cursors/ase.png deleted file mode 100644 index a3a30e0bcdce..000000000000 Binary files a/vcl/aqua/source/res/cursors/ase.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/asn.png b/vcl/aqua/source/res/cursors/asn.png deleted file mode 100644 index 7a140b1ec926..000000000000 Binary files a/vcl/aqua/source/res/cursors/asn.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/asne.png b/vcl/aqua/source/res/cursors/asne.png deleted file mode 100644 index 311506aeb349..000000000000 Binary files a/vcl/aqua/source/res/cursors/asne.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/asns.png b/vcl/aqua/source/res/cursors/asns.png deleted file mode 100644 index 1c8950eb28bc..000000000000 Binary files a/vcl/aqua/source/res/cursors/asns.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/asnswe.png b/vcl/aqua/source/res/cursors/asnswe.png deleted file mode 100644 index aae5246fbbc0..000000000000 Binary files a/vcl/aqua/source/res/cursors/asnswe.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/asnw.png b/vcl/aqua/source/res/cursors/asnw.png deleted file mode 100644 index 9fd0036df077..000000000000 Binary files a/vcl/aqua/source/res/cursors/asnw.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/ass.png b/vcl/aqua/source/res/cursors/ass.png deleted file mode 100644 index bee09e736ad1..000000000000 Binary files a/vcl/aqua/source/res/cursors/ass.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/asse.png b/vcl/aqua/source/res/cursors/asse.png deleted file mode 100644 index d7883211d44f..000000000000 Binary files a/vcl/aqua/source/res/cursors/asse.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/assw.png b/vcl/aqua/source/res/cursors/assw.png deleted file mode 100644 index 0b0a496a52ec..000000000000 Binary files a/vcl/aqua/source/res/cursors/assw.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/asw.png b/vcl/aqua/source/res/cursors/asw.png deleted file mode 100644 index 5a4b9519e075..000000000000 Binary files a/vcl/aqua/source/res/cursors/asw.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/aswe.png b/vcl/aqua/source/res/cursors/aswe.png deleted file mode 100644 index b9c5afaac043..000000000000 Binary files a/vcl/aqua/source/res/cursors/aswe.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/chain.png b/vcl/aqua/source/res/cursors/chain.png deleted file mode 100644 index dbf069924d73..000000000000 Binary files a/vcl/aqua/source/res/cursors/chain.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/chainnot.png b/vcl/aqua/source/res/cursors/chainnot.png deleted file mode 100644 index 547703edf12c..000000000000 Binary files a/vcl/aqua/source/res/cursors/chainnot.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/chart.png b/vcl/aqua/source/res/cursors/chart.png deleted file mode 100644 index de5514006e1f..000000000000 Binary files a/vcl/aqua/source/res/cursors/chart.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/copydata.png b/vcl/aqua/source/res/cursors/copydata.png deleted file mode 100644 index b6202fd9144f..000000000000 Binary files a/vcl/aqua/source/res/cursors/copydata.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/copydlnk.png b/vcl/aqua/source/res/cursors/copydlnk.png deleted file mode 100644 index fab24c9f8f7c..000000000000 Binary files a/vcl/aqua/source/res/cursors/copydlnk.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/copyf.png b/vcl/aqua/source/res/cursors/copyf.png deleted file mode 100644 index 70546d0c0c22..000000000000 Binary files a/vcl/aqua/source/res/cursors/copyf.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/copyf2.png b/vcl/aqua/source/res/cursors/copyf2.png deleted file mode 100644 index b6f76051f10f..000000000000 Binary files a/vcl/aqua/source/res/cursors/copyf2.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/copyflnk.png b/vcl/aqua/source/res/cursors/copyflnk.png deleted file mode 100644 index 23561e484e36..000000000000 Binary files a/vcl/aqua/source/res/cursors/copyflnk.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/crook.png b/vcl/aqua/source/res/cursors/crook.png deleted file mode 100644 index 4378f8df8351..000000000000 Binary files a/vcl/aqua/source/res/cursors/crook.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/crop.png b/vcl/aqua/source/res/cursors/crop.png deleted file mode 100644 index 92a778ada31a..000000000000 Binary files a/vcl/aqua/source/res/cursors/crop.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/darc.png b/vcl/aqua/source/res/cursors/darc.png deleted file mode 100644 index 9772a1c6b85a..000000000000 Binary files a/vcl/aqua/source/res/cursors/darc.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/dbezier.png b/vcl/aqua/source/res/cursors/dbezier.png deleted file mode 100644 index 988498137e9a..000000000000 Binary files a/vcl/aqua/source/res/cursors/dbezier.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/dcapt.png b/vcl/aqua/source/res/cursors/dcapt.png deleted file mode 100644 index d1ef82818735..000000000000 Binary files a/vcl/aqua/source/res/cursors/dcapt.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/dcirccut.png b/vcl/aqua/source/res/cursors/dcirccut.png deleted file mode 100644 index cb4ed0e85ecd..000000000000 Binary files a/vcl/aqua/source/res/cursors/dcirccut.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/dconnect.png b/vcl/aqua/source/res/cursors/dconnect.png deleted file mode 100644 index e4a43bdbe021..000000000000 Binary files a/vcl/aqua/source/res/cursors/dconnect.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/dellipse.png b/vcl/aqua/source/res/cursors/dellipse.png deleted file mode 100644 index 319c4574c7c1..000000000000 Binary files a/vcl/aqua/source/res/cursors/dellipse.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/detectiv.png b/vcl/aqua/source/res/cursors/detectiv.png deleted file mode 100644 index abe93f263d4d..000000000000 Binary files a/vcl/aqua/source/res/cursors/detectiv.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/dfree.png b/vcl/aqua/source/res/cursors/dfree.png deleted file mode 100644 index 2de92942adde..000000000000 Binary files a/vcl/aqua/source/res/cursors/dfree.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/dline.png b/vcl/aqua/source/res/cursors/dline.png deleted file mode 100644 index 6afb670ef8a8..000000000000 Binary files a/vcl/aqua/source/res/cursors/dline.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/dpie.png b/vcl/aqua/source/res/cursors/dpie.png deleted file mode 100644 index 44a9474846b9..000000000000 Binary files a/vcl/aqua/source/res/cursors/dpie.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/dpolygon.png b/vcl/aqua/source/res/cursors/dpolygon.png deleted file mode 100644 index 847e6ad9bea5..000000000000 Binary files a/vcl/aqua/source/res/cursors/dpolygon.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/drect.png b/vcl/aqua/source/res/cursors/drect.png deleted file mode 100644 index ff3dcbba07b4..000000000000 Binary files a/vcl/aqua/source/res/cursors/drect.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/dtext.png b/vcl/aqua/source/res/cursors/dtext.png deleted file mode 100644 index ee375f0e47a0..000000000000 Binary files a/vcl/aqua/source/res/cursors/dtext.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/fill.png b/vcl/aqua/source/res/cursors/fill.png deleted file mode 100644 index 220641b9beb4..000000000000 Binary files a/vcl/aqua/source/res/cursors/fill.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/help.png b/vcl/aqua/source/res/cursors/help.png deleted file mode 100644 index e29c19eccd22..000000000000 Binary files a/vcl/aqua/source/res/cursors/help.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/hourglass.png b/vcl/aqua/source/res/cursors/hourglass.png deleted file mode 100644 index 07bb5af73e6e..000000000000 Binary files a/vcl/aqua/source/res/cursors/hourglass.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/hshear.png b/vcl/aqua/source/res/cursors/hshear.png deleted file mode 100644 index b45beded2d93..000000000000 Binary files a/vcl/aqua/source/res/cursors/hshear.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/linkdata.png b/vcl/aqua/source/res/cursors/linkdata.png deleted file mode 100644 index 6432db0155b6..000000000000 Binary files a/vcl/aqua/source/res/cursors/linkdata.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/linkf.png b/vcl/aqua/source/res/cursors/linkf.png deleted file mode 100644 index e17107fec9ff..000000000000 Binary files a/vcl/aqua/source/res/cursors/linkf.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/magnify.png b/vcl/aqua/source/res/cursors/magnify.png deleted file mode 100644 index 4e73146b91e4..000000000000 Binary files a/vcl/aqua/source/res/cursors/magnify.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/mirror.png b/vcl/aqua/source/res/cursors/mirror.png deleted file mode 100644 index 8fac93f0b6df..000000000000 Binary files a/vcl/aqua/source/res/cursors/mirror.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/movebw.png b/vcl/aqua/source/res/cursors/movebw.png deleted file mode 100644 index 63bf76ad3942..000000000000 Binary files a/vcl/aqua/source/res/cursors/movebw.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/movedata.png b/vcl/aqua/source/res/cursors/movedata.png deleted file mode 100644 index 60ece8a53e59..000000000000 Binary files a/vcl/aqua/source/res/cursors/movedata.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/movedlnk.png b/vcl/aqua/source/res/cursors/movedlnk.png deleted file mode 100644 index 6951cd718d97..000000000000 Binary files a/vcl/aqua/source/res/cursors/movedlnk.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/movef.png b/vcl/aqua/source/res/cursors/movef.png deleted file mode 100644 index 97a01c88fa4d..000000000000 Binary files a/vcl/aqua/source/res/cursors/movef.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/movef2.png b/vcl/aqua/source/res/cursors/movef2.png deleted file mode 100644 index 2cdddb410aae..000000000000 Binary files a/vcl/aqua/source/res/cursors/movef2.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/moveflnk.png b/vcl/aqua/source/res/cursors/moveflnk.png deleted file mode 100644 index 53301ba58c50..000000000000 Binary files a/vcl/aqua/source/res/cursors/moveflnk.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/movept.png b/vcl/aqua/source/res/cursors/movept.png deleted file mode 100644 index 41945deb1916..000000000000 Binary files a/vcl/aqua/source/res/cursors/movept.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/neswsize.png b/vcl/aqua/source/res/cursors/neswsize.png deleted file mode 100644 index 91b89b5803ec..000000000000 Binary files a/vcl/aqua/source/res/cursors/neswsize.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/notallow.png b/vcl/aqua/source/res/cursors/notallow.png deleted file mode 100644 index df770a495194..000000000000 Binary files a/vcl/aqua/source/res/cursors/notallow.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/nullptr.png b/vcl/aqua/source/res/cursors/nullptr.png deleted file mode 100644 index 489636595bec..000000000000 Binary files a/vcl/aqua/source/res/cursors/nullptr.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/nwsesize.png b/vcl/aqua/source/res/cursors/nwsesize.png deleted file mode 100644 index fc6a33288ef2..000000000000 Binary files a/vcl/aqua/source/res/cursors/nwsesize.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/pen.png b/vcl/aqua/source/res/cursors/pen.png deleted file mode 100644 index 81b583086778..000000000000 Binary files a/vcl/aqua/source/res/cursors/pen.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/pivotcol.png b/vcl/aqua/source/res/cursors/pivotcol.png deleted file mode 100644 index 1c38b915b886..000000000000 Binary files a/vcl/aqua/source/res/cursors/pivotcol.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/pivotdel.png b/vcl/aqua/source/res/cursors/pivotdel.png deleted file mode 100644 index fbd663ee36c1..000000000000 Binary files a/vcl/aqua/source/res/cursors/pivotdel.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/pivotfld.png b/vcl/aqua/source/res/cursors/pivotfld.png deleted file mode 100644 index 04375de1efe6..000000000000 Binary files a/vcl/aqua/source/res/cursors/pivotfld.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/pivotrow.png b/vcl/aqua/source/res/cursors/pivotrow.png deleted file mode 100644 index 18ef0e8e59ba..000000000000 Binary files a/vcl/aqua/source/res/cursors/pivotrow.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/pntbrsh.png b/vcl/aqua/source/res/cursors/pntbrsh.png deleted file mode 100644 index ec8d799f66c2..000000000000 Binary files a/vcl/aqua/source/res/cursors/pntbrsh.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/rotate.png b/vcl/aqua/source/res/cursors/rotate.png deleted file mode 100644 index a8137e077e56..000000000000 Binary files a/vcl/aqua/source/res/cursors/rotate.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/tblsele.png b/vcl/aqua/source/res/cursors/tblsele.png deleted file mode 100644 index a2da05e009d1..000000000000 Binary files a/vcl/aqua/source/res/cursors/tblsele.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/tblsels.png b/vcl/aqua/source/res/cursors/tblsels.png deleted file mode 100644 index ba20589c794f..000000000000 Binary files a/vcl/aqua/source/res/cursors/tblsels.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/tblselse.png b/vcl/aqua/source/res/cursors/tblselse.png deleted file mode 100644 index 4ee7f62b304b..000000000000 Binary files a/vcl/aqua/source/res/cursors/tblselse.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/tblselsw.png b/vcl/aqua/source/res/cursors/tblselsw.png deleted file mode 100644 index 11d7cb34d64d..000000000000 Binary files a/vcl/aqua/source/res/cursors/tblselsw.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/tblselw.png b/vcl/aqua/source/res/cursors/tblselw.png deleted file mode 100644 index 62813a975855..000000000000 Binary files a/vcl/aqua/source/res/cursors/tblselw.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/timemove.png b/vcl/aqua/source/res/cursors/timemove.png deleted file mode 100644 index 3dae038a2011..000000000000 Binary files a/vcl/aqua/source/res/cursors/timemove.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/timesize.png b/vcl/aqua/source/res/cursors/timesize.png deleted file mode 100644 index 22178c9b8d0e..000000000000 Binary files a/vcl/aqua/source/res/cursors/timesize.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/vshear.png b/vcl/aqua/source/res/cursors/vshear.png deleted file mode 100644 index b01cb6c935e1..000000000000 Binary files a/vcl/aqua/source/res/cursors/vshear.png and /dev/null differ diff --git a/vcl/aqua/source/res/cursors/vtext.png b/vcl/aqua/source/res/cursors/vtext.png deleted file mode 100644 index 2d6c847c9fc7..000000000000 Binary files a/vcl/aqua/source/res/cursors/vtext.png and /dev/null differ diff --git a/vcl/aqua/source/window/salframe.cxx b/vcl/aqua/source/window/salframe.cxx deleted file mode 100644 index 0a9081e859f2..000000000000 --- a/vcl/aqua/source/window/salframe.cxx +++ /dev/null @@ -1,1769 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include - -#include "rtl/ustrbuf.hxx" - -#include "osl/file.h" - -#include "vcl/svapp.hxx" -#include "vcl/window.hxx" -#include "vcl/syswin.hxx" - -#include "aqua/saldata.hxx" -#include "coretext/salgdi.h" -#include "aqua/salframe.h" -#include "aqua/salmenu.h" -#include "aqua/salinst.h" -#include "aqua/salframeview.h" -#include "aqua/aqua11yfactory.h" -#include "quartz/utils.h" - -#include "salwtype.hxx" - -#include "premac.h" -#include -// needed for theming -// FIXME: move theming code to salnativewidgets.cxx -#include -#include "postmac.h" - -using namespace std; - -// ======================================================================= - -AquaSalFrame* AquaSalFrame::s_pCaptureFrame = NULL; - -// ======================================================================= - -AquaSalFrame::AquaSalFrame( SalFrame* pParent, sal_uLong salFrameStyle ) : - mpNSWindow(nil), - mpNSView(nil), - mpDockMenuEntry(nil), - mpGraphics(NULL), - mpParent(NULL), - mnMinWidth(0), - mnMinHeight(0), - mnMaxWidth(0), - mnMaxHeight(0), - mbGraphics(false), - mbFullScreen( false ), - mbShown(false), - mbInitShow(true), - mbPositioned(false), - mbSized(false), - mbPresentation( false ), - mnStyle( salFrameStyle ), - mnStyleMask( 0 ), - mnLastEventTime( 0 ), - mnLastModifierFlags( 0 ), - mpMenu( NULL ), - mnExtStyle( 0 ), - mePointerStyle( POINTER_ARROW ), - mnTrackingRectTag( 0 ), - mrClippingPath( 0 ), - mnICOptions( 0 ) -{ - maSysData.nSize = sizeof( SystemEnvData ); - - mpParent = dynamic_cast(pParent); - - initWindowAndView(); - - SalData* pSalData = GetSalData(); - pSalData->maFrames.push_front( this ); - pSalData->maFrameCheck.insert( this ); -} - -// ----------------------------------------------------------------------- - -AquaSalFrame::~AquaSalFrame() -{ - // if the frame is destroyed and has the current menubar - // set the default menubar - if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu ) - AquaSalMenu::setDefaultMenu(); - - // cleanup clipping stuff - ResetClipRegion(); - - [SalFrameView unsetMouseFrame: this]; - - SalData* pSalData = GetSalData(); - pSalData->maFrames.remove( this ); - pSalData->maFrameCheck.erase( this ); - pSalData->maPresentationFrames.remove( this ); - - DBG_ASSERT( this != s_pCaptureFrame, "capture frame destroyed" ); - if( this == s_pCaptureFrame ) - s_pCaptureFrame = NULL; - - delete mpGraphics; - - if( mpDockMenuEntry ) - // life cycle comment: the menu has ownership of the item, so no release - [AquaSalInstance::GetDynamicDockMenu() removeItem: mpDockMenuEntry]; - if ( mpNSView ) { - [AquaA11yFactory revokeView: mpNSView]; - [mpNSView release]; - } - if ( mpNSWindow ) - [mpNSWindow release]; -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::initWindowAndView() -{ - // initialize mirroring parameters - // FIXME: screens changing - NSScreen* pNSScreen = [mpNSWindow screen]; - if( pNSScreen == nil ) - pNSScreen = [NSScreen mainScreen]; - maScreenRect = [pNSScreen frame]; - - // calculate some default geometry - NSRect aVisibleRect = [pNSScreen visibleFrame]; - CocoaToVCL( aVisibleRect ); - - maGeometry.nX = static_cast(aVisibleRect.origin.x + aVisibleRect.size.width / 10); - maGeometry.nY = static_cast(aVisibleRect.origin.y + aVisibleRect.size.height / 10); - maGeometry.nWidth = static_cast(aVisibleRect.size.width * 0.8); - maGeometry.nHeight = static_cast(aVisibleRect.size.height * 0.8); - - // calculate style mask - if( (mnStyle & SAL_FRAME_STYLE_FLOAT) || - (mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) - mnStyleMask = NSBorderlessWindowMask; - else if( mnStyle & SAL_FRAME_STYLE_DEFAULT ) - { - mnStyleMask = NSTitledWindowMask | - NSMiniaturizableWindowMask | - NSResizableWindowMask | - NSClosableWindowMask; - // make default window "maximized" - maGeometry.nX = static_cast(aVisibleRect.origin.x); - maGeometry.nY = static_cast(aVisibleRect.origin.y); - maGeometry.nWidth = static_cast(aVisibleRect.size.width); - maGeometry.nHeight = static_cast(aVisibleRect.size.height); - mbPositioned = mbSized = true; - } - else - { - if( (mnStyle & SAL_FRAME_STYLE_MOVEABLE) ) - { - mnStyleMask |= NSTitledWindowMask; - if( mpParent == NULL ) - mnStyleMask |= NSMiniaturizableWindowMask; - } - if( (mnStyle & SAL_FRAME_STYLE_SIZEABLE) ) - mnStyleMask |= NSResizableWindowMask; - if( (mnStyle & SAL_FRAME_STYLE_CLOSEABLE) ) - mnStyleMask |= NSClosableWindowMask; - // documentation says anything other than NSBorderlessWindowMask (=0) - // should also include NSTitledWindowMask; - if( mnStyleMask != 0 ) - mnStyleMask |= NSTitledWindowMask; - } - - // #i91990# support GUI-less (daemon) execution - @try - { - mpNSWindow = [[SalFrameWindow alloc] initWithSalFrame: this]; - mpNSView = [[SalFrameView alloc] initWithSalFrame: this]; - } - @catch ( id exception ) - { - return; - } - - if( (mnStyle & SAL_FRAME_STYLE_TOOLTIP) ) - [mpNSWindow setIgnoresMouseEvents: YES]; - else - [mpNSWindow setAcceptsMouseMovedEvents: YES]; - [mpNSWindow setHasShadow: YES]; - - // WTF? With the 10.6 SDK and gcc 4.2.1, we get: class 'NSWindow' - // does not implement the 'NSWindowDelegate' protocol. Anyway, - // having the window object be its own delegate object is - // apparently what the code does on purpose, see discussion in - // https://issues.apache.org/ooo/show_bug.cgi?id=91990 - - // So to silence the warning when compiling with -Werror, instead of: - // [mpNSWindow setDelegate: mpNSWindow]; - // do this: - objc_msgSend(mpNSWindow, @selector(setDelegate:), mpNSWindow); - - if( [mpNSWindow respondsToSelector: @selector(setRestorable:)]) - { - objc_msgSend(mpNSWindow, @selector(setRestorable:), NO); - } - NSRect aRect = { { 0,0 }, { static_cast(maGeometry.nWidth), static_cast(maGeometry.nHeight) } }; - mnTrackingRectTag = [mpNSView addTrackingRect: aRect owner: mpNSView userData: nil assumeInside: NO]; - - maSysData.mpNSView = mpNSView; - - UpdateFrameGeometry(); - - [mpNSWindow setContentView: mpNSView]; -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::CocoaToVCL( NSRect& io_rRect, bool bRelativeToScreen ) -{ - if( bRelativeToScreen ) - io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height); - else - io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height); -} - -void AquaSalFrame::VCLToCocoa( NSRect& io_rRect, bool bRelativeToScreen ) -{ - if( bRelativeToScreen ) - io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height); - else - io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height); -} - -void AquaSalFrame::CocoaToVCL( NSPoint& io_rPoint, bool bRelativeToScreen ) -{ - if( bRelativeToScreen ) - io_rPoint.y = maScreenRect.size.height - io_rPoint.y; - else - io_rPoint.y = maGeometry.nHeight - io_rPoint.y; -} - -void AquaSalFrame::VCLToCocoa( NSPoint& io_rPoint, bool bRelativeToScreen ) -{ - if( bRelativeToScreen ) - io_rPoint.y = maScreenRect.size.height - io_rPoint.y; - else - io_rPoint.y = maGeometry.nHeight - io_rPoint.y; -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::screenParametersChanged() -{ - UpdateFrameGeometry(); - - if( mpGraphics ) - mpGraphics->updateResolution(); - CallCallback( SALEVENT_DISPLAYCHANGED, 0 ); -} - -// ----------------------------------------------------------------------- - -SalGraphics* AquaSalFrame::GetGraphics() -{ - if ( mbGraphics ) - return NULL; - - if ( !mpGraphics ) - { - mpGraphics = new AquaSalGraphics; - mpGraphics->SetWindowGraphics( this ); - } - - mbGraphics = TRUE; - return mpGraphics; -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::ReleaseGraphics( SalGraphics *pGraphics ) -{ - (void)pGraphics; - DBG_ASSERT( pGraphics == mpGraphics, "graphics released on wrong frame" ); - mbGraphics = FALSE; -} - -// ----------------------------------------------------------------------- - -sal_Bool AquaSalFrame::PostEvent( void *pData ) -{ - GetSalData()->mpFirstInstance->PostUserEvent( this, SALEVENT_USEREVENT, pData ); - return TRUE; -} - -// ----------------------------------------------------------------------- -void AquaSalFrame::SetTitle(const OUString& rTitle) -{ - if ( !mpNSWindow ) - return; - - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - NSString* pTitle = CreateNSString( rTitle ); - [mpNSWindow setTitle: pTitle]; - - // create an entry in the dock menu - const sal_uLong nAppWindowStyle = (SAL_FRAME_STYLE_CLOSEABLE | SAL_FRAME_STYLE_MOVEABLE); - if( mpParent == NULL && - (mnStyle & nAppWindowStyle) == nAppWindowStyle ) - { - if( mpDockMenuEntry == NULL ) - { - NSMenu* pDock = AquaSalInstance::GetDynamicDockMenu(); - mpDockMenuEntry = [pDock insertItemWithTitle: pTitle - action: @selector(dockMenuItemTriggered:) - keyEquivalent: @"" - atIndex: 0]; - [mpDockMenuEntry setTarget: mpNSWindow]; - - // TODO: image (either the generic window image or an icon - // check mark (for "main" window ?) - } - else - [mpDockMenuEntry setTitle: pTitle]; - } - - if (pTitle) - [pTitle release]; -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::SetIcon( sal_uInt16 ) -{ -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::SetRepresentedURL( const OUString& i_rDocURL ) -{ - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - if( i_rDocURL.startsWith( "file:" ) ) - { - OUString aSysPath; - osl_getSystemPathFromFileURL( i_rDocURL.pData, &aSysPath.pData ); - NSString* pStr = CreateNSString( aSysPath ); - if( pStr ) - { - [pStr autorelease]; - [mpNSWindow setRepresentedFilename: pStr]; - } - } -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::initShow() -{ - mbInitShow = false; - if( ! mbPositioned && ! mbFullScreen ) - { - Rectangle aScreenRect; - GetWorkArea( aScreenRect ); - if( mpParent ) // center relative to parent - { - // center on parent - long nNewX = mpParent->maGeometry.nX + ((long)mpParent->maGeometry.nWidth - (long)maGeometry.nWidth)/2; - if( nNewX < aScreenRect.Left() ) - nNewX = aScreenRect.Left(); - if( long(nNewX + maGeometry.nWidth) > aScreenRect.Right() ) - nNewX = aScreenRect.Right() - maGeometry.nWidth-1; - long nNewY = mpParent->maGeometry.nY + ((long)mpParent->maGeometry.nHeight - (long)maGeometry.nHeight)/2; - if( nNewY < aScreenRect.Top() ) - nNewY = aScreenRect.Top(); - if( nNewY > aScreenRect.Bottom() ) - nNewY = aScreenRect.Bottom() - maGeometry.nHeight-1; - SetPosSize( nNewX - mpParent->maGeometry.nX, - nNewY - mpParent->maGeometry.nY, - 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ); - } - else if( ! (mnStyle & SAL_FRAME_STYLE_SIZEABLE) ) - { - // center on screen - long nNewX = (aScreenRect.GetWidth() - maGeometry.nWidth)/2; - long nNewY = (aScreenRect.GetHeight() - maGeometry.nHeight)/2; - SetPosSize( nNewX, nNewY, 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ); - } - } - - // make sure the view is present in the wrapper list before any children receive focus - [AquaA11yFactory registerView: mpNSView]; -} - -void AquaSalFrame::SendPaintEvent( const Rectangle* pRect ) -{ - SalPaintEvent aPaintEvt( 0, 0, maGeometry.nWidth, maGeometry.nHeight, true ); - if( pRect ) - { - aPaintEvt.mnBoundX = pRect->Left(); - aPaintEvt.mnBoundY = pRect->Top(); - aPaintEvt.mnBoundWidth = pRect->GetWidth(); - aPaintEvt.mnBoundHeight = pRect->GetHeight(); - } - - CallCallback(SALEVENT_PAINT, &aPaintEvt); -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::Show(sal_Bool bVisible, sal_Bool bNoActivate) -{ - if ( !mpNSWindow ) - return; - - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - mbShown = bVisible; - if(bVisible) - { - if( mbInitShow ) - initShow(); - - CallCallback(SALEVENT_RESIZE, 0); - // trigger filling our backbuffer - SendPaintEvent(); - - if( bNoActivate || [mpNSWindow canBecomeKeyWindow] == NO ) - [mpNSWindow orderFront: NSApp]; - else - [mpNSWindow makeKeyAndOrderFront: NSApp]; - - if( mpParent ) - { - /* #i92674# #i96433# we do not want an invisible parent to show up (which adding a visible - child implicitly does). However we also do not want a parentless toolbar. - - HACK: try to decide when we should not insert a child to its parent - floaters and ownerdraw windows have not yet shown up in cases where - we don't want the parent to become visible - */ - if( mpParent->mbShown || (mnStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_FLOAT) ) ) - { - [mpParent->mpNSWindow addChildWindow: mpNSWindow ordered: NSWindowAbove]; - } - } - - if( mbPresentation ) - [mpNSWindow makeMainWindow]; - } - else - { - // if the frame holding the current menubar gets hidden - // show the default menubar - if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu ) - AquaSalMenu::setDefaultMenu(); - - // #i90440# #i94443# work around the focus going back to some other window - // if a child gets hidden for a parent window - if( mpParent && mpParent->mbShown && [mpNSWindow isKeyWindow] ) - [mpParent->mpNSWindow makeKeyAndOrderFront: NSApp]; - - [SalFrameView unsetMouseFrame: this]; - if( mpParent && [mpNSWindow parentWindow] == mpParent->mpNSWindow ) - [mpParent->mpNSWindow removeChildWindow: mpNSWindow]; - - [mpNSWindow orderOut: NSApp]; - } -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::Enable( sal_Bool ) -{ -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::SetMinClientSize( long nWidth, long nHeight ) -{ - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - mnMinWidth = nWidth; - mnMinHeight = nHeight; - - if( mpNSWindow ) - { - // Always add the decoration as the dimension concerns only - // the content rectangle - nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration; - nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration; - - NSSize aSize = { static_cast(nWidth), static_cast(nHeight) }; - - // Size of full window (content+structure) although we only - // have the client size in arguments - [mpNSWindow setMinSize: aSize]; - } -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::SetMaxClientSize( long nWidth, long nHeight ) -{ - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - mnMaxWidth = nWidth; - mnMaxHeight = nHeight; - - if( mpNSWindow ) - { - // Always add the decoration as the dimension concerns only - // the content rectangle - nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration; - nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration; - - // Carbon windows can't have a size greater than 32767x32767 - if (nWidth>32767) nWidth=32767; - if (nHeight>32767) nHeight=32767; - - NSSize aSize = { static_cast(nWidth), static_cast(nHeight) }; - - // Size of full window (content+structure) although we only - // have the client size in arguments - [mpNSWindow setMaxSize: aSize]; - } -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::SetClientSize( long nWidth, long nHeight ) -{ - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - if( mpNSWindow ) - { - NSSize aSize = { static_cast(nWidth), static_cast(nHeight) }; - - [mpNSWindow setContentSize: aSize]; - UpdateFrameGeometry(); - if( mbShown ) - // trigger filling our backbuffer - SendPaintEvent(); - } -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::GetClientSize( long& rWidth, long& rHeight ) -{ - if( mbShown || mbInitShow ) - { - rWidth = maGeometry.nWidth; - rHeight = maGeometry.nHeight; - } - else - { - rWidth = 0; - rHeight = 0; - } -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::SetWindowState( const SalFrameState* pState ) -{ - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - if ( mpNSWindow ) - { - // set normal state - NSRect aStateRect = [mpNSWindow frame]; - aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask]; - CocoaToVCL( aStateRect ); - if( pState->mnMask & WINDOWSTATE_MASK_X ) - aStateRect.origin.x = float(pState->mnX); - if( pState->mnMask & WINDOWSTATE_MASK_Y ) - aStateRect.origin.y = float(pState->mnY); - if( pState->mnMask & WINDOWSTATE_MASK_WIDTH ) - aStateRect.size.width = float(pState->mnWidth); - if( pState->mnMask & WINDOWSTATE_MASK_HEIGHT ) - aStateRect.size.height = float(pState->mnHeight); - VCLToCocoa( aStateRect ); - aStateRect = [NSWindow frameRectForContentRect: aStateRect styleMask: mnStyleMask]; - - [mpNSWindow setFrame: aStateRect display: NO]; - if( pState->mnState == WINDOWSTATE_STATE_MINIMIZED ) - [mpNSWindow miniaturize: NSApp]; - else if( [mpNSWindow isMiniaturized] ) - [mpNSWindow deminiaturize: NSApp]; - - - /* ZOOMED is not really maximized (actually it toggles between a user set size and - the program specified one), but comes closest since the default behavior is - "maximized" if the user did not intervene - */ - if( pState->mnState == WINDOWSTATE_STATE_MAXIMIZED ) - { - if(! [mpNSWindow isZoomed]) - [mpNSWindow zoom: NSApp]; - } - else - { - if( [mpNSWindow isZoomed] ) - [mpNSWindow zoom: NSApp]; - } - } - - // get new geometry - UpdateFrameGeometry(); - - sal_uInt16 nEvent = 0; - if( pState->mnMask & (WINDOWSTATE_MASK_X | WINDOWSTATE_MASK_Y) ) - { - mbPositioned = true; - nEvent = SALEVENT_MOVE; - } - - if( pState->mnMask & (WINDOWSTATE_MASK_WIDTH | WINDOWSTATE_MASK_HEIGHT) ) - { - mbSized = true; - nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE; - } - // send event that we were moved/sized - if( nEvent ) - CallCallback( nEvent, NULL ); - - if( mbShown && mpNSWindow ) - { - // trigger filling our backbuffer - SendPaintEvent(); - - // tell the system the views need to be updated - [mpNSWindow display]; - } -} - -// ----------------------------------------------------------------------- - -sal_Bool AquaSalFrame::GetWindowState( SalFrameState* pState ) -{ - if ( !mpNSWindow ) - return FALSE; - - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - pState->mnMask = WINDOWSTATE_MASK_X | - WINDOWSTATE_MASK_Y | - WINDOWSTATE_MASK_WIDTH | - WINDOWSTATE_MASK_HEIGHT | - WINDOWSTATE_MASK_STATE; - - NSRect aStateRect = [mpNSWindow frame]; - aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask]; - CocoaToVCL( aStateRect ); - pState->mnX = long(aStateRect.origin.x); - pState->mnY = long(aStateRect.origin.y); - pState->mnWidth = long(aStateRect.size.width); - pState->mnHeight = long(aStateRect.size.height); - - if( [mpNSWindow isMiniaturized] ) - pState->mnState = WINDOWSTATE_STATE_MINIMIZED; - else if( ! [mpNSWindow isZoomed] ) - pState->mnState = WINDOWSTATE_STATE_NORMAL; - else - pState->mnState = WINDOWSTATE_STATE_MAXIMIZED; - - return TRUE; -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::SetScreenNumber(unsigned int nScreen) -{ - if ( !mpNSWindow ) - return; - - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - NSArray* pScreens = [NSScreen screens]; - Rectangle aRet; - NSScreen* pScreen = nil; - if( pScreens && nScreen < [pScreens count] ) - { - // get new screen frame - pScreen = [pScreens objectAtIndex: nScreen]; - NSRect aNewScreen = [pScreen frame]; - - // get current screen frame - pScreen = [mpNSWindow screen]; - if( pScreen ) - { - NSRect aCurScreen = [pScreen frame]; - if( aCurScreen.origin.x != aNewScreen.origin.x || - aCurScreen.origin.y != aNewScreen.origin.y ) - { - NSRect aFrameRect = [mpNSWindow frame]; - aFrameRect.origin.x += aNewScreen.origin.x - aCurScreen.origin.x; - aFrameRect.origin.y += aNewScreen.origin.y - aCurScreen.origin.y; - [mpNSWindow setFrame: aFrameRect display: NO]; - UpdateFrameGeometry(); - } - } - } -} - -void AquaSalFrame::SetApplicationID( const OUString &/*rApplicationID*/ ) -{ -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::ShowFullScreen( sal_Bool bFullScreen, sal_Int32 nDisplay ) -{ - if ( !mpNSWindow ) - return; - - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - SAL_INFO("vcl.macosx", OSL_THIS_FUNC << ": mbFullScreen=" << mbFullScreen << ", bFullScreen=" << bFullScreen); - - if( mbFullScreen == bFullScreen ) - return; - - mbFullScreen = bFullScreen; - - if( bFullScreen ) - { - // hide the dock and the menubar if we are on the menu screen - // which is always on index 0 according to documentation - bool bHideMenu = (nDisplay == 0); - - NSRect aNewContentRect = { { 0, 0 }, { 0, 0 } }; - // get correct screen - NSScreen* pScreen = nil; - NSArray* pScreens = [NSScreen screens]; - if( pScreens ) - { - if( nDisplay >= 0 && (unsigned int)nDisplay < [pScreens count] ) - pScreen = [pScreens objectAtIndex: nDisplay]; - else - { - // this means span all screens - bHideMenu = true; - NSEnumerator* pEnum = [pScreens objectEnumerator]; - while( (pScreen = [pEnum nextObject]) != nil ) - { - NSRect aScreenRect = [pScreen frame]; - if( aScreenRect.origin.x < aNewContentRect.origin.x ) - { - aNewContentRect.size.width += aNewContentRect.origin.x - aScreenRect.origin.x; - aNewContentRect.origin.x = aScreenRect.origin.x; - } - if( aScreenRect.origin.y < aNewContentRect.origin.y ) - { - aNewContentRect.size.height += aNewContentRect.origin.y - aScreenRect.origin.y; - aNewContentRect.origin.y = aScreenRect.origin.y; - } - if( aScreenRect.origin.x + aScreenRect.size.width > aNewContentRect.origin.x + aNewContentRect.size.width ) - aNewContentRect.size.width = aScreenRect.origin.x + aScreenRect.size.width - aNewContentRect.origin.x; - if( aScreenRect.origin.y + aScreenRect.size.height > aNewContentRect.origin.y + aNewContentRect.size.height ) - aNewContentRect.size.height = aScreenRect.origin.y + aScreenRect.size.height - aNewContentRect.origin.y; - } - } - } - if( aNewContentRect.size.width == 0 && aNewContentRect.size.height == 0 ) - { - if( pScreen == nil ) - pScreen = [mpNSWindow screen]; - if( pScreen == nil ) - pScreen = [NSScreen mainScreen]; - - aNewContentRect = [pScreen frame]; - } - - if( bHideMenu ) - [NSMenu setMenuBarVisible:NO]; - - maFullScreenRect = [mpNSWindow frame]; - { - [mpNSWindow setFrame: [NSWindow frameRectForContentRect: aNewContentRect styleMask: mnStyleMask] display: mbShown ? YES : NO]; - } - - UpdateFrameGeometry(); - - if( mbShown ) - CallCallback( SALEVENT_MOVERESIZE, NULL ); - } - else - { - { - [mpNSWindow setFrame: maFullScreenRect display: mbShown ? YES : NO]; - } - UpdateFrameGeometry(); - - if( mbShown ) - CallCallback( SALEVENT_MOVERESIZE, NULL ); - - // show the dock and the menubar - [NSMenu setMenuBarVisible:YES]; - } - if( mbShown ) - // trigger filling our backbuffer - SendPaintEvent(); -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::StartPresentation( sal_Bool bStart ) -{ - if ( !mpNSWindow ) - return; - - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - if( bStart ) - { - GetSalData()->maPresentationFrames.push_back( this ); - IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, - kIOPMAssertionLevelOn, - CFSTR("LibreOffice presentation running"), - &mnAssertionID); - [mpNSWindow setLevel: NSPopUpMenuWindowLevel]; - if( mbShown ) - [mpNSWindow makeMainWindow]; - } - else - { - GetSalData()->maPresentationFrames.remove( this ); - IOPMAssertionRelease(mnAssertionID); - [mpNSWindow setLevel: NSNormalWindowLevel]; - } -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::SetAlwaysOnTop( sal_Bool ) -{ -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::ToTop(sal_uInt16 nFlags) -{ - if ( !mpNSWindow ) - return; - - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - if( ! (nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN) ) - { - if( ! [mpNSWindow isVisible] || [mpNSWindow isMiniaturized] ) - return; - } - if( nFlags & SAL_FRAME_TOTOP_GRABFOCUS ) - [mpNSWindow makeKeyAndOrderFront: NSApp]; - else - [mpNSWindow orderFront: NSApp]; -} - -// ----------------------------------------------------------------------- - -NSCursor* AquaSalFrame::getCurrentCursor() const -{ - NSCursor* pCursor = nil; - switch( mePointerStyle ) - { - case POINTER_TEXT: pCursor = [NSCursor IBeamCursor]; break; - case POINTER_CROSS: pCursor = [NSCursor crosshairCursor]; break; - case POINTER_HAND: - case POINTER_MOVE: pCursor = [NSCursor openHandCursor]; break; - case POINTER_NSIZE: pCursor = [NSCursor resizeUpCursor]; break; - case POINTER_SSIZE: pCursor = [NSCursor resizeDownCursor]; break; - case POINTER_ESIZE: pCursor = [NSCursor resizeRightCursor]; break; - case POINTER_WSIZE: pCursor = [NSCursor resizeLeftCursor]; break; - case POINTER_ARROW: pCursor = [NSCursor arrowCursor]; break; - case POINTER_VSPLIT: - case POINTER_VSIZEBAR: - case POINTER_WINDOW_NSIZE: - case POINTER_WINDOW_SSIZE: - pCursor = [NSCursor resizeUpDownCursor]; break; - case POINTER_HSPLIT: - case POINTER_HSIZEBAR: - case POINTER_WINDOW_ESIZE: - case POINTER_WINDOW_WSIZE: - pCursor = [NSCursor resizeLeftRightCursor]; break; - case POINTER_REFHAND: pCursor = [NSCursor pointingHandCursor]; break; - case POINTER_NULL: [NSCursor hide]; break; - - default: - pCursor = GetSalData()->getCursor( mePointerStyle ); - if( pCursor == nil ) - { - OSL_FAIL( "unmapped cursor" ); - pCursor = [NSCursor arrowCursor]; - } - break; - } - return pCursor; -} - -void AquaSalFrame::SetPointer( PointerStyle ePointerStyle ) -{ - if ( !mpNSWindow ) - return; - - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - if( ePointerStyle >= POINTER_COUNT || ePointerStyle == mePointerStyle ) - return; - mePointerStyle = ePointerStyle; - - [mpNSWindow invalidateCursorRectsForView: mpNSView]; -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::SetPointerPos( long nX, long nY ) -{ - // FIXME: use Cocoa functions - - // FIXME: multiscreen support - CGPoint aPoint = { static_cast(nX + maGeometry.nX), static_cast(nY + maGeometry.nY) }; - CGDirectDisplayID mainDisplayID = CGMainDisplayID(); - CGDisplayMoveCursorToPoint( mainDisplayID, aPoint ); -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::Flush( void ) -{ - if( !(mbGraphics && mpGraphics && mpNSView && mbShown) ) - return; - - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - - [mpNSView setNeedsDisplay: YES]; - - // outside of the application's event loop (e.g. IntroWindow) - // nothing would trigger paint event handling - // => fall back to synchronous painting - if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 ) - { - [mpNSView display]; - } -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::Flush( const Rectangle& rRect ) -{ - if( !(mbGraphics && mpGraphics && mpNSView && mbShown) ) - return; - - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - NSRect aNSRect = { { static_cast(rRect.Left()), static_cast(rRect.Top()) }, { static_cast(rRect.GetWidth()), static_cast(rRect.GetHeight()) } }; - VCLToCocoa( aNSRect, false ); - [mpNSView setNeedsDisplayInRect: aNSRect]; - - // outside of the application's event loop (e.g. IntroWindow) - // nothing would trigger paint event handling - // => fall back to synchronous painting - if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 ) - { - [mpNSView display]; - } -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::Sync() -{ - if( mbGraphics && mpGraphics && mpNSView && mbShown ) - { - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - [mpNSView setNeedsDisplay: YES]; - [mpNSView display]; - } -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::SetInputContext( SalInputContext* pContext ) -{ - if (!pContext) - { - mnICOptions = 0; - return; - } - - mnICOptions = pContext->mnOptions; - - if(!(pContext->mnOptions & SAL_INPUTCONTEXT_TEXT)) - return; -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::EndExtTextInput( sal_uInt16 ) -{ -} - -// ----------------------------------------------------------------------- - -OUString AquaSalFrame::GetKeyName( sal_uInt16 nKeyCode ) -{ - static std::map< sal_uInt16, OUString > aKeyMap; - if( aKeyMap.empty() ) - { - sal_uInt16 i; - for( i = KEY_A; i <= KEY_Z; i++ ) - aKeyMap[ i ] = OUString( sal_Unicode( 'A' + (i - KEY_A) ) ); - for( i = KEY_0; i <= KEY_9; i++ ) - aKeyMap[ i ] = OUString( sal_Unicode( '0' + (i - KEY_0) ) ); - for( i = KEY_F1; i <= KEY_F26; i++ ) - { - OUStringBuffer aKey( 3 ); - aKey.append( 'F' ); - aKey.append( sal_Int32( i - KEY_F1 + 1 ) ); - aKeyMap[ i ] = aKey.makeStringAndClear(); - } - - aKeyMap[ KEY_DOWN ] = OUString( sal_Unicode( 0x21e3 ) ); - aKeyMap[ KEY_UP ] = OUString( sal_Unicode( 0x21e1 ) ); - aKeyMap[ KEY_LEFT ] = OUString( sal_Unicode( 0x21e0 ) ); - aKeyMap[ KEY_RIGHT ] = OUString( sal_Unicode( 0x21e2 ) ); - aKeyMap[ KEY_HOME ] = OUString( sal_Unicode( 0x2196 ) ); - aKeyMap[ KEY_END ] = OUString( sal_Unicode( 0x2198 ) ); - aKeyMap[ KEY_PAGEUP ] = OUString( sal_Unicode( 0x21de ) ); - aKeyMap[ KEY_PAGEDOWN ] = OUString( sal_Unicode( 0x21df ) ); - aKeyMap[ KEY_RETURN ] = OUString( sal_Unicode( 0x21a9 ) ); - aKeyMap[ KEY_ESCAPE ] = OUString( "esc" ); - aKeyMap[ KEY_TAB ] = OUString( sal_Unicode( 0x21e5 ) ); - aKeyMap[ KEY_BACKSPACE ]= OUString( sal_Unicode( 0x232b ) ); - aKeyMap[ KEY_SPACE ] = OUString( sal_Unicode( 0x2423 ) ); - aKeyMap[ KEY_DELETE ] = OUString( sal_Unicode( 0x2326 ) ); - aKeyMap[ KEY_ADD ] = OUString( '+' ); - aKeyMap[ KEY_SUBTRACT ] = OUString( '-' ); - aKeyMap[ KEY_DIVIDE ] = OUString( '/' ); - aKeyMap[ KEY_MULTIPLY ] = OUString( '*' ); - aKeyMap[ KEY_POINT ] = OUString( '.' ); - aKeyMap[ KEY_COMMA ] = OUString( ',' ); - aKeyMap[ KEY_LESS ] = OUString( '<' ); - aKeyMap[ KEY_GREATER ] = OUString( '>' ); - aKeyMap[ KEY_EQUAL ] = OUString( '=' ); - aKeyMap[ KEY_OPEN ] = OUString( sal_Unicode( 0x23cf ) ); - - /* yet unmapped KEYCODES: - aKeyMap[ KEY_INSERT ] = OUString( sal_Unicode( ) ); - aKeyMap[ KEY_CUT ] = OUString( sal_Unicode( ) ); - aKeyMap[ KEY_COPY ] = OUString( sal_Unicode( ) ); - aKeyMap[ KEY_PASTE ] = OUString( sal_Unicode( ) ); - aKeyMap[ KEY_UNDO ] = OUString( sal_Unicode( ) ); - aKeyMap[ KEY_REPEAT ] = OUString( sal_Unicode( ) ); - aKeyMap[ KEY_FIND ] = OUString( sal_Unicode( ) ); - aKeyMap[ KEY_PROPERTIES ] = OUString( sal_Unicode( ) ); - aKeyMap[ KEY_FRONT ] = OUString( sal_Unicode( ) ); - aKeyMap[ KEY_CONTEXTMENU ] = OUString( sal_Unicode( ) ); - aKeyMap[ KEY_MENU ] = OUString( sal_Unicode( ) ); - aKeyMap[ KEY_HELP ] = OUString( sal_Unicode( ) ); - aKeyMap[ KEY_HANGUL_HANJA ] = OUString( sal_Unicode( ) ); - aKeyMap[ KEY_DECIMAL ] = OUString( sal_Unicode( ) ); - aKeyMap[ KEY_TILDE ] = OUString( sal_Unicode( ) ); - aKeyMap[ KEY_QUOTELEFT ]= OUString( sal_Unicode( ) ); - */ - - } - - OUStringBuffer aResult( 16 ); - - sal_uInt16 nUnmodifiedCode = (nKeyCode & KEY_CODE); - std::map< sal_uInt16, OUString >::const_iterator it = aKeyMap.find( nUnmodifiedCode ); - if( it != aKeyMap.end() ) - { - if( (nKeyCode & KEY_SHIFT) != 0 ) - aResult.append( sal_Unicode( 0x21e7 ) ); - if( (nKeyCode & KEY_MOD1) != 0 ) - aResult.append( sal_Unicode( 0x2318 ) ); - // we do not really handle Alt (see below) - // we map it to MOD3, whichis actually Command - if( (nKeyCode & (KEY_MOD2|KEY_MOD3)) != 0 ) - aResult.append( sal_Unicode( 0x2303 ) ); - - aResult.append( it->second ); - } - - return aResult.makeStringAndClear(); -} - -// ----------------------------------------------------------------------- - -static void getAppleScrollBarVariant(StyleSettings &rSettings) -{ - bool bIsScrollbarDoubleMax = true; // default is DoubleMax - - CFStringRef AppleScrollBarType = CFSTR("AppleScrollBarVariant"); - if( AppleScrollBarType ) - { - CFStringRef ScrollBarVariant = ((CFStringRef)CFPreferencesCopyAppValue( AppleScrollBarType, kCFPreferencesCurrentApplication )); - if( ScrollBarVariant ) - { - if( CFGetTypeID( ScrollBarVariant ) == CFStringGetTypeID() ) - { - // TODO: check for the less important variants "DoubleMin" and "DoubleBoth" too - CFStringRef DoubleMax = CFSTR("DoubleMax"); - if (DoubleMax) - { - if ( !CFStringCompare(ScrollBarVariant, DoubleMax, kCFCompareCaseInsensitive) ) - bIsScrollbarDoubleMax = true; - else - bIsScrollbarDoubleMax = false; - CFRelease(DoubleMax); - } - } - CFRelease( ScrollBarVariant ); - } - CFRelease(AppleScrollBarType); - } - - GetSalData()->mbIsScrollbarDoubleMax = bIsScrollbarDoubleMax; - - CFStringRef jumpScroll = CFSTR("AppleScrollerPagingBehavior"); - if( jumpScroll ) - { - CFBooleanRef jumpStr = ((CFBooleanRef)CFPreferencesCopyAppValue( jumpScroll, kCFPreferencesCurrentApplication )); - if( jumpStr ) - { - if( CFGetTypeID( jumpStr ) == CFBooleanGetTypeID() ) - rSettings.SetPrimaryButtonWarpsSlider(jumpStr == kCFBooleanTrue); - CFRelease( jumpStr ); - } - CFRelease( jumpScroll ); - } -} - -static Color getColor( NSColor* pSysColor, const Color& rDefault, NSWindow* pWin ) -{ - Color aRet( rDefault ); - if( pSysColor ) - { - // transform to RGB - NSColor* pRBGColor = [pSysColor colorUsingColorSpaceName: NSDeviceRGBColorSpace device: [pWin deviceDescription]]; - if( pRBGColor ) - { - CGFloat r = 0, g = 0, b = 0, a = 0; - [pRBGColor getRed: &r green: &g blue: &b alpha: &a]; - aRet = Color( int(r*255.999), int(g*255.999), int(b*255.999) ); - /* - do not release here; leads to duplicate free in yield - it seems the converted color comes out autoreleased, although this - is not documented - [pRBGColor release]; - */ - } - } - return aRet; -} - -static Font getFont( NSFont* pFont, long nDPIY, const Font& rDefault ) -{ - Font aResult( rDefault ); - if( pFont ) - { - aResult.SetName( GetOUString( [pFont familyName] ) ); - aResult.SetHeight( static_cast(([pFont pointSize] * 72.0 / (float)nDPIY)+0.5) ); - aResult.SetItalic( ([pFont italicAngle] != 0.0) ? ITALIC_NORMAL : ITALIC_NONE ); - // FIMXE: bold ? - } - - return aResult; -} - -void AquaSalFrame::getResolution( sal_Int32& o_rDPIX, sal_Int32& o_rDPIY ) -{ - if( ! mpGraphics ) - { - GetGraphics(); - ReleaseGraphics( mpGraphics ); - } - mpGraphics->GetResolution( o_rDPIX, o_rDPIY ); -} - -// on OSX-Aqua the style settings are independent of the frame, so it does -// not really belong here. Since the connection to the Appearance_Manager -// is currently done in salnativewidgets.cxx this would be a good place. -// On the other hand VCL's platform independent code currently only asks -// SalFrames for system settings anyway, so moving the code somewhere else -// doesn't make the anything cleaner for now -void AquaSalFrame::UpdateSettings( AllSettings& rSettings ) -{ - if ( !mpNSWindow ) - return; - - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - [mpNSView lockFocus]; - - StyleSettings aStyleSettings = rSettings.GetStyleSettings(); - - // Background Color - Color aBackgroundColor = Color( 0xEC, 0xEC, 0xEC ); - aStyleSettings.Set3DColors( aBackgroundColor ); - aStyleSettings.SetFaceColor( aBackgroundColor ); - Color aInactiveTabColor( aBackgroundColor ); - aInactiveTabColor.DecreaseLuminance( 32 ); - aStyleSettings.SetInactiveTabColor( aInactiveTabColor ); - - aStyleSettings.SetDialogColor( aBackgroundColor ); - aStyleSettings.SetLightBorderColor( aBackgroundColor ); - Color aShadowColor( aStyleSettings.GetShadowColor() ); - aShadowColor.IncreaseLuminance( 32 ); - aStyleSettings.SetShadowColor( aShadowColor ); - - // get the system font settings - Font aAppFont = aStyleSettings.GetAppFont(); - sal_Int32 nDPIX = 72, nDPIY = 72; - getResolution( nDPIX, nDPIY ); - aAppFont = getFont( [NSFont systemFontOfSize: 0], nDPIY, aAppFont ); - - aStyleSettings.SetToolbarIconSize( STYLE_TOOLBAR_ICONSIZE_LARGE ); - - // TODO: better mapping of aqua<->ooo font settings - aStyleSettings.SetAppFont( aAppFont ); - aStyleSettings.SetHelpFont( aAppFont ); - aStyleSettings.SetPushButtonFont( aAppFont ); - - Font aTitleFont( getFont( [NSFont titleBarFontOfSize: 0], nDPIY, aAppFont ) ); - aStyleSettings.SetTitleFont( aTitleFont ); - aStyleSettings.SetFloatTitleFont( aTitleFont ); - - Font aMenuFont( getFont( [NSFont menuFontOfSize: 0], nDPIY, aAppFont ) ); - aStyleSettings.SetMenuFont( aMenuFont ); - - aStyleSettings.SetToolFont( aAppFont ); - - Font aLabelFont( getFont( [NSFont labelFontOfSize: 0], nDPIY, aAppFont ) ); - aStyleSettings.SetLabelFont( aLabelFont ); - aStyleSettings.SetInfoFont( aLabelFont ); - aStyleSettings.SetRadioCheckFont( aLabelFont ); - aStyleSettings.SetFieldFont( aLabelFont ); - aStyleSettings.SetGroupFont( aLabelFont ); - aStyleSettings.SetIconFont( aLabelFont ); - - Color aHighlightColor( getColor( [NSColor selectedTextBackgroundColor], - aStyleSettings.GetHighlightColor(), mpNSWindow ) ); - aStyleSettings.SetHighlightColor( aHighlightColor ); - Color aHighlightTextColor( getColor( [NSColor selectedTextColor], - aStyleSettings.GetHighlightTextColor(), mpNSWindow ) ); - aStyleSettings.SetHighlightTextColor( aHighlightTextColor ); - - Color aMenuHighlightColor( getColor( [NSColor selectedMenuItemColor], - aStyleSettings.GetMenuHighlightColor(), mpNSWindow ) ); - aStyleSettings.SetMenuHighlightColor( aMenuHighlightColor ); - Color aMenuHighlightTextColor( getColor( [NSColor selectedMenuItemTextColor], - aStyleSettings.GetMenuHighlightTextColor(), mpNSWindow ) ); - aStyleSettings.SetMenuHighlightTextColor( aMenuHighlightTextColor ); - - aStyleSettings.SetMenuColor( aBackgroundColor ); - Color aMenuTextColor( getColor( [NSColor textColor], - aStyleSettings.GetMenuTextColor(), mpNSWindow ) ); - aStyleSettings.SetMenuTextColor( aMenuTextColor ); - aStyleSettings.SetMenuBarTextColor( aMenuTextColor ); - aStyleSettings.SetMenuBarRolloverTextColor( aMenuTextColor ); - - aStyleSettings.SetCursorBlinkTime( 500 ); - - // no mnemonics on aqua - aStyleSettings.SetOptions( aStyleSettings.GetOptions() | STYLE_OPTION_NOMNEMONICS ); - - getAppleScrollBarVariant(aStyleSettings); - - // set scrollbar size - aStyleSettings.SetScrollBarSize( static_cast([NSScroller scrollerWidth]) ); - - // images in menus false for MacOSX - aStyleSettings.SetPreferredUseImagesInMenus( false ); - aStyleSettings.SetHideDisabledMenuItems( sal_True ); - aStyleSettings.SetAcceleratorsInContextMenus( sal_False ); - - rSettings.SetStyleSettings( aStyleSettings ); - - [mpNSView unlockFocus]; -} - -// ----------------------------------------------------------------------- - -const SystemEnvData* AquaSalFrame::GetSystemData() const -{ - return &maSysData; -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::Beep() -{ - NSBeep(); -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::SetPosSize(long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags) -{ - if ( !mpNSWindow ) - return; - - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - sal_uInt16 nEvent = 0; - - if( [mpNSWindow isMiniaturized] ) - [mpNSWindow deminiaturize: NSApp]; // expand the window - - if (nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y)) - { - mbPositioned = true; - nEvent = SALEVENT_MOVE; - } - - if (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) - { - mbSized = true; - nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE; - } - - NSRect aFrameRect = [mpNSWindow frame]; - NSRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask]; - - // position is always relative to parent frame - NSRect aParentContentRect; - - if( mpParent ) - { - if( Application::GetSettings().GetLayoutRTL() ) - { - if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 ) - nX = mpParent->maGeometry.nWidth - nWidth-1 - nX; - else - nX = mpParent->maGeometry.nWidth - static_cast( aContentRect.size.width-1) - nX; - } - NSRect aParentFrameRect = [mpParent->mpNSWindow frame]; - aParentContentRect = [NSWindow contentRectForFrameRect: aParentFrameRect styleMask: mpParent->mnStyleMask]; - } - else - aParentContentRect = maScreenRect; // use screen if no parent - - CocoaToVCL( aContentRect ); - CocoaToVCL( aParentContentRect ); - - bool bPaint = false; - if( (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) != 0 ) - { - if( nWidth != aContentRect.size.width || nHeight != aContentRect.size.height ) - bPaint = true; - } - - // use old window pos if no new pos requested - if( (nFlags & SAL_FRAME_POSSIZE_X) != 0 ) - aContentRect.origin.x = nX + aParentContentRect.origin.x; - if( (nFlags & SAL_FRAME_POSSIZE_Y) != 0) - aContentRect.origin.y = nY + aParentContentRect.origin.y; - - // use old size if no new size requested - if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 ) - aContentRect.size.width = nWidth; - if( (nFlags & SAL_FRAME_POSSIZE_HEIGHT) != 0) - aContentRect.size.height = nHeight; - - VCLToCocoa( aContentRect ); - - // do not display yet, we need to update our backbuffer - { - [mpNSWindow setFrame: [NSWindow frameRectForContentRect: aContentRect styleMask: mnStyleMask] display: NO]; - } - - UpdateFrameGeometry(); - - if (nEvent) - CallCallback(nEvent, NULL); - - if( mbShown && bPaint ) - { - // trigger filling our backbuffer - SendPaintEvent(); - - // now inform the system that the views need to be drawn - [mpNSWindow display]; - } -} - -void AquaSalFrame::GetWorkArea( Rectangle& rRect ) -{ - if ( !mpNSWindow ) - return; - - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - NSScreen* pScreen = [mpNSWindow screen]; - if( pScreen == nil ) - pScreen = [NSScreen mainScreen]; - NSRect aRect = [pScreen visibleFrame]; - CocoaToVCL( aRect ); - rRect.Left() = static_cast(aRect.origin.x); - rRect.Top() = static_cast(aRect.origin.y); - rRect.Right() = static_cast(aRect.origin.x + aRect.size.width - 1); - rRect.Bottom() = static_cast(aRect.origin.y + aRect.size.height - 1); -} - -SalPointerState AquaSalFrame::GetPointerState() -{ - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - SalPointerState state; - state.mnState = 0; - - // get position - NSPoint aPt = [mpNSWindow mouseLocationOutsideOfEventStream]; - CocoaToVCL( aPt, false ); - state.maPos = Point(static_cast(aPt.x), static_cast(aPt.y)); - - NSEvent* pCur = [NSApp currentEvent]; - bool bMouseEvent = false; - if( pCur ) - { - bMouseEvent = true; - switch( [pCur type] ) - { - case NSLeftMouseDown: state.mnState |= MOUSE_LEFT; break; - case NSLeftMouseUp: break; - case NSRightMouseDown: state.mnState |= MOUSE_RIGHT; break; - case NSRightMouseUp: break; - case NSOtherMouseDown: state.mnState |= ([pCur buttonNumber] == 2) ? MOUSE_MIDDLE : 0; break; - case NSOtherMouseUp: break; - case NSMouseMoved: break; - case NSLeftMouseDragged: state.mnState |= MOUSE_LEFT; break; - case NSRightMouseDragged: state.mnState |= MOUSE_RIGHT; break; - case NSOtherMouseDragged: state.mnState |= ([pCur buttonNumber] == 2) ? MOUSE_MIDDLE : 0; break; - break; - default: - bMouseEvent = false; - break; - } - } - if( bMouseEvent ) - { - unsigned int nMask = (unsigned int)[pCur modifierFlags]; - if( (nMask & NSShiftKeyMask) != 0 ) - state.mnState |= KEY_SHIFT; - if( (nMask & NSControlKeyMask) != 0 ) - state.mnState |= KEY_MOD3; - if( (nMask & NSAlternateKeyMask) != 0 ) - state.mnState |= KEY_MOD2; - if( (nMask & NSCommandKeyMask) != 0 ) - state.mnState |= KEY_MOD1; - - } - else - { - // FIXME: replace Carbon by Cocoa - // Cocoa does not have an equivalent for GetCurrentEventButtonState - // and GetCurrentEventKeyModifiers. - // we could try to get away with tracking all events for modifierKeys - // and all mouse events for button state in VCL_NSApllication::sendEvent, - // but it is unclear whether this will get us the same result. - // leave in GetCurrentEventButtonState and GetCurrentEventKeyModifiers for now - - // fill in button state - UInt32 nState = GetCurrentEventButtonState(); - state.mnState = 0; - if( nState & 1 ) - state.mnState |= MOUSE_LEFT; // primary button - if( nState & 2 ) - state.mnState |= MOUSE_RIGHT; // secondary button - if( nState & 4 ) - state.mnState |= MOUSE_MIDDLE; // tertiary button - - // fill in modifier state - nState = GetCurrentEventKeyModifiers(); - if( nState & shiftKey ) - state.mnState |= KEY_SHIFT; - if( nState & controlKey ) - state.mnState |= KEY_MOD3; - if( nState & optionKey ) - state.mnState |= KEY_MOD2; - if( nState & cmdKey ) - state.mnState |= KEY_MOD1; - } - - - return state; -} - -SalFrame::SalIndicatorState AquaSalFrame::GetIndicatorState() -{ - SalIndicatorState aState; - aState.mnState = 0; - return aState; -} - -void AquaSalFrame::SimulateKeyPress( sal_uInt16 /*nKeyCode*/ ) -{ -} - -bool AquaSalFrame::SetPluginParent( SystemParentData* ) -{ - // plugin parent may be killed unexpectedly by - // plugging process; - - //TODO: implement - return sal_False; -} - -sal_Bool AquaSalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , KeyCode& ) -{ - // not supported yet - return FALSE; -} - -LanguageType AquaSalFrame::GetInputLanguage() -{ - //TODO: implement - return LANGUAGE_DONTKNOW; -} - -void AquaSalFrame::DrawMenuBar() -{ -} - -void AquaSalFrame::SetMenu( SalMenu* pSalMenu ) -{ - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - AquaSalMenu* pMenu = static_cast(pSalMenu); - DBG_ASSERT( ! pMenu || pMenu->mbMenuBar, "setting non menubar on frame" ); - mpMenu = pMenu; - if( mpMenu ) - mpMenu->setMainMenu(); -} - -void AquaSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle ) -{ - if ( mpNSWindow ) - { - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - if( (mnExtStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) != (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) ) - [mpNSWindow setDocumentEdited: (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) ? YES : NO]; - } - - mnExtStyle = nStyle; -} - -SalFrame* AquaSalFrame::GetParent() const -{ - return mpParent; -} - -void AquaSalFrame::SetParent( SalFrame* pNewParent ) -{ - bool bShown = mbShown; - // remove from child list - Show( FALSE ); - mpParent = (AquaSalFrame*)pNewParent; - // insert to correct parent and paint - Show( bShown ); -} - -void AquaSalFrame::UpdateFrameGeometry() -{ - if ( !mpNSWindow ) - { - return; - } - - // keep in mind that view and window coordinates are lower left - // whereas vcl's are upper left - - // update screen rect - NSScreen * pScreen = [mpNSWindow screen]; - if( pScreen ) - { - maScreenRect = [pScreen frame]; - NSArray* pScreens = [NSScreen screens]; - if( pScreens ) - maGeometry.nDisplayScreenNumber = [pScreens indexOfObject: pScreen]; - } - - NSRect aFrameRect = [mpNSWindow frame]; - NSRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask]; - - // release old track rect - [mpNSView removeTrackingRect: mnTrackingRectTag]; - // install the new track rect - NSRect aTrackRect = { { 0, 0 }, aContentRect.size }; - mnTrackingRectTag = [mpNSView addTrackingRect: aTrackRect owner: mpNSView userData: nil assumeInside: NO]; - - // convert to vcl convention - CocoaToVCL( aFrameRect ); - CocoaToVCL( aContentRect ); - - maGeometry.nX = static_cast(aContentRect.origin.x); - maGeometry.nY = static_cast(aContentRect.origin.y); - - maGeometry.nLeftDecoration = static_cast(aContentRect.origin.x - aFrameRect.origin.x); - maGeometry.nRightDecoration = static_cast((aFrameRect.origin.x + aFrameRect.size.width) - - (aContentRect.origin.x + aContentRect.size.width)); - - maGeometry.nTopDecoration = static_cast(aContentRect.origin.y - aFrameRect.origin.y); - maGeometry.nBottomDecoration = static_cast((aFrameRect.origin.y + aFrameRect.size.height) - - (aContentRect.origin.y + aContentRect.size.height)); - - maGeometry.nWidth = static_cast(aContentRect.size.width); - maGeometry.nHeight = static_cast(aContentRect.size.height); -} - -// ----------------------------------------------------------------------- - -void AquaSalFrame::CaptureMouse( sal_Bool bCapture ) -{ - /* Remark: - we'll try to use a pidgin version of capture mouse - on MacOSX (neither carbon nor cocoa) there is a - CaptureMouse equivalent (in Carbon there is TrackMouseLocation - but this is useless to use since it is blocking) - - However on cocoa the active frame seems to get mouse events - also outside the window, so we'll try to forward mouse events - to the capture frame in the hope that one of our frames - gets a mouse event. - - This will break as soon as the user activates another app, but - a mouse click will normally lead to a release of the mouse anyway. - - Let's see how far we get this way. Alternatively we could use one - large overlay window like we did for the carbon implementation, - however that is resource intensive. - */ - - if( bCapture ) - s_pCaptureFrame = this; - else if( ! bCapture && s_pCaptureFrame == this ) - s_pCaptureFrame = NULL; -} - -void AquaSalFrame::ResetClipRegion() -{ - if ( !mpNSWindow ) - { - return; - } - - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - // release old path and indicate no clipping - CGPathRelease( mrClippingPath ); - mrClippingPath = NULL; - - if( mpNSView && mbShown ) - [mpNSView setNeedsDisplay: YES]; - if( mpNSWindow ) - { - [mpNSWindow setOpaque: YES]; - [mpNSWindow invalidateShadow]; - } -} - -void AquaSalFrame::BeginSetClipRegion( sal_uLong nRects ) -{ - if ( !mpNSWindow ) - { - return; - } - - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - // release old path - if( mrClippingPath ) - { - CGPathRelease( mrClippingPath ); - mrClippingPath = NULL; - } - - if( maClippingRects.size() > SAL_CLIPRECT_COUNT && nRects < maClippingRects.size() ) - { - std::vector aEmptyVec; - maClippingRects.swap( aEmptyVec ); - } - maClippingRects.clear(); - maClippingRects.reserve( nRects ); -} - -void AquaSalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) -{ - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - if( nWidth && nHeight ) - { - NSRect aRect = { { static_cast(nX), static_cast(nY) }, { static_cast(nWidth), static_cast(nHeight) } }; - VCLToCocoa( aRect, false ); - maClippingRects.push_back( CGRectMake(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height) ); - } -} - -void AquaSalFrame::EndSetClipRegion() -{ - if ( !mpNSWindow ) - { - return; - } - - // #i113170# may not be the main thread if called from UNO API - SalData::ensureThreadAutoreleasePool(); - - if( ! maClippingRects.empty() ) - { - mrClippingPath = CGPathCreateMutable(); - CGPathAddRects( mrClippingPath, NULL, &maClippingRects[0], maClippingRects.size() ); - } - if( mpNSView && mbShown ) - [mpNSView setNeedsDisplay: YES]; - if( mpNSWindow ) - { - [mpNSWindow setOpaque: (mrClippingPath != NULL) ? NO : YES]; - [mpNSWindow setBackgroundColor: [NSColor clearColor]]; - // shadow is invalidated when view gets drawn again - } -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/window/salframeview.mm b/vcl/aqua/source/window/salframeview.mm deleted file mode 100644 index 10986d06b423..000000000000 --- a/vcl/aqua/source/window/salframeview.mm +++ /dev/null @@ -1,1805 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include -#include - -#include "tools/helpers.hxx" -#include "vcl/window.hxx" -#include "vcl/svapp.hxx" - -#include "aqua/salinst.h" -#include "coretext/salgdi.h" -#include "aqua/salframe.h" -#include "aqua/salframeview.h" -#include "aqua/aqua11yfactory.h" -#include "quartz/utils.h" - -#define WHEEL_EVENT_FACTOR 1.5 - -// for allowing fullscreen support on deployment targets < OSX 10.7 -#if !defined(MAC_OS_X_VERSION_10_7) - #define NSWindowCollectionBehaviorFullScreenPrimary (1 << 7) - #define NSWindowCollectionBehaviorFullScreenAuxiliary (1 << 8) -// #define NSFullScreenWindowMask (1 << 14) -#endif - - -static sal_uInt16 ImplGetModifierMask( unsigned int nMask ) -{ - sal_uInt16 nRet = 0; - if( (nMask & NSShiftKeyMask) != 0 ) - nRet |= KEY_SHIFT; - if( (nMask & NSControlKeyMask) != 0 ) - nRet |= KEY_MOD3; - if( (nMask & NSAlternateKeyMask) != 0 ) - nRet |= KEY_MOD2; - if( (nMask & NSCommandKeyMask) != 0 ) - nRet |= KEY_MOD1; - return nRet; -} - -static sal_uInt16 ImplMapCharCode( sal_Unicode aCode ) -{ - static sal_uInt16 aKeyCodeMap[ 128 ] = - { - 0, 0, 0, 0, 0, 0, 0, 0, - KEY_BACKSPACE, KEY_TAB, KEY_RETURN, 0, 0, KEY_RETURN, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, KEY_TAB, 0, KEY_ESCAPE, 0, 0, 0, 0, - KEY_SPACE, 0, 0, 0, 0, 0, 0, 0, - 0, 0, KEY_MULTIPLY, KEY_ADD, KEY_COMMA, KEY_SUBTRACT, KEY_POINT, KEY_DIVIDE, - KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, - KEY_8, KEY_9, 0, 0, KEY_LESS, KEY_EQUAL, KEY_GREATER, 0, - 0, KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, - KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, - KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, - KEY_X, KEY_Y, KEY_Z, 0, 0, 0, 0, 0, - KEY_QUOTELEFT, KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, - KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, - KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, - KEY_X, KEY_Y, KEY_Z, 0, 0, 0, KEY_TILDE, KEY_BACKSPACE - }; - - // Note: the mapping 0x7f should by rights be KEY_DELETE - // however if you press "backspace" 0x7f is reported - // whereas for "delete" 0xf728 gets reported - - // Note: the mapping of 0x19 to KEY_TAB is because for unknown reasons - // tab alone is reported as 0x09 (as expected) but shift-tab is - // reported as 0x19 (end of medium) - - static sal_uInt16 aFunctionKeyCodeMap[ 128 ] = - { - KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_F1, KEY_F2, KEY_F3, KEY_F4, - KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, - KEY_F13, KEY_F14, KEY_F15, KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20, - KEY_F21, KEY_F22, KEY_F23, KEY_F24, KEY_F25, KEY_F26, 0, 0, - 0, 0, 0, 0, 0, 0, 0, KEY_INSERT, - KEY_DELETE, KEY_HOME, 0, KEY_END, KEY_PAGEUP, KEY_PAGEDOWN, 0, 0, - 0, 0, 0, 0, 0, KEY_MENU, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, KEY_UNDO, KEY_REPEAT, KEY_FIND, KEY_HELP, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 - }; - - sal_uInt16 nKeyCode = 0; - if( aCode < SAL_N_ELEMENTS( aKeyCodeMap) ) - nKeyCode = aKeyCodeMap[ aCode ]; - else if( aCode >= 0xf700 && aCode < 0xf780 ) - nKeyCode = aFunctionKeyCodeMap[ aCode - 0xf700 ]; - return nKeyCode; -} - -static sal_uInt16 ImplMapKeyCode(sal_uInt16 nKeyCode) -{ - /* - http://stackoverflow.com/questions/2080312/where-can-i-find-a-list-of-key-codes-for-use-with-cocoas-nsevent-class/2080324#2080324 - /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h - */ - - static sal_uInt16 aKeyCodeMap[ 0x80 ] = - { - KEY_A, KEY_S, KEY_D, KEY_F, KEY_H, KEY_G, KEY_Z, KEY_X, - KEY_C, KEY_V, 0, KEY_B, KEY_Q, KEY_W, KEY_E, KEY_R, - KEY_Y, KEY_T, KEY_1, KEY_2, KEY_3, KEY_4, KEY_6, KEY_5, - KEY_EQUAL, KEY_9, KEY_7, KEY_SUBTRACT, KEY_8, KEY_0, KEY_BRACKETRIGHT, KEY_0, - KEY_U, KEY_BRACKETLEFT, KEY_I, KEY_P, KEY_RETURN, KEY_L, KEY_J, KEY_QUOTELEFT, - KEY_K, KEY_SEMICOLON, 0, KEY_COMMA, KEY_DIVIDE, KEY_N, KEY_M, KEY_POINT, - KEY_TAB, KEY_SPACE, KEY_TILDE, KEY_DELETE, 0, KEY_ESCAPE, 0, 0, - 0, KEY_CAPSLOCK, 0, 0, 0, 0, 0, 0, - KEY_F17, KEY_DECIMAL, 0, KEY_MULTIPLY, 0, KEY_ADD, 0, 0, - 0, 0, 0, KEY_DIVIDE, KEY_RETURN, 0, KEY_SUBTRACT, KEY_F18, - KEY_F19, KEY_EQUAL, 0, 0, 0, 0, 0, 0, - 0, 0, KEY_F20, 0, 0, 0, 0, 0, - KEY_F5, KEY_F6, KEY_F7, KEY_F3, KEY_F8, KEY_F9, 0, KEY_F11, - 0, KEY_F13, KEY_F16, KEY_F14, 0, KEY_F10, 0, KEY_F12, - 0, KEY_F15, KEY_HELP, KEY_HOME, KEY_PAGEUP, KEY_DELETE, KEY_F4, KEY_END, - KEY_F2, KEY_PAGEDOWN, KEY_F1, KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_UP, 0 - }; - - if (nKeyCode < SAL_N_ELEMENTS(aKeyCodeMap)) - return aKeyCodeMap[nKeyCode]; - return 0; -} - -// store the frame the mouse last entered -static AquaSalFrame* s_pMouseFrame = NULL; -// store the last pressed button for enter/exit events -// which lack that information -static sal_uInt16 s_nLastButton = 0; - -// combinations of keys we need to handle ourselves -static const struct ExceptionalKey -{ - const sal_uInt16 nKeyCode; - const unsigned int nModifierMask; -} aExceptionalKeys[] = -{ - { KEY_D, NSControlKeyMask | NSShiftKeyMask | NSAlternateKeyMask }, - { KEY_D, NSCommandKeyMask | NSShiftKeyMask | NSAlternateKeyMask } -}; - -static AquaSalFrame* getMouseContainerFrame() -{ - NSInteger nWindows = 0; - NSCountWindows( &nWindows ); - NSInteger* pWindows = (NSInteger*)alloca( nWindows * sizeof(NSInteger) ); - // note: NSWindowList is supposed to be in z-order front to back - NSWindowList( nWindows, pWindows ); - AquaSalFrame* pDispatchFrame = NULL; - for(int i = 0; i < nWindows && ! pDispatchFrame; i++ ) - { - NSWindow* pWin = [NSApp windowWithWindowNumber: pWindows[i]]; - if( pWin && [pWin isMemberOfClass: [SalFrameWindow class]] && [(SalFrameWindow*)pWin containsMouse] ) - pDispatchFrame = [(SalFrameWindow*)pWin getSalFrame]; - } - return pDispatchFrame; -} - -@implementation SalFrameWindow --(id)initWithSalFrame: (AquaSalFrame*)pFrame -{ - mDraggingDestinationHandler = nil; - mpFrame = pFrame; - NSRect aRect = { { static_cast(pFrame->maGeometry.nX), static_cast(pFrame->maGeometry.nY) }, - { static_cast(pFrame->maGeometry.nWidth), static_cast(pFrame->maGeometry.nHeight) } }; - pFrame->VCLToCocoa( aRect ); - NSWindow* pNSWindow = [super initWithContentRect: aRect styleMask: mpFrame->getStyleMask() backing: NSBackingStoreBuffered defer: NO ]; - [pNSWindow useOptimizedDrawing: YES]; // OSX recommendation when there are no overlapping subviews within the receiver - - // enable OSX>=10.7 fullscreen options if available and useful - bool bAllowFullScreen = (0 == (mpFrame->mnStyle & (SAL_FRAME_STYLE_DIALOG | SAL_FRAME_STYLE_TOOLTIP | SAL_FRAME_STYLE_SYSTEMCHILD | SAL_FRAME_STYLE_FLOAT | SAL_FRAME_STYLE_TOOLWINDOW | SAL_FRAME_STYLE_INTRO))); - bAllowFullScreen &= (0 == (~mpFrame->mnStyle & (SAL_FRAME_STYLE_SIZEABLE))); - bAllowFullScreen &= (mpFrame->mpParent == NULL); - const SEL setCollectionBehavior = @selector(setCollectionBehavior:); - if( bAllowFullScreen && [pNSWindow respondsToSelector: setCollectionBehavior]) - { - const int bMode= (bAllowFullScreen ? NSWindowCollectionBehaviorFullScreenPrimary : NSWindowCollectionBehaviorFullScreenAuxiliary); - [pNSWindow performSelector:setCollectionBehavior withObject:(id)(intptr_t)bMode]; - } - - // disable OSX>=10.7 window restoration until we support it directly - const SEL setRestorable = @selector(setRestorable:); - if( [pNSWindow respondsToSelector: setRestorable]) { - [pNSWindow performSelector:setRestorable withObject:(id)NO]; - } - - return (SalFrameWindow *) pNSWindow; -} - --(AquaSalFrame*)getSalFrame -{ - return mpFrame; -} - --(void)displayIfNeeded -{ - if( GetSalData() && GetSalData()->mpFirstInstance ) - { - comphelper::SolarMutex* pMutex = GetSalData()->mpFirstInstance->GetYieldMutex(); - if( pMutex ) - { - pMutex->acquire(); - [super displayIfNeeded]; - pMutex->release(); - } - } -} - --(BOOL)containsMouse -{ - // is this event actually inside that NSWindow ? - NSPoint aPt = [NSEvent mouseLocation]; - NSRect aFrameRect = [self frame]; - BOOL bInRect = NSPointInRect( aPt, aFrameRect ); - return bInRect; -} - --(BOOL)canBecomeKeyWindow -{ - if( (mpFrame->mnStyle & - ( SAL_FRAME_STYLE_FLOAT | - SAL_FRAME_STYLE_TOOLTIP | - SAL_FRAME_STYLE_INTRO - )) == 0 ) - return YES; - if( (mpFrame->mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) != 0 ) - return YES; - if( mpFrame->mbFullScreen ) - return YES; - if( (mpFrame->mnStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) ) - return YES; - return [super canBecomeKeyWindow]; -} - --(void)windowDidBecomeKey: (NSNotification*)pNotification -{ - (void)pNotification; - YIELD_GUARD; - - if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) - { - static const sal_uLong nGuessDocument = SAL_FRAME_STYLE_MOVEABLE| - SAL_FRAME_STYLE_SIZEABLE| - SAL_FRAME_STYLE_CLOSEABLE; - - if( mpFrame->mpMenu ) - mpFrame->mpMenu->setMainMenu(); - else if( ! mpFrame->mpParent && - ( (mpFrame->mnStyle & nGuessDocument) == nGuessDocument || // set default menu for e.g. help - mpFrame->mbFullScreen ) ) // ser default menu for e.g. presentation - { - AquaSalMenu::setDefaultMenu(); - } - #if 0 - // FIXME: we should disable menus while in modal mode - // however from down here there is currently no reliable way to - // find out when to do this - if( (mpFrame->mpParent && mpFrame->mpParent->GetWindow()->IsInModalMode()) ) - AquaSalMenu::enableMainMenu( false ); - #endif - mpFrame->CallCallback( SALEVENT_GETFOCUS, 0 ); - mpFrame->SendPaintEvent(); // repaint controls as active - } -} - --(void)windowDidResignKey: (NSNotification*)pNotification -{ - (void)pNotification; - YIELD_GUARD; - - if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) - { - mpFrame->CallCallback(SALEVENT_LOSEFOCUS, 0); - mpFrame->SendPaintEvent(); // repaint controls as inactive - } -} - --(void)windowDidChangeScreen: (NSNotification*)pNotification -{ - (void)pNotification; - YIELD_GUARD; - - if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) - mpFrame->screenParametersChanged(); -} - --(void)windowDidMove: (NSNotification*)pNotification -{ - (void)pNotification; - YIELD_GUARD; - - if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) - { - mpFrame->UpdateFrameGeometry(); - mpFrame->CallCallback( SALEVENT_MOVE, 0 ); - } -} - --(void)windowDidResize: (NSNotification*)pNotification -{ - (void)pNotification; - YIELD_GUARD; - - if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) - { - mpFrame->UpdateFrameGeometry(); - mpFrame->CallCallback( SALEVENT_RESIZE, 0 ); - mpFrame->SendPaintEvent(); - } -} - --(void)windowDidMiniaturize: (NSNotification*)pNotification -{ - (void)pNotification; - YIELD_GUARD; - - if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) - { - mpFrame->mbShown = false; - mpFrame->UpdateFrameGeometry(); - mpFrame->CallCallback( SALEVENT_RESIZE, 0 ); - } -} - --(void)windowDidDeminiaturize: (NSNotification*)pNotification -{ - (void)pNotification; - YIELD_GUARD; - - if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) - { - mpFrame->mbShown = true; - mpFrame->UpdateFrameGeometry(); - mpFrame->CallCallback( SALEVENT_RESIZE, 0 ); - } -} - --(BOOL)windowShouldClose: (NSNotification*)pNotification -{ - (void)pNotification; - YIELD_GUARD; - - BOOL bRet = YES; - if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) - { - // #i84461# end possible input - mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 ); - if( AquaSalFrame::isAlive( mpFrame ) ) - { - mpFrame->CallCallback( SALEVENT_CLOSE, 0 ); - bRet = NO; // application will close the window or not, AppKit shouldn't - } - } - - return bRet; -} - --(void)windowDidEnterFullScreen: (NSNotification*)pNotification -{ - YIELD_GUARD; - - if( !mpFrame || !AquaSalFrame::isAlive( mpFrame)) - return; - mpFrame->mbFullScreen = true; - (void)pNotification; -} - --(void)windowDidExitFullScreen: (NSNotification*)pNotification -{ - YIELD_GUARD; - - if( !mpFrame || !AquaSalFrame::isAlive( mpFrame)) - return; - mpFrame->mbFullScreen = false; - (void)pNotification; -} - --(void)dockMenuItemTriggered: (id)sender -{ - (void)sender; - YIELD_GUARD; - - if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) - mpFrame->ToTop( SAL_FRAME_TOTOP_RESTOREWHENMIN | SAL_FRAME_TOTOP_GRABFOCUS ); -} - --(::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >)accessibleContext -{ - return mpFrame -> GetWindow() -> GetAccessible() -> getAccessibleContext(); -} - --(NSDragOperation)draggingEntered:(id )sender -{ - return [mDraggingDestinationHandler draggingEntered: sender]; -} - --(NSDragOperation)draggingUpdated:(id )sender -{ - return [mDraggingDestinationHandler draggingUpdated: sender]; -} - --(void)draggingExited:(id )sender -{ - [mDraggingDestinationHandler draggingExited: sender]; -} - --(BOOL)prepareForDragOperation:(id )sender -{ - return [mDraggingDestinationHandler prepareForDragOperation: sender]; -} - --(BOOL)performDragOperation:(id )sender -{ - return [mDraggingDestinationHandler performDragOperation: sender]; -} - --(void)concludeDragOperation:(id )sender -{ - [mDraggingDestinationHandler concludeDragOperation: sender]; -} - --(void)registerDraggingDestinationHandler:(id)theHandler -{ - mDraggingDestinationHandler = theHandler; -} - --(void)unregisterDraggingDestinationHandler:(id)theHandler -{ - (void)theHandler; - mDraggingDestinationHandler = nil; -} - -@end - -@implementation SalFrameView -+(void)unsetMouseFrame: (AquaSalFrame*)pFrame -{ - if( pFrame == s_pMouseFrame ) - s_pMouseFrame = NULL; -} - --(id)initWithSalFrame: (AquaSalFrame*)pFrame -{ - if ((self = [super initWithFrame: [NSWindow contentRectForFrameRect: [pFrame->getNSWindow() frame] styleMask: pFrame->mnStyleMask]]) != nil) - { - mDraggingDestinationHandler = nil; - mpFrame = pFrame; - mMarkedRange = NSMakeRange(NSNotFound, 0); - mSelectedRange = NSMakeRange(NSNotFound, 0); - mpReferenceWrapper = nil; - mpMouseEventListener = nil; - mpLastSuperEvent = nil; - } - - mfLastMagnifyTime = 0.0; - return self; -} - --(AquaSalFrame*)getSalFrame -{ - return mpFrame; -} - --(void)resetCursorRects -{ - if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) - { - // FIXME: does this leak the returned NSCursor of getCurrentCursor ? - NSRect aRect = { { 0, 0 }, { static_cast(mpFrame->maGeometry.nWidth), static_cast(mpFrame->maGeometry.nHeight) } }; - [self addCursorRect: aRect cursor: mpFrame->getCurrentCursor()]; - } -} - --(BOOL)acceptsFirstResponder -{ - return YES; -} - --(BOOL)acceptsFirstMouse: (NSEvent*)pEvent -{ - (void)pEvent; - return YES; -} - --(BOOL)isOpaque -{ - if( !mpFrame) - return YES; - if( !AquaSalFrame::isAlive( mpFrame)) - return YES; - if( !mpFrame->getClipPath()) - return YES; - return NO; -} - -// helper class similar to a osl::Guard< comphelper::SolarMutex > for the -// SalYieldMutex; the difference is that it only does tryToAcquire instead of -// acquire so dreaded deadlocks like #i93512# are prevented -class TryGuard -{ -public: - TryGuard() { mbGuarded = ImplSalYieldMutexTryToAcquire(); } - ~TryGuard() { if( mbGuarded ) ImplSalYieldMutexRelease(); } - bool IsGuarded() { return mbGuarded; } -private: - bool mbGuarded; -}; - --(void)drawRect: (NSRect)aRect -{ - // HOTFIX: #i93512# prevent deadlocks if any other thread already has the SalYieldMutex - TryGuard aTryGuard; - if( !aTryGuard.IsGuarded() ) - { - // NOTE: the mpFrame access below is not guarded yet! - // TODO: mpFrame et al need to be guarded by an independent mutex - AquaSalGraphics* pGraphics = (mpFrame && AquaSalFrame::isAlive(mpFrame)) ? mpFrame->mpGraphics : NULL; - if( pGraphics ) - { - // we did not get the mutex so we cannot draw now => request to redraw later - // convert the NSRect to a CGRect for Refreshrect() - const CGRect aCGRect = {{aRect.origin.x,aRect.origin.y},{aRect.size.width,aRect.size.height}}; - pGraphics->RefreshRect( aCGRect ); - } - return; - } - - if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) - { - if( mpFrame->mpGraphics ) - { - mpFrame->mpGraphics->UpdateWindow( aRect ); - if( mpFrame->getClipPath() ) - [mpFrame->getNSWindow() invalidateShadow]; - } - } -} - --(void)sendMouseEventToFrame: (NSEvent*)pEvent button:(sal_uInt16)nButton eventtype:(sal_uInt16)nEvent -{ - YIELD_GUARD; - - AquaSalFrame* pDispatchFrame = AquaSalFrame::GetCaptureFrame(); - bool bIsCaptured = false; - if( pDispatchFrame ) - { - bIsCaptured = true; - if( nEvent == SALEVENT_MOUSELEAVE ) // no leave events if mouse is captured - nEvent = SALEVENT_MOUSEMOVE; - } - else if( s_pMouseFrame ) - pDispatchFrame = s_pMouseFrame; - else - pDispatchFrame = mpFrame; - - /* #i81645# Cocoa reports mouse events while a button is pressed - to the window in which it was first pressed. This is reasonable and fine and - gets one around most cases where on other platforms one uses CaptureMouse or XGrabPointer, - however vcl expects mouse events to occur in the window the mouse is over, unless the - mouse is explicitly captured. So we need to find the window the mouse is actually - over for conformance with other platforms. - */ - if( ! bIsCaptured && nButton && pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) ) - { - // is this event actually inside that NSWindow ? - NSPoint aPt = [NSEvent mouseLocation]; - NSRect aFrameRect = [pDispatchFrame->getNSWindow() frame]; - - if ( ! NSPointInRect( aPt, aFrameRect ) ) - { - // no, it is not - // now we need to find the one it may be in - /* #i93756# we ant to get enumerate the application windows in z-order - to check if any contains the mouse. This could be elegantly done with this - code: - - // use NSApp to check windows in ZOrder whether they contain the mouse pointer - NSWindow* pWindow = [NSApp makeWindowsPerform: @selector(containsMouse) inOrder: YES]; - if( pWindow && [pWindow isMemberOfClass: [SalFrameWindow class]] ) - pDispatchFrame = [(SalFrameWindow*)pWindow getSalFrame]; - - However if a non SalFrameWindow is on screen (like e.g. the file dialog) - it can be hit with the containsMouse selector, which it doesn't support. - Sadly NSApplication:makeWindowsPerform does not check (for performance reasons - I assume) whether a window supports a selector before sending it. - */ - AquaSalFrame* pMouseFrame = getMouseContainerFrame(); - if( pMouseFrame ) - pDispatchFrame = pMouseFrame; - } - } - - if( pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) ) - { - pDispatchFrame->mnLastEventTime = static_cast( [pEvent timestamp] * 1000.0 ); - pDispatchFrame->mnLastModifierFlags = [pEvent modifierFlags]; - - NSPoint aPt = [NSEvent mouseLocation]; - pDispatchFrame->CocoaToVCL( aPt ); - - sal_uInt16 nModMask = ImplGetModifierMask( [pEvent modifierFlags] ); - // #i82284# emulate ctrl left - if( nModMask == KEY_MOD3 && nButton == MOUSE_LEFT ) - { - nModMask = 0; - nButton = MOUSE_RIGHT; - } - - SalMouseEvent aEvent; - aEvent.mnTime = pDispatchFrame->mnLastEventTime; - aEvent.mnX = static_cast(aPt.x) - pDispatchFrame->maGeometry.nX; - aEvent.mnY = static_cast(aPt.y) - pDispatchFrame->maGeometry.nY; - aEvent.mnButton = nButton; - aEvent.mnCode = aEvent.mnButton | nModMask; - - // --- RTL --- (mirror mouse pos) - if( Application::GetSettings().GetLayoutRTL() ) - aEvent.mnX = pDispatchFrame->maGeometry.nWidth-1-aEvent.mnX; - - pDispatchFrame->CallCallback( nEvent, &aEvent ); - } -} - --(void)mouseDown: (NSEvent*)pEvent -{ - if ( mpMouseEventListener != nil && - [mpMouseEventListener respondsToSelector: @selector(mouseDown:)]) - { - [mpMouseEventListener mouseDown: [pEvent copyWithZone: NULL]]; - } - - s_nLastButton = MOUSE_LEFT; - [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEBUTTONDOWN]; -} - --(void)mouseDragged: (NSEvent*)pEvent -{ - if ( mpMouseEventListener != nil && - [mpMouseEventListener respondsToSelector: @selector(mouseDragged:)]) - { - [mpMouseEventListener mouseDragged: [pEvent copyWithZone: NULL]]; - } - s_nLastButton = MOUSE_LEFT; - [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEMOVE]; -} - --(void)mouseUp: (NSEvent*)pEvent -{ - s_nLastButton = 0; - [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEBUTTONUP]; -} - --(void)mouseMoved: (NSEvent*)pEvent -{ - s_nLastButton = 0; - [self sendMouseEventToFrame:pEvent button:0 eventtype:SALEVENT_MOUSEMOVE]; -} - --(void)mouseEntered: (NSEvent*)pEvent -{ - s_pMouseFrame = mpFrame; - - // #i107215# the only mouse events we get when inactive are enter/exit - // actually we would like to have all of them, but better none than some - if( [NSApp isActive] ) - [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SALEVENT_MOUSEMOVE]; -} - --(void)mouseExited: (NSEvent*)pEvent -{ - if( s_pMouseFrame == mpFrame ) - s_pMouseFrame = NULL; - - // #i107215# the only mouse events we get when inactive are enter/exit - // actually we would like to have all of them, but better none than some - if( [NSApp isActive] ) - [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SALEVENT_MOUSELEAVE]; -} - --(void)rightMouseDown: (NSEvent*)pEvent -{ - s_nLastButton = MOUSE_RIGHT; - [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEBUTTONDOWN]; -} - --(void)rightMouseDragged: (NSEvent*)pEvent -{ - s_nLastButton = MOUSE_RIGHT; - [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEMOVE]; -} - --(void)rightMouseUp: (NSEvent*)pEvent -{ - s_nLastButton = 0; - [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEBUTTONUP]; -} - --(void)otherMouseDown: (NSEvent*)pEvent -{ - if( [pEvent buttonNumber] == 2 ) - { - s_nLastButton = MOUSE_MIDDLE; - [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONDOWN]; - } - else - s_nLastButton = 0; -} - --(void)otherMouseDragged: (NSEvent*)pEvent -{ - if( [pEvent buttonNumber] == 2 ) - { - s_nLastButton = MOUSE_MIDDLE; - [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEMOVE]; - } - else - s_nLastButton = 0; -} - --(void)otherMouseUp: (NSEvent*)pEvent -{ - s_nLastButton = 0; - if( [pEvent buttonNumber] == 2 ) - [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONUP]; -} - -- (void)magnifyWithEvent: (NSEvent*)pEvent -{ - YIELD_GUARD; - - // TODO: ?? -(float)magnification; - if( AquaSalFrame::isAlive( mpFrame ) ) - { - const NSTimeInterval fMagnifyTime = [pEvent timestamp]; - mpFrame->mnLastEventTime = static_cast( fMagnifyTime * 1000.0 ); - mpFrame->mnLastModifierFlags = [pEvent modifierFlags]; - - // check if this is a new series of magnify events - static const NSTimeInterval fMaxDiffTime = 0.3; - const bool bNewSeries = (fMagnifyTime - mfLastMagnifyTime > fMaxDiffTime); - - if( bNewSeries ) - mfMagnifyDeltaSum = 0.0; - mfMagnifyDeltaSum += [pEvent deltaZ]; - - mfLastMagnifyTime = [pEvent timestamp]; - // TODO: change to 0.1 when COMMAND_WHEEL_ZOOM handlers allow finer zooming control - static const float fMagnifyFactor = 0.25; - static const float fMinMagnifyStep = 15.0 / fMagnifyFactor; - if( fabs(mfMagnifyDeltaSum) <= fMinMagnifyStep ) - return; - - // adapt NSEvent-sensitivity to application expectations - // TODO: rather make COMMAND_WHEEL_ZOOM handlers smarter - const float fDeltaZ = mfMagnifyDeltaSum * fMagnifyFactor; - int nDeltaZ = FRound( fDeltaZ ); - if( !nDeltaZ ) - { - // handle new series immediately - if( !bNewSeries ) - return; - nDeltaZ = (fDeltaZ >= 0.0) ? +1 : -1; - } - // eventually give credit for delta sum - mfMagnifyDeltaSum -= nDeltaZ / fMagnifyFactor; - - NSPoint aPt = [NSEvent mouseLocation]; - mpFrame->CocoaToVCL( aPt ); - - SalWheelMouseEvent aEvent; - aEvent.mnTime = mpFrame->mnLastEventTime; - aEvent.mnX = static_cast(aPt.x) - mpFrame->maGeometry.nX; - aEvent.mnY = static_cast(aPt.y) - mpFrame->maGeometry.nY; - aEvent.mnCode = ImplGetModifierMask( mpFrame->mnLastModifierFlags ); - aEvent.mnCode |= KEY_MOD1; // we want zooming, no scrolling - aEvent.mbDeltaIsPixel = TRUE; - - // --- RTL --- (mirror mouse pos) - if( Application::GetSettings().GetLayoutRTL() ) - aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX; - - aEvent.mnDelta = nDeltaZ; - aEvent.mnNotchDelta = (nDeltaZ >= 0) ? +1 : -1; - if( aEvent.mnDelta == 0 ) - aEvent.mnDelta = aEvent.mnNotchDelta; - aEvent.mbHorz = FALSE; - aEvent.mnScrollLines = nDeltaZ; - if( aEvent.mnScrollLines == 0 ) - aEvent.mnScrollLines = 1; - mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent ); - } -} - -- (void)rotateWithEvent: (NSEvent*)pEvent -{ - //Rotation : -(float)rotation; - // TODO: create new CommandType so rotation is available to the applications - (void)pEvent; -} - -- (void)swipeWithEvent: (NSEvent*)pEvent -{ - YIELD_GUARD; - - if( AquaSalFrame::isAlive( mpFrame ) ) - { - mpFrame->mnLastEventTime = static_cast( [pEvent timestamp] * 1000.0 ); - mpFrame->mnLastModifierFlags = [pEvent modifierFlags]; - - // merge pending scroll wheel events - float dX = 0.0; - float dY = 0.0; - for(;;) - { - dX += [pEvent deltaX]; - dY += [pEvent deltaY]; - NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask - untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ]; - if( !pNextEvent ) - break; - pEvent = pNextEvent; - } - - NSPoint aPt = [NSEvent mouseLocation]; - mpFrame->CocoaToVCL( aPt ); - - SalWheelMouseEvent aEvent; - aEvent.mnTime = mpFrame->mnLastEventTime; - aEvent.mnX = static_cast(aPt.x) - mpFrame->maGeometry.nX; - aEvent.mnY = static_cast(aPt.y) - mpFrame->maGeometry.nY; - aEvent.mnCode = ImplGetModifierMask( mpFrame->mnLastModifierFlags ); - aEvent.mbDeltaIsPixel = TRUE; - - // --- RTL --- (mirror mouse pos) - if( Application::GetSettings().GetLayoutRTL() ) - aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX; - - if( dX != 0.0 ) - { - aEvent.mnDelta = static_cast(floor(dX)); - aEvent.mnNotchDelta = dX < 0 ? -1 : 1; - if( aEvent.mnDelta == 0 ) - aEvent.mnDelta = aEvent.mnNotchDelta; - aEvent.mbHorz = TRUE; - aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL; - mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent ); - } - if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame )) - { - aEvent.mnDelta = static_cast(floor(dY)); - aEvent.mnNotchDelta = dY < 0 ? -1 : 1; - if( aEvent.mnDelta == 0 ) - aEvent.mnDelta = aEvent.mnNotchDelta; - aEvent.mbHorz = FALSE; - aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL; - mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent ); - } - } -} - --(void)scrollWheel: (NSEvent*)pEvent -{ - YIELD_GUARD; - - if( AquaSalFrame::isAlive( mpFrame ) ) - { - mpFrame->mnLastEventTime = static_cast( [pEvent timestamp] * 1000.0 ); - mpFrame->mnLastModifierFlags = [pEvent modifierFlags]; - - // merge pending scroll wheel events - float dX = 0.0; - float dY = 0.0; - for(;;) - { - dX += [pEvent deltaX]; - dY += [pEvent deltaY]; - NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask - untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ]; - if( !pNextEvent ) - break; - pEvent = pNextEvent; - } - - NSPoint aPt = [NSEvent mouseLocation]; - mpFrame->CocoaToVCL( aPt ); - - SalWheelMouseEvent aEvent; - aEvent.mnTime = mpFrame->mnLastEventTime; - aEvent.mnX = static_cast(aPt.x) - mpFrame->maGeometry.nX; - aEvent.mnY = static_cast(aPt.y) - mpFrame->maGeometry.nY; - aEvent.mnCode = ImplGetModifierMask( mpFrame->mnLastModifierFlags ); - aEvent.mbDeltaIsPixel = FALSE; - - // --- RTL --- (mirror mouse pos) - if( Application::GetSettings().GetLayoutRTL() ) - aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX; - - if( dX != 0.0 ) - { - aEvent.mnDelta = static_cast(floor(dX)); - aEvent.mnNotchDelta = dX < 0 ? -1 : 1; - if( aEvent.mnDelta == 0 ) - aEvent.mnDelta = aEvent.mnNotchDelta; - aEvent.mbHorz = TRUE; - aEvent.mnScrollLines = dX > 0 ? dX/WHEEL_EVENT_FACTOR : -dX/WHEEL_EVENT_FACTOR; - if( aEvent.mnScrollLines == 0 ) - aEvent.mnScrollLines = 1; - - mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent ); - } - if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame ) ) - { - aEvent.mnDelta = static_cast(floor(dY)); - aEvent.mnNotchDelta = dY < 0 ? -1 : 1; - if( aEvent.mnDelta == 0 ) - aEvent.mnDelta = aEvent.mnNotchDelta; - aEvent.mbHorz = FALSE; - aEvent.mnScrollLines = dY > 0 ? dY/WHEEL_EVENT_FACTOR : -dY/WHEEL_EVENT_FACTOR; - if( aEvent.mnScrollLines < 1 ) - aEvent.mnScrollLines = 1; - - mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent ); - } - } -} - - --(void)keyDown: (NSEvent*)pEvent -{ - YIELD_GUARD; - - if( AquaSalFrame::isAlive( mpFrame ) ) - { - mpLastEvent = pEvent; - mbInKeyInput = true; - mbNeedSpecialKeyHandle = false; - mbKeyHandled = false; - - mpFrame->mnLastEventTime = static_cast( [pEvent timestamp] * 1000.0 ); - mpFrame->mnLastModifierFlags = [pEvent modifierFlags]; - - if( ! [self handleKeyDownException: pEvent] ) - { - NSArray* pArray = [NSArray arrayWithObject: pEvent]; - [self interpretKeyEvents: pArray]; - } - - mbInKeyInput = false; - } -} - --(BOOL)handleKeyDownException:(NSEvent*)pEvent -{ - // check for a very special set of modified characters - NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers]; - - if( pUnmodifiedString && [pUnmodifiedString length] == 1 ) - { - /* #i103102# key events with command and alternate don't make it through - interpretKeyEvents (why ?). Try to dispatch them here first, - if not successful continue normally - */ - if( (mpFrame->mnLastModifierFlags & (NSAlternateKeyMask | NSCommandKeyMask)) - == (NSAlternateKeyMask | NSCommandKeyMask) ) - { - if( [self sendSingleCharacter: mpLastEvent] ) - return YES; - } - unichar keyChar = [pUnmodifiedString characterAtIndex: 0]; - sal_uInt16 nKeyCode = ImplMapCharCode( keyChar ); - - // Caution: should the table grow to more than 5 or 6 entries, - // we must consider moving it to a kind of hash map - const unsigned int nExceptions = SAL_N_ELEMENTS( aExceptionalKeys ); - for( unsigned int i = 0; i < nExceptions; i++ ) - { - if( nKeyCode == aExceptionalKeys[i].nKeyCode && - (mpFrame->mnLastModifierFlags & aExceptionalKeys[i].nModifierMask) - == aExceptionalKeys[i].nModifierMask ) - { - [self sendKeyInputAndReleaseToFrame: nKeyCode character: 0]; - - return YES; - } - } - } - return NO; -} - --(void)flagsChanged: (NSEvent*)pEvent -{ - YIELD_GUARD; - - if( AquaSalFrame::isAlive( mpFrame ) ) - { - mpFrame->mnLastEventTime = static_cast( [pEvent timestamp] * 1000.0 ); - mpFrame->mnLastModifierFlags = [pEvent modifierFlags]; - } -} - --(void)insertText:(id)aString -{ - YIELD_GUARD; - - if( AquaSalFrame::isAlive( mpFrame ) ) - { - NSString* pInsert = nil; - if( [aString isMemberOfClass: [NSAttributedString class]] ) - pInsert = [aString string]; - else - pInsert = aString; - - int nLen = 0; - if( pInsert && ( nLen = [pInsert length] ) > 0 ) - { - OUString aInsertString( GetOUString( pInsert ) ); - // aCharCode initializer is safe since aInsertString will at least contain '\0' - sal_Unicode aCharCode = *aInsertString.getStr(); - - if( nLen == 1 && - aCharCode < 0x80 && - aCharCode > 0x1f && - ! [self hasMarkedText ] - ) - { - sal_uInt16 nKeyCode = ImplMapCharCode( aCharCode ); - unsigned int nLastModifiers = mpFrame->mnLastModifierFlags; - - // #i99567# - // find out the unmodified key code - - // sanity check - if( mpLastEvent && ( [mpLastEvent type] == NSKeyDown || [mpLastEvent type] == NSKeyUp ) ) - { - // get unmodified string - NSString* pUnmodifiedString = [mpLastEvent charactersIgnoringModifiers]; - if( pUnmodifiedString && [pUnmodifiedString length] == 1 ) - { - // map the unmodified key code - unichar keyChar = [pUnmodifiedString characterAtIndex: 0]; - nKeyCode = ImplMapCharCode( keyChar ); - } - nLastModifiers = [mpLastEvent modifierFlags]; - - } - // #i99567# - // applications and vcl's edit fields ignore key events with ALT - // however we're at a place where we know text should be inserted - // so it seems we need to strip the Alt modifier here - if( (nLastModifiers & (NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask)) - == NSAlternateKeyMask ) - { - nLastModifiers = 0; - } - [self sendKeyInputAndReleaseToFrame: nKeyCode character: aCharCode modifiers: nLastModifiers]; - } - else - { - SalExtTextInputEvent aEvent; - aEvent.mnTime = mpFrame->mnLastEventTime; - aEvent.maText = aInsertString; - aEvent.mpTextAttr = NULL; - aEvent.mnCursorPos = aInsertString.getLength(); - aEvent.mnDeltaStart = 0; - aEvent.mnCursorFlags = 0; - aEvent.mbOnlyCursor = FALSE; - mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, &aEvent ); - if( AquaSalFrame::isAlive( mpFrame ) ) - mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 ); - } - } - else - { - SalExtTextInputEvent aEvent; - aEvent.mnTime = mpFrame->mnLastEventTime; - aEvent.maText = OUString(); - aEvent.mpTextAttr = NULL; - aEvent.mnCursorPos = 0; - aEvent.mnDeltaStart = 0; - aEvent.mnCursorFlags = 0; - aEvent.mbOnlyCursor = FALSE; - mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, &aEvent ); - if( AquaSalFrame::isAlive( mpFrame ) ) - mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 ); - - } - mbKeyHandled = true; - [self unmarkText]; - } -} - --(void)insertTab: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: KEY_TAB character: '\t' modifiers: 0]; -} - --(void)insertBacktab: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: (KEY_TAB | KEY_SHIFT) character: '\t' modifiers: 0]; -} - --(void)moveLeft: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: 0]; -} - --(void)moveLeftAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: NSShiftKeyMask]; -} - --(void)moveBackwardAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_BACKWARD character: 0 modifiers: 0]; -} - --(void)moveRight: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: 0]; -} - --(void)moveRightAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: NSShiftKeyMask]; -} - --(void)moveForwardAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_FORWARD character: 0 modifiers: 0]; -} - --(void)moveWordLeft: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_BACKWARD character: 0 modifiers: 0]; -} - --(void)moveWordBackward: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_BACKWARD character: 0 modifiers: 0]; -} - --(void)moveWordBackwardAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_BACKWARD character: 0 modifiers: 0]; -} - --(void)moveWordLeftAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_BACKWARD character: 0 modifiers: 0]; -} - --(void)moveWordRight: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_FORWARD character: 0 modifiers: 0]; -} - --(void)moveWordForward: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_FORWARD character: 0 modifiers: 0]; -} - --(void)moveWordForwardAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_FORWARD character: 0 modifiers: 0]; -} - --(void)moveWordRightAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_FORWARD character: 0 modifiers: 0]; -} - --(void)moveToEndOfLine: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_LINE character: 0 modifiers: 0]; -} - --(void)moveToRightEndOfLine: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_LINE character: 0 modifiers: 0]; -} - --(void)moveToEndOfLineAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_LINE character: 0 modifiers: 0]; -} - --(void)moveToRightEndOfLineAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_LINE character: 0 modifiers: 0]; -} - --(void)moveToBeginningOfLine: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE character: 0 modifiers: 0]; -} - --(void)moveToLeftEndOfLine: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE character: 0 modifiers: 0]; -} - --(void)moveToBeginningOfLineAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE character: 0 modifiers: 0]; -} - --(void)moveToLeftEndOfLineAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE character: 0 modifiers: 0]; -} - --(void)moveToEndOfParagraph: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0 modifiers: 0]; -} - --(void)moveToEndOfParagraphAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0 modifiers: 0]; -} - --(void)moveParagraphForward: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0 modifiers: 0]; -} - --(void)moveParagraphForwardAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0 modifiers: 0]; -} - --(void)moveToBeginningOfParagraph: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0 modifiers: 0]; -} - --(void)moveParagraphBackward: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0 modifiers: 0]; -} - --(void)moveToBeginningOfParagraphAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0 modifiers: 0]; -} - --(void)moveParagraphBackwardAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0 modifiers: 0]; -} - --(void)moveToEndOfDocument: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT character: 0 modifiers: 0]; -} - --(void)scrollToEndOfDocument: (id)aSender -{ - (void)aSender; - // this is not exactly what we should do, but it makes "End" and "Shift-End" behave consistent - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT character: 0 modifiers: 0]; -} - --(void)moveToEndOfDocumentAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT character: 0 modifiers: 0]; -} - --(void)moveToBeginningOfDocument: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT character: 0 modifiers: 0]; -} - --(void)scrollToBeginningOfDocument: (id)aSender -{ - (void)aSender; - // this is not exactly what we should do, but it makes "Home" and "Shift-Home" behave consistent - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT character: 0 modifiers: 0]; -} - --(void)moveToBeginningOfDocumentAndModifySelection: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT character: 0 modifiers: 0]; -} - --(void)moveUp: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: KEY_UP character: 0 modifiers: 0]; -} - --(void)moveDown: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: KEY_DOWN character: 0 modifiers: 0]; -} - --(void)insertNewline: (id)aSender -{ - (void)aSender; - // #i91267# make enter and shift-enter work by evaluating the modifiers - [self sendKeyInputAndReleaseToFrame: KEY_RETURN character: '\n' modifiers: mpFrame->mnLastModifierFlags]; -} - --(void)deleteBackward: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0]; -} - --(void)deleteForward: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: KEY_DELETE character: 0x7f modifiers: 0]; -} - --(void)deleteBackwardByDecomposingPreviousCharacter: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0]; -} - --(void)deleteWordBackward: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_WORD_BACKWARD character: 0 modifiers: 0]; -} - --(void)deleteWordForward: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_WORD_FORWARD character: 0 modifiers: 0]; -} - --(void)deleteToBeginningOfLine: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE character: 0 modifiers: 0]; -} - --(void)deleteToEndOfLine: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_END_OF_LINE character: 0 modifiers: 0]; -} - --(void)deleteToBeginningOfParagraph: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH character: 0 modifiers: 0]; -} - --(void)deleteToEndOfParagraph: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_END_OF_PARAGRAPH character: 0 modifiers: 0]; -} - --(void)insertLineBreak: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::INSERT_LINEBREAK character: 0 modifiers: 0]; -} - --(void)insertParagraphSeparator: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::INSERT_PARAGRAPH character: 0 modifiers: 0]; -} - --(void)selectWord: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD character: 0 modifiers: 0]; -} - --(void)selectLine: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_LINE character: 0 modifiers: 0]; -} - --(void)selectParagraph: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_PARAGRAPH character: 0 modifiers: 0]; -} - --(void)selectAll: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_ALL character: 0 modifiers: 0]; -} - --(void)cancelOperation: (id)aSender -{ - (void)aSender; - [self sendKeyInputAndReleaseToFrame: KEY_ESCAPE character: 0x1b modifiers: 0]; -} - --(void)noop: (id)aSender -{ - (void)aSender; - if( ! mbKeyHandled ) - { - if( ! [self sendSingleCharacter:mpLastEvent] ) - { - /* prevent recursion */ - if( mpLastEvent != mpLastSuperEvent && [NSApp respondsToSelector: @selector(sendSuperEvent:)] ) - { - id pLastSuperEvent = mpLastSuperEvent; - mpLastSuperEvent = mpLastEvent; - [NSApp performSelector:@selector(sendSuperEvent:) withObject: mpLastEvent]; - mpLastSuperEvent = pLastSuperEvent; - - std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent ); - if( it != GetSalData()->maKeyEventAnswer.end() ) - it->second = true; - } - } - } -} - --(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar -{ - return [self sendKeyInputAndReleaseToFrame: nKeyCode character: aChar modifiers: mpFrame->mnLastModifierFlags]; -} - --(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar modifiers: (unsigned int)nMod -{ - return [self sendKeyToFrameDirect: nKeyCode character: aChar modifiers: nMod] || - [self sendSingleCharacter: mpLastEvent]; -} - --(BOOL)sendKeyToFrameDirect: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar modifiers: (unsigned int)nMod -{ - YIELD_GUARD; - - long nRet = 0; - if( AquaSalFrame::isAlive( mpFrame ) ) - { - SalKeyEvent aEvent; - aEvent.mnTime = mpFrame->mnLastEventTime; - aEvent.mnCode = nKeyCode | ImplGetModifierMask( nMod ); - aEvent.mnCharCode = aChar; - aEvent.mnRepeat = FALSE; - nRet = mpFrame->CallCallback( SALEVENT_KEYINPUT, &aEvent ); - std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent ); - if( it != GetSalData()->maKeyEventAnswer.end() ) - it->second = nRet ? true : false; - if( AquaSalFrame::isAlive( mpFrame ) ) - mpFrame->CallCallback( SALEVENT_KEYUP, &aEvent ); - } - return nRet ? YES : NO; -} - - --(BOOL)sendSingleCharacter: (NSEvent *)pEvent -{ - NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers]; - - if( pUnmodifiedString && [pUnmodifiedString length] == 1 ) - { - unichar keyChar = [pUnmodifiedString characterAtIndex: 0]; - sal_uInt16 nKeyCode = ImplMapCharCode( keyChar ); - if (nKeyCode == 0) - { - sal_uInt16 nOtherKeyCode = [pEvent keyCode]; - nKeyCode = ImplMapKeyCode(nOtherKeyCode); - } - if( nKeyCode != 0 ) - { - // don't send unicodes in the private use area - if( keyChar >= 0xf700 && keyChar < 0xf780 ) - keyChar = 0; - BOOL bRet = [self sendKeyToFrameDirect: nKeyCode character: keyChar modifiers: mpFrame->mnLastModifierFlags]; - mbInKeyInput = false; - - return bRet; - } - } - return NO; -} - - -// NSTextInput protocol -- (NSArray *)validAttributesForMarkedText -{ - return [NSArray arrayWithObjects:NSUnderlineStyleAttributeName, nil]; -} - -- (BOOL)hasMarkedText -{ - BOOL bHasMarkedText; - - bHasMarkedText = ( mMarkedRange.location != NSNotFound ) && - ( mMarkedRange.length != 0 ); - // hack to check keys like "Control-j" - if( mbInKeyInput ) - { - mbNeedSpecialKeyHandle = true; - } - - // FIXME: - // #i106901# - // if we come here outside of mbInKeyInput, this is likely to be because - // of the keyboard viewer. For unknown reasons having no marked range - // in this case causes a crash. So we say we have a marked range anyway - // This is a hack, since it is not understood what a) causes that crash - // and b) why we should have a marked range at this point. - if( ! mbInKeyInput ) - bHasMarkedText = YES; - - return bHasMarkedText; -} - -- (NSRange)markedRange -{ - // FIXME: - // #i106901# - // if we come here outside of mbInKeyInput, this is likely to be because - // of the keyboard viewer. For unknown reasons having no marked range - // in this case causes a crash. So we say we have a marked range anyway - // This is a hack, since it is not understood what a) causes that crash - // and b) why we should have a marked range at this point. - if( ! mbInKeyInput ) - return NSMakeRange( 0, 0 ); - - return [self hasMarkedText] ? mMarkedRange : NSMakeRange( NSNotFound, 0 ); -} - -- (NSRange)selectedRange -{ - return mSelectedRange; -} - -- (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange -{ - if( ![aString isKindOfClass:[NSAttributedString class]] ) - aString = [[[NSAttributedString alloc] initWithString:aString] autorelease]; - NSRange rangeToReplace = [self hasMarkedText] ? [self markedRange] : [self selectedRange]; - if( rangeToReplace.location == NSNotFound ) - { - mMarkedRange = NSMakeRange( selRange.location, [aString length] ); - mSelectedRange = NSMakeRange( selRange.location, selRange.length ); - } - else - { - mMarkedRange = NSMakeRange( rangeToReplace.location, [aString length] ); - mSelectedRange = NSMakeRange( rangeToReplace.location + selRange.location, selRange.length ); - } - - int len = [aString length]; - SalExtTextInputEvent aInputEvent; - aInputEvent.mnTime = mpFrame->mnLastEventTime; - aInputEvent.mnDeltaStart = 0; - aInputEvent.mbOnlyCursor = FALSE; - if( len > 0 ) { - NSString *pString = [aString string]; - OUString aInsertString( GetOUString( pString ) ); - std::vector aInputFlags = std::vector( std::max( 1, len ), 0 ); - for ( int i = 0; i < len; i++ ) - { - unsigned int nUnderlineValue; - NSRange effectiveRange; - - effectiveRange = NSMakeRange(i, 1); - nUnderlineValue = [[aString attribute:NSUnderlineStyleAttributeName atIndex:i effectiveRange:&effectiveRange] unsignedIntValue]; - - switch (nUnderlineValue & 0xff) { - case NSUnderlineStyleSingle: - aInputFlags[i] = EXTTEXTINPUT_ATTR_UNDERLINE; - break; - case NSUnderlineStyleThick: - aInputFlags[i] = EXTTEXTINPUT_ATTR_UNDERLINE | EXTTEXTINPUT_ATTR_HIGHLIGHT; - break; - case NSUnderlineStyleDouble: - aInputFlags[i] = EXTTEXTINPUT_ATTR_BOLDUNDERLINE; - break; - default: - aInputFlags[i] = EXTTEXTINPUT_ATTR_HIGHLIGHT; - break; - } - } - - aInputEvent.maText = aInsertString; - aInputEvent.mnCursorPos = selRange.location; - aInputEvent.mpTextAttr = &aInputFlags[0]; - mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void *)&aInputEvent ); - } else { - aInputEvent.maText = OUString(); - aInputEvent.mnCursorPos = 0; - aInputEvent.mnCursorFlags = 0; - aInputEvent.mpTextAttr = 0; - mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void *)&aInputEvent ); - mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 ); - } - mbKeyHandled= true; -} - -- (void)unmarkText -{ - mSelectedRange = mMarkedRange = NSMakeRange(NSNotFound, 0); -} - -- (NSAttributedString *)attributedSubstringFromRange:(NSRange)theRange -{ - (void)theRange; - // FIXME - return nil; -} - -- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint -{ - (void)thePoint; - // FIXME - return 0; -} - -- (NSInteger)conversationIdentifier -{ - return (long)self; -} - -- (void)doCommandBySelector:(SEL)aSelector -{ - if( AquaSalFrame::isAlive( mpFrame ) ) - { - #if OSL_DEBUG_LEVEL > 1 - // fprintf( stderr, "SalFrameView: doCommandBySelector %s\n", (char*)aSelector ); - #endif - if( (mpFrame->mnICOptions & SAL_INPUTCONTEXT_TEXT) != 0 && - aSelector != NULL && [self respondsToSelector: aSelector] ) - { - [self performSelector: aSelector]; - } - else - { - [self sendSingleCharacter:mpLastEvent]; - } - } - - mbKeyHandled = true; -} - --(void)clearLastEvent -{ - mpLastEvent = nil; -} - -- (NSRect)firstRectForCharacterRange:(NSRange)theRange -{ - (void)theRange; - SalExtTextInputPosEvent aPosEvent; - mpFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void *)&aPosEvent ); - - NSRect rect; - - rect.origin.x = aPosEvent.mnX + mpFrame->maGeometry.nX; - rect.origin.y = aPosEvent.mnY + mpFrame->maGeometry.nY + 4; // add some space for underlines - rect.size.width = aPosEvent.mnWidth; - rect.size.height = aPosEvent.mnHeight; - - mpFrame->VCLToCocoa( rect ); - return rect; -} - --(id)parentAttribute { - return mpFrame->getNSWindow(); -} - --(::com::sun::star::accessibility::XAccessibleContext *)accessibleContext -{ - if ( mpReferenceWrapper == nil ) { - // some frames never become visible .. - Window *pWindow = mpFrame -> GetWindow(); - if ( ! pWindow ) - return nil; - - mpReferenceWrapper = new ReferenceWrapper; - mpReferenceWrapper -> rAccessibleContext = pWindow -> /*GetAccessibleChildWindow( 0 ) ->*/ GetAccessible() -> getAccessibleContext(); - [ AquaA11yFactory insertIntoWrapperRepository: self forAccessibleContext: mpReferenceWrapper -> rAccessibleContext ]; - } - return [ super accessibleContext ]; -} - --(NSView*)viewElementForParent -{ - return mpFrame->getNSView(); -} - --(void)registerMouseEventListener: (id)theListener -{ - mpMouseEventListener = theListener; -} - --(void)unregisterMouseEventListener: (id)theListener -{ - (void)theListener; - mpMouseEventListener = nil; -} - --(NSDragOperation)draggingEntered:(id )sender -{ - return [mDraggingDestinationHandler draggingEntered: sender]; -} - --(NSDragOperation)draggingUpdated:(id )sender -{ - return [mDraggingDestinationHandler draggingUpdated: sender]; -} - --(void)draggingExited:(id )sender -{ - [mDraggingDestinationHandler draggingExited: sender]; -} - --(BOOL)prepareForDragOperation:(id )sender -{ - return [mDraggingDestinationHandler prepareForDragOperation: sender]; -} - --(BOOL)performDragOperation:(id )sender -{ - return [mDraggingDestinationHandler performDragOperation: sender]; -} - --(void)concludeDragOperation:(id )sender -{ - [mDraggingDestinationHandler concludeDragOperation: sender]; -} - --(void)registerDraggingDestinationHandler:(id)theHandler -{ - mDraggingDestinationHandler = theHandler; -} - --(void)unregisterDraggingDestinationHandler:(id)theHandler -{ - (void)theHandler; - mDraggingDestinationHandler = nil; -} - -@end - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/window/salmenu.cxx b/vcl/aqua/source/window/salmenu.cxx deleted file mode 100644 index 37d28c5f9712..000000000000 --- a/vcl/aqua/source/window/salmenu.cxx +++ /dev/null @@ -1,963 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include - -#include "rtl/ustrbuf.hxx" - -#include "vcl/cmdevt.hxx" -#include "vcl/floatwin.hxx" -#include "vcl/window.hxx" -#include "vcl/svapp.hxx" - -#include "aqua/saldata.hxx" -#include "aqua/salinst.h" -#include "aqua/salmenu.h" -#include "aqua/salnsmenu.h" -#include "aqua/salframe.h" -#include "aqua/aqua11ywrapper.h" -#include "quartz/utils.h" - -#include "svids.hrc" -#include "window.h" - -#include - -const AquaSalMenu* AquaSalMenu::pCurrentMenuBar = NULL; - -@interface MainMenuSelector : NSObject -{ -} --(void)showDialog: (int)nDialog; --(void)showPreferences: (id)sender; --(void)showAbout: (id)sender; -@end - -@implementation MainMenuSelector --(void)showDialog: (int)nDialog -{ - if( AquaSalMenu::pCurrentMenuBar ) - { - const AquaSalFrame* pFrame = AquaSalMenu::pCurrentMenuBar->mpFrame; - if( pFrame && AquaSalFrame::isAlive( pFrame ) ) - { - pFrame->CallCallback( SALEVENT_SHOWDIALOG, reinterpret_cast(nDialog) ); - } - } - else - { - OUString aDialog; - if( nDialog == SHOWDIALOG_ID_ABOUT ) - aDialog = "ABOUT"; - else if( nDialog == SHOWDIALOG_ID_PREFERENCES ) - aDialog = "PREFERENCES"; - const ApplicationEvent* pAppEvent = new ApplicationEvent( - ApplicationEvent::TYPE_SHOWDIALOG, aDialog); - AquaSalInstance::aAppEventList.push_back( pAppEvent ); - } -} - --(void)showPreferences: (id) sender -{ - (void)sender; - YIELD_GUARD; - - [self showDialog: SHOWDIALOG_ID_PREFERENCES]; -} --(void)showAbout: (id) sender -{ - (void)sender; - YIELD_GUARD; - - [self showDialog: SHOWDIALOG_ID_ABOUT]; -} -@end - - -// FIXME: currently this is leaked -static MainMenuSelector* pMainMenuSelector = nil; - -static void initAppMenu() -{ - static bool bOnce = true; - if( bOnce ) - { - bOnce = false; - - ResMgr* pMgr = ImplGetResMgr(); - if( pMgr ) - { - // get the main menu - NSMenu* pMainMenu = [NSApp mainMenu]; - if( pMainMenu != nil ) - { - // create the action selector - pMainMenuSelector = [[MainMenuSelector alloc] init]; - - // get the proper submenu - NSMenu* pAppMenu = [[pMainMenu itemAtIndex: 0] submenu]; - if( pAppMenu ) - { - // insert about entry - OUString aAbout( ResId( SV_STDTEXT_ABOUT, *pMgr ) ); - NSString* pString = CreateNSString( aAbout ); - NSMenuItem* pNewItem = [pAppMenu insertItemWithTitle: pString - action: @selector(showAbout:) - keyEquivalent: @"" - atIndex: 0]; - if (pString) - [pString release]; - if( pNewItem ) - { - [pNewItem setTarget: pMainMenuSelector]; - [pAppMenu insertItem: [NSMenuItem separatorItem] atIndex: 1]; - } - - // insert preferences entry - OUString aPref( ResId( SV_STDTEXT_PREFERENCES, *pMgr ) ); - pString = CreateNSString( aPref ); - pNewItem = [pAppMenu insertItemWithTitle: pString - action: @selector(showPreferences:) - keyEquivalent: @"," - atIndex: 2]; - if (pString) - [pString release]; - if( pNewItem ) - { - [pNewItem setKeyEquivalentModifierMask: NSCommandKeyMask]; - [pNewItem setTarget: pMainMenuSelector]; - [pAppMenu insertItem: [NSMenuItem separatorItem] atIndex: 3]; - } - - // WARNING: ultra ugly code ahead - - // rename standard entries - // rename "Services" - pNewItem = [pAppMenu itemAtIndex: 4]; - if( pNewItem ) - { - pString = CreateNSString( OUString( ResId( SV_MENU_MAC_SERVICES, *pMgr ) ) ); - [pNewItem setTitle: pString]; - if( pString ) - [pString release]; - } - - // rename "Hide NewApplication" - pNewItem = [pAppMenu itemAtIndex: 6]; - if( pNewItem ) - { - pString = CreateNSString( OUString( ResId( SV_MENU_MAC_HIDEAPP, *pMgr ) ) ); - [pNewItem setTitle: pString]; - if( pString ) - [pString release]; - } - - // rename "Hide Others" - pNewItem = [pAppMenu itemAtIndex: 7]; - if( pNewItem ) - { - pString = CreateNSString( OUString( ResId( SV_MENU_MAC_HIDEALL, *pMgr ) ) ); - [pNewItem setTitle: pString]; - if( pString ) - [pString release]; - } - - // rename "Show all" - pNewItem = [pAppMenu itemAtIndex: 8]; - if( pNewItem ) - { - pString = CreateNSString( OUString( ResId( SV_MENU_MAC_SHOWALL, *pMgr ) ) ); - [pNewItem setTitle: pString]; - if( pString ) - [pString release]; - } - - // rename "Quit NewApplication" - pNewItem = [pAppMenu itemAtIndex: 10]; - if( pNewItem ) - { - pString = CreateNSString( OUString( ResId( SV_MENU_MAC_QUITAPP, *pMgr ) ) ); - [pNewItem setTitle: pString]; - if( pString ) - [pString release]; - } - } - } - } - } -} - -// ======================================================================= - -SalMenu* AquaSalInstance::CreateMenu( sal_Bool bMenuBar, Menu* pVCLMenu ) -{ - initAppMenu(); - - AquaSalMenu *pAquaSalMenu = new AquaSalMenu( bMenuBar ); - pAquaSalMenu->mpVCLMenu = pVCLMenu; - - return pAquaSalMenu; -} - -void AquaSalInstance::DestroyMenu( SalMenu* pSalMenu ) -{ - delete pSalMenu; -} - -SalMenuItem* AquaSalInstance::CreateMenuItem( const SalItemParams* pItemData ) -{ - if( !pItemData ) - return NULL; - - AquaSalMenuItem *pSalMenuItem = new AquaSalMenuItem( pItemData ); - - return pSalMenuItem; -} - -void AquaSalInstance::DestroyMenuItem( SalMenuItem* pSalMenuItem ) -{ - delete pSalMenuItem; -} - - -// ======================================================================= - - -/* - * AquaSalMenu - */ - -AquaSalMenu::AquaSalMenu( bool bMenuBar ) : - mbMenuBar( bMenuBar ), - mpMenu( nil ), - mpVCLMenu( NULL ), - mpFrame( NULL ), - mpParentSalMenu( NULL ) -{ - if( ! mbMenuBar ) - { - mpMenu = [[SalNSMenu alloc] initWithMenu: this]; - // With the 10.6 SDK and gcc 4.2.1, we get: class 'NSMenu' - // does not implement the 'NSMenuDelegate' protocol. Anyway, - // having the menu object be its own delegate object is - // apparently what the code does on purpose. - - // So to silcense the warning, instead of: - // [mpMenu setDelegate: mpMenu]; - // do this: - objc_msgSend(mpMenu, @selector(setDelegate:), mpMenu); - } - else - { - mpMenu = [NSApp mainMenu]; - } - [mpMenu setAutoenablesItems: NO]; -} - -AquaSalMenu::~AquaSalMenu() -{ - // actually someone should have done AquaSalFrame::SetMenu( NULL ) - // on our frame, alas it is not so - if( mpFrame && AquaSalFrame::isAlive( mpFrame ) && mpFrame->mpMenu == this ) - const_cast(mpFrame)->mpMenu = NULL; - - // this should normally be empty already, but be careful... - for( size_t i = 0; i < maButtons.size(); i++ ) - releaseButtonEntry( maButtons[i] ); - maButtons.clear(); - - // is this leaking in some cases ? the release often leads to a duplicate release - // it seems the parent item gets ownership of the menu - if( mpMenu ) - { - if( mbMenuBar ) - { - if( pCurrentMenuBar == this ) - { - // if the current menubar gets destroyed, set the default menubar - setDefaultMenu(); - } - } - else - // the system may still hold a reference on mpMenu - { - // so set the pointer to this AquaSalMenu to NULL - // to protect from calling a dead object - - // in ! mbMenuBar case our mpMenu is actually a SalNSMenu* - // so we can safely cast here - [static_cast(mpMenu) setSalMenu: NULL]; - /* #i89860# FIXME: - using [autorelease] here (and in AquaSalMenuItem::~AquaSalMenuItem) - instead of [release] fixes an occasional crash. That should - indicate that we release menus / menu items in the wrong order - somewhere, but I could not find that case. - */ - [mpMenu autorelease]; - } - } -} - -sal_Int32 removeUnusedItemsRunner(NSMenu * pMenu) -{ - NSArray * elements = [pMenu itemArray]; - NSEnumerator * it = [elements objectEnumerator]; - id elem; - NSMenuItem * lastDisplayedMenuItem = nil; - sal_Int32 drawnItems = 0; - bool firstEnabledItemIsNoSeparator = false; - while((elem=[it nextObject]) != nil) { - NSMenuItem * item = static_cast(elem); - if( (![item isEnabled] && ![item isSeparatorItem]) || ([item isSeparatorItem] && (lastDisplayedMenuItem != nil && [lastDisplayedMenuItem isSeparatorItem])) ) { - [[item menu]removeItem:item]; - } else { - if( ! firstEnabledItemIsNoSeparator && [item isSeparatorItem] ) { - [[item menu]removeItem:item]; - } else { - firstEnabledItemIsNoSeparator = true; - lastDisplayedMenuItem = item; - drawnItems++; - if( [item hasSubmenu] ) { - removeUnusedItemsRunner( [item submenu] ); - } - } - } - } - if( lastDisplayedMenuItem != nil && [lastDisplayedMenuItem isSeparatorItem]) { - [[lastDisplayedMenuItem menu]removeItem:lastDisplayedMenuItem]; - } - return drawnItems; -} - -bool AquaSalMenu::ShowNativePopupMenu(FloatingWindow * pWin, const Rectangle& rRect, sal_uLong nFlags) -{ - // do not use native popup menu when AQUA_NATIVE_MENUS is set to sal_False - if( ! VisibleMenuBar() ) { - return false; - } - - // set offsets for positioning - const float offset = 9.0; - - // get the pointers - AquaSalFrame * pParentAquaSalFrame = (AquaSalFrame *) pWin->ImplGetWindowImpl()->mpRealParent->ImplGetFrame(); - NSWindow* pParentNSWindow = pParentAquaSalFrame->mpNSWindow; - NSView* pParentNSView = [pParentNSWindow contentView]; - NSView* pPopupNSView = ((AquaSalFrame *) pWin->ImplGetWindow()->ImplGetFrame())->mpNSView; - NSRect popupFrame = [pPopupNSView frame]; - - // since we manipulate the menu below (removing entries) - // let's rather make a copy here and work with that - NSMenu* pCopyMenu = [mpMenu copy]; - - // filter disabled elements - removeUnusedItemsRunner( pCopyMenu ); - - // create frame rect - NSRect displayPopupFrame = NSMakeRect( rRect.Left()+(offset-1), rRect.Top()+(offset+1), popupFrame.size.width, 0 ); - pParentAquaSalFrame->VCLToCocoa(displayPopupFrame, false); - - // do the same strange semantics as vcl popup windows to arrive at a frame geometry - // in mirrored UI case; best done by actually executing the same code - sal_uInt16 nArrangeIndex; - pWin->SetPosPixel( pWin->ImplCalcPos( pWin, rRect, nFlags, nArrangeIndex ) ); - displayPopupFrame.origin.x = pWin->ImplGetFrame()->maGeometry.nX - pParentAquaSalFrame->maGeometry.nX + offset; - displayPopupFrame.origin.y = pWin->ImplGetFrame()->maGeometry.nY - pParentAquaSalFrame->maGeometry.nY + offset; - pParentAquaSalFrame->VCLToCocoa(displayPopupFrame, false); - - // #i111992# if this menu was opened due to a key event, prevent dispatching that yet again - if( [pParentNSView respondsToSelector: @selector(clearLastEvent)] ) - [pParentNSView performSelector:@selector(clearLastEvent)]; - - // open popup menu - NSPopUpButtonCell * pPopUpButtonCell = [[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]; - [pPopUpButtonCell setMenu: pCopyMenu]; - [pPopUpButtonCell selectItem:nil]; - [AquaA11yWrapper setPopupMenuOpen: YES]; - [pPopUpButtonCell performClickWithFrame:displayPopupFrame inView:pParentNSView]; - [pPopUpButtonCell release]; - [AquaA11yWrapper setPopupMenuOpen: NO]; - - // clean up the copy - [pCopyMenu release]; - return true; -} - -int AquaSalMenu::getItemIndexByPos( sal_uInt16 nPos ) const -{ - int nIndex = 0; - if( nPos == MENU_APPEND ) - nIndex = [mpMenu numberOfItems]; - else - nIndex = sal::static_int_cast( mbMenuBar ? nPos+1 : nPos ); - return nIndex; -} - -const AquaSalFrame* AquaSalMenu::getFrame() const -{ - const AquaSalMenu* pMenu = this; - while( pMenu && ! pMenu->mpFrame ) - pMenu = pMenu->mpParentSalMenu; - return pMenu ? pMenu->mpFrame : NULL; -} - -void AquaSalMenu::unsetMainMenu() -{ - pCurrentMenuBar = NULL; - - // remove items from main menu - NSMenu* pMenu = [NSApp mainMenu]; - for( int nItems = [pMenu numberOfItems]; nItems > 1; nItems-- ) - [pMenu removeItemAtIndex: 1]; -} - -void AquaSalMenu::setMainMenu() -{ - DBG_ASSERT( mbMenuBar, "setMainMenu on non menubar" ); - if( mbMenuBar ) - { - if( pCurrentMenuBar != this ) - { - unsetMainMenu(); - // insert our items - for( unsigned int i = 0; i < maItems.size(); i++ ) - { - NSMenuItem* pItem = maItems[i]->mpMenuItem; - [mpMenu insertItem: pItem atIndex: i+1]; - } - pCurrentMenuBar = this; - - // change status item - statusLayout(); - } - enableMainMenu( true ); - } -} - -void AquaSalMenu::setDefaultMenu() -{ - NSMenu* pMenu = [NSApp mainMenu]; - - unsetMainMenu(); - - // insert default items - std::vector< NSMenuItem* >& rFallbackMenu( GetSalData()->maFallbackMenu ); - for( unsigned int i = 0, nAddItems = rFallbackMenu.size(); i < nAddItems; i++ ) - { - NSMenuItem* pItem = rFallbackMenu[i]; - if( [pItem menu] == nil ) - [pMenu insertItem: pItem atIndex: i+1]; - } -} - -void AquaSalMenu::enableMainMenu( bool bEnable ) -{ - NSMenu* pMainMenu = [NSApp mainMenu]; - if( pMainMenu ) - { - // enable/disable items from main menu - int nItems = [pMainMenu numberOfItems]; - for( int n = 1; n < nItems; n++ ) - { - NSMenuItem* pItem = [pMainMenu itemAtIndex: n]; - [pItem setEnabled: bEnable ? YES : NO]; - } - } -} - -void AquaSalMenu::addFallbackMenuItem( NSMenuItem* pNewItem ) -{ - initAppMenu(); - - std::vector< NSMenuItem* >& rFallbackMenu( GetSalData()->maFallbackMenu ); - - // prevent duplicate insertion - int nItems = rFallbackMenu.size(); - for( int i = 0; i < nItems; i++ ) - { - if( rFallbackMenu[i] == pNewItem ) - return; - } - - // push the item to the back and retain it - [pNewItem retain]; - rFallbackMenu.push_back( pNewItem ); - - if( pCurrentMenuBar == NULL ) - setDefaultMenu(); -} - -void AquaSalMenu::removeFallbackMenuItem( NSMenuItem* pOldItem ) -{ - std::vector< NSMenuItem* >& rFallbackMenu( GetSalData()->maFallbackMenu ); - - // find item - unsigned int nItems = rFallbackMenu.size(); - for( unsigned int i = 0; i < nItems; i++ ) - { - if( rFallbackMenu[i] == pOldItem ) - { - // remove item and release - rFallbackMenu.erase( rFallbackMenu.begin() + i ); - [pOldItem release]; - - if( pCurrentMenuBar == NULL ) - setDefaultMenu(); - - return; - } - } -} - -sal_Bool AquaSalMenu::VisibleMenuBar() -{ - // Enable/disable experimental native menus code? - // - // To disable native menus, set the environment variable AQUA_NATIVE_MENUS to FALSE - - static const char *pExperimental = getenv ("AQUA_NATIVE_MENUS"); - - if ( pExperimental && !strcasecmp(pExperimental, "FALSE") ) - return sal_False; - - // End of experimental code enable/disable part - - return sal_True; -} - -void AquaSalMenu::SetFrame( const SalFrame *pFrame ) -{ - mpFrame = static_cast(pFrame); -} - -void AquaSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos ) -{ - AquaSalMenuItem *pAquaSalMenuItem = static_cast(pSalMenuItem); - - pAquaSalMenuItem->mpParentMenu = this; - DBG_ASSERT( pAquaSalMenuItem->mpVCLMenu == NULL || - pAquaSalMenuItem->mpVCLMenu == mpVCLMenu || - mpVCLMenu == NULL, - "resetting menu ?" ); - if( pAquaSalMenuItem->mpVCLMenu ) - mpVCLMenu = pAquaSalMenuItem->mpVCLMenu; - - if( nPos == MENU_APPEND || nPos == maItems.size() ) - maItems.push_back( pAquaSalMenuItem ); - else if( nPos < maItems.size() ) - maItems.insert( maItems.begin() + nPos, pAquaSalMenuItem ); - else - { - OSL_FAIL( "invalid item index in insert" ); - return; - } - - if( ! mbMenuBar || pCurrentMenuBar == this ) - [mpMenu insertItem: pAquaSalMenuItem->mpMenuItem atIndex: getItemIndexByPos(nPos)]; -} - -void AquaSalMenu::RemoveItem( unsigned nPos ) -{ - AquaSalMenuItem* pRemoveItem = NULL; - if( nPos == MENU_APPEND || nPos == (maItems.size()-1) ) - { - pRemoveItem = maItems.back(); - maItems.pop_back(); - } - else if( nPos < maItems.size() ) - { - pRemoveItem = maItems[ nPos ]; - maItems.erase( maItems.begin()+nPos ); - } - else - { - OSL_FAIL( "invalid item index in remove" ); - return; - } - - pRemoveItem->mpParentMenu = NULL; - - if( ! mbMenuBar || pCurrentMenuBar == this ) - [mpMenu removeItemAtIndex: getItemIndexByPos(nPos)]; -} - -void AquaSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned /*nPos*/ ) -{ - AquaSalMenuItem *pAquaSalMenuItem = static_cast(pSalMenuItem); - AquaSalMenu *subAquaSalMenu = static_cast(pSubMenu); - - if (subAquaSalMenu) - { - pAquaSalMenuItem->mpSubMenu = subAquaSalMenu; - if( subAquaSalMenu->mpParentSalMenu == NULL ) - { - subAquaSalMenu->mpParentSalMenu = this; - [pAquaSalMenuItem->mpMenuItem setSubmenu: subAquaSalMenu->mpMenu]; - - // set title of submenu - [subAquaSalMenu->mpMenu setTitle: [pAquaSalMenuItem->mpMenuItem title]]; - } - else if( subAquaSalMenu->mpParentSalMenu != this ) - { - // cocoa doesn't allow menus to be submenus of multiple - // menu items, so place a copy in the menu item instead ? - // let's hope that NSMenu copy does the right thing - NSMenu* pCopy = [subAquaSalMenu->mpMenu copy]; - [pAquaSalMenuItem->mpMenuItem setSubmenu: pCopy]; - - // set title of submenu - [pCopy setTitle: [pAquaSalMenuItem->mpMenuItem title]]; - } - } - else - { - if( pAquaSalMenuItem->mpSubMenu ) - { - if( pAquaSalMenuItem->mpSubMenu->mpParentSalMenu == this ) - pAquaSalMenuItem->mpSubMenu->mpParentSalMenu = NULL; - } - pAquaSalMenuItem->mpSubMenu = NULL; - [pAquaSalMenuItem->mpMenuItem setSubmenu: nil]; - } -} - -void AquaSalMenu::CheckItem( unsigned nPos, sal_Bool bCheck ) -{ - if( nPos < maItems.size() ) - { - NSMenuItem* pItem = maItems[nPos]->mpMenuItem; - [pItem setState: bCheck ? NSOnState : NSOffState]; - } -} - -void AquaSalMenu::EnableItem( unsigned nPos, sal_Bool bEnable ) -{ - if( nPos < maItems.size() ) - { - NSMenuItem* pItem = maItems[nPos]->mpMenuItem; - [pItem setEnabled: bEnable ? YES : NO]; - } -} - -void AquaSalMenu::SetItemImage( unsigned /*nPos*/, SalMenuItem* pSMI, const Image& rImage ) -{ - AquaSalMenuItem* pSalMenuItem = static_cast( pSMI ); - if( ! pSalMenuItem || ! pSalMenuItem->mpMenuItem ) - return; - - NSImage* pImage = CreateNSImage( rImage ); - - [pSalMenuItem->mpMenuItem setImage: pImage]; - if( pImage ) - [pImage release]; -} - -void AquaSalMenu::SetItemText( unsigned /*i_nPos*/, SalMenuItem* i_pSalMenuItem, const OUString& i_rText ) -{ - if (!i_pSalMenuItem) - return; - - AquaSalMenuItem *pAquaSalMenuItem = (AquaSalMenuItem *) i_pSalMenuItem; - - // Delete mnemonics - OUString aText( comphelper::string::remove(i_rText, '~') ); - - /* #i90015# until there is a correct solution - strip out any appended (.*) in menubar entries - */ - if( mbMenuBar ) - { - sal_Int32 nPos = aText.lastIndexOf( '(' ); - if( nPos != -1 ) - { - sal_Int32 nPos2 = aText.indexOf( ')' ); - if( nPos2 != -1 ) - aText = aText.replaceAt( nPos, nPos2-nPos+1, "" ); - } - } - - NSString* pString = CreateNSString( aText ); - if (pString) - { - [pAquaSalMenuItem->mpMenuItem setTitle: pString]; - // if the menu item has a submenu, change its title as well - if (pAquaSalMenuItem->mpSubMenu) - [pAquaSalMenuItem->mpSubMenu->mpMenu setTitle: pString]; - [pString release]; - } -} - -void AquaSalMenu::SetAccelerator( unsigned /*nPos*/, SalMenuItem* pSalMenuItem, const KeyCode& rKeyCode, const OUString& /*rKeyName*/ ) -{ - sal_uInt16 nModifier; - sal_Unicode nCommandKey = 0; - - sal_uInt16 nKeyCode=rKeyCode.GetCode(); - if( nKeyCode ) - { - if ((nKeyCode>=KEY_A) && (nKeyCode<=KEY_Z)) // letter A..Z - nCommandKey = nKeyCode-KEY_A + 'a'; - else if ((nKeyCode>=KEY_0) && (nKeyCode<=KEY_9)) // numbers 0..9 - nCommandKey = nKeyCode-KEY_0 + '0'; - else if ((nKeyCode>=KEY_F1) && (nKeyCode<=KEY_F26)) // function keys F1..F26 - nCommandKey = nKeyCode-KEY_F1 + NSF1FunctionKey; - else if( nKeyCode == KEY_REPEAT ) - nCommandKey = NSRedoFunctionKey; - else if( nKeyCode == KEY_SPACE ) - nCommandKey = ' '; - else - { - switch (nKeyCode) - { - case KEY_ADD: - nCommandKey='+'; - break; - case KEY_SUBTRACT: - nCommandKey='-'; - break; - case KEY_MULTIPLY: - nCommandKey='*'; - break; - case KEY_DIVIDE: - nCommandKey='/'; - break; - case KEY_POINT: - nCommandKey='.'; - break; - case KEY_LESS: - nCommandKey='<'; - break; - case KEY_GREATER: - nCommandKey='>'; - break; - case KEY_EQUAL: - nCommandKey='='; - break; - } - } - } - else // not even a code ? nonsense -> ignore - return; - - DBG_ASSERT( nCommandKey, "unmapped accelerator key" ); - - nModifier=rKeyCode.GetAllModifier(); - - // should always use the command key - int nItemModifier = 0; - - if (nModifier & KEY_SHIFT) - { - nItemModifier |= NSShiftKeyMask; // actually useful only for function keys - if( nKeyCode >= KEY_A && nKeyCode <= KEY_Z ) - nCommandKey = nKeyCode - KEY_A + 'A'; - } - - if (nModifier & KEY_MOD1) - nItemModifier |= NSCommandKeyMask; - - if(nModifier & KEY_MOD2) - nItemModifier |= NSAlternateKeyMask; - - if(nModifier & KEY_MOD3) - nItemModifier |= NSControlKeyMask; - - AquaSalMenuItem *pAquaSalMenuItem = (AquaSalMenuItem *) pSalMenuItem; - NSString* pString = CreateNSString( OUString( &nCommandKey, 1 ) ); - [pAquaSalMenuItem->mpMenuItem setKeyEquivalent: pString]; - [pAquaSalMenuItem->mpMenuItem setKeyEquivalentModifierMask: nItemModifier]; - if (pString) - [pString release]; -} - -void AquaSalMenu::GetSystemMenuData( SystemMenuData* ) -{ -} - -AquaSalMenu::MenuBarButtonEntry* AquaSalMenu::findButtonItem( sal_uInt16 i_nItemId ) -{ - for( size_t i = 0; i < maButtons.size(); ++i ) - { - if( maButtons[i].maButton.mnId == i_nItemId ) - return &maButtons[i]; - } - return NULL; -} - -void AquaSalMenu::statusLayout() -{ - if( GetSalData()->mpStatusItem ) - { - NSView* pNSView = [GetSalData()->mpStatusItem view]; - if( [pNSView isMemberOfClass: [OOStatusItemView class]] ) // well of course it is - [(OOStatusItemView*)pNSView layout]; - else - OSL_FAIL( "someone stole our status view" ); - } -} - -void AquaSalMenu::releaseButtonEntry( MenuBarButtonEntry& i_rEntry ) -{ - if( i_rEntry.mpNSImage ) - { - [i_rEntry.mpNSImage release]; - i_rEntry.mpNSImage = nil; - } - if( i_rEntry.mpToolTipString ) - { - [i_rEntry.mpToolTipString release]; - i_rEntry.mpToolTipString = nil; - } -} - -bool AquaSalMenu::AddMenuBarButton( const SalMenuButtonItem& i_rNewItem ) -{ - if( ! mbMenuBar || ! VisibleMenuBar() ) - return false; - - MenuBarButtonEntry* pEntry = findButtonItem( i_rNewItem.mnId ); - if( pEntry ) - { - releaseButtonEntry( *pEntry ); - pEntry->maButton = i_rNewItem; - pEntry->mpNSImage = CreateNSImage( i_rNewItem.maImage ); - if( i_rNewItem.maToolTipText.getLength() ) - pEntry->mpToolTipString = CreateNSString( i_rNewItem.maToolTipText ); - } - else - { - maButtons.push_back( MenuBarButtonEntry( i_rNewItem ) ); - maButtons.back().mpNSImage = CreateNSImage( i_rNewItem.maImage ); - maButtons.back().mpToolTipString = CreateNSString( i_rNewItem.maToolTipText ); - } - - // lazy create status item - SalData::getStatusItem(); - - if( pCurrentMenuBar == this ) - statusLayout(); - - return true; -} - -void AquaSalMenu::RemoveMenuBarButton( sal_uInt16 i_nId ) -{ - MenuBarButtonEntry* pEntry = findButtonItem( i_nId ); - if( pEntry ) - { - releaseButtonEntry( *pEntry ); - // note: vector guarantees that its contents are in a plain array - maButtons.erase( maButtons.begin() + (pEntry - &maButtons[0]) ); - } - - if( pCurrentMenuBar == this ) - statusLayout(); -} - -Rectangle AquaSalMenu::GetMenuBarButtonRectPixel( sal_uInt16 i_nItemId, SalFrame* i_pReferenceFrame ) -{ - if( ! i_pReferenceFrame || ! AquaSalFrame::isAlive( static_cast(i_pReferenceFrame) ) ) - return Rectangle(); - - MenuBarButtonEntry* pEntry = findButtonItem( i_nItemId ); - - if( ! pEntry ) - return Rectangle(); - - NSStatusItem* pItem = SalData::getStatusItem(); - if( ! pItem ) - return Rectangle(); - - NSView* pNSView = [pItem view]; - if( ! pNSView ) - return Rectangle(); - NSWindow* pNSWin = [pNSView window]; - if( ! pNSWin ) - return Rectangle(); - - NSRect aRect = [pNSWin frame]; - aRect.origin = [pNSWin convertBaseToScreen: NSMakePoint( 0, 0 )]; - - // make coordinates relative to reference frame - static_cast(i_pReferenceFrame)->CocoaToVCL( aRect.origin ); - aRect.origin.x -= i_pReferenceFrame->maGeometry.nX; - aRect.origin.y -= i_pReferenceFrame->maGeometry.nY + aRect.size.height; - - return Rectangle( Point(static_cast(aRect.origin.x), - static_cast(aRect.origin.y) - ), - Size( static_cast(aRect.size.width), - static_cast(aRect.size.height) - ) - ); -} - -// ======================================================================= - -/* - * SalMenuItem - */ - -AquaSalMenuItem::AquaSalMenuItem( const SalItemParams* pItemData ) : - mnId( pItemData->nId ), - mpVCLMenu( pItemData->pMenu ), - mpParentMenu( NULL ), - mpSubMenu( NULL ), - mpMenuItem( nil ) -{ - // Delete mnemonics - OUString aText( comphelper::string::remove(pItemData->aText, '~') ); - - if (pItemData->eType == MENUITEM_SEPARATOR) - { - mpMenuItem = [NSMenuItem separatorItem]; - // these can go occasionally go in and out of a menu, ensure their lifecycle - // also for the release in AquaSalMenuItem destructor - [mpMenuItem retain]; - } - else - { - mpMenuItem = [[SalNSMenuItem alloc] initWithMenuItem: this]; - [mpMenuItem setEnabled: YES]; - NSString* pString = CreateNSString( aText ); - if (pString) - { - [mpMenuItem setTitle: pString]; - [pString release]; - } - // anything but a separator should set a menu to dispatch to - DBG_ASSERT( mpVCLMenu, "no menu" ); - } -} - -AquaSalMenuItem::~AquaSalMenuItem() -{ - /* #i89860# FIXME: - using [autorelease] here (and in AquaSalMenu:::~AquaSalMenu) instead of - [release] fixes an occasional crash. That should indicate that we release - menus / menu items in the wrong order somewhere, but I - could not find that case. - */ - if( mpMenuItem ) - [mpMenuItem autorelease]; -} - -// ------------------------------------------------------------------- - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/window/salnsmenu.mm b/vcl/aqua/source/window/salnsmenu.mm deleted file mode 100644 index 39c36aec7615..000000000000 --- a/vcl/aqua/source/window/salnsmenu.mm +++ /dev/null @@ -1,207 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "aqua/salinst.h" -#include "aqua/saldata.hxx" -#include "aqua/salframe.h" -#include "aqua/salmenu.h" -#include "aqua/salnsmenu.h" - -#include "vcl/window.hxx" - -@implementation SalNSMenu --(id)initWithMenu: (AquaSalMenu*)pMenu -{ - mpMenu = pMenu; - return [super initWithTitle: [NSString string]]; -} - --(void)menuNeedsUpdate: (NSMenu*)pMenu -{ - (void)pMenu; - YIELD_GUARD; - - if( mpMenu ) - { - const AquaSalFrame* pFrame = mpMenu->getFrame(); - if( pFrame && AquaSalFrame::isAlive( pFrame ) ) - { - SalMenuEvent aMenuEvt; - aMenuEvt.mnId = 0; - aMenuEvt.mpMenu = mpMenu->mpVCLMenu; - if( aMenuEvt.mpMenu ) - { - pFrame->CallCallback(SALEVENT_MENUACTIVATE, &aMenuEvt); - pFrame->CallCallback(SALEVENT_MENUDEACTIVATE, &aMenuEvt); - } - else - OSL_FAIL( "unconnected menu" ); - } - } -} - --(void)setSalMenu: (AquaSalMenu*)pMenu -{ - mpMenu = pMenu; -} -@end - -@implementation SalNSMenuItem --(id)initWithMenuItem: (AquaSalMenuItem*)pMenuItem -{ - mpMenuItem = pMenuItem; - id ret = [super initWithTitle: [NSString string] - action: @selector(menuItemTriggered:) - keyEquivalent: [NSString string]]; - [ret setTarget: self]; - return ret; -} --(void)menuItemTriggered: (id)aSender -{ - (void)aSender; - YIELD_GUARD; - - const AquaSalFrame* pFrame = mpMenuItem->mpParentMenu ? mpMenuItem->mpParentMenu->getFrame() : NULL; - if( pFrame && AquaSalFrame::isAlive( pFrame ) && ! pFrame->GetWindow()->IsInModalMode() ) - { - SalMenuEvent aMenuEvt( mpMenuItem->mnId, mpMenuItem->mpVCLMenu ); - pFrame->CallCallback(SALEVENT_MENUCOMMAND, &aMenuEvt); - } - else if( mpMenuItem->mpVCLMenu ) - { - // if an item from submenu was selected. the corresponding Window does not exist because - // we use native popup menus, so we have to set the selected menuitem directly - // incidentally this of course works for top level popup menus, too - PopupMenu * pPopupMenu = dynamic_cast(mpMenuItem->mpVCLMenu); - if( pPopupMenu ) - { - // FIXME: revise this ugly code - - // select handlers in vcl are dispatch on the original menu - // if not consumed by the select handler of the current menu - // however since only the starting menu ever came into Execute - // the hierarchy is not build up. Workaround this by getting - // the menu it should have been - - // get started from hierarchy in vcl menus - AquaSalMenu* pParentMenu = mpMenuItem->mpParentMenu; - Menu* pCurMenu = mpMenuItem->mpVCLMenu; - while( pParentMenu && pParentMenu->mpVCLMenu ) - { - pCurMenu = pParentMenu->mpVCLMenu; - pParentMenu = pParentMenu->mpParentSalMenu; - } - - pPopupMenu->SetSelectedEntry( mpMenuItem->mnId ); - pPopupMenu->ImplSelectWithStart( pCurMenu ); - } - else - OSL_FAIL( "menubar item without frame !" ); - } -} -@end - -@implementation OOStatusItemView --(void)drawRect: (NSRect)aRect -{ - NSGraphicsContext* pContext = [NSGraphicsContext currentContext]; - [pContext saveGraphicsState]; - [SalData::getStatusItem() drawStatusBarBackgroundInRect: aRect withHighlight: NO]; - if( AquaSalMenu::pCurrentMenuBar ) - { - const std::vector< AquaSalMenu::MenuBarButtonEntry >& rButtons( AquaSalMenu::pCurrentMenuBar->getButtons() ); - NSRect aFrame = [self frame]; - NSRect aImgRect = { { 2, 0 }, { 0, 0 } }; - for( size_t i = 0; i < rButtons.size(); ++i ) - { - NSRect aFromRect = { { 0, 0 }, - { static_cast(rButtons[i].maButton.maImage.GetSizePixel().Width()), - static_cast(rButtons[i].maButton.maImage.GetSizePixel().Height()) } }; - aImgRect.origin.y = floor((aFrame.size.height - aFromRect.size.height)/2); - aImgRect.size = aFromRect.size; - if( rButtons[i].mpNSImage ) - [rButtons[i].mpNSImage drawInRect: aImgRect fromRect: aFromRect operation: NSCompositeSourceOver fraction: 1.0]; - aImgRect.origin.x += aFromRect.size.width + 2; - } - } - [pContext restoreGraphicsState]; -} - --(void)mouseUp: (NSEvent *)pEvent -{ - /* check if button goes up inside one of our status buttons */ - if( AquaSalMenu::pCurrentMenuBar ) - { - const std::vector< AquaSalMenu::MenuBarButtonEntry >& rButtons( AquaSalMenu::pCurrentMenuBar->getButtons() ); - NSRect aFrame = [self frame]; - NSRect aImgRect = { { 2, 0 }, { 0, 0 } }; - NSPoint aMousePt = [pEvent locationInWindow]; - for( size_t i = 0; i < rButtons.size(); ++i ) - { - NSRect aFromRect = { { 0, 0 }, - { static_cast(rButtons[i].maButton.maImage.GetSizePixel().Width()), - static_cast(rButtons[i].maButton.maImage.GetSizePixel().Height()) } }; - aImgRect.origin.y = (aFrame.size.height - aFromRect.size.height)/2; - aImgRect.size = aFromRect.size; - if( aMousePt.x >= aImgRect.origin.x && aMousePt.x <= (aImgRect.origin.x+aImgRect.size.width) && - aMousePt.y >= aImgRect.origin.y && aMousePt.y <= (aImgRect.origin.y+aImgRect.size.height) ) - { - if( AquaSalMenu::pCurrentMenuBar->mpFrame && AquaSalFrame::isAlive( AquaSalMenu::pCurrentMenuBar->mpFrame ) ) - { - SalMenuEvent aMenuEvt( rButtons[i].maButton.mnId, AquaSalMenu::pCurrentMenuBar->mpVCLMenu ); - AquaSalMenu::pCurrentMenuBar->mpFrame->CallCallback(SALEVENT_MENUBUTTONCOMMAND, &aMenuEvt); - } - return; - } - - aImgRect.origin.x += aFromRect.size.width + 2; - } - } -} - --(void)layout -{ - NSStatusBar* pStatBar = [NSStatusBar systemStatusBar]; - NSSize aSize = { 0, [pStatBar thickness] }; - [self removeAllToolTips]; - if( AquaSalMenu::pCurrentMenuBar ) - { - const std::vector< AquaSalMenu::MenuBarButtonEntry >& rButtons( AquaSalMenu::pCurrentMenuBar->getButtons() ); - if( ! rButtons.empty() ) - { - aSize.width = 2; - for( size_t i = 0; i < rButtons.size(); ++i ) - { - NSRect aImgRect = { { static_cast(aSize.width), - static_cast(floor((aSize.height-rButtons[i].maButton.maImage.GetSizePixel().Height())/2)) }, - { static_cast(rButtons[i].maButton.maImage.GetSizePixel().Width()), - static_cast(rButtons[i].maButton.maImage.GetSizePixel().Height()) } }; - if( rButtons[i].mpToolTipString ) - [self addToolTipRect: aImgRect owner: rButtons[i].mpToolTipString userData: NULL]; - aSize.width += 2 + aImgRect.size.width; - } - } - } - [self setFrameSize: aSize]; -} -@end - - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/window/salobj.cxx b/vcl/aqua/source/window/salobj.cxx deleted file mode 100644 index c5d09d73dac8..000000000000 --- a/vcl/aqua/source/window/salobj.cxx +++ /dev/null @@ -1,206 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include - -#include "aqua/saldata.hxx" -#include "aqua/salobj.h" -#include "aqua/salframe.h" - -// ======================================================================= - -AquaSalObject::AquaSalObject( AquaSalFrame* pFrame ) : - mpFrame( pFrame ), - mnClipX( -1 ), - mnClipY( -1 ), - mnClipWidth( -1 ), - mnClipHeight( -1 ), - mbClip( false ), - mnX( 0 ), - mnY( 0 ), - mnWidth( 20 ), - mnHeight( 20 ) -{ - maSysData.nSize = sizeof( maSysData ); - maSysData.mpNSView = NULL; - - NSRect aInitFrame = { { 0, 0 }, { 20, 20 } }; - mpClipView = [[NSClipView alloc] initWithFrame: aInitFrame ]; - if( mpClipView ) - { - [mpFrame->getNSView() addSubview: mpClipView]; - [mpClipView setHidden: YES]; - } - maSysData.mpNSView = [[NSView alloc] initWithFrame: aInitFrame]; - if( maSysData.mpNSView ) - { - if( mpClipView ) - [mpClipView setDocumentView: maSysData.mpNSView]; - } -} - -// ----------------------------------------------------------------------- - -AquaSalObject::~AquaSalObject() -{ - if( maSysData.mpNSView ) - { - NSView *pView = maSysData.mpNSView; - [pView removeFromSuperview]; - [pView release]; - } - if( mpClipView ) - { - [mpClipView removeFromSuperview]; - [mpClipView release]; - } -} - -/* - sadly there seems to be no way to impose clipping on a child view, - especially a QTMovieView which seems to ignore the current context - completely. Also there is no real way to shape a window; on Aqua a - similar effect to non-rectangular windows is achieved by using a - non-opaque window and not painting where one wants the background - to shine through. - - With respect to SalObject this leaves us to having an NSClipView - containing the child view. Even a QTMovieView respects the boundaries of - that, which gives us a clip "region" consisting of one rectangle. - This is gives us an 80% solution only, though. -*/ - -// ----------------------------------------------------------------------- - -void AquaSalObject::ResetClipRegion() -{ - mbClip = false; - setClippedPosSize(); -} - -// ----------------------------------------------------------------------- - -sal_uInt16 AquaSalObject::GetClipRegionType() -{ - return SAL_OBJECT_CLIP_INCLUDERECTS; -} - -// ----------------------------------------------------------------------- - -void AquaSalObject::BeginSetClipRegion( sal_uLong ) -{ - mbClip = false; -} - -// ----------------------------------------------------------------------- - -void AquaSalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) -{ - if( mbClip ) - { - if( nX < mnClipX ) - { - mnClipWidth += mnClipX - nX; - mnClipX = nX; - } - if( nX + nWidth > mnClipX + mnClipWidth ) - mnClipWidth = nX + nWidth - mnClipX; - if( nY < mnClipY ) - { - mnClipHeight += mnClipY - nY; - mnClipY = nY; - } - if( nY + nHeight > mnClipY + mnClipHeight ) - mnClipHeight = nY + nHeight - mnClipY; - } - else - { - mnClipX = nX; - mnClipY = nY; - mnClipWidth = nWidth; - mnClipHeight = nHeight; - mbClip = true; - } -} - -// ----------------------------------------------------------------------- - -void AquaSalObject::EndSetClipRegion() -{ - setClippedPosSize(); -} - -// ----------------------------------------------------------------------- - -void AquaSalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight ) -{ - mnX = nX; - mnY = nY; - mnWidth = nWidth; - mnHeight = nHeight; - setClippedPosSize(); -} - -// ----------------------------------------------------------------------- - -void AquaSalObject::setClippedPosSize() -{ - NSRect aViewRect = { { 0, 0 }, { static_cast(mnWidth), static_cast(mnHeight) } }; - if( maSysData.mpNSView ) - { - NSView* pNSView = maSysData.mpNSView; - [pNSView setFrame: aViewRect]; - } - - NSRect aClipViewRect = { { static_cast(mnX), static_cast(mnY) }, { static_cast(mnWidth), static_cast(mnHeight) } }; - NSPoint aClipPt = { 0, 0 }; - if( mbClip ) - { - aClipViewRect.origin.x += mnClipX; - aClipViewRect.origin.y += mnClipY; - aClipViewRect.size.width = mnClipWidth; - aClipViewRect.size.height = mnClipHeight; - aClipPt.x = mnClipX; - if( mnClipY == 0 ) - aClipPt.y = mnHeight - mnClipHeight; - } - - mpFrame->VCLToCocoa( aClipViewRect, false ); - [mpClipView setFrame: aClipViewRect]; - - [mpClipView scrollToPoint: aClipPt]; -} - -// ----------------------------------------------------------------------- - -void AquaSalObject::Show( sal_Bool bVisible ) -{ - if( mpClipView ) - [mpClipView setHidden: (bVisible ? NO : YES)]; -} - -// ----------------------------------------------------------------------- - -const SystemEnvData* AquaSalObject::GetSystemData() const -{ - return &maSysData; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/coretext/ctfonts.cxx b/vcl/coretext/ctfonts.cxx deleted file mode 100644 index fd113b892099..000000000000 --- a/vcl/coretext/ctfonts.cxx +++ /dev/null @@ -1,478 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include - -#include "impfont.hxx" -#include "outfont.hxx" -#include "sallayout.hxx" - -#ifdef MACOSX -#include "aqua/salinst.h" -#include "aqua/saldata.hxx" -#endif -#include "coretext/salgdi.h" -#include "quartz/utils.h" -#include "ctfonts.hxx" - -#include "basegfx/polygon/b2dpolygon.hxx" -#include "basegfx/matrix/b2dhommatrix.hxx" - -// ======================================================================= - -inline double toRadian(int nDegree) -{ - return nDegree * (M_PI / 1800.0); -} - -CoreTextStyle::CoreTextStyle( const FontSelectPattern& rFSD ) -: mpFontData( (CoreTextFontData*)rFSD.mpFontData ) -, mfFontStretch( 1.0 ) -, mfFontRotation( 0.0 ) -, mpStyleDict( NULL ) -{ - mpFontData = (CoreTextFontData*)rFSD.mpFontData; - const FontSelectPattern* const pReqFont = &rFSD; - - double fScaledFontHeight = pReqFont->mfExactHeight; - - // convert font rotation to radian - mfFontRotation = toRadian(pReqFont->mnOrientation); - - // dummy matrix so we can use CGAffineTransformConcat() below - CGAffineTransform aMatrix = CGAffineTransformMakeTranslation(0, 0); - - // handle font stretching if any - if( (pReqFont->mnWidth != 0) && (pReqFont->mnWidth != pReqFont->mnHeight) ) - { - mfFontStretch = (float)pReqFont->mnWidth / pReqFont->mnHeight; - aMatrix = CGAffineTransformConcat(aMatrix, CGAffineTransformMakeScale(mfFontStretch, 1.0F)); - } - - // create the style object for CoreText font attributes - static const CFIndex nMaxDictSize = 16; // TODO: does this really suffice? - mpStyleDict = CFDictionaryCreateMutable( NULL, nMaxDictSize, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); - - CFBooleanRef pCFVertBool = pReqFont->mbVertical ? kCFBooleanTrue : kCFBooleanFalse; - CFDictionarySetValue( mpStyleDict, kCTVerticalFormsAttributeName, pCFVertBool ); - - // fake bold - if ((pReqFont->GetWeight() >= WEIGHT_BOLD) && (mpFontData->GetWeight() < WEIGHT_SEMIBOLD)) - { - int nStroke = -10.0; - CFNumberRef rStroke = CFNumberCreate(NULL, kCFNumberSInt32Type, &nStroke); - CFDictionarySetValue(mpStyleDict, kCTStrokeWidthAttributeName, rStroke); - } - - // fake italic - if (((pReqFont->GetSlant() == ITALIC_NORMAL) || (pReqFont->GetSlant() == ITALIC_OBLIQUE)) - && !((mpFontData->GetSlant() == ITALIC_NORMAL) || (mpFontData->GetSlant() == ITALIC_OBLIQUE))) - { - aMatrix = CGAffineTransformConcat(aMatrix, CGAffineTransformMake(1, 0, toRadian(120), 1, 0, 0)); - } - - CTFontDescriptorRef pFontDesc = (CTFontDescriptorRef)mpFontData->GetFontId(); - CTFontRef pNewCTFont = CTFontCreateWithFontDescriptor( pFontDesc, fScaledFontHeight, &aMatrix ); - CFDictionarySetValue( mpStyleDict, kCTFontAttributeName, pNewCTFont ); - CFRelease( pNewCTFont); - -#if 0 // LastResort is implicit in CoreText's font cascading - const void* aGFBDescriptors[] = { CTFontDescriptorCreateWithNameAndSize( CFSTR("LastResort"), 0) }; // TODO: use the full GFB list - const int nGfbCount = sizeof(aGFBDescriptors) / sizeof(*aGFBDescriptors); - CFArrayRef pGfbList = CFArrayCreate( NULL, aGFBDescriptors, nGfbCount, &kCFTypeArrayCallBacks); - CFDictionaryAddValue( mpStyleDict, kCTFontCascadeListAttribute, pGfbList); - CFRelease( pGfbList); -#endif -} - -// ----------------------------------------------------------------------- - -CoreTextStyle::~CoreTextStyle( void ) -{ - if( mpStyleDict ) - CFRelease( mpStyleDict ); -} - -// ----------------------------------------------------------------------- - -void CoreTextStyle::GetFontMetric( float fPixelSize, ImplFontMetricData& rMetric ) const -{ - // get the matching CoreText font handle - // TODO: is it worth it to cache the CTFontRef in SetFont() and reuse it here? - CTFontRef aCTFontRef = (CTFontRef)CFDictionaryGetValue( mpStyleDict, kCTFontAttributeName ); - - rMetric.mnAscent = lrint( CTFontGetAscent( aCTFontRef ) * fPixelSize); - rMetric.mnDescent = lrint( CTFontGetDescent( aCTFontRef ) * fPixelSize); - rMetric.mnExtLeading = lrint( CTFontGetLeading( aCTFontRef ) * fPixelSize); - rMetric.mnIntLeading = 0; - // since ImplFontMetricData::mnWidth is only used for stretching/squeezing fonts - // setting this width to the pixel height of the fontsize is good enough - // it also makes the calculation of the stretch factor simple - rMetric.mnWidth = lrint( CTFontGetSize( aCTFontRef ) * fPixelSize * mfFontStretch); - - // all CoreText fonts are scalable - rMetric.mbScalableFont = true; - rMetric.mbKernableFont = true; -} - -// ----------------------------------------------------------------------- - -bool CoreTextStyle::GetGlyphBoundRect( sal_GlyphId nGlyphId, Rectangle& rRect ) const -{ - CGGlyph nCGGlyph = nGlyphId & GF_IDXMASK; - // XXX: this is broken if the glyph came from fallback font - CTFontRef aCTFontRef = (CTFontRef)CFDictionaryGetValue( mpStyleDict, kCTFontAttributeName ); - - const CTFontOrientation aFontOrientation = kCTFontDefaultOrientation; // TODO: horz/vert - const CGRect aCGRect = CTFontGetBoundingRectsForGlyphs( aCTFontRef, aFontOrientation, &nCGGlyph, NULL, 1 ); - - rRect.Left() = lrint( aCGRect.origin.x ); - rRect.Top() = lrint( aCGRect.origin.y ); - rRect.Right() = lrint( aCGRect.origin.x + aCGRect.size.width ); - rRect.Bottom() = lrint( aCGRect.origin.y + aCGRect.size.height ); - return true; -} - -// ----------------------------------------------------------------------- - -// callbacks from CTFontCreatePathForGlyph+CGPathApply for GetGlyphOutline() -struct GgoData { basegfx::B2DPolygon maPolygon; basegfx::B2DPolyPolygon* mpPolyPoly; }; - -static void MyCGPathApplierFunc( void* pData, const CGPathElement* pElement ) -{ - basegfx::B2DPolygon& rPolygon = static_cast(pData)->maPolygon; - const int nPointCount = rPolygon.count(); - - switch( pElement->type ) - { - case kCGPathElementCloseSubpath: - case kCGPathElementMoveToPoint: - if( nPointCount > 0 ) { - static_cast(pData)->mpPolyPoly->append( rPolygon ); - rPolygon.clear(); - } - // fall through for kCGPathElementMoveToPoint: - if( pElement->type != kCGPathElementMoveToPoint ) - break; - case kCGPathElementAddLineToPoint: - rPolygon.append( basegfx::B2DPoint( +pElement->points[0].x, -pElement->points[0].y ) ); - break; - case kCGPathElementAddCurveToPoint: - rPolygon.append( basegfx::B2DPoint( +pElement->points[2].x, -pElement->points[2].y ) ); - rPolygon.setNextControlPoint( nPointCount-1, basegfx::B2DPoint( pElement->points[0].x, -pElement->points[0].y ) ); - rPolygon.setPrevControlPoint( nPointCount+0, basegfx::B2DPoint( pElement->points[1].x, -pElement->points[1].y ) ); - break; - case kCGPathElementAddQuadCurveToPoint: { - const basegfx::B2DPoint aStartPt = rPolygon.getB2DPoint( nPointCount-1 ); - const basegfx::B2DPoint aCtrPt1( (aStartPt.getX() + 2* pElement->points[0].x) / 3.0, - (aStartPt.getY() - 2 * pElement->points[0].y) / 3.0 ); - const basegfx::B2DPoint aCtrPt2( (+2 * +pElement->points[0].x + pElement->points[1].x) / 3.0, - (-2 * pElement->points[0].y - pElement->points[1].y) / 3.0 ); - rPolygon.append( basegfx::B2DPoint( +pElement->points[1].x, -pElement->points[1].y ) ); - rPolygon.setNextControlPoint( nPointCount-1, aCtrPt1 ); - rPolygon.setPrevControlPoint( nPointCount+0, aCtrPt2 ); - } break; - } -} - -bool CoreTextStyle::GetGlyphOutline( sal_GlyphId nGlyphId, basegfx::B2DPolyPolygon& rResult ) const -{ - rResult.clear(); - - CGGlyph nCGGlyph = nGlyphId & GF_IDXMASK; - // XXX: this is broken if the glyph came from fallback font - CTFontRef pCTFont = (CTFontRef)CFDictionaryGetValue( mpStyleDict, kCTFontAttributeName ); - CGPathRef xPath = CTFontCreatePathForGlyph( pCTFont, nCGGlyph, NULL ); - - GgoData aGgoData; - aGgoData.mpPolyPoly = &rResult; - CGPathApply( xPath, (void*)&aGgoData, MyCGPathApplierFunc ); -#if 0 // TODO: does OSX ensure that the last polygon is always closed? - const CGPathElement aClosingElement = { kCGPathElementCloseSubpath, NULL }; - MyCGPathApplierFunc( (void*)&aGgoData, &aClosingElement ); -#endif - - return true; -} - -// ----------------------------------------------------------------------- - -void CoreTextStyle::SetTextColor( const RGBAColor& rColor ) -{ - CGFloat aColor[] = { rColor.GetRed(), rColor.GetGreen(), rColor.GetBlue(), rColor.GetAlpha() }; - CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); - CGColorRef pCGColor = CGColorCreate( cs, aColor ); - CGColorSpaceRelease( cs ); - CFDictionarySetValue( mpStyleDict, kCTForegroundColorAttributeName, pCGColor ); - CFRelease( pCGColor); -} - -// ======================================================================= - -PhysicalFontFace* CoreTextFontData::Clone( void ) const -{ - return new CoreTextFontData( *this); -} - -// ----------------------------------------------------------------------- - -CoreTextStyle* CoreTextFontData::CreateTextStyle( const FontSelectPattern& rFSD ) const -{ - return new CoreTextStyle( rFSD); -} - -// ----------------------------------------------------------------------- - -ImplFontEntry* CoreTextFontData::CreateFontInstance( /*const*/ FontSelectPattern& rFSD ) const -{ - return new ImplFontEntry( rFSD); -} - -// ----------------------------------------------------------------------- - -int CoreTextFontData::GetFontTable( const char pTagName[5], unsigned char* pResultBuf ) const -{ - DBG_ASSERT( pTagName[4]=='\0', "CoreTextFontData::GetFontTable with invalid tagname!\n" ); - - const CTFontTableTag nTagCode = (pTagName[0]<<24) + (pTagName[1]<<16) + (pTagName[2]<<8) + (pTagName[3]<<0); - - // get the raw table length - CTFontDescriptorRef pFontDesc = reinterpret_cast( GetFontId()); - CTFontRef rCTFont = CTFontCreateWithFontDescriptor( pFontDesc, 0.0, NULL); -#if defined(MACOSX) && MACOSX_SDK_VERSION < 1080 - const uint32_t opts( kCTFontTableOptionExcludeSynthetic ); -#else - const uint32_t opts( kCTFontTableOptionNoOptions ); -#endif - CFDataRef pDataRef = CTFontCopyTable( rCTFont, nTagCode, opts); - CFRelease( rCTFont); - if( !pDataRef) - return 0; - - const CFIndex nByteLength = CFDataGetLength( pDataRef); - - // get the raw table data if requested - if( pResultBuf && (nByteLength > 0)) - { - const CFRange aFullRange = CFRangeMake( 0, nByteLength); - CFDataGetBytes( pDataRef, aFullRange, (UInt8*)pResultBuf); - } - - CFRelease( pDataRef); - - return (int)nByteLength; -} - -// ======================================================================= - -ImplDevFontAttributes DevFontFromCTFontDescriptor( CTFontDescriptorRef pFD, bool* bFontEnabled ) -{ - // all CoreText fonts are device fonts that can rotate just fine - ImplDevFontAttributes rDFA; - rDFA.mbOrientation = true; - rDFA.mbDevice = true; - rDFA.mnQuality = 0; - - // reset the font attributes - rDFA.SetFamilyType( FAMILY_DONTKNOW ); - rDFA.SetPitch( PITCH_VARIABLE ); - rDFA.SetWidthType( WIDTH_NORMAL ); - rDFA.SetWeight( WEIGHT_NORMAL ); - rDFA.SetItalic( ITALIC_NONE ); - rDFA.SetSymbolFlag( false ); - - // all scalable fonts on this platform are subsettable - rDFA.mbEmbeddable = false; - rDFA.mbSubsettable = true; - - // get font name - CFStringRef pFamilyName = (CFStringRef)CTFontDescriptorCopyAttribute( pFD, kCTFontFamilyNameAttribute ); - rDFA.SetFamilyName( GetOUString( pFamilyName ) ); - // get font style - CFStringRef pStyleName = (CFStringRef)CTFontDescriptorCopyAttribute( pFD, kCTFontStyleNameAttribute ); - rDFA.SetStyleName( GetOUString( pStyleName ) ); - - // get font-enabled status - if( bFontEnabled ) { - int bEnabled = FALSE; - CFNumberRef pEnabled = (CFNumberRef)CTFontDescriptorCopyAttribute( pFD, kCTFontEnabledAttribute ); - CFNumberGetValue( pEnabled, kCFNumberIntType, &bEnabled ); - *bFontEnabled = bEnabled; - } - - // get font attributes - CFDictionaryRef pAttrDict = (CFDictionaryRef)CTFontDescriptorCopyAttribute( pFD, kCTFontTraitsAttribute ); - - // get symbolic trait - // TODO: use other traits such as MonoSpace/Condensed/Expanded or Vertical too - SInt64 nSymbolTrait = 0; - CFNumberRef pSymbolNum = NULL; - if( CFDictionaryGetValueIfPresent( pAttrDict, kCTFontSymbolicTrait, (const void**)&pSymbolNum ) ) { - CFNumberGetValue( pSymbolNum, kCFNumberSInt64Type, &nSymbolTrait ); - rDFA.SetSymbolFlag( ((nSymbolTrait & kCTFontClassMaskTrait) == kCTFontSymbolicClass) ); - } - - // get the font weight - double fWeight = 0; - CFNumberRef pWeightNum = (CFNumberRef)CFDictionaryGetValue( pAttrDict, kCTFontWeightTrait ); - CFNumberGetValue( pWeightNum, kCFNumberDoubleType, &fWeight ); - int nInt = WEIGHT_NORMAL; - if( fWeight > 0 ) { - nInt = rint(WEIGHT_NORMAL + fWeight * ((WEIGHT_BLACK - WEIGHT_NORMAL)/0.68)); - if( nInt > WEIGHT_BLACK ) - nInt = WEIGHT_BLACK; - } else if( fWeight < 0 ) { - nInt = rint(WEIGHT_NORMAL + fWeight * ((WEIGHT_NORMAL - WEIGHT_THIN)/0.9)); - if( nInt < WEIGHT_THIN ) - nInt = WEIGHT_THIN; - } - rDFA.SetWeight( (FontWeight)nInt ); - - // get the font slant - double fSlant = 0; - CFNumberRef pSlantNum = (CFNumberRef)CFDictionaryGetValue( pAttrDict, kCTFontSlantTrait ); - CFNumberGetValue( pSlantNum, kCFNumberDoubleType, &fSlant ); - if( fSlant >= 0.035 ) - rDFA.SetItalic( ITALIC_NORMAL ); - - // get width trait - double fWidth = 0; - CFNumberRef pWidthNum = (CFNumberRef)CFDictionaryGetValue( pAttrDict, kCTFontWidthTrait ); - CFNumberGetValue( pWidthNum, kCFNumberDoubleType, &fWidth ); - nInt = WIDTH_NORMAL; - if( fWidth > 0 ) { - nInt = rint( WIDTH_NORMAL + fWidth * ((WIDTH_ULTRA_EXPANDED - WIDTH_NORMAL)/0.4)); - if( nInt > WIDTH_ULTRA_EXPANDED ) - nInt = WIDTH_ULTRA_EXPANDED; - } else if( fWidth < 0 ) { - nInt = rint( WIDTH_NORMAL + fWidth * ((WIDTH_NORMAL - WIDTH_ULTRA_CONDENSED)/0.5)); - if( nInt < WIDTH_ULTRA_CONDENSED ) - nInt = WIDTH_ULTRA_CONDENSED; - } - rDFA.SetWidthType( (FontWidth)nInt ); - - // release the attribute dict that we had copied - CFRelease( pAttrDict ); - - // TODO? also use the HEAD table if available to get more attributes -// CFDataRef CTFontCopyTable( CTFontRef, kCTFontTableHead, /*kCTFontTableOptionNoOptions*/kCTFontTableOptionExcludeSynthetic ); - - return rDFA; -} - -static void CTFontEnumCallBack( const void* pValue, void* pContext ) -{ - CTFontDescriptorRef pFD = static_cast(pValue); - - bool bFontEnabled; - ImplDevFontAttributes rDFA = DevFontFromCTFontDescriptor( pFD, &bFontEnabled ); - - if( bFontEnabled) - { - const sal_IntPtr nFontId = (sal_IntPtr)pValue; - CoreTextFontData* pFontData = new CoreTextFontData( rDFA, nFontId ); - SystemFontList* pFontList = (SystemFontList*)pContext; - pFontList->AddFont( pFontData ); - } -} - -// ======================================================================= - -SystemFontList::SystemFontList() -: mpCTFontCollection( NULL ) -, mpCTFontArray( NULL ) -{} - -// ----------------------------------------------------------------------- - -SystemFontList::~SystemFontList() -{ - CTFontContainer::const_iterator it = maFontContainer.begin(); - for(; it != maFontContainer.end(); ++it ) - delete (*it).second; - maFontContainer.clear(); - - if( mpCTFontArray ) - CFRelease( mpCTFontArray ); - if( mpCTFontCollection ) - CFRelease( mpCTFontCollection ); -} - -// ----------------------------------------------------------------------- - -void SystemFontList::AddFont( CoreTextFontData* pFontData ) -{ - sal_IntPtr nFontId = pFontData->GetFontId(); - maFontContainer[ nFontId ] = pFontData; -} - -// ----------------------------------------------------------------------- - -void SystemFontList::AnnounceFonts( ImplDevFontList& rFontList ) const -{ - CTFontContainer::const_iterator it = maFontContainer.begin(); - for(; it != maFontContainer.end(); ++it ) - rFontList.Add( (*it).second->Clone() ); -} - -// ----------------------------------------------------------------------- - -CoreTextFontData* SystemFontList::GetFontDataFromId( sal_IntPtr nFontId ) const -{ - CTFontContainer::const_iterator it = maFontContainer.find( nFontId ); - if( it == maFontContainer.end() ) - return NULL; - return (*it).second; -} - -// ----------------------------------------------------------------------- - -bool SystemFontList::Init( void ) -{ - // enumerate available system fonts - static const int nMaxDictEntries = 8; - CFMutableDictionaryRef pCFDict = CFDictionaryCreateMutable( NULL, - nMaxDictEntries, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); - CFDictionaryAddValue( pCFDict, kCTFontCollectionRemoveDuplicatesOption, kCFBooleanTrue ); - mpCTFontCollection = CTFontCollectionCreateFromAvailableFonts( pCFDict ); - CFRelease( pCFDict ); - - mpCTFontArray = CTFontCollectionCreateMatchingFontDescriptors( mpCTFontCollection ); - const int nFontCount = CFArrayGetCount( mpCTFontArray ); - const CFRange aFullRange = CFRangeMake( 0, nFontCount ); - CFArrayApplyFunction( mpCTFontArray, aFullRange, CTFontEnumCallBack, this ); - - return true; -} - -// ======================================================================= - -SystemFontList* GetCoretextFontList( void ) -{ - SystemFontList* pList = new SystemFontList(); - if( !pList->Init() ) { - delete pList; - return NULL; - } - - return pList; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/coretext/ctfonts.hxx b/vcl/coretext/ctfonts.hxx deleted file mode 100644 index 44153115bb94..000000000000 --- a/vcl/coretext/ctfonts.hxx +++ /dev/null @@ -1,28 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include "coretext/salgdi.h" -#ifdef IOS -#include "headless/svpgdi.hxx" -#endif -#include "sallayout.hxx" - -SystemFontList* GetCoretextFontList(void); -ImplDevFontAttributes DevFontFromCTFontDescriptor( CTFontDescriptorRef, bool* ); -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/coretext/ctlayout.cxx b/vcl/coretext/ctlayout.cxx deleted file mode 100644 index 56d86967aa53..000000000000 --- a/vcl/coretext/ctlayout.cxx +++ /dev/null @@ -1,501 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include "tools/debug.hxx" - -#include "ctfonts.hxx" - -class CTLayout -: public SalLayout -{ -public: - explicit CTLayout( const CoreTextStyle* ); - virtual ~CTLayout( void ); - - virtual bool LayoutText( ImplLayoutArgs& ); - virtual void AdjustLayout( ImplLayoutArgs& ); - virtual void DrawText( SalGraphics& ) const; - - virtual int GetNextGlyphs( int nLen, sal_GlyphId* pGlyphs, Point& rPos, int&, - sal_Int32* pGlyphAdvances, int* pCharIndexes, - const PhysicalFontFace** pFallbackFonts ) const; - - virtual long GetTextWidth() const; - virtual long FillDXArray( sal_Int32* pDXArray ) const; - virtual sal_Int32 GetTextBreak(long nMaxWidth, long nCharExtra, int nFactor) const SAL_OVERRIDE; - virtual void GetCaretPositions( int nArraySize, sal_Int32* pCaretXArray ) const; - virtual bool GetGlyphOutlines( SalGraphics&, PolyPolyVector& ) const; - virtual bool GetBoundRect( SalGraphics&, Rectangle& ) const; - - virtual void InitFont( void) const; - virtual void MoveGlyph( int nStart, long nNewXPos ); - virtual void DropGlyph( int nStart ); - virtual void Simplify( bool bIsBase ); - -private: - CGPoint GetTextDrawPosition(void) const; - double GetWidth(void) const; - - const CoreTextStyle* const mpTextStyle; - - // CoreText specific objects - CFAttributedStringRef mpAttrString; - CTLineRef mpCTLine; - - int mnCharCount; // ==mnEndCharPos-mnMinCharPos - - // cached details about the resulting layout - // mutable members since these details are all lazy initialized - mutable double mfCachedWidth; // cached value of resulting typographical width - - // x-offset relative to layout origin - // currently only used in RTL-layouts - mutable double mfBaseAdv; -}; - -CTLayout::CTLayout( const CoreTextStyle* pTextStyle ) -: mpTextStyle( pTextStyle ) -, mpAttrString( NULL ) -, mpCTLine( NULL ) -, mnCharCount( 0 ) -, mfCachedWidth( -1 ) -, mfBaseAdv( 0 ) -{ -} - -CTLayout::~CTLayout() -{ - if( mpCTLine ) - CFRelease( mpCTLine ); - if( mpAttrString ) - CFRelease( mpAttrString ); -} - -bool CTLayout::LayoutText( ImplLayoutArgs& rArgs ) -{ - if( mpAttrString ) - CFRelease( mpAttrString ); - mpAttrString = NULL; - if( mpCTLine ) - CFRelease( mpCTLine ); - mpCTLine = NULL; - - SalLayout::AdjustLayout( rArgs ); - mnCharCount = mnEndCharPos - mnMinCharPos; - - // short circuit if there is nothing to do - if( mnCharCount <= 0 ) - return false; - - // create the CoreText line layout - CFStringRef aCFText = CFStringCreateWithCharactersNoCopy( NULL, rArgs.mpStr + mnMinCharPos, mnCharCount, kCFAllocatorNull ); - // CFAttributedStringCreate copies the attribues parameter - mpAttrString = CFAttributedStringCreate( NULL, aCFText, mpTextStyle->GetStyleDict() ); - mpCTLine = CTLineCreateWithAttributedString( mpAttrString ); - CFRelease( aCFText); - - return true; -} - -void CTLayout::AdjustLayout( ImplLayoutArgs& rArgs ) -{ - if( !mpCTLine) - return; - - int nOrigWidth = GetTextWidth(); - int nPixelWidth = rArgs.mnLayoutWidth; - if( nPixelWidth ) - { - if( nPixelWidth <= 0) - return; - } - else if( rArgs.mpDXArray ) - { - // for now we are only interested in the layout width - // TODO: use all mpDXArray elements for layouting - nPixelWidth = rArgs.mpDXArray[ mnCharCount - 1 ]; - } - - float fTrailingSpace = CTLineGetTrailingWhitespaceWidth( mpCTLine ); - // in RTL-layouts trailing spaces are leftmost - // TODO: use BiDi-algorithm to thoroughly check this assumption - if( rArgs.mnFlags & SAL_LAYOUT_BIDI_RTL) - mfBaseAdv = fTrailingSpace; - - // return early if there is nothing to do - if( nPixelWidth <= 0 ) - return; - - // HACK: justification requests which change the width by just one pixel are probably - // #i86038# introduced by lossy conversions between integer based coordinate system - if( (nOrigWidth >= nPixelWidth-1) && (nOrigWidth <= nPixelWidth+1) ) - return; - - CTLineRef pNewCTLine = CTLineCreateJustifiedLine( mpCTLine, 1.0, nPixelWidth - fTrailingSpace ); - if( !pNewCTLine ) { // CTLineCreateJustifiedLine can and does fail - // handle failure by keeping the unjustified layout - // TODO: a better solution such as - // - forcing glyph overlap - // - changing the font size - // - changing the CTM matrix - return; - } - CFRelease( mpCTLine ); - mpCTLine = pNewCTLine; - mfCachedWidth = nPixelWidth; -} - -// When drawing right aligned text, rounding errors in the position returned by -// GetDrawPosition() cause the right margin of the text to change whenever text -// width changes causing "jumping letters" effect. So here we calculate the -// drawing position relative to the right margin on our own to avoid the -// rounding errors. That is basically a hack, and it should go away if one day -// we managed to get rid of those rounding errors. -// -// We continue using GetDrawPosition() for non-right aligned text, to minimize -// any unforeseen side effects. -CGPoint CTLayout::GetTextDrawPosition(void) const -{ - float fPosX, fPosY; - - if (mnLayoutFlags & SAL_LAYOUT_RIGHT_ALIGN) - { - // text is always drawn at its leftmost point - const Point aPos = DrawBase(); - fPosX = aPos.X() + mfBaseAdv - GetWidth(); - fPosY = aPos.Y(); - } - else - { - const Point aPos = GetDrawPosition(Point(mfBaseAdv, 0)); - fPosX = aPos.X(); - fPosY = aPos.Y(); - } - - CGPoint aTextPos = { +fPosX, -fPosY }; - return aTextPos; -} - -void CTLayout::DrawText( SalGraphics& rGraphics ) const -{ - AquaSalGraphics& rAquaGraphics = static_cast(rGraphics); - - // short circuit if there is nothing to do - if( (mnCharCount <= 0) - || !rAquaGraphics.CheckContext() ) - return; - - // the view is vertically flipped => flipped glyphs - // so apply a temporary transformation that it flips back - // also compensate if the font was size limited - CGContextSaveGState( rAquaGraphics.mrContext ); - CGContextScaleCTM( rAquaGraphics.mrContext, 1.0, -1.0 ); - CGContextSetShouldAntialias( rAquaGraphics.mrContext, !rAquaGraphics.mbNonAntialiasedText ); - - // Draw the text - CGPoint aTextPos = GetTextDrawPosition(); - - if( mpTextStyle->mfFontRotation != 0.0 ) - { - const CGFloat fRadians = mpTextStyle->mfFontRotation; - CGContextRotateCTM( rAquaGraphics.mrContext, +fRadians ); - - const CGAffineTransform aInvMatrix = CGAffineTransformMakeRotation( -fRadians ); - aTextPos = CGPointApplyAffineTransform( aTextPos, aInvMatrix ); - } - - CGContextSetTextPosition( rAquaGraphics.mrContext, aTextPos.x, aTextPos.y ); - CTLineDraw( mpCTLine, rAquaGraphics.mrContext ); -#ifndef IOS - // request an update of the changed window area - if( rAquaGraphics.IsWindowGraphics() ) - { - const CGRect aInkRect = CTLineGetImageBounds( mpCTLine, rAquaGraphics.mrContext ); - const CGRect aRefreshRect = CGContextConvertRectToDeviceSpace( rAquaGraphics.mrContext, aInkRect ); - rAquaGraphics.RefreshRect( aRefreshRect ); - } -#endif - // restore the original graphic context transformations - CGContextRestoreGState( rAquaGraphics.mrContext ); -} - -int CTLayout::GetNextGlyphs( int nLen, sal_GlyphId* pGlyphIDs, Point& rPos, int& nStart, - sal_Int32* pGlyphAdvances, int* pCharIndexes, - const PhysicalFontFace** pFallbackFonts ) const -{ - if( !mpCTLine ) - return 0; - - if( nStart < 0 ) // first glyph requested? - nStart = 0; - nLen = 1; // TODO: handle nLen>1 below - - // prepare to iterate over the glyph runs - int nCount = 0; - int nSubIndex = nStart; - - typedef std::vector CGGlyphVector; - typedef std::vector CGPointVector; - typedef std::vector CGSizeVector; - typedef std::vector CFIndexVector; - CGGlyphVector aCGGlyphVec; - CGPointVector aCGPointVec; - CGSizeVector aCGSizeVec; - CFIndexVector aCFIndexVec; - - // TODO: iterate over cached layout - CFArrayRef aGlyphRuns = CTLineGetGlyphRuns( mpCTLine ); - const int nRunCount = CFArrayGetCount( aGlyphRuns ); - for( int nRunIndex = 0; nRunIndex < nRunCount; ++nRunIndex ) { - CTRunRef pGlyphRun = (CTRunRef)CFArrayGetValueAtIndex( aGlyphRuns, nRunIndex ); - const CFIndex nGlyphsInRun = CTRunGetGlyphCount( pGlyphRun ); - // skip to the first glyph run of interest - if( nSubIndex >= nGlyphsInRun ) { - nSubIndex -= nGlyphsInRun; - continue; - } - const CFRange aFullRange = CFRangeMake( 0, nGlyphsInRun ); - - // get glyph run details - const CGGlyph* pCGGlyphIdx = CTRunGetGlyphsPtr( pGlyphRun ); - if( !pCGGlyphIdx ) { - aCGGlyphVec.reserve( nGlyphsInRun ); - CTRunGetGlyphs( pGlyphRun, aFullRange, &aCGGlyphVec[0] ); - pCGGlyphIdx = &aCGGlyphVec[0]; - } - const CGPoint* pCGGlyphPos = CTRunGetPositionsPtr( pGlyphRun ); - if( !pCGGlyphPos ) { - aCGPointVec.reserve( nGlyphsInRun ); - CTRunGetPositions( pGlyphRun, aFullRange, &aCGPointVec[0] ); - pCGGlyphPos = &aCGPointVec[0]; - } - - const CGSize* pCGGlyphAdvs = NULL; - if( pGlyphAdvances) { - pCGGlyphAdvs = CTRunGetAdvancesPtr( pGlyphRun ); - if( !pCGGlyphAdvs) { - aCGSizeVec.reserve( nGlyphsInRun ); - CTRunGetAdvances( pGlyphRun, aFullRange, &aCGSizeVec[0] ); - pCGGlyphAdvs = &aCGSizeVec[0]; - } - } - - const CFIndex* pCGGlyphStrIdx = NULL; - if( pCharIndexes) { - pCGGlyphStrIdx = CTRunGetStringIndicesPtr( pGlyphRun ); - if( !pCGGlyphStrIdx) { - aCFIndexVec.reserve( nGlyphsInRun ); - CTRunGetStringIndices( pGlyphRun, aFullRange, &aCFIndexVec[0] ); - pCGGlyphStrIdx = &aCFIndexVec[0]; - } - } - - const PhysicalFontFace* pFallbackFont = NULL; - if( pFallbackFonts ) { - CFDictionaryRef pRunAttributes = CTRunGetAttributes( pGlyphRun ); - CTFontRef pRunFont = (CTFontRef)CFDictionaryGetValue( pRunAttributes, kCTFontAttributeName ); - - CFDictionaryRef pAttributes = mpTextStyle->GetStyleDict(); - CTFontRef pFont = (CTFontRef)CFDictionaryGetValue( pAttributes, kCTFontAttributeName ); - if ( !CFEqual( pRunFont, pFont ) ) { - CTFontDescriptorRef pFontDesc = CTFontCopyFontDescriptor( pRunFont ); - ImplDevFontAttributes rDevFontAttr = DevFontFromCTFontDescriptor( pFontDesc, NULL ); - pFallbackFont = new CoreTextFontData( rDevFontAttr, (sal_IntPtr)pFontDesc ); - } - } - - // get the details for each interesting glyph - // TODO: handle nLen>1 - for(; (--nLen >= 0) && (nSubIndex < nGlyphsInRun); ++nSubIndex, ++nStart ) - { - // convert glyph details for VCL - *(pGlyphIDs++) = pCGGlyphIdx[ nSubIndex ]; - if( pGlyphAdvances ) - *(pGlyphAdvances++) = lrint(pCGGlyphAdvs[ nSubIndex ].width); - if( pCharIndexes ) - *(pCharIndexes++) = pCGGlyphStrIdx[ nSubIndex] + mnMinCharPos; - if( pFallbackFonts ) - *(pFallbackFonts++) = pFallbackFont; - if( !nCount++ ) { - const CGPoint& rCurPos = pCGGlyphPos[ nSubIndex ]; - rPos = GetDrawPosition( Point( rCurPos.x, rCurPos.y) ); - } - } - nSubIndex = 0; // prepare for the next glyph run - break; // TODO: handle nLen>1 - } - - return nCount; -} - -double CTLayout::GetWidth() const -{ - if( (mnCharCount <= 0) || !mpCTLine ) - return 0; - - if( mfCachedWidth < 0.0 ) { - mfCachedWidth = CTLineGetTypographicBounds( mpCTLine, NULL, NULL, NULL); - } - - return mfCachedWidth; -} - -long CTLayout::GetTextWidth() const -{ - return lrint(GetWidth()); -} - -long CTLayout::FillDXArray( sal_Int32* pDXArray ) const -{ - // short circuit requests which don't need full details - if( !pDXArray ) - return GetTextWidth(); - - long nPixWidth = GetTextWidth(); - if( pDXArray ) { - // initialize the result array - for( int i = 0; i < mnCharCount; ++i) - pDXArray[i] = 0; - // handle each glyph run - CFArrayRef aGlyphRuns = CTLineGetGlyphRuns( mpCTLine ); - const int nRunCount = CFArrayGetCount( aGlyphRuns ); - typedef std::vector CGSizeVector; - CGSizeVector aSizeVec; - typedef std::vector CFIndexVector; - CFIndexVector aIndexVec; - for( int nRunIndex = 0; nRunIndex < nRunCount; ++nRunIndex ) { - CTRunRef pGlyphRun = (CTRunRef)CFArrayGetValueAtIndex( aGlyphRuns, nRunIndex ); - const CFIndex nGlyphCount = CTRunGetGlyphCount( pGlyphRun ); - const CFRange aFullRange = CFRangeMake( 0, nGlyphCount ); - aSizeVec.reserve( nGlyphCount ); - aIndexVec.reserve( nGlyphCount ); - CTRunGetAdvances( pGlyphRun, aFullRange, &aSizeVec[0] ); - CTRunGetStringIndices( pGlyphRun, aFullRange, &aIndexVec[0] ); - for( int i = 0; i != nGlyphCount; ++i ) { - const int nRelIdx = aIndexVec[i]; - pDXArray[ nRelIdx ] += lrint(aSizeVec[i].width); - } - } - } - - return nPixWidth; -} - -sal_Int32 CTLayout::GetTextBreak( long nMaxWidth, long /*nCharExtra*/, int nFactor ) const -{ - if( !mpCTLine ) - return -1; - - CTTypesetterRef aCTTypeSetter = CTTypesetterCreateWithAttributedString( mpAttrString ); - const double fCTMaxWidth = (double)nMaxWidth / nFactor; - CFIndex nIndex = CTTypesetterSuggestClusterBreak( aCTTypeSetter, 0, fCTMaxWidth ); - if( nIndex >= mnCharCount ) - return -1; - - nIndex += mnMinCharPos; - return nIndex; -} - -void CTLayout::GetCaretPositions( int nMaxIndex, sal_Int32* pCaretXArray ) const -{ - DBG_ASSERT( ((nMaxIndex>0)&&!(nMaxIndex&1)), - "CTLayout::GetCaretPositions() : invalid number of caret pairs requested"); - - // initialize the caret positions - for( int i = 0; i < nMaxIndex; ++i ) - pCaretXArray[ i ] = -1; - - for( int n = 0; n <= mnCharCount; ++n ) - { - // measure the characters cursor position - CGFloat fPos2 = -1; - const CGFloat fPos1 = CTLineGetOffsetForStringIndex( mpCTLine, n, &fPos2 ); - (void)fPos2; // TODO: split cursor at line direction change - // update previous trailing position - if( n > 0 ) - pCaretXArray[ 2*n-1 ] = lrint( fPos1 ); - // update current leading position - if( 2*n >= nMaxIndex ) - break; - pCaretXArray[ 2*n+0 ] = lrint( fPos1 ); - } -} - -bool CTLayout::GetBoundRect( SalGraphics& rGraphics, Rectangle& rVCLRect ) const -{ - // Closely mimic DrawText(), except that instead of calling - // CTLineDraw() to draw the line, we call CTLineGetImageBounds() - // to get its bounds. But all the coordinate system manipulation - // before that is the same => should be factored out? - - AquaSalGraphics& rAquaGraphics = static_cast(rGraphics); - - if( !rAquaGraphics.CheckContext() ) - return false; - - CGContextSaveGState( rAquaGraphics.mrContext ); - CGContextScaleCTM( rAquaGraphics.mrContext, 1.0, -1.0 ); - CGContextSetShouldAntialias( rAquaGraphics.mrContext, !rAquaGraphics.mbNonAntialiasedText ); - - const CGPoint aVclPos = GetTextDrawPosition(); - CGPoint aTextPos = GetTextDrawPosition(); - - if( mpTextStyle->mfFontRotation != 0.0 ) - { - const CGFloat fRadians = mpTextStyle->mfFontRotation; - CGContextRotateCTM( rAquaGraphics.mrContext, +fRadians ); - - const CGAffineTransform aInvMatrix = CGAffineTransformMakeRotation( -fRadians ); - aTextPos = CGPointApplyAffineTransform( aTextPos, aInvMatrix ); - } - - CGContextSetTextPosition( rAquaGraphics.mrContext, aTextPos.x, aTextPos.y ); - CGRect aMacRect = CTLineGetImageBounds( mpCTLine, rAquaGraphics.mrContext ); - - if( mpTextStyle->mfFontRotation != 0.0 ) - { - const CGFloat fRadians = mpTextStyle->mfFontRotation; - const CGAffineTransform aMatrix = CGAffineTransformMakeRotation( +fRadians ); - aMacRect = CGRectApplyAffineTransform( aMacRect, aMatrix ); - } - - CGContextRestoreGState( rAquaGraphics.mrContext ); - - rVCLRect.Left() = aVclPos.x + lrint(aMacRect.origin.x); - rVCLRect.Right() = aVclPos.x + lrint(aMacRect.origin.x + aMacRect.size.width); - rVCLRect.Bottom() = aVclPos.x - lrint(aMacRect.origin.y); - rVCLRect.Top() = aVclPos.x - lrint(aMacRect.origin.y + aMacRect.size.height); - - return true; -} - -// glyph fallback is supported directly by Aqua -// so methods used only by MultiSalLayout can be dummy implementated -bool CTLayout::GetGlyphOutlines( SalGraphics&, PolyPolyVector& ) const { return false; } -void CTLayout::InitFont() const {} -void CTLayout::MoveGlyph( int /*nStart*/, long /*nNewXPos*/ ) {} -void CTLayout::DropGlyph( int /*nStart*/ ) {} -void CTLayout::Simplify( bool /*bIsBase*/ ) {} - -SalLayout* CoreTextStyle::GetTextLayout( void ) const -{ - return new CTLayout( this); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/coretext/salgdi.cxx b/vcl/coretext/salgdi.cxx deleted file mode 100644 index ee6c834aead9..000000000000 --- a/vcl/coretext/salgdi.cxx +++ /dev/null @@ -1,889 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include - -#include "sal/config.h" - -#include "osl/file.hxx" -#include "osl/process.h" - -#include "osl/mutex.hxx" - -#include "rtl/bootstrap.h" -#include "rtl/strbuf.hxx" - -#include "basegfx/range/b2drectangle.hxx" -#include "basegfx/polygon/b2dpolygon.hxx" -#include "basegfx/polygon/b2dpolygontools.hxx" -#include "basegfx/matrix/b2dhommatrix.hxx" -#include "basegfx/matrix/b2dhommatrixtools.hxx" - -#include "vcl/sysdata.hxx" -#include "vcl/svapp.hxx" - -#include "coretext/salgdi.h" - -#ifdef MACOSX -#include "aqua/salframe.h" -#endif - -#ifdef IOS -#include "saldatabasic.hxx" -#include -#endif - -#include "ctfonts.hxx" - -#include "fontsubset.hxx" -#include "impfont.hxx" -#include "sallayout.hxx" -#include "sft.hxx" - - -using namespace vcl; - -// ======================================================================= - -CoreTextFontData::CoreTextFontData( const CoreTextFontData& rSrc ) -: PhysicalFontFace( rSrc ) -, mnFontId( rSrc.mnFontId ) -, mpCharMap( rSrc.mpCharMap ) -, mbOs2Read( rSrc.mbOs2Read ) -, mbHasOs2Table( rSrc.mbHasOs2Table ) -, mbCmapEncodingRead( rSrc.mbCmapEncodingRead ) -{ - if( mpCharMap ) - mpCharMap->AddReference(); -} - -// ----------------------------------------------------------------------- - -CoreTextFontData::CoreTextFontData( const ImplDevFontAttributes& rDFA, sal_IntPtr nFontId ) -: PhysicalFontFace( rDFA, 0 ) -, mnFontId( nFontId ) -, mpCharMap( NULL ) -, mbOs2Read( false ) -, mbHasOs2Table( false ) -, mbCmapEncodingRead( false ) -, mbFontCapabilitiesRead( false ) -{ -} - -// ----------------------------------------------------------------------- - -CoreTextFontData::~CoreTextFontData() -{ - if( mpCharMap ) - mpCharMap->DeReference(); -} - -// ----------------------------------------------------------------------- - -sal_IntPtr CoreTextFontData::GetFontId() const -{ - return (sal_IntPtr)mnFontId; -} - -// ----------------------------------------------------------------------- - -static unsigned GetUShort( const unsigned char* p ){return((p[0]<<8)+p[1]);} - -const ImplFontCharMap* CoreTextFontData::GetImplFontCharMap() const -{ - // return the cached charmap - if( mpCharMap ) - return mpCharMap; - - // set the default charmap - mpCharMap = ImplFontCharMap::GetDefaultMap(); - mpCharMap->AddReference(); - - // get the CMAP byte size - // allocate a buffer for the CMAP raw data - const int nBufSize = GetFontTable( "cmap", NULL ); - DBG_ASSERT( (nBufSize > 0), "CoreTextFontData::GetImplFontCharMap : GetFontTable1 failed!\n"); - if( nBufSize <= 0 ) - return mpCharMap; - - // get the CMAP raw data - ByteVector aBuffer( nBufSize ); - const int nRawLength = GetFontTable( "cmap", &aBuffer[0] ); - DBG_ASSERT( (nRawLength > 0), "CoreTextFontData::GetImplFontCharMap : GetFontTable2 failed!\n"); - if( nRawLength <= 0 ) - return mpCharMap; - DBG_ASSERT( (nBufSize==nRawLength), "CoreTextFontData::GetImplFontCharMap : ByteCount mismatch!\n"); - - // parse the CMAP - CmapResult aCmapResult; - if( ParseCMAP( &aBuffer[0], nRawLength, aCmapResult ) ) - { - // create the matching charmap - mpCharMap->DeReference(); - mpCharMap = new ImplFontCharMap( aCmapResult ); - mpCharMap->AddReference(); - } - - return mpCharMap; -} - -bool CoreTextFontData::GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const -{ - // read this only once per font - if( mbFontCapabilitiesRead ) - { - rFontCapabilities = maFontCapabilities; - return !rFontCapabilities.maUnicodeRange.empty() || !rFontCapabilities.maCodePageRange.empty(); - } - mbFontCapabilitiesRead = true; - - int nBufSize = 0; - // prepare to get the GSUB table raw data - nBufSize = GetFontTable( "GSUB", NULL ); - if( nBufSize > 0 ) - { - // allocate a buffer for the GSUB raw data - ByteVector aBuffer( nBufSize ); - // get the GSUB raw data - const int nRawLength = GetFontTable( "GSUB", &aBuffer[0] ); - if( nRawLength > 0 ) - { - const unsigned char* pGSUBTable = &aBuffer[0]; - vcl::getTTScripts(maFontCapabilities.maGSUBScriptTags, pGSUBTable, nRawLength); - } - } - nBufSize = GetFontTable( "OS/2", NULL ); - if( nBufSize > 0 ) - { - // allocate a buffer for the OS/2 raw data - ByteVector aBuffer( nBufSize ); - // get the OS/2 raw data - const int nRawLength = GetFontTable( "OS/2", &aBuffer[0] ); - if( nRawLength > 0 ) - { - const unsigned char* pOS2Table = &aBuffer[0]; - vcl::getTTCoverage( - maFontCapabilities.maUnicodeRange, - maFontCapabilities.maCodePageRange, - pOS2Table, nRawLength); - } - } - rFontCapabilities = maFontCapabilities; - return !rFontCapabilities.maUnicodeRange.empty() || !rFontCapabilities.maCodePageRange.empty(); -} - -// ----------------------------------------------------------------------- - -void CoreTextFontData::ReadOs2Table( void ) const -{ - // read this only once per font - if( mbOs2Read ) - return; - mbOs2Read = true; - mbHasOs2Table = false; - - // prepare to get the OS/2 table raw data - const int nBufSize = GetFontTable( "OS/2", NULL ); - DBG_ASSERT( (nBufSize > 0), "CoreTextFontData::ReadOs2Table : GetFontTable1 failed!\n"); - if( nBufSize <= 0 ) - return; - - // get the OS/2 raw data - ByteVector aBuffer( nBufSize ); - const int nRawLength = GetFontTable( "cmap", &aBuffer[0] ); - DBG_ASSERT( (nRawLength > 0), "CoreTextFontData::ReadOs2Table : GetFontTable2 failed!\n"); - if( nRawLength <= 0 ) - return; - DBG_ASSERT( (nBufSize==nRawLength), "CoreTextFontData::ReadOs2Table : ByteCount mismatch!\n"); - mbHasOs2Table = true; - - // parse the OS/2 raw data - // TODO: also analyze panose info, etc. -} - -void CoreTextFontData::ReadMacCmapEncoding( void ) const -{ - // read this only once per font - if( mbCmapEncodingRead ) - return; - mbCmapEncodingRead = true; - - const int nBufSize = GetFontTable( "cmap", NULL ); - if( nBufSize <= 0 ) - return; - - // get the CMAP raw data - ByteVector aBuffer( nBufSize ); - const int nRawLength = GetFontTable( "cmap", &aBuffer[0] ); - if( nRawLength < 24 ) - return; - DBG_ASSERT( (nBufSize==nRawLength), "CoreTextFontData::ReadMacCmapEncoding : ByteCount mismatch!\n"); - - const unsigned char* pCmap = &aBuffer[0]; - if( GetUShort( pCmap ) != 0x0000 ) - return; -} - -// ----------------------------------------------------------------------- - -AquaSalGraphics::AquaSalGraphics() -#ifdef MACOSX - : mpFrame( NULL ) - , mxLayer( NULL ) - , mrContext( NULL ) - , mpXorEmulation( NULL ) - , mnXorMode( 0 ) - , mnWidth( 0 ) - , mnHeight( 0 ) - , mnBitmapDepth( 0 ) - , mnRealDPIX( 0 ) - , mnRealDPIY( 0 ) - , mfFakeDPIScale( 1.0 ) - , mxClipPath( NULL ) - , maLineColor( COL_WHITE ) - , maFillColor( COL_BLACK ) - , mpFontData( NULL ) - , mpTextStyle( NULL ) - , maTextColor( COL_BLACK ) - , mbNonAntialiasedText( false ) - , mbPrinter( false ) - , mbVirDev( false ) - , mbWindow( false ) -#else - : mrContext( NULL ) - , mfFakeDPIScale( 1.0 ) - , mpFontData( NULL ) - , mpTextStyle( NULL ) - , maTextColor( COL_BLACK ) - , mbNonAntialiasedText( false ) -#endif -{} - -// ----------------------------------------------------------------------- - -AquaSalGraphics::~AquaSalGraphics() -{ -#ifdef MACOSX - CGPathRelease( mxClipPath ); - delete mpTextStyle; - - if( mpXorEmulation ) - delete mpXorEmulation; - - if( mxLayer ) - CGLayerRelease( mxLayer ); - else if( mrContext && mbWindow ) - { - // destroy backbuffer bitmap context that we created ourself - CGContextRelease( mrContext ); - mrContext = NULL; - } -#endif -} - -// ======================================================================= - -void AquaSalGraphics::SetTextColor( SalColor nSalColor ) -{ - maTextColor = RGBAColor( nSalColor ); - if( mpTextStyle) - mpTextStyle->SetTextColor( maTextColor ); -} - -// ----------------------------------------------------------------------- - -void AquaSalGraphics::GetFontMetric( ImplFontMetricData* pMetric, int /*nFallbackLevel*/ ) -{ - mpTextStyle->GetFontMetric( mfFakeDPIScale, *pMetric ); -} - -// ----------------------------------------------------------------------- - -static bool AddTempDevFont(const OUString& rFontFileURL) -{ - OUString aUSytemPath; - OSL_VERIFY( !osl::FileBase::getSystemPathFromFileURL( rFontFileURL, aUSytemPath ) ); - OString aCFileName = OUStringToOString( aUSytemPath, RTL_TEXTENCODING_UTF8 ); - - CFStringRef rFontPath = CFStringCreateWithCString(NULL, aCFileName.getStr(), kCFStringEncodingUTF8); - CFURLRef rFontURL = CFURLCreateWithFileSystemPath(NULL, rFontPath, kCFURLPOSIXPathStyle, true); - - CFErrorRef error; - bool success = CTFontManagerRegisterFontsForURL(rFontURL, kCTFontManagerScopeProcess, &error); - - if (!success) - { - CFRelease(error); - return false; - } - - return true; -} - -static void AddTempFontDir( const OUString &rFontDirUrl ) -{ - osl::Directory aFontDir( rFontDirUrl ); - osl::FileBase::RC rcOSL = aFontDir.open(); - if( rcOSL == osl::FileBase::E_None ) - { - osl::DirectoryItem aDirItem; - - while( aFontDir.getNextItem( aDirItem, 10 ) == osl::FileBase::E_None ) - { - osl::FileStatus aFileStatus( osl_FileStatus_Mask_FileURL ); - rcOSL = aDirItem.getFileStatus( aFileStatus ); - if ( rcOSL == osl::FileBase::E_None ) - AddTempDevFont(aFileStatus.getFileURL()); - } - } -} - -static void AddLocalTempFontDirs() -{ - static bool bFirst = true; - if( !bFirst ) - return; - bFirst = false; - - // add private font files - - OUString aBrandStr( "$BRAND_BASE_DIR" ); - rtl_bootstrap_expandMacros( &aBrandStr.pData ); - AddTempFontDir( aBrandStr + "/" LIBO_SHARE_FOLDER "/fonts/truetype/" ); -} - -void AquaSalGraphics::GetDevFontList( ImplDevFontList* pFontList ) -{ - DBG_ASSERT( pFontList, "AquaSalGraphics::GetDevFontList(NULL) !"); - - AddLocalTempFontDirs(); - - // The idea is to cache the list of system fonts once it has been generated. - // SalData seems to be a good place for this caching. However we have to - // carefully make the access to the font list thread-safe. If we register - // a font-change event handler to update the font list in case fonts have - // changed on the system we have to lock access to the list. The right - // way to do that is the solar mutex since GetDevFontList is protected - // through it as should be all event handlers - - SalData* pSalData = GetSalData(); - if( !pSalData->mpFontList ) - pSalData->mpFontList = GetCoretextFontList(); - - // Copy all PhysicalFontFace objects contained in the SystemFontList - pSalData->mpFontList->AnnounceFonts( *pFontList ); -} - -void AquaSalGraphics::ClearDevFontCache() -{ - SalData* pSalData = GetSalData(); - delete pSalData->mpFontList; - pSalData->mpFontList = NULL; -} - -// ----------------------------------------------------------------------- - -bool AquaSalGraphics::AddTempDevFont( ImplDevFontList*, - const OUString& rFontFileURL, const OUString& /*rFontName*/ ) -{ - return ::AddTempDevFont(rFontFileURL); -} - -// ----------------------------------------------------------------------- - -sal_Bool AquaSalGraphics::GetGlyphOutline( sal_GlyphId nGlyphId, basegfx::B2DPolyPolygon& rPolyPoly ) -{ - const bool bRC = mpTextStyle->GetGlyphOutline( nGlyphId, rPolyPoly ); - return bRC; -} - -// ----------------------------------------------------------------------- - -sal_Bool AquaSalGraphics::GetGlyphBoundRect( sal_GlyphId nGlyphId, Rectangle& rRect ) -{ - const bool bRC = mpTextStyle->GetGlyphBoundRect( nGlyphId, rRect ); - return bRC; -} - -// ----------------------------------------------------------------------- - -void AquaSalGraphics::DrawServerFontLayout( const ServerFontLayout& ) -{ -} - -// ----------------------------------------------------------------------- - -sal_uInt16 AquaSalGraphics::SetFont( FontSelectPattern* pReqFont, int /*nFallbackLevel*/ ) -{ - // release the text style - delete mpTextStyle; - mpTextStyle = NULL; - - // handle NULL request meaning: release-font-resources request - if( !pReqFont ) - { - mpFontData = NULL; - return 0; - } - - // update the text style - mpFontData = static_cast( pReqFont->mpFontData ); - mpTextStyle = mpFontData->CreateTextStyle( *pReqFont ); - mpTextStyle->SetTextColor( maTextColor ); - - SAL_INFO("vcl.coretext", - "SetFont" - << " to " << mpFontData->GetFamilyName() - << ", " << mpFontData->GetStyleName() - << " fontid=" << mpFontData->GetFontId() - << " for " << pReqFont->GetFamilyName() - << ", " << pReqFont->GetStyleName() - << " weight=" << pReqFont->GetWeight() - << " slant=" << pReqFont->GetSlant() - << " size=" << pReqFont->mnHeight << "x" << pReqFont->mnWidth - << " orientation=" << pReqFont->mnOrientation - ); - - return 0; -} - -// ----------------------------------------------------------------------- - -SalLayout* AquaSalGraphics::GetTextLayout( ImplLayoutArgs& /*rArgs*/, int /*nFallbackLevel*/ ) -{ - SalLayout* pSalLayout = mpTextStyle->GetTextLayout(); - return pSalLayout; -} - -// ----------------------------------------------------------------------- - -const ImplFontCharMap* AquaSalGraphics::GetImplFontCharMap() const -{ - if( !mpFontData ) - return ImplFontCharMap::GetDefaultMap(); - - return mpFontData->GetImplFontCharMap(); -} - -bool AquaSalGraphics::GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const -{ - if( !mpFontData ) - return false; - - return mpFontData->GetImplFontCapabilities(rFontCapabilities); -} - -// ----------------------------------------------------------------------- - -// fake a SFNT font directory entry for a font table -// see http://developer.apple.com/fonts/TTRefMan/RM06/Chap6.html#Directory -static void FakeDirEntry( const char aTag[5], ByteCount nOfs, ByteCount nLen, - const unsigned char* /*pData*/, unsigned char*& rpDest ) -{ - // write entry tag - rpDest[ 0] = aTag[0]; - rpDest[ 1] = aTag[1]; - rpDest[ 2] = aTag[2]; - rpDest[ 3] = aTag[3]; - // TODO: get entry checksum and write it - // not too important since the subsetter doesn't care currently - // for( pData+nOfs ... pData+nOfs+nLen ) - // write entry offset - rpDest[ 8] = (char)(nOfs >> 24); - rpDest[ 9] = (char)(nOfs >> 16); - rpDest[10] = (char)(nOfs >> 8); - rpDest[11] = (char)(nOfs >> 0); - // write entry length - rpDest[12] = (char)(nLen >> 24); - rpDest[13] = (char)(nLen >> 16); - rpDest[14] = (char)(nLen >> 8); - rpDest[15] = (char)(nLen >> 0); - // advance to next entry - rpDest += 16; -} - -// fake a TTF or CFF font as directly accessing font file is not possible -// when only the fontid is known. This approach also handles *.dfont fonts. -bool AquaSalGraphics::GetRawFontData( const PhysicalFontFace* pFontData, - ByteVector& rBuffer, bool* pJustCFF ) -{ - const CoreTextFontData* pMacFont = static_cast(pFontData); - - // short circuit for CFF-only fonts - const int nCffSize = pMacFont->GetFontTable( "CFF ", NULL); - if( pJustCFF != NULL ) - { - *pJustCFF = (nCffSize > 0); - if( *pJustCFF) - { - rBuffer.resize( nCffSize); - const int nCffRead = pMacFont->GetFontTable( "CFF ", &rBuffer[0]); - if( nCffRead != nCffSize) - return false; - return true; - } - } - - // get font table availability and size in bytes - const int nHeadSize = pMacFont->GetFontTable( "head", NULL); - if( nHeadSize <= 0) - return false; - const int nMaxpSize = pMacFont->GetFontTable( "maxp", NULL); - if( nMaxpSize <= 0) - return false; - const int nCmapSize = pMacFont->GetFontTable( "cmap", NULL); - if( nCmapSize <= 0) - return false; - const int nNameSize = pMacFont->GetFontTable( "name", NULL); - if( nNameSize <= 0) - return false; - const int nHheaSize = pMacFont->GetFontTable( "hhea", NULL); - if( nHheaSize <= 0) - return false; - const int nHmtxSize = pMacFont->GetFontTable( "hmtx", NULL); - if( nHmtxSize <= 0) - return false; - - // get the ttf-glyf outline tables - int nLocaSize = 0; - int nGlyfSize = 0; - if( nCffSize <= 0) - { - nLocaSize = pMacFont->GetFontTable( "loca", NULL); - if( nLocaSize <= 0) - return false; - nGlyfSize = pMacFont->GetFontTable( "glyf", NULL); - if( nGlyfSize <= 0) - return false; - } - - int nPrepSize = 0, nCvtSize = 0, nFpgmSize = 0; - if( nGlyfSize) // TODO: reduce PDF size by making hint subsetting optional - { - nPrepSize = pMacFont->GetFontTable( "prep", NULL); - nCvtSize = pMacFont->GetFontTable( "cvt ", NULL); - nFpgmSize = pMacFont->GetFontTable( "fpgm", NULL); - } - - // prepare a byte buffer for a fake font - int nTableCount = 7; - nTableCount += (nPrepSize>0) + (nCvtSize>0) + (nFpgmSize>0) + (nGlyfSize>0); - const ByteCount nFdirSize = 12 + 16*nTableCount; - ByteCount nTotalSize = nFdirSize; - nTotalSize += nHeadSize + nMaxpSize + nNameSize + nCmapSize; - if( nGlyfSize ) - nTotalSize += nLocaSize + nGlyfSize; - else - nTotalSize += nCffSize; - nTotalSize += nHheaSize + nHmtxSize; - nTotalSize += nPrepSize + nCvtSize + nFpgmSize; - rBuffer.resize( nTotalSize ); - - // fake a SFNT font directory header - if( nTableCount < 16 ) - { - int nLog2 = 0; - while( (nTableCount >> nLog2) > 1 ) ++nLog2; - rBuffer[ 1] = 1; // Win-TTF style scaler - rBuffer[ 5] = nTableCount; // table count - rBuffer[ 7] = nLog2*16; // searchRange - rBuffer[ 9] = nLog2; // entrySelector - rBuffer[11] = (nTableCount-nLog2)*16; // rangeShift - } - - // get font table raw data and update the fake directory entries - ByteCount nOfs = nFdirSize; - unsigned char* pFakeEntry = &rBuffer[12]; - if( nCmapSize != pMacFont->GetFontTable( "cmap", &rBuffer[nOfs])) - return false; - FakeDirEntry( "cmap", nOfs, nCmapSize, &rBuffer[0], pFakeEntry ); - nOfs += nCmapSize; - if( nCvtSize ) { - if( nCvtSize != pMacFont->GetFontTable( "cvt ", &rBuffer[nOfs])) - return false; - FakeDirEntry( "cvt ", nOfs, nCvtSize, &rBuffer[0], pFakeEntry ); - nOfs += nCvtSize; - } - if( nFpgmSize ) { - if( nFpgmSize != pMacFont->GetFontTable( "fpgm", &rBuffer[nOfs])) - return false; - FakeDirEntry( "fpgm", nOfs, nFpgmSize, &rBuffer[0], pFakeEntry ); - nOfs += nFpgmSize; - } - if( nCffSize ) { - if( nCffSize != pMacFont->GetFontTable( "CFF ", &rBuffer[nOfs])) - return false; - FakeDirEntry( "CFF ", nOfs, nCffSize, &rBuffer[0], pFakeEntry ); - nOfs += nGlyfSize; - } else { - if( nGlyfSize != pMacFont->GetFontTable( "glyf", &rBuffer[nOfs])) - return false; - FakeDirEntry( "glyf", nOfs, nGlyfSize, &rBuffer[0], pFakeEntry ); - nOfs += nGlyfSize; - if( nLocaSize != pMacFont->GetFontTable( "loca", &rBuffer[nOfs])) - return false; - FakeDirEntry( "loca", nOfs, nLocaSize, &rBuffer[0], pFakeEntry ); - nOfs += nLocaSize; - } - if( nHeadSize != pMacFont->GetFontTable( "head", &rBuffer[nOfs])) - return false; - FakeDirEntry( "head", nOfs, nHeadSize, &rBuffer[0], pFakeEntry ); - nOfs += nHeadSize; - if( nHheaSize != pMacFont->GetFontTable( "hhea", &rBuffer[nOfs])) - return false; - FakeDirEntry( "hhea", nOfs, nHheaSize, &rBuffer[0], pFakeEntry ); - nOfs += nHheaSize; - if( nHmtxSize != pMacFont->GetFontTable( "hmtx", &rBuffer[nOfs])) - return false; - FakeDirEntry( "hmtx", nOfs, nHmtxSize, &rBuffer[0], pFakeEntry ); - nOfs += nHmtxSize; - if( nMaxpSize != pMacFont->GetFontTable( "maxp", &rBuffer[nOfs])) - return false; - FakeDirEntry( "maxp", nOfs, nMaxpSize, &rBuffer[0], pFakeEntry ); - nOfs += nMaxpSize; - if( nNameSize != pMacFont->GetFontTable( "name", &rBuffer[nOfs])) - return false; - FakeDirEntry( "name", nOfs, nNameSize, &rBuffer[0], pFakeEntry ); - nOfs += nNameSize; - if( nPrepSize ) { - if( nPrepSize != pMacFont->GetFontTable( "prep", &rBuffer[nOfs])) - return false; - FakeDirEntry( "prep", nOfs, nPrepSize, &rBuffer[0], pFakeEntry ); - nOfs += nPrepSize; - } - - DBG_ASSERT( (nOfs==nTotalSize), "AquaSalGraphics::CreateFontSubset (nOfs!=nTotalSize)"); - - return true; -} - -// ----------------------------------------------------------------------- - -void AquaSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFontData, bool bVertical, - Int32Vector& rGlyphWidths, Ucs2UIntMap& rUnicodeEnc ) -{ - rGlyphWidths.clear(); - rUnicodeEnc.clear(); - - if( pFontData->IsSubsettable() ) - { - ByteVector aBuffer; - if( !GetRawFontData( pFontData, aBuffer, NULL ) ) - return; - - // TODO: modernize psprint's horrible fontsubset C-API - // this probably only makes sense after the switch to another SCM - // that can preserve change history after file renames - - // use the font subsetter to get the widths - TrueTypeFont* pSftFont = NULL; - int nRC = ::OpenTTFontBuffer( (void*)&aBuffer[0], aBuffer.size(), 0, &pSftFont); - if( nRC != SF_OK ) - return; - - const int nGlyphCount = ::GetTTGlyphCount( pSftFont ); - if( nGlyphCount > 0 ) - { - // get glyph metrics - rGlyphWidths.resize(nGlyphCount); - std::vector aGlyphIds(nGlyphCount); - for( int i = 0; i < nGlyphCount; i++ ) - aGlyphIds[i] = static_cast(i); - const TTSimpleGlyphMetrics* pGlyphMetrics = ::GetTTSimpleGlyphMetrics( - pSftFont, &aGlyphIds[0], nGlyphCount, bVertical ); - if( pGlyphMetrics ) - { - for( int i = 0; i < nGlyphCount; ++i ) - rGlyphWidths[i] = pGlyphMetrics[i].adv; - free( (void*)pGlyphMetrics ); - } - - const ImplFontCharMap* pMap = mpFontData->GetImplFontCharMap(); - DBG_ASSERT( pMap && pMap->GetCharCount(), "no charmap" ); - pMap->AddReference(); // TODO: add and use RAII object instead - - // get unicode<->glyph encoding - // TODO? avoid sft mapping by using the pMap itself - int nCharCount = pMap->GetCharCount(); - sal_uInt32 nChar = pMap->GetFirstChar(); - for(; --nCharCount >= 0; nChar = pMap->GetNextChar( nChar ) ) - { - if( nChar > 0xFFFF ) // TODO: allow UTF-32 chars - break; - sal_Ucs nUcsChar = static_cast(nChar); - sal_uInt32 nGlyph = ::MapChar( pSftFont, nUcsChar, bVertical ); - if( nGlyph > 0 ) - rUnicodeEnc[ nUcsChar ] = nGlyph; - } - - pMap->DeReference(); // TODO: add and use RAII object instead - } - - ::CloseTTFont( pSftFont ); - } - else if( pFontData->IsEmbeddable() ) - { - // get individual character widths - OSL_FAIL("not implemented for non-subsettable fonts!\n"); - } -} - -// ----------------------------------------------------------------------- - -const Ucs2SIntMap* AquaSalGraphics::GetFontEncodingVector( - const PhysicalFontFace*, const Ucs2OStrMap** /*ppNonEncoded*/ ) -{ - return NULL; -} - -// ----------------------------------------------------------------------- - -const void* AquaSalGraphics::GetEmbedFontData( const PhysicalFontFace*, - const sal_Ucs* /*pUnicodes*/, - sal_Int32* /*pWidths*/, - FontSubsetInfo&, - long* /*pDataLen*/ ) -{ - return NULL; -} - -// ----------------------------------------------------------------------- - -void AquaSalGraphics::FreeEmbedFontData( const void* pData, long /*nDataLen*/ ) -{ - // TODO: implementing this only makes sense when the implementation of - // AquaSalGraphics::GetEmbedFontData() returns non-NULL - (void)pData; - DBG_ASSERT( (pData!=NULL), "AquaSalGraphics::FreeEmbedFontData() is not implemented\n"); -} - -// ----------------------------------------------------------------------- - -SystemFontData AquaSalGraphics::GetSysFontData( int /* nFallbacklevel */ ) const -{ - SystemFontData aSysFontData; - aSysFontData.nSize = sizeof( SystemFontData ); - - aSysFontData.bAntialias = !mbNonAntialiasedText; - - return aSysFontData; -} - -#ifdef IOS - -// Note that "SvpSalGraphics" is actually called AquaSalGraphics for iOS - -bool SvpSalGraphics::CheckContext() -{ - const basegfx::B2IVector size = m_aDevice->getSize(); - const basegfx::B2IVector bufferSize = m_aDevice->getBufferSize(); - const sal_Int32 scanlineStride = m_aDevice->getScanlineStride(); - basebmp::RawMemorySharedArray pixelBuffer = m_aDevice->getBuffer(); - bool warned = false; - - SAL_INFO( "vcl.ios", - "CheckContext: device=" << m_aDevice.get() << - " size=" << size.getX() << "x" << size.getY() << - (m_aDevice->isTopDown() ? " top-down" : " bottom-up") << - " stride=" << scanlineStride << - " bufferSize=(" << bufferSize.getX() << "," << bufferSize.getY() << ")" ); - - switch( m_aDevice->getScanlineFormat() ) { - case basebmp::FORMAT_EIGHT_BIT_PAL: - mrContext = CGBitmapContextCreate(pixelBuffer.get(), - bufferSize.getX(), bufferSize.getY(), - 8, scanlineStride, - CGColorSpaceCreateDeviceGray(), - kCGImageAlphaNone); - break; - case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_RGBA: - mrContext = CGBitmapContextCreate(pixelBuffer.get(), - bufferSize.getX(), bufferSize.getY(), - 8, scanlineStride, - CGColorSpaceCreateDeviceRGB(), - kCGImageAlphaNoneSkipLast); - break; - case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_BGRA: - mrContext = CGBitmapContextCreate(pixelBuffer.get(), - bufferSize.getX(), bufferSize.getY(), - 8, scanlineStride, - CGColorSpaceCreateDeviceRGB(), - kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little); - break; - default: - SAL_WARN( "vcl.ios", "CheckContext: unsupported color format " << basebmp::formatName( m_aDevice->getScanlineFormat() ) ); - warned = true; - } - - SAL_WARN_IF( mrContext == NULL && !warned, "vcl.ios", "CheckContext: CGBitmapContextCreate() failed" ); - - // Should we also clip the context? (Then we need to add a - // getBounds() function to BitmapDevice.) - - if( mrContext != NULL && m_aDevice->isTopDown() ) - { - CGContextTranslateCTM( mrContext, 0, bufferSize.getY() ); - CGContextScaleCTM( mrContext, 1, -1 ); - } - - - if (mrContext) - { - RectangleVector aRectangles; - m_aClipRegion.GetRegionRectangles(aRectangles); - - CGContextBeginPath( mrContext ); - - for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter) - { - const long nW(aRectIter->Right() - aRectIter->Left() + 1); // uses +1 logic in original - - if(nW) - { - const long nH(aRectIter->Bottom() - aRectIter->Top() + 1); // uses +1 logic in original - - if(nH) - { - CGRect aRect = {{ (CGFloat) aRectIter->Left(), (CGFloat) aRectIter->Top() }, { (CGFloat) nW, (CGFloat) nH }}; - CGContextAddRect( mrContext, aRect ); - } - } - } - - if (!CGContextIsPathEmpty(mrContext)) - CGContextClip(mrContext); - } - - - SAL_INFO( "vcl.ios", "CheckContext: context=" << mrContext ); - - return ( mrContext != NULL ); -} - -CGContextRef SvpSalGraphics::GetContext() -{ - if ( !mrContext ) - CheckContext(); - - return mrContext; -} - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/aqua11yfactory.h b/vcl/inc/aqua/aqua11yfactory.h deleted file mode 100644 index 2a4a7dc49467..000000000000 --- a/vcl/inc/aqua/aqua11yfactory.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_AQUA11YFACTORY_H -#define INCLUDED_VCL_INC_AQUA_AQUA11YFACTORY_H - -#include "aquavcltypes.h" -#include "aqua11ywrapper.h" -#include - -@interface AquaA11yFactory : NSObject -{ -} -+(void)insertIntoWrapperRepository: (NSView *) viewElement forAccessibleContext: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) rxAccessibleContext; -+(AquaA11yWrapper *)wrapperForAccessible: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessible >) rxAccessible; -+(AquaA11yWrapper *)wrapperForAccessibleContext: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) rxAccessibleContext; -+(AquaA11yWrapper *)wrapperForAccessibleContext: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) rxAccessibleContext createIfNotExists:(BOOL) bCreate; -+(AquaA11yWrapper *)wrapperForAccessibleContext: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) rxAccessibleContext createIfNotExists:(BOOL) bCreate asRadioGroup:(BOOL) asRadioGroup; -+(void)removeFromWrapperRepositoryFor: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) rxAccessibleContext; -+(void)registerView: (NSView *) theView; -+(void)revokeView: (NSView *) theViewt; -@end -#endif // INCLUDED_VCL_INC_AQUA_AQUA11YFACTORY_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/aqua11yfocustracker.hxx b/vcl/inc/aqua/aqua11yfocustracker.hxx deleted file mode 100644 index 22896c2a8b1d..000000000000 --- a/vcl/inc/aqua/aqua11yfocustracker.hxx +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_AQUA11YFOCUSTRACKER_HXX -#define INCLUDED_VCL_INC_AQUA_AQUA11YFOCUSTRACKER_HXX - -#include - -#include "keyboardfocuslistener.hxx" - -#include - -#include -#include -#include - -class Window; -class ToolBox; -class DocumentFocusListener; - -// ------------------------ -// - AquaA11yFocusTracker - -// ------------------------ - -class AquaA11yFocusTracker : public rtl::Static< AquaA11yFocusTracker, AquaA11yFocusTracker> -{ - -public: - AquaA11yFocusTracker(); - - ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getFocusedObject() { return m_xFocusedObject; }; - - // sets the currently focus object and notifies the FocusEventListener (if any) - void setFocusedObject(const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible); - - // may evolve to add/remove later - void setFocusListener(const rtl::Reference< KeyboardFocusListener >& aFocusListener) { m_aFocusListener = aFocusListener; }; - -protected: - - // received a WINDOW_GETFOCUS event for this window - virtual void window_got_focus(Window *pWindow); - - // received a TOOLBOX_HIGHLIGHT event for this window - virtual void toolbox_highlight_on(Window *pWindow); - - // received a TOOLBOX_HIGHLIGHTOFF event for this window - virtual void toolbox_highlight_off(Window *pWindow); - - // received a TABPAGE_ACTIVATE event for this window - virtual void tabpage_activated(Window *pWindow); - - // received a MENU_HIGHLIGHT event for this window - virtual void menu_highlighted(const ::VclMenuEvent *pEvent); - - // toolbox items are widgets in gtk+ and Cocoa - virtual void notify_toolbox_item_focus(ToolBox *pToolBox); - - // toolbox item opened a floating window (e.g. color chooser) - virtual void toolbox_open_floater(Window *pWindow); - - // callback function for Application::addEventListener - static long WindowEventHandler(AquaA11yFocusTracker *pFocusTracker, ::VclSimpleEvent const *pEvent); - -private: - // the accessible object that has the keyboard focus (if any) - ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > m_xFocusedObject; - - // the listener for focus events - rtl::Reference< KeyboardFocusListener > m_aFocusListener; - - // the list of Windows that need deeper (focus) investigation - std::set< Window *> m_aDocumentWindowList; - - // the link object needed for Application::addEventListener - Link m_aWindowEventLink; - - // the UNO XAccessibilityEventListener for Documents and other non VCL objects - const ::com::sun::star::uno::Reference< DocumentFocusListener > m_xDocumentFocusListener; -}; - -#endif // INCLUDED_VCL_INC_AQUA_AQUA11YFOCUSTRACKER_HXX - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/aqua11ylistener.hxx b/vcl/inc/aqua/aqua11ylistener.hxx deleted file mode 100644 index 97c71ef447ee..000000000000 --- a/vcl/inc/aqua/aqua11ylistener.hxx +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_AQUA11YLISTENER_HXX -#define INCLUDED_VCL_INC_AQUA_AQUA11YLISTENER_HXX - -#include -#include - -#include "aqua11yfocustracker.hxx" -#include "aquavcltypes.h" -#include -#include - -// ------------------------- -// - AquaA11yEventListener - -// ------------------------- - -class AquaA11yEventListener : - public ::cppu::WeakImplHelper1< ::com::sun::star::accessibility::XAccessibleEventListener > -{ - -public: - AquaA11yEventListener(id wrapperObject, sal_Int16 role); - virtual ~AquaA11yEventListener(); - - // XEventListener - virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) - throw (::com::sun::star::uno::RuntimeException); - - // XAccessibleEventListener - virtual void SAL_CALL notifyEvent( const ::com::sun::star::accessibility::AccessibleEventObject& aEvent ) - throw( ::com::sun::star::uno::RuntimeException ); - -private: - const id m_wrapperObject; - const sal_Int16 m_role; - ::com::sun::star::awt::Rectangle m_oldBounds; -}; - -#endif // INCLUDED_VCL_INC_AQUA_AQUA11YLISTENER_HXX -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/aqua11ywrapper.h b/vcl/inc/aqua/aqua11ywrapper.h deleted file mode 100644 index 95edcae2e040..000000000000 --- a/vcl/inc/aqua/aqua11ywrapper.h +++ /dev/null @@ -1,110 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_AQUA11YWRAPPER_H -#define INCLUDED_VCL_INC_AQUA_AQUA11YWRAPPER_H - -#include "aquavcltypes.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// rAccessibleXYZ as a field in an Objective-C-Class would not call Con-/Destructor, so use a struct instead -struct ReferenceWrapper -{ - ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleAction > rAccessibleAction; - ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext > rAccessibleContext; - ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleComponent > rAccessibleComponent; - ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleExtendedComponent > rAccessibleExtendedComponent; - ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleSelection > rAccessibleSelection; - ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleTable > rAccessibleTable; - ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleText > rAccessibleText; - ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleEditableText > rAccessibleEditableText; - ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleValue > rAccessibleValue; - ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleTextAttributes > rAccessibleTextAttributes; - ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleMultiLineText > rAccessibleMultiLineText; - ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleTextMarkup > rAccessibleTextMarkup; -}; - -@interface AquaA11yWrapper : NSView -{ - ReferenceWrapper * mpReferenceWrapper; - BOOL mActsAsRadioGroup; - BOOL mIsTableCell; -} -// NSAccessibility Protocol --(id)accessibilityAttributeValue:(NSString *)attribute; --(BOOL)accessibilityIsIgnored; --(NSArray *)accessibilityAttributeNames; --(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute; --(NSArray *)accessibilityParameterizedAttributeNames; --(BOOL)accessibilitySetOverrideValue:(id)value forAttribute:(NSString *)attribute; --(void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute; --(id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter; --(id)accessibilityFocusedUIElement; --(NSString *)accessibilityActionDescription:(NSString *)action; --(void)accessibilityPerformAction:(NSString *)action; --(NSArray *)accessibilityActionNames; --(id)accessibilityHitTest:(NSPoint)point; -// Attribute values --(id)parentAttribute; --(id)valueAttribute; --(id)titleAttribute; --(id)helpAttribute; --(id)numberOfCharactersAttribute; --(id)selectedTextAttribute; --(id)selectedTextRangeAttribute; --(id)visibleCharacterRangeAttribute; --(id)childrenAttribute; --(id)orientationAttribute; --(id)windowAttribute; -// Wrapper-specific --(void)setActsAsRadioGroup:(BOOL)actsAsRadioGroup; --(BOOL)actsAsRadioGroup; --(NSView *)viewElementForParent; --(id)initWithAccessibleContext: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) anAccessibleContext; --(void) setDefaults: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) rxAccessibleContext; --(void) dealloc; -+(void)setPopupMenuOpen:(BOOL)popupMenuOpen; --(::com::sun::star::accessibility::XAccessibleAction *)accessibleAction; --(::com::sun::star::accessibility::XAccessibleContext *)accessibleContext; --(::com::sun::star::accessibility::XAccessibleComponent *)accessibleComponent; --(::com::sun::star::accessibility::XAccessibleExtendedComponent *)accessibleExtendedComponent; --(::com::sun::star::accessibility::XAccessibleSelection *)accessibleSelection; --(::com::sun::star::accessibility::XAccessibleTable *)accessibleTable; --(::com::sun::star::accessibility::XAccessibleText *)accessibleText; --(::com::sun::star::accessibility::XAccessibleEditableText *)accessibleEditableText; --(::com::sun::star::accessibility::XAccessibleValue *)accessibleValue; --(::com::sun::star::accessibility::XAccessibleTextAttributes *)accessibleTextAttributes; --(::com::sun::star::accessibility::XAccessibleMultiLineText *)accessibleMultiLineText; --(::com::sun::star::accessibility::XAccessibleTextMarkup *)accessibleTextMarkup; -@end - -#endif // INCLUDED_VCL_INC_AQUA_AQUA11YWRAPPER_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/aquaprintview.h b/vcl/inc/aqua/aquaprintview.h deleted file mode 100644 index fbd8077ea96b..000000000000 --- a/vcl/inc/aqua/aquaprintview.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_AQUAPRINTVIEW_H -#define INCLUDED_VCL_INC_AQUA_AQUAPRINTVIEW_H - -#include "premac.h" -#include -#include "postmac.h" - -#include "vcl/print.hxx" - -class AquaSalInfoPrinter; - -struct PrintAccessoryViewState -{ - bool bNeedRestart; - sal_Int32 nLastPage; - - PrintAccessoryViewState() - : bNeedRestart( false ), nLastPage( 0 ) {} -}; - -@interface AquaPrintView : NSView -{ - vcl::PrinterController* mpController; - AquaSalInfoPrinter* mpInfoPrinter; -} --(id)initWithController: (vcl::PrinterController*)pController withInfoPrinter: (AquaSalInfoPrinter*)pInfoPrinter; --(BOOL)knowsPageRange: (NSRangePointer)range; --(NSRect)rectForPage: (int)page; --(NSPoint)locationOfPrintRect: (NSRect)aRect; --(void)drawRect: (NSRect)rect; -@end - -@interface AquaPrintAccessoryView : NSObject -{ -} -+(NSObject*)setupPrinterPanel: (NSPrintOperation*)pOp withController: (vcl::PrinterController*)pController withState: (PrintAccessoryViewState*)pState; -@end - - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/aquavcltypes.h b/vcl/inc/aqua/aquavcltypes.h deleted file mode 100644 index 5101a5a2615e..000000000000 --- a/vcl/inc/aqua/aquavcltypes.h +++ /dev/null @@ -1,30 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_AQUAVCLTYPES_H -#define INCLUDED_VCL_INC_AQUA_AQUAVCLTYPES_H - -#include "premac.h" -#import -#import -#include "postmac.h" - -#endif // INCLUDED_VCL_INC_AQUA_AQUAVCLTYPES_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/keyboardfocuslistener.hxx b/vcl/inc/aqua/keyboardfocuslistener.hxx deleted file mode 100644 index 45979e28a374..000000000000 --- a/vcl/inc/aqua/keyboardfocuslistener.hxx +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_KEYBOARDFOCUSLISTENER_HXX -#define INCLUDED_VCL_INC_AQUA_KEYBOARDFOCUSLISTENER_HXX - -#include - -#include - -// ------------------------- -// - KeyboardFocusListener - -// ------------------------- - -class KeyboardFocusListener : public rtl::IReference -{ -public: - virtual void SAL_CALL focusedObjectChanged(const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible) = 0; -}; - -#endif // INCLUDED_VCL_INC_AQUA_KEYBOARDFOCUSLISTENER_HXX -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/saldata.hxx b/vcl/inc/aqua/saldata.hxx deleted file mode 100644 index 74e10f5e44db..000000000000 --- a/vcl/inc/aqua/saldata.hxx +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_SALDATA_HXX -#define INCLUDED_VCL_INC_AQUA_SALDATA_HXX - -#include - -#include "premac.h" -#include -#include "postmac.h" - -#include "com/sun/star/uno/Reference.hxx" - -#include "vcl/ptrstyle.hxx" - -#include "svdata.hxx" -#include "salwtype.hxx" - -#include -#include -#include -#include - -#include -#include - -#include "apple_remote/RemoteMainController.h" - -class AquaSalInstance; -class SalObject; -class SalFrame; -class SalVirtualDevice; -class SalPrinter; -class SystemFontList; - -#define SAL_CLIPRECT_COUNT 16 - -class AquaSalFrame; -struct FrameHash : public boost::hash -{ - size_t operator()(const AquaSalFrame* frame) const - { return boost::hash::operator()( reinterpret_cast(frame) ); } -}; - -#define INVALID_CURSOR_PTR (NSCursor*)0xdeadbeef - -class SalData -{ -public: - SALTIMERPROC mpTimerProc; // timer callback proc - AquaSalInstance *mpFirstInstance; // pointer of first instance - std::list maFrames; // list of all frames - boost::unordered_set maFrameCheck; // for fast check of frame existance - std::list maPresentationFrames; // list of frames in presentation mode - SalObject *mpFirstObject; // pointer of first object window - SalVirtualDevice *mpFirstVD; // first VirDev - SalPrinter *mpFirstPrinter; // first printing printer - SystemFontList *mpFontList; - NSStatusItem* mpStatusItem; // one status item that draws all our stati - // at the moment this is only one add menu button - - CGColorSpaceRef mxRGBSpace; - CGColorSpaceRef mxGraySpace; - CGColorSpaceRef mxP50Space; - CGPatternRef mxP50Pattern; - - std::vector< NSCursor* > maCursors; - std::vector< NSMenuItem* > maFallbackMenu; - std::map< NSEvent*, bool > maKeyEventAnswer; - - static oslThreadKey s_aAutoReleaseKey; - - bool mbIsScrollbarDoubleMax; // TODO: support DoubleMin and DoubleBoth too -#if !HAVE_FEATURE_MACOSX_SANDBOX - MainController* mpMainController; // Apple Remote -#endif - NSObject* mpDockIconClickHandler; - long mnDPIX; // #i100617# read DPI only once per office life - long mnDPIY; // #i100617# read DPI only once per office life - - com::sun::star::uno::Reference< com::sun::star::uno::XInterface > - mxClipboard; - - SalData(); - ~SalData(); - - NSCursor* getCursor( PointerStyle i_eStyle ); - - static void ensureThreadAutoreleasePool(); - - static NSStatusItem* getStatusItem(); -}; - -inline void SetSalData( SalData* pData ) { ImplGetSVData()->mpSalData = pData; } -inline SalData *GetSalData() { return ImplGetSVData()->mpSalData; } - -sal_Bool ImplSalYieldMutexTryToAcquire(); -void ImplSalYieldMutexAcquire(); -void ImplSalYieldMutexRelease(); - -#endif // INCLUDED_VCL_INC_AQUA_SALDATA_HXX - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/salframe.h b/vcl/inc/aqua/salframe.h deleted file mode 100644 index 06a82702221c..000000000000 --- a/vcl/inc/aqua/salframe.h +++ /dev/null @@ -1,217 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_SALFRAME_H -#define INCLUDED_VCL_INC_AQUA_SALFRAME_H - -#include -#include -#include - -#include "vcl/sysdata.hxx" - -#include "aqua/salmenu.h" -#include "aqua/saldata.hxx" -#include "aqua/aquavcltypes.h" - -#include "salframe.hxx" - -#include -#include -#include - -class AquaSalGraphics; -class AquaSalFrame; -class AquaSalTimer; -class AquaSalInstance; -class AquaSalMenu; -class AquaBlinker; - -typedef struct SalFrame::SalPointerState SalPointerState; - -// ---------------- -// - AquaSalFrame - -// ---------------- - -class AquaSalFrame : public SalFrame -{ -public: - NSWindow* mpNSWindow; // Cocoa window - NSView* mpNSView; // Cocoa view (actually a custom view) - NSMenuItem* mpDockMenuEntry; // entry in the dynamic dock menu - NSRect maScreenRect; // for mirroring purposes - AquaSalGraphics* mpGraphics; // current frame graphics - AquaSalFrame* mpParent; // pointer to parent frame - SystemEnvData maSysData; // system data - int mnMinWidth; // min. client width in pixels - int mnMinHeight; // min. client height in pixels - int mnMaxWidth; // max. client width in pixels - int mnMaxHeight; // max. client height in pixels - NSRect maFullScreenRect; // old window size when in FullScreen - bool mbGraphics:1; // is Graphics used? - bool mbFullScreen:1; // is Window in FullScreen? - bool mbShown:1; - bool mbInitShow:1; - bool mbPositioned:1; - bool mbSized:1; - bool mbPresentation:1; - - sal_uLong mnStyle; - unsigned int mnStyleMask; // our style mask from NSWindow creation - - sal_uLong mnLastEventTime; - unsigned int mnLastModifierFlags; - AquaSalMenu* mpMenu; - - SalExtStyle mnExtStyle; // currently document frames are marked this way - - PointerStyle mePointerStyle; // currently active pointer style - - NSTrackingRectTag mnTrackingRectTag; // used to get enter/leave messages - - CGMutablePathRef mrClippingPath; // used for "shaping" - std::vector< CGRect > maClippingRects; - - std::list maBlinkers; - - Rectangle maInvalidRect; - - sal_uLong mnICOptions; - - // To prevent display sleep during presentation - IOPMAssertionID mnAssertionID; - -public: - /** Constructor - - Creates a system window and connects this frame with it. - - @throws std::runtime_error in case window creation fails - */ - AquaSalFrame( SalFrame* pParent, sal_uLong salFrameStyle ); - - virtual ~AquaSalFrame(); - - virtual SalGraphics* GetGraphics(); - virtual void ReleaseGraphics( SalGraphics* pGraphics ); - virtual sal_Bool PostEvent( void* pData ); - virtual void SetTitle( const OUString& rTitle ); - virtual void SetIcon( sal_uInt16 nIcon ); - virtual void SetRepresentedURL( const OUString& ); - virtual void SetMenu( SalMenu* pSalMenu ); - virtual void DrawMenuBar(); - virtual void Show( sal_Bool bVisible, sal_Bool bNoActivate = sal_False ); - virtual void Enable( sal_Bool bEnable ); - virtual void SetMinClientSize( long nWidth, long nHeight ); - virtual void SetMaxClientSize( long nWidth, long nHeight ); - virtual void SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags ); - virtual void GetClientSize( long& rWidth, long& rHeight ); - virtual void GetWorkArea( Rectangle& rRect ); - virtual SalFrame* GetParent() const; - virtual void SetWindowState( const SalFrameState* pState ); - virtual sal_Bool GetWindowState( SalFrameState* pState ); - virtual void ShowFullScreen( sal_Bool bFullScreen, sal_Int32 nDisplay ); - virtual void StartPresentation( sal_Bool bStart ); - virtual void SetAlwaysOnTop( sal_Bool bOnTop ); - virtual void ToTop( sal_uInt16 nFlags ); - virtual void SetPointer( PointerStyle ePointerStyle ); - virtual void CaptureMouse( sal_Bool bMouse ); - virtual void SetPointerPos( long nX, long nY ); - virtual void Flush( void ); - virtual void Flush( const Rectangle& ); - virtual void Sync(); - virtual void SetInputContext( SalInputContext* pContext ); - virtual void EndExtTextInput( sal_uInt16 nFlags ); - virtual OUString GetKeyName( sal_uInt16 nKeyCode ); - virtual sal_Bool MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, KeyCode& rKeyCode ); - virtual LanguageType GetInputLanguage(); - virtual void UpdateSettings( AllSettings& rSettings ); - virtual void Beep(); - virtual const SystemEnvData* GetSystemData() const; - virtual SalPointerState GetPointerState(); - virtual SalIndicatorState GetIndicatorState(); - virtual void SimulateKeyPress( sal_uInt16 nKeyCode ); - virtual void SetParent( SalFrame* pNewParent ); - virtual bool SetPluginParent( SystemParentData* pNewParent ); - virtual void SetExtendedFrameStyle( SalExtStyle ); - virtual void SetScreenNumber(unsigned int); - virtual void SetApplicationID( const OUString &rApplicationID ); - - // shaped system windows - // set clip region to none (-> rectangular windows, normal state) - virtual void ResetClipRegion(); - // start setting the clipregion consisting of nRects rectangles - virtual void BeginSetClipRegion( sal_uLong nRects ); - // add a rectangle to the clip region - virtual void UnionClipRegion( long nX, long nY, long nWidth, long nHeight ); - // done setting up the clipregion - virtual void EndSetClipRegion(); - - virtual void SetClientSize( long nWidth, long nHeight ); - - void UpdateFrameGeometry(); - - // trigger painting of the window - void SendPaintEvent( const Rectangle* pRect = NULL ); - - static bool isAlive( const AquaSalFrame* pFrame ) - { return GetSalData()->maFrameCheck.find( pFrame ) != GetSalData()->maFrameCheck.end(); } - - static AquaSalFrame* GetCaptureFrame() { return s_pCaptureFrame; } - - NSWindow* getNSWindow() const { return mpNSWindow; } - NSView* getNSView() const { return mpNSView; } - unsigned int getStyleMask() const { return mnStyleMask; } - - void getResolution( sal_Int32& o_rDPIX, sal_Int32& o_rDPIY ); - - // actually the follwing methods do the same thing: flipping y coordinates - // but having two of them makes clearer what the coordinate system - // is supposed to be before and after - void VCLToCocoa( NSRect& io_rRect, bool bRelativeToScreen = true ); - void CocoaToVCL( NSRect& io_rRect, bool bRelativeToScreen = true ); - - void VCLToCocoa( NSPoint& io_rPoint, bool bRelativeToScreen = true ); - void CocoaToVCL( NSPoint& io_Point, bool bRelativeToScreen = true ); - - NSCursor* getCurrentCursor() const; - - CGMutablePathRef getClipPath() const { return mrClippingPath; } - - // called by VCL_NSApplication to indicate screen settings have changed - void screenParametersChanged(); - - private: // methods - /** do things on initial show (like centering on parent or on screen) - */ - void initShow(); - - void initWindowAndView(); - - private: // data - static AquaSalFrame* s_pCaptureFrame; - - // make AquaSalFrame non copyable - AquaSalFrame( const AquaSalFrame& ); - AquaSalFrame& operator=(const AquaSalFrame&); -}; - -#endif // INCLUDED_VCL_INC_AQUA_SALFRAME_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/salframeview.h b/vcl/inc/aqua/salframeview.h deleted file mode 100644 index 4be71b3b7e5c..000000000000 --- a/vcl/inc/aqua/salframeview.h +++ /dev/null @@ -1,208 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_SALFRAMEVIEW_H -#define INCLUDED_VCL_INC_AQUA_SALFRAMEVIEW_H - -#include "aqua/aqua11ywrapper.h" - -@interface SalFrameWindow : NSWindow -{ - AquaSalFrame* mpFrame; - id mDraggingDestinationHandler; -} --(id)initWithSalFrame: (AquaSalFrame*)pFrame; --(BOOL)canBecomeKeyWindow; --(void)displayIfNeeded; --(void)windowDidBecomeKey: (NSNotification*)pNotification; --(void)windowDidResignKey: (NSNotification*)pNotification; --(void)windowDidChangeScreen: (NSNotification*)pNotification; --(void)windowDidMove: (NSNotification*)pNotification; --(void)windowDidResize: (NSNotification*)pNotification; --(void)windowDidMiniaturize: (NSNotification*)pNotification; --(void)windowDidDeminiaturize: (NSNotification*)pNotification; --(BOOL)windowShouldClose: (NSNotification*)pNotification; --(void)dockMenuItemTriggered: (id)sender; --(AquaSalFrame*)getSalFrame; --(BOOL)containsMouse; --(::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >)accessibleContext; - -/* NSDraggingDestination protocol methods - */ --(NSDragOperation)draggingEntered:(id )sender; --(NSDragOperation)draggingUpdated:(id )sender; --(void)draggingExited:(id )sender; --(BOOL)prepareForDragOperation:(id )sender; --(BOOL)performDragOperation:(id )sender; --(void)concludeDragOperation:(id )sender; - --(void)registerDraggingDestinationHandler:(id)theHandler; --(void)unregisterDraggingDestinationHandler:(id)theHandler; -@end - -@interface SalFrameView : AquaA11yWrapper -{ - AquaSalFrame* mpFrame; - - // for NSTextInput - NSEvent* mpLastEvent; - BOOL mbNeedSpecialKeyHandle; - BOOL mbInKeyInput; - BOOL mbKeyHandled; - NSRange mMarkedRange; - NSRange mSelectedRange; - id mpMouseEventListener; - id mDraggingDestinationHandler; - NSEvent* mpLastSuperEvent; - - // #i102807# used by magnify event handler - NSTimeInterval mfLastMagnifyTime; - float mfMagnifyDeltaSum; -} -+(void)unsetMouseFrame: (AquaSalFrame*)pFrame; --(id)initWithSalFrame: (AquaSalFrame*)pFrame; --(AquaSalFrame*)getSalFrame; --(BOOL)acceptsFirstResponder; --(BOOL)acceptsFirstMouse: (NSEvent *)pEvent; --(BOOL)isOpaque; --(void)drawRect: (NSRect)aRect; --(void)mouseDown: (NSEvent*)pEvent; --(void)mouseDragged: (NSEvent*)pEvent; --(void)mouseUp: (NSEvent*)pEvent; --(void)mouseMoved: (NSEvent*)pEvent; --(void)mouseEntered: (NSEvent*)pEvent; --(void)mouseExited: (NSEvent*)pEvent; --(void)rightMouseDown: (NSEvent*)pEvent; --(void)rightMouseDragged: (NSEvent*)pEvent; --(void)rightMouseUp: (NSEvent*)pEvent; --(void)otherMouseDown: (NSEvent*)pEvent; --(void)otherMouseDragged: (NSEvent*)pEvent; --(void)otherMouseUp: (NSEvent*)pEvent; --(void)scrollWheel: (NSEvent*)pEvent; --(void)magnifyWithEvent: (NSEvent*)pEvent; --(void)rotateWithEvent: (NSEvent*)pEvent; --(void)swipeWithEvent: (NSEvent*)pEvent; --(void)keyDown: (NSEvent*)pEvent; --(void)flagsChanged: (NSEvent*)pEvent; --(void)sendMouseEventToFrame:(NSEvent*)pEvent button:(sal_uInt16)nButton eventtype:(sal_uInt16)nEvent; --(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar; --(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar modifiers: (unsigned int)nMod; --(BOOL)sendKeyToFrameDirect: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar modifiers: (unsigned int)nMod; --(BOOL)sendSingleCharacter:(NSEvent*)pEvent; --(BOOL)handleKeyDownException:(NSEvent*)pEvent; --(void)clearLastEvent; -/* - text action methods -*/ --(void)insertText:(id)aString; --(void)insertTab: (id)aSender; --(void)insertBacktab: (id)aSender; --(void)moveLeft: (id)aSender; --(void)moveLeftAndModifySelection: (id)aSender; --(void)moveBackwardAndModifySelection: (id)aSender; --(void)moveRight: (id)aSender; --(void)moveRightAndModifySelection: (id)aSender; --(void)moveForwardAndModifySelection: (id)aSender; --(void)moveUp: (id)aSender; --(void)moveDown: (id)aSender; --(void)moveWordBackward: (id)aSender; --(void)moveWordBackwardAndModifySelection: (id)aSender; --(void)moveWordLeftAndModifySelection: (id)aSender; --(void)moveWordForward: (id)aSender; --(void)moveWordForwardAndModifySelection: (id)aSender; --(void)moveWordRightAndModifySelection: (id)aSender; --(void)moveToEndOfLine: (id)aSender; --(void)moveToRightEndOfLine: (id)aSender; --(void)moveToLeftEndOfLine: (id)aSender; --(void)moveToEndOfLineAndModifySelection: (id)aSender; --(void)moveToRightEndOfLineAndModifySelection: (id)aSender; --(void)moveToLeftEndOfLineAndModifySelection: (id)aSender; --(void)moveToBeginningOfLine: (id)aSender; --(void)moveToBeginningOfLineAndModifySelection: (id)aSender; --(void)moveToEndOfParagraph: (id)aSender; --(void)moveToEndOfParagraphAndModifySelection: (id)aSender; --(void)moveToBeginningOfParagraph: (id)aSender; --(void)moveToBeginningOfParagraphAndModifySelection: (id)aSender; --(void)moveParagraphForward: (id)aSender; --(void)moveParagraphForwardAndModifySelection: (id)aSender; --(void)moveParagraphBackward: (id)aSender; --(void)moveParagraphBackwardAndModifySelection: (id)aSender; --(void)moveToEndOfDocument: (id)aSender; --(void)scrollToEndOfDocument: (id)aSender; --(void)moveToEndOfDocumentAndModifySelection: (id)aSender; --(void)moveToBeginningOfDocument: (id)aSender; --(void)scrollToBeginningOfDocument: (id)aSender; --(void)moveToBeginningOfDocumentAndModifySelection: (id)aSender; --(void)insertNewline: (id)aSender; --(void)deleteBackward: (id)aSender; --(void)deleteForward: (id)aSender; --(void)cancelOperation: (id)aSender; --(void)deleteBackwardByDecomposingPreviousCharacter: (id)aSender; --(void)deleteWordBackward: (id)aSender; --(void)deleteWordForward: (id)aSender; --(void)deleteToBeginningOfLine: (id)aSender; --(void)deleteToEndOfLine: (id)aSender; --(void)deleteToBeginningOfParagraph: (id)aSender; --(void)deleteToEndOfParagraph: (id)aSender; --(void)insertLineBreak: (id)aSender; --(void)insertParagraphSeparator: (id)aSender; --(void)selectWord: (id)aSender; --(void)selectLine: (id)aSender; --(void)selectParagraph: (id)aSender; --(void)selectAll: (id)aSender; --(void)noop: (id)aSender; -/* set the correct pointer for our view */ --(void)resetCursorRects; --(::com::sun::star::accessibility::XAccessibleContext *)accessibleContext; --(id)parentAttribute; --(NSView *)viewElementForParent; -/* - Event hook for D&D service. - - A drag operation will be invoked on a NSView using - the method 'dragImage'. This method requires the - actual mouse event initiating this drag operation. - Mouse events can only be received by subclassing - NSView and overriding methods like 'mouseDown' etc. - hence we implement a event hook here so that the - D&D service can register as listener for mouse - messages and use the last 'mouseDown' or - 'mouseDragged' message to initiate the drag - operation. -*/ --(void)registerMouseEventListener: (id)theListener; --(void)unregisterMouseEventListener: (id)theListener; - -/* NSDraggingDestination protocol methods - */ --(NSDragOperation)draggingEntered:(id )sender; --(NSDragOperation)draggingUpdated:(id )sender; --(void)draggingExited:(id )sender; --(BOOL)prepareForDragOperation:(id )sender; --(BOOL)performDragOperation:(id )sender; --(void)concludeDragOperation:(id )sender; - --(void)registerDraggingDestinationHandler:(id)theHandler; --(void)unregisterDraggingDestinationHandler:(id)theHandler; - -@end - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/salinst.h b/vcl/inc/aqua/salinst.h deleted file mode 100644 index 2e6045b11767..000000000000 --- a/vcl/inc/aqua/salinst.h +++ /dev/null @@ -1,175 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_SALINST_H -#define INCLUDED_VCL_INC_AQUA_SALINST_H - -#include "comphelper/solarmutex.hxx" -#include "osl/thread.hxx" -#include "osl/conditn.h" -#include - -#include "aqua/aquavcltypes.h" - -#include "salinst.hxx" - -#include - -class AquaSalFrame; -class ApplicationEvent; -class Image; - -class SalYieldMutex : public vcl::SolarMutexObject -{ - sal_uLong mnCount; - oslThreadIdentifier mnThreadId; - -public: - SalYieldMutex(); - virtual void acquire(); - virtual void release(); - virtual bool tryToAcquire(); - sal_uLong GetAcquireCount() const { return mnCount; } - oslThreadIdentifier GetThreadId() const { return mnThreadId; } -}; - -#define YIELD_GUARD osl::Guard< comphelper::SolarMutex > aGuard( GetSalData()->mpFirstInstance->GetYieldMutex() ) - - -class AquaSalInstance : public SalInstance -{ - struct SalUserEvent - { - AquaSalFrame* mpFrame; - void* mpData; - sal_uInt16 mnType; - - SalUserEvent( AquaSalFrame* pFrame, void* pData, sal_uInt16 nType ) : - mpFrame( pFrame ), mpData( pData ), mnType( nType ) - {} - }; - -public: - SalYieldMutex* mpSalYieldMutex; // Sal-Yield-Mutex - OUString maDefaultPrinter; - oslThreadIdentifier maMainThread; - bool mbWaitingYield; - int mnActivePrintJobs; - std::list< SalUserEvent > maUserEvents; - oslMutex maUserEventListMutex; - oslCondition maWaitingYieldCond; - - typedef std::list AppEventList; - static AppEventList aAppEventList; - -public: - AquaSalInstance(); - virtual ~AquaSalInstance(); - - virtual SalSystem* CreateSystem(); - virtual void DestroySystem(SalSystem*); - virtual SalFrame* CreateChildFrame( SystemParentData* pParent, sal_uLong nStyle ); - virtual SalFrame* CreateFrame( SalFrame* pParent, sal_uLong nStyle ); - virtual void DestroyFrame( SalFrame* pFrame ); - virtual SalObject* CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, sal_Bool bShow = sal_True ); - virtual void DestroyObject( SalObject* pObject ); - virtual SalVirtualDevice* CreateVirtualDevice( SalGraphics* pGraphics, - long nDX, long nDY, - sal_uInt16 nBitCount, const SystemGraphicsData *pData ); - virtual void DestroyVirtualDevice( SalVirtualDevice* pDevice ); - - virtual SalInfoPrinter* CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo, - ImplJobSetup* pSetupData ); - virtual void DestroyInfoPrinter( SalInfoPrinter* pPrinter ); - virtual SalPrinter* CreatePrinter( SalInfoPrinter* pInfoPrinter ); - virtual void DestroyPrinter( SalPrinter* pPrinter ); - virtual void GetPrinterQueueInfo( ImplPrnQueueList* pList ); - virtual void GetPrinterQueueState( SalPrinterQueueInfo* pInfo ); - virtual void DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo ); - virtual OUString GetDefaultPrinter(); - virtual SalTimer* CreateSalTimer(); - virtual SalI18NImeStatus* CreateI18NImeStatus(); - virtual SalSystem* CreateSalSystem(); - virtual SalBitmap* CreateSalBitmap(); - virtual comphelper::SolarMutex* GetYieldMutex(); - virtual sal_uLong ReleaseYieldMutex(); - virtual void AcquireYieldMutex( sal_uLong nCount ); - virtual bool CheckYieldMutex(); - virtual void Yield( bool bWait, bool bHandleAllCurrentEvents ); - virtual bool AnyInput( sal_uInt16 nType ); - virtual SalMenu* CreateMenu( sal_Bool bMenuBar, Menu* pVCLMenu ); - virtual void DestroyMenu( SalMenu* ); - virtual SalMenuItem* CreateMenuItem( const SalItemParams* pItemData ); - virtual void DestroyMenuItem( SalMenuItem* ); - virtual SalSession* CreateSalSession(); - virtual void* GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes ); - virtual void AddToRecentDocumentList(const OUString& rFileUrl, const OUString& rMimeType, const OUString& rDocumentService); - virtual void SetEventCallback( void* pInstance, bool(*pCallback)(void*,void*,int) ); - virtual void SetErrorEventCallback( void* pInstance, bool(*pCallback)(void*,void*,int) ); - - // dtrans implementation - virtual com::sun::star::uno::Reference< com::sun::star::uno::XInterface > - CreateClipboard( const com::sun::star::uno::Sequence< com::sun::star::uno::Any >& i_rArguments ); - virtual com::sun::star::uno::Reference< com::sun::star::uno::XInterface > CreateDragSource(); - virtual com::sun::star::uno::Reference< com::sun::star::uno::XInterface > CreateDropTarget(); - - static void handleAppDefinedEvent( NSEvent* pEvent ); - - // check whether a particular string is passed on the command line - // this is needed to avoid duplicate open events through a) command line and b) NSApp's openFile - static bool isOnCommandLine( const OUString& ); - - void wakeupYield(); - - public: - friend class AquaSalFrame; - - void PostUserEvent( AquaSalFrame* pFrame, sal_uInt16 nType, void* pData ); - void delayedSettingsChanged( bool bInvalidate ); - - bool isNSAppThread() const; - - void startedPrintJob() { mnActivePrintJobs++; } - void endedPrintJob() { mnActivePrintJobs--; } - - // event subtypes for NSApplicationDefined events - static const short AppExecuteSVMain = 0x7fff; - static const short AppEndLoopEvent = 1; - static const short AppStartTimerEvent = 10; - static const short AppleRemoteEvent = 15; - static const short YieldWakeupEvent = 20; - - static NSMenu* GetDynamicDockMenu(); -}; - -// helper class: inverted solar guard -class YieldMutexReleaser -{ - sal_uLong mnCount; - public: - YieldMutexReleaser(); - ~YieldMutexReleaser(); -}; - -CGImageRef CreateCGImage( const Image& ); -NSImage* CreateNSImage( const Image& ); - -#endif // INCLUDED_VCL_INC_AQUA_SALINST_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/salmathutils.hxx b/vcl/inc/aqua/salmathutils.hxx deleted file mode 100644 index e3c223ee3f26..000000000000 --- a/vcl/inc/aqua/salmathutils.hxx +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_SALMATHUTILS_HXX -#define INCLUDED_VCL_INC_AQUA_SALMATHUTILS_HXX - -#ifdef __cplusplus -extern "C" { -#endif - -// ------------------------------------------------------------------ -// -// Structures -// -// ------------------------------------------------------------------ - -// LRectCoor is an abreviation for rectangular coordinates -// represented as long integers - -struct LRectCoor -{ - long x; - long y; - long z; -}; - -// ------------------------------------------------------------------ -// -// Type Definitions -// -// ------------------------------------------------------------------ - -// LRectCoorVec is an abreviation for vectors in rectangular -// coordinates represented as long integers - -typedef struct LRectCoor LRectCoor; -typedef LRectCoor *LRectCoorVector; -typedef LRectCoorVector *LRectCoorTensor; - -// ------------------------------------------------------------------ -// -// Function Headers -// -// ------------------------------------------------------------------ - -void CSwap ( char &rX, char &rY ); -void UCSwap ( unsigned char &rX, unsigned char &rY ); -void SSwap ( short &rX, short &rY ); -void USSwap ( unsigned short &rX, unsigned short &rY ); -void LSwap ( long &rX, long &rY ); -void ULSwap ( unsigned long &rX, unsigned long &rY ); - -// ------------------------------------------------------------------ - -unsigned long Euclidian2Norm ( const LRectCoorVector pVec ); - -// ------------------------------------------------------------------ - -#ifdef __cplusplus -} -#endif - -#endif // INCLUDED_VCL_INC_AQUA_SALMATHUTILS_HXX - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/salmenu.h b/vcl/inc/aqua/salmenu.h deleted file mode 100644 index 4be94eaf04e7..000000000000 --- a/vcl/inc/aqua/salmenu.h +++ /dev/null @@ -1,114 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_SALMENU_H -#define INCLUDED_VCL_INC_AQUA_SALMENU_H - -#include "premac.h" -#include -#include "postmac.h" - -#include "salmenu.hxx" - -#include - -class AquaSalFrame; -class AquaSalMenuItem; - -class AquaSalMenu : public SalMenu -{ - std::vector< AquaSalMenuItem* > maItems; - -public: // for OOStatusView - struct MenuBarButtonEntry - { - SalMenuButtonItem maButton; - NSImage* mpNSImage; // cached image - NSString* mpToolTipString; - - MenuBarButtonEntry() : mpNSImage( nil ), mpToolTipString( nil ) {} - MenuBarButtonEntry( const SalMenuButtonItem& i_rItem ) - : maButton( i_rItem), mpNSImage( nil ), mpToolTipString( nil ) {} - }; -private: - std::vector< MenuBarButtonEntry > maButtons; - - MenuBarButtonEntry* findButtonItem( sal_uInt16 i_nItemId ); - void releaseButtonEntry( MenuBarButtonEntry& i_rEntry ); - static void statusLayout(); -public: - AquaSalMenu( bool bMenuBar ); - virtual ~AquaSalMenu(); - - virtual sal_Bool VisibleMenuBar(); // must return TRUE to actually DISPLAY native menu bars - // otherwise only menu messages are processed (eg, OLE on Windows) - - virtual void InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos ); - virtual void RemoveItem( unsigned nPos ); - virtual void SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos ); - virtual void SetFrame( const SalFrame* pFrame ); - virtual void CheckItem( unsigned nPos, sal_Bool bCheck ); - virtual void EnableItem( unsigned nPos, sal_Bool bEnable ); - virtual void SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const OUString& rText ); - virtual void SetItemImage( unsigned nPos, SalMenuItem* pSalMenuItem, const Image& rImage); - virtual void SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const KeyCode& rKeyCode, const OUString& rKeyName ); - virtual void GetSystemMenuData( SystemMenuData* pData ); - virtual bool ShowNativePopupMenu(FloatingWindow * pWin, const Rectangle& rRect, sal_uLong nFlags); - virtual bool AddMenuBarButton( const SalMenuButtonItem& ); - virtual void RemoveMenuBarButton( sal_uInt16 nId ); - virtual Rectangle GetMenuBarButtonRectPixel( sal_uInt16 i_nItemId, SalFrame* i_pReferenceFrame ); - - int getItemIndexByPos( sal_uInt16 nPos ) const; - const AquaSalFrame* getFrame() const; - - void setMainMenu(); - static void unsetMainMenu(); - static void setDefaultMenu(); - static void enableMainMenu( bool bEnable ); - static void addFallbackMenuItem( NSMenuItem* NewItem ); - static void removeFallbackMenuItem( NSMenuItem* pOldItem ); - - const std::vector< MenuBarButtonEntry >& getButtons() const { return maButtons; } - - bool mbMenuBar; // true - Menubar, false - Menu - NSMenu* mpMenu; // The Carbon reference to this menu - Menu* mpVCLMenu; // the corresponding vcl Menu object - const AquaSalFrame* mpFrame; // the frame to dispatch the menu events to - AquaSalMenu* mpParentSalMenu; // the parent menu that contains us (and perhaps has a frame) - - static const AquaSalMenu* pCurrentMenuBar; - -}; - -class AquaSalMenuItem : public SalMenuItem -{ -public: - AquaSalMenuItem( const SalItemParams* ); - virtual ~AquaSalMenuItem(); - - sal_uInt16 mnId; // Item ID - Menu* mpVCLMenu; // VCL Menu into which this MenuItem is inserted - AquaSalMenu* mpParentMenu; // The menu in which this menu item is inserted - AquaSalMenu* mpSubMenu; // Sub menu of this item (if defined) - NSMenuItem* mpMenuItem; // The NSMenuItem -}; - -#endif // INCLUDED_VCL_INC_AQUA_SALMENU_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/salnativewidgets.h b/vcl/inc/aqua/salnativewidgets.h deleted file mode 100644 index 5c67a825962c..000000000000 --- a/vcl/inc/aqua/salnativewidgets.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_SALNATIVEWIDGETS_H -#define INCLUDED_VCL_INC_AQUA_SALNATIVEWIDGETS_H - -// since 10.4 ... no metrics are returned, and we have to fix the values -#define BUTTON_WIDTH 16 -#define BUTTON_HEIGHT 17 - -//standard height of the AHIG -//tabs -#define TAB_HEIGHT_NORMAL 20 -#define TAB_HEIGHT_SMALL 17 -#define TAB_HEIGHT_MINI 15 - -#define TAB_TEXT_OFFSET 12 -#define VCL_TAB_TEXT_OFFSET 2 - -//listboxes, comboboxes (they have the same dimensions) -#define COMBOBOX_HEIGHT_NORMAL 20 -#define DROPDOWN_BUTTON_WIDTH 20 - -//text edit -#define TEXT_EDIT_HEIGHT_NORMAL 22 - -//spin box -#define SPIN_BUTTON_SPACE 2 -#define SPIN_BUTTON_WIDTH 13 -#define SPIN_UPPER_BUTTON_HEIGHT 11 -#define SPIN_LOWER_BUTTON_HEIGHT 10 - -// progress bar -#define INTRO_PROGRESS_HEIGHT 9 - -// for some controls, like spinbuttons + spinboxes, or listboxes -// we need it to adjust text position beside radio and check buttons - -#define TEXT_SEPARATOR 3 - -// extra border for focus ring -#define FOCUS_RING_WIDTH 4 - -#define CLIP_FUZZ 1 - -#endif // INCLUDED_VCL_INC_AQUA_SALNATIVEWIDGETS_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/salnsmenu.h b/vcl/inc/aqua/salnsmenu.h deleted file mode 100644 index 585961280c3f..000000000000 --- a/vcl/inc/aqua/salnsmenu.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_SALNSMENU_H -#define INCLUDED_VCL_INC_AQUA_SALNSMENU_H - -class AquaSalMenu; -class AquaSalMenuItem; - -@interface OOStatusItemView : NSView -{ -} --(void)drawRect: (NSRect)aRect; --(void)layout; --(void)mouseUp: (NSEvent *)pEvent; -@end - -@interface SalNSMenu : NSMenu -{ - /* Caution: SalNSMenu instances occasionally are binary copied - in AquaSalMenu::ShowNativePopupMenu. If any members are added, - please take this into account ! - */ - AquaSalMenu* mpMenu; -} --(id)initWithMenu: (AquaSalMenu*)pMenu; --(void)menuNeedsUpdate: (NSMenu*)pMenu; --(void)setSalMenu: (AquaSalMenu*)pMenu; -@end - -@interface SalNSMenuItem : NSMenuItem -{ - /* Caution: SalNSMenuItem instances occasionally are binary copied - in AquaSalMenu::ShowNativePopupMenu. If any members are added, - please take this into account ! - */ - AquaSalMenuItem* mpMenuItem; -} --(id)initWithMenuItem: (AquaSalMenuItem*)pMenuItem; --(void)menuItemTriggered: (id)aSender; -@end - - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/salnstimer.h b/vcl/inc/aqua/salnstimer.h deleted file mode 100644 index 3d05fc8fc247..000000000000 --- a/vcl/inc/aqua/salnstimer.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ -#ifndef INCLUDED_VCL_INC_AQUA_SALNSTIMER_H -#define INCLUDED_VCL_INC_AQUA_SALNSTIMER_H - -#include "premac.h" -#include "Cocoa/Cocoa.h" -#include "postmac.h" - -@interface TimerCallbackCaller : NSObject -{ -} --(void)timerElapsed:(NSTimer*)pTimer; -@end - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/salobj.h b/vcl/inc/aqua/salobj.h deleted file mode 100644 index 0bd82821ab1e..000000000000 --- a/vcl/inc/aqua/salobj.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_SALOBJ_H -#define INCLUDED_VCL_INC_AQUA_SALOBJ_H - -#include "vcl/sysdata.hxx" -#include "salobj.hxx" - -class AquaSalFrame; -class AquaSalObject; - - -// ----------------- -// - SalObjectData - -// ----------------- - -struct SalObjectData -{ -}; - -class AquaSalObject : public SalObject -{ -public: - AquaSalFrame* mpFrame; // parent frame - NSClipView* mpClipView; - SystemEnvData maSysData; - - long mnClipX; - long mnClipY; - long mnClipWidth; - long mnClipHeight; - bool mbClip; - - long mnX; - long mnY; - long mnWidth; - long mnHeight; - - - void setClippedPosSize(); - - - AquaSalObject( AquaSalFrame* pFrame ); - virtual ~AquaSalObject(); - - virtual void ResetClipRegion(); - virtual sal_uInt16 GetClipRegionType(); - virtual void BeginSetClipRegion( sal_uLong nRects ); - virtual void UnionClipRegion( long nX, long nY, long nWidth, long nHeight ); - virtual void EndSetClipRegion(); - virtual void SetPosSize( long nX, long nY, long nWidth, long nHeight ); - virtual void Show( sal_Bool bVisible ); - virtual const SystemEnvData* GetSystemData() const; -}; - -#endif // INCLUDED_VCL_INC_AQUA_SALOBJ_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/salprn.h b/vcl/inc/aqua/salprn.h deleted file mode 100644 index cd8c32651b18..000000000000 --- a/vcl/inc/aqua/salprn.h +++ /dev/null @@ -1,165 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_SALPRN_H -#define INCLUDED_VCL_INC_AQUA_SALPRN_H - -#include "aqua/aquavcltypes.h" - -#include "salprn.hxx" - -#include - - -// --------------------- -// - AquaSalInfoPrinter - -// --------------------- - -class AquaSalGraphics; - -class AquaSalInfoPrinter : public SalInfoPrinter -{ - /// Printer graphics - AquaSalGraphics* mpGraphics; - /// is Graphics used - bool mbGraphics; - /// job active ? - bool mbJob; - - /// cocoa printer object - NSPrinter* mpPrinter; - /// cocoa print info object - NSPrintInfo* mpPrintInfo; - - /// FIXME: get real printer context for infoprinter if possible - /// fake context for info printer - /// graphics context for Quartz 2D - CGContextRef mrContext; - /// memory for graphics bitmap context for querying metrics - boost::shared_array< sal_uInt8 > maContextMemory; - - // since changes to NSPrintInfo during a job are ignored - // we have to care for some settings ourselves - // currently we do this for orientation; - // really needed however is a solution for paper formats - Orientation mePageOrientation; - - int mnStartPageOffsetX; - int mnStartPageOffsetY; - sal_Int32 mnCurPageRangeStart; - sal_Int32 mnCurPageRangeCount; - - public: - AquaSalInfoPrinter( const SalPrinterQueueInfo& pInfo ); - virtual ~AquaSalInfoPrinter(); - - void SetupPrinterGraphics( CGContextRef i_xContext ) const; - - virtual SalGraphics* GetGraphics(); - virtual void ReleaseGraphics( SalGraphics* i_pGraphics ); - virtual sal_Bool Setup( SalFrame* i_pFrame, ImplJobSetup* i_pSetupData ); - virtual sal_Bool SetPrinterData( ImplJobSetup* pSetupData ); - virtual sal_Bool SetData( sal_uLong i_nFlags, ImplJobSetup* i_pSetupData ); - virtual void GetPageInfo( const ImplJobSetup* i_pSetupData, - long& o_rOutWidth, long& o_rOutHeight, - long& o_rPageOffX, long& o_rPageOffY, - long& o_rPageWidth, long& o_rPageHeight ); - virtual sal_uLong GetCapabilities( const ImplJobSetup* i_pSetupData, sal_uInt16 i_nType ); - virtual sal_uLong GetPaperBinCount( const ImplJobSetup* i_pSetupData ); - virtual OUString GetPaperBinName( const ImplJobSetup* i_pSetupData, sal_uLong i_nPaperBin ); - virtual void InitPaperFormats( const ImplJobSetup* i_pSetupData ); - virtual int GetLandscapeAngle( const ImplJobSetup* i_pSetupData ); - - // the artificial separation between InfoPrinter and Printer - // is not really useful for us - // so let's make AquaSalPrinter just a forwarder to AquaSalInfoPrinter - // and concentrate the real work in one class - // implement pull model print system - sal_Bool StartJob( const OUString* i_pFileName, - const OUString& rJobName, - const OUString& i_rAppName, - ImplJobSetup* i_pSetupData, - vcl::PrinterController& i_rController ); - sal_Bool EndJob(); - sal_Bool AbortJob(); - SalGraphics* StartPage( ImplJobSetup* i_pSetupData, sal_Bool i_bNewJobData ); - sal_Bool EndPage(); - sal_uLong GetErrorCode() const; - - NSPrintInfo* getPrintInfo() const { return mpPrintInfo; } - void setStartPageOffset( int nOffsetX, int nOffsetY ) { mnStartPageOffsetX = nOffsetX; mnStartPageOffsetY = nOffsetY; } - sal_Int32 getCurPageRangeStart() const { return mnCurPageRangeStart; } - sal_Int32 getCurPageRangeCount() const { return mnCurPageRangeCount; } - - // match width/height against known paper formats, possibly switching orientation - const PaperInfo* matchPaper( long i_nWidth, long i_nHeight, Orientation& o_rOrientation ) const; - void setPaperSize( long i_nWidth, long i_nHeight, Orientation i_eSetOrientation ); - - private: - AquaSalInfoPrinter( const AquaSalInfoPrinter& ); - AquaSalInfoPrinter& operator=(const AquaSalInfoPrinter&); -}; - -// ----------------- -// - AquaSalPrinter - -// ----------------- - -class AquaSalPrinter : public SalPrinter -{ - AquaSalInfoPrinter* mpInfoPrinter; // pointer to the compatible InfoPrinter - public: - AquaSalPrinter( AquaSalInfoPrinter* i_pInfoPrinter ); - virtual ~AquaSalPrinter(); - - virtual sal_Bool StartJob( const OUString* i_pFileName, - const OUString& i_rJobName, - const OUString& i_rAppName, - sal_uLong i_nCopies, - bool i_bCollate, - bool i_bDirect, - ImplJobSetup* i_pSetupData ); - // implement pull model print system - virtual sal_Bool StartJob( const OUString* i_pFileName, - const OUString& rJobName, - const OUString& i_rAppName, - ImplJobSetup* i_pSetupData, - vcl::PrinterController& i_rListener ); - - virtual sal_Bool EndJob(); - virtual sal_Bool AbortJob(); - virtual SalGraphics* StartPage( ImplJobSetup* i_pSetupData, sal_Bool i_bNewJobData ); - virtual sal_Bool EndPage(); - virtual sal_uLong GetErrorCode(); - - private: - AquaSalPrinter( const AquaSalPrinter& ); - AquaSalPrinter& operator=(const AquaSalPrinter&); -}; - -const double fPtTo100thMM = 35.27777778; - -inline int PtTo10Mu( double nPoints ) { return (int)(((nPoints)*fPtTo100thMM)+0.5); } - -inline double TenMuToPt( double nUnits ) { return floor(((nUnits)/fPtTo100thMM)+0.5); } - - - -#endif // INCLUDED_VCL_INC_AQUA_SALPRN_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/salsys.h b/vcl/inc/aqua/salsys.h deleted file mode 100644 index e68bdbb0b346..000000000000 --- a/vcl/inc/aqua/salsys.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_SALSYS_H -#define INCLUDED_VCL_INC_AQUA_SALSYS_H - -#include "salsys.hxx" - -#include - -// ----------------- -// - SalSystemData - -// ----------------- - -class VCL_DLLPUBLIC AquaSalSystem : public SalSystem -{ -public: - AquaSalSystem() {} - virtual ~AquaSalSystem(); - - // get info about the display - virtual unsigned int GetDisplayScreenCount(); - virtual Rectangle GetDisplayScreenPosSizePixel( unsigned int nScreen ); - - virtual OUString GetDisplayScreenName( unsigned int nScreen ); - virtual int ShowNativeMessageBox( const OUString& rTitle, - const OUString& rMessage, - int nButtonCombination, - int nDefaultButton, bool bUseResources); -}; - - -#endif // INCLUDED_VCL_INC_AQUA_SALSYS_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/saltimer.h b/vcl/inc/aqua/saltimer.h deleted file mode 100644 index e51740ff4ba1..000000000000 --- a/vcl/inc/aqua/saltimer.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_SALTIMER_H -#define INCLUDED_VCL_INC_AQUA_SALTIMER_H - -#include "premac.h" -#include -#include "postmac.h" - -#include "saltimer.hxx" - -class AquaSalTimer : public SalTimer -{ - public: - - AquaSalTimer(); - virtual ~AquaSalTimer(); - - void Start( sal_uLong nMS ); - void Stop(); - - static void handleStartTimerEvent( NSEvent* pEvent ); - - - static NSTimer* pRunningTimer; - static bool bDispatchTimer; -}; - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/salvd.h b/vcl/inc/aqua/salvd.h deleted file mode 100644 index 09e2a01c1897..000000000000 --- a/vcl/inc/aqua/salvd.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_SALVD_H -#define INCLUDED_VCL_INC_AQUA_SALVD_H - -#include "premac.h" -#include -#include "postmac.h" - -#include "coretext/salgdi.h" - -#include "salvd.hxx" - -#if PRAGMA_ONCE - #pragma once -#endif - -// ======================================================================= - -// ======================================================================= - -// ----------------- -// - SalVirDevData - -// ----------------- - -struct SalVirDevData -{ -}; - -typedef struct SalVirDevData SalVirDevData; -typedef SalVirDevData *SalVirDevDataPtr; -typedef SalVirDevDataPtr *SalVirDevDataHandle; - -// ======================================================================= - -class AquaSalGraphics; - -// ----------------- -// - SalVirDevData - -// ----------------- - -class AquaSalVirtualDevice : public SalVirtualDevice -{ -private: - bool mbGraphicsUsed; // is Graphics used - bool mbForeignContext; // is mxContext from outside VCL - CGContextRef mxBitmapContext; - int mnBitmapDepth; - CGLayerRef mxLayer; // Quartz layer - AquaSalGraphics* mpGraphics; // current VirDev graphics - - void Destroy(); - -public: - AquaSalVirtualDevice( AquaSalGraphics* pGraphic, long nDX, long nDY, sal_uInt16 nBitCount, const SystemGraphicsData *pData ); - virtual ~AquaSalVirtualDevice(); - - virtual SalGraphics* GetGraphics(); - virtual void ReleaseGraphics( SalGraphics* pGraphics ); - virtual sal_Bool SetSize( long nNewDX, long nNewDY ); - virtual void GetSize( long& rWidth, long& rHeight ); -}; - -// ======================================================================= - -#endif // INCLUDED_VCL_INC_AQUA_SALVD_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/svsys.h b/vcl/inc/aqua/svsys.h deleted file mode 100644 index 89bb7dce2016..000000000000 --- a/vcl/inc/aqua/svsys.h +++ /dev/null @@ -1,29 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_SVSYS_H -#define INCLUDED_VCL_INC_AQUA_SVSYS_H - -#include "premac.h" -#include "Cocoa/Cocoa.h" -#include "postmac.h" - -#endif // INCLUDED_VCL_INC_AQUA_SVSYS_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/vclnsapp.h b/vcl/inc/aqua/vclnsapp.h deleted file mode 100644 index 7413361114db..000000000000 --- a/vcl/inc/aqua/vclnsapp.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_AQUA_VCLNSAPP_H -#define INCLUDED_VCL_INC_AQUA_VCLNSAPP_H - -#include - -#include "premac.h" -#include "Cocoa/Cocoa.h" -#include "postmac.h" - -class AquaSalFrame; - -@interface CocoaThreadEnabler : NSObject -{ -} --(void)enableCocoaThreads:(id)param; -@end - -// our very own application -@interface VCL_NSApplication : NSApplication -{ -} --(void)sendEvent:(NSEvent*)pEvent; --(void)sendSuperEvent:(NSEvent*)pEvent; --(NSMenu*)applicationDockMenu:(NSApplication *)sender; --(BOOL)application: (NSApplication*) app openFile: (NSString*)file; --(void)application: (NSApplication*) app openFiles: (NSArray*)files; --(BOOL)application: (NSApplication*) app printFile: (NSString*)file; --(NSApplicationPrintReply)application: (NSApplication *) app printFiles:(NSArray *)files withSettings: (NSDictionary *)printSettings showPrintPanels:(BOOL)bShowPrintPanels; --(NSApplicationTerminateReply)applicationShouldTerminate: (NSApplication *) app; --(void)systemColorsChanged: (NSNotification*) pNotification; --(void)screenParametersChanged: (NSNotification*) pNotification; --(void)scrollbarVariantChanged: (NSNotification*) pNotification; --(void)scrollbarSettingsChanged: (NSNotification*) pNotification; --(void)addFallbackMenuItem: (NSMenuItem*)pNewItem; --(void)removeFallbackMenuItem: (NSMenuItem*)pOldItem; --(void)addDockMenuItem: (NSMenuItem*)pNewItem; -#if !HAVE_FEATURE_MACOSX_SANDBOX --(void)applicationWillBecomeActive: (NSNotification *)pNotification; --(void)applicationWillResignActive: (NSNotification *)pNotification; -#endif --(BOOL)applicationShouldHandleReopen: (NSApplication*)pApp hasVisibleWindows: (BOOL)bWinVisible; --(void)setDockIconClickHandler: (NSObject*)pHandler; --(void)cycleFrameForward: (AquaSalFrame*)pCurFrame; --(void)cycleFrameBackward: (AquaSalFrame*)pCurFrame; -@end - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/coretext/common.h b/vcl/inc/coretext/common.h deleted file mode 100644 index 1f1211b05c12..000000000000 --- a/vcl/inc/coretext/common.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_CORETEXT_COMMON_H -#define INCLUDED_VCL_INC_CORETEXT_COMMON_H - -#include - -#include -#ifdef MACOSX -#include -#else -#include -#include -#endif -#include - -#include - -#include - -// CoreFoundation designers, in their wisdom, decided that CFRelease of NULL -// cause a Crash, yet few API can return NULL when asking for the creation -// of an object, which force us to peper the code with egly if construct everywhere -// and open the door to very nasty crash on rare occasion -// this macro hide the mess -#define SafeCFRelease(a) do { if(a) { CFRelease(a); (a)=NULL; } } while(false) - -#define round_to_long(a) ((a) >= 0 ? ((long)((a) + 0.5)) : ((long)((a) - 0.5))) - -#include "vcl/salgtype.hxx" - -std::ostream &operator <<(std::ostream& s, CTFontRef pFont); - -#endif // INCLUDED_VCL_INC_CORETEXT_COMMON_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/coretext/salgdi.h b/vcl/inc/coretext/salgdi.h deleted file mode 100644 index d6f8682dba03..000000000000 --- a/vcl/inc/coretext/salgdi.h +++ /dev/null @@ -1,433 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_CORETEXT_SALGDI_H -#define INCLUDED_VCL_INC_CORETEXT_SALGDI_H - -#include - -#include "basegfx/polygon/b2dpolypolygon.hxx" - -#include "premac.h" -#ifdef MACOSX -#include -#include "aqua/aquavcltypes.h" -#include "aqua/salframe.h" -#else -#include -#include -#endif -#include "postmac.h" - -#include - -#include "outfont.hxx" -#include "salgdi.hxx" - -#include "quartz/salgdicommon.hxx" - -class AquaSalFrame; -class ImplDevFontAttributes; -class CoreTextStyle; - -typedef sal_uInt32 sal_GlyphId; -typedef std::vector ByteVector; - -// CoreText-specific physically available font face -class CoreTextFontData : public PhysicalFontFace -{ -public: - CoreTextFontData( const ImplDevFontAttributes&, sal_IntPtr nFontID ); - - ~CoreTextFontData(); - - PhysicalFontFace* Clone() const; - ImplFontEntry* CreateFontInstance( FontSelectPattern& ) const; - sal_IntPtr GetFontId() const; - - CoreTextStyle* CreateTextStyle( const FontSelectPattern& ) const; - int GetFontTable( const char pTagName[5], unsigned char* ) const; - - const ImplFontCharMap* GetImplFontCharMap() const; - bool GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const; - bool HasChar( sal_uInt32 cChar ) const; - - void ReadOs2Table() const; - void ReadMacCmapEncoding() const; - -protected: - CoreTextFontData( const CoreTextFontData&); - -private: - const sal_IntPtr mnFontId; - mutable const ImplFontCharMap* mpCharMap; - mutable vcl::FontCapabilities maFontCapabilities; - mutable bool mbOs2Read; // true if OS2-table related info is valid - mutable bool mbHasOs2Table; - mutable bool mbCmapEncodingRead; // true if cmap encoding of Mac font is read - mutable bool mbFontCapabilitiesRead; -}; - -class CoreTextStyle -{ -public: - CoreTextStyle( const FontSelectPattern& ); - ~CoreTextStyle( void ); - - SalLayout* GetTextLayout( void ) const; - - void GetFontMetric( float fPDIY, ImplFontMetricData& ) const; - bool GetGlyphBoundRect( sal_GlyphId, Rectangle& ) const; - bool GetGlyphOutline( sal_GlyphId, basegfx::B2DPolyPolygon& ) const; - - void SetTextColor( const RGBAColor& ); - - const CoreTextFontData* mpFontData; - /// <1.0: font is squeezed, >1.0 font is stretched, else 1.0 - float mfFontStretch; - /// text rotation in radian - float mfFontRotation; - -private: - /// CoreText text style object - CFMutableDictionaryRef mpStyleDict; - - friend class CTLayout; - CFMutableDictionaryRef GetStyleDict( void ) const { return mpStyleDict; } -}; - -// ------------------ -// - SystemFontList - -// TODO: move into cross-platform headers -// ------------------ -class SystemFontList -{ -public: - SystemFontList( void ); - ~SystemFontList( void ); - - bool Init( void ); - void AddFont( CoreTextFontData* ); - - void AnnounceFonts( ImplDevFontList& ) const; - CoreTextFontData* GetFontDataFromId( sal_IntPtr nFontId ) const; - -private: - CTFontCollectionRef mpCTFontCollection; - CFArrayRef mpCTFontArray; - - typedef boost::unordered_map CTFontContainer; - CTFontContainer maFontContainer; -}; - -#ifdef MACOSX - -// ------------------- -// - AquaSalGraphics - -// ------------------- -class AquaSalGraphics : public SalGraphics -{ - friend class CTLayout; -protected: - AquaSalFrame* mpFrame; - CGLayerRef mxLayer; // Quartz graphics layer - CGContextRef mrContext; // Quartz drawing context - class XorEmulation* mpXorEmulation; - int mnXorMode; // 0: off 1: on 2: invert only - int mnWidth; - int mnHeight; - int mnBitmapDepth; // zero unless bitmap - /// device resolution of this graphics - long mnRealDPIX; - long mnRealDPIY; - /// some graphics implementations (e.g. AquaSalInfoPrinter) scale - /// everything down by a factor (see SetupPrinterGraphics for details) - /// so we have to compensate for it with the inverse factor - double mfFakeDPIScale; - - /// path representing current clip region - CGMutablePathRef mxClipPath; - - /// Drawing colors - /// pen color RGBA - RGBAColor maLineColor; - /// brush color RGBA - RGBAColor maFillColor; - - // Device Font settings - const CoreTextFontData* mpFontData; - CoreTextStyle* mpTextStyle; - RGBAColor maTextColor; - /// allows text to be rendered without antialiasing - bool mbNonAntialiasedText; - - // Graphics types - - /// is this a printer graphics - bool mbPrinter; - /// is this a virtual device graphics - bool mbVirDev; - /// is this a window graphics - bool mbWindow; - -public: - AquaSalGraphics(); - virtual ~AquaSalGraphics(); - - bool IsPenVisible() const { return maLineColor.IsVisible(); } - bool IsBrushVisible() const { return maFillColor.IsVisible(); } - - void SetWindowGraphics( AquaSalFrame* pFrame ); - void SetPrinterGraphics( CGContextRef, long nRealDPIX, long nRealDPIY, double fFakeScale ); - void SetVirDevGraphics( CGLayerRef, CGContextRef, int nBitDepth = 0 ); - - void initResolution( NSWindow* ); - void copyResolution( AquaSalGraphics& ); - void updateResolution(); - - bool IsWindowGraphics() const { return mbWindow; } - AquaSalFrame* getGraphicsFrame() const { return mpFrame; } - void setGraphicsFrame( AquaSalFrame* pFrame ) { mpFrame = pFrame; } - - void ImplDrawPixel( long nX, long nY, const RGBAColor& ); // helper to draw single pixels - - bool CheckContext(); - CGContextRef GetContext(); - void UpdateWindow( NSRect& ); // delivered in NSView coordinates -#if !defined(__LP64__) && !defined(NS_BUILD_32_LIKE_64) - void RefreshRect( const CGRect& ); -#endif - void RefreshRect( const NSRect& ); - void RefreshRect(float lX, float lY, float lWidth, float lHeight); - - void SetState(); - void UnsetState(); - // InvalidateContext does an UnsetState and sets mrContext to 0 - void InvalidateContext(); - - virtual bool setClipRegion( const Region& ); - - // draw --> LineColor and FillColor and RasterOp and ClipRegion - virtual void drawPixel( long nX, long nY ); - virtual void drawPixel( long nX, long nY, SalColor nSalColor ); - virtual void drawLine( long nX1, long nY1, long nX2, long nY2 ); - virtual void drawRect( long nX, long nY, long nWidth, long nHeight ); - virtual void drawPolyLine( sal_uLong nPoints, const SalPoint* pPtAry ); - virtual void drawPolygon( sal_uLong nPoints, const SalPoint* pPtAry ); - virtual void drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry ); - virtual bool drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double fTransparency ); - virtual sal_Bool drawPolyLineBezier( sal_uLong nPoints, const SalPoint* pPtAry, const sal_uInt8* pFlgAry ); - virtual sal_Bool drawPolygonBezier( sal_uLong nPoints, const SalPoint* pPtAry, const sal_uInt8* pFlgAry ); - virtual sal_Bool drawPolyPolygonBezier( sal_uInt32 nPoly, const sal_uInt32* pPoints, const SalPoint* const* pPtAry, const sal_uInt8* const* pFlgAry ); - virtual bool drawPolyLine( - const ::basegfx::B2DPolygon&, - double fTransparency, - const ::basegfx::B2DVector& rLineWidths, - basegfx::B2DLineJoin, - com::sun::star::drawing::LineCap eLineCap); - - // CopyArea --> No RasterOp, but ClipRegion - virtual void copyArea( long nDestX, long nDestY, long nSrcX, long nSrcY, long nSrcWidth, - long nSrcHeight, sal_uInt16 nFlags ); - - // CopyBits and DrawBitmap --> RasterOp and ClipRegion - // CopyBits() --> pSrcGraphics == NULL, then CopyBits on same Graphics - virtual void copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ); - virtual void drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap ); - virtual void drawBitmap( const SalTwoRect& rPosAry, - const SalBitmap& rSalBitmap, - SalColor nTransparentColor ); - virtual void drawBitmap( const SalTwoRect& rPosAry, - const SalBitmap& rSalBitmap, - const SalBitmap& rTransparentBitmap ); - virtual void drawMask( const SalTwoRect& rPosAry, - const SalBitmap& rSalBitmap, - SalColor nMaskColor ); - - virtual SalBitmap* getBitmap( long nX, long nY, long nWidth, long nHeight ); - virtual SalColor getPixel( long nX, long nY ); - - // invert --> ClipRegion (only Windows or VirDevs) - virtual void invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags); - virtual void invert( sal_uLong nPoints, const SalPoint* pPtAry, SalInvert nFlags ); - - virtual sal_Bool drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uLong nSize ); - - virtual bool drawAlphaBitmap( const SalTwoRect&, - const SalBitmap& rSourceBitmap, - const SalBitmap& rAlphaBitmap ); - - bool drawTransformedBitmap( - const basegfx::B2DPoint& rNull, - const basegfx::B2DPoint& rX, - const basegfx::B2DPoint& rY, - const SalBitmap& rSourceBitmap, - const SalBitmap* pAlphaBitmap); - - virtual bool drawAlphaRect( long nX, long nY, long nWidth, - long nHeight, sal_uInt8 nTransparency ); - - CGPoint* makeCGptArray(sal_uLong nPoints, const SalPoint* pPtAry); - // native widget rendering methods that require mirroring - virtual sal_Bool hitTestNativeControl( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, - const Point& aPos, sal_Bool& rIsInside ); - virtual sal_Bool drawNativeControl( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, - ControlState nState, const ImplControlValue& aValue, - const OUString& aCaption ); - virtual sal_Bool getNativeControlRegion( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, ControlState nState, - const ImplControlValue& aValue, const OUString& aCaption, - Rectangle &rNativeBoundingRegion, Rectangle &rNativeContentRegion ); - - // get device resolution - virtual void GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY ); - // get the depth of the device - virtual sal_uInt16 GetBitCount() const; - // get the width of the device - virtual long GetGraphicsWidth() const; - - // set the clip region to empty - virtual void ResetClipRegion(); - - // set the line color to transparent (= don't draw lines) - virtual void SetLineColor(); - // set the line color to a specific color - virtual void SetLineColor( SalColor nSalColor ); - // set the fill color to transparent (= don't fill) - virtual void SetFillColor(); - // set the fill color to a specific color, shapes will be - // filled accordingly - virtual void SetFillColor( SalColor nSalColor ); - // enable/disable XOR drawing - virtual void SetXORMode( bool bSet, bool bInvertOnly ); - // set line color for raster operations - virtual void SetROPLineColor( SalROPColor nROPColor ); - // set fill color for raster operations - virtual void SetROPFillColor( SalROPColor nROPColor ); - // set the text color to a specific color - virtual void SetTextColor( SalColor nSalColor ); - // set the font - virtual sal_uInt16 SetFont( FontSelectPattern*, int nFallbackLevel ); - // get the current font's metrics - virtual void GetFontMetric( ImplFontMetricData*, int nFallbackLevel ); - // get the repertoire of the current font - virtual const ImplFontCharMap* GetImplFontCharMap() const; - virtual bool GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const; - // graphics must fill supplied font list - virtual void GetDevFontList( ImplDevFontList* ); - // graphics must drop any cached font info - virtual void ClearDevFontCache(); - virtual bool AddTempDevFont( ImplDevFontList*, const OUString& rFileURL, const OUString& rFontName ); - // CreateFontSubset: a method to get a subset of glyhps of a font - // inside a new valid font file - // returns TRUE if creation of subset was successful - // parameters: rToFile: contains a osl file URL to write the subset to - // pFont: describes from which font to create a subset - // pGlyphIDs: the glyph ids to be extracted - // pEncoding: the character code corresponding to each glyph - // pWidths: the advance widths of the correspoding glyphs (in PS font units) - // nGlyphs: the number of glyphs - // rInfo: additional outgoing information - // implementation note: encoding 0 with glyph id 0 should be added implicitly - // as "undefined character" - virtual sal_Bool CreateFontSubset( const OUString& rToFile, - const PhysicalFontFace* pFont, - sal_Int32* pGlyphIDs, - sal_uInt8* pEncoding, - sal_Int32* pWidths, - int nGlyphs, - FontSubsetInfo& rInfo // out parameter - ); - - // GetFontEncodingVector: a method to get the encoding map Unicode - // to font encoded character; this is only used for type1 fonts and - // may return NULL in case of unknown encoding vector - // if ppNonEncoded is set and non encoded characters (that is type1 - // glyphs with only a name) exist it is set to the corresponding - // map for non encoded glyphs; the encoding vector contains -1 - // as encoding for these cases - virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded ); - - // GetEmbedFontData: gets the font data for a font marked - // embeddable by GetDevFontList or NULL in case of error - // parameters: pFont: describes the font in question - // pWidths: the widths of all glyphs from char code 0 to 255 - // pWidths MUST support at least 256 members; - // rInfo: additional outgoing information - // pDataLen: out parameter, contains the byte length of the returned buffer - virtual const void* GetEmbedFontData( const PhysicalFontFace*, - const sal_Ucs* pUnicodes, - sal_Int32* pWidths, - FontSubsetInfo& rInfo, - long* pDataLen ); - // frees the font data again - virtual void FreeEmbedFontData( const void* pData, long nDataLen ); - - virtual void GetGlyphWidths( const PhysicalFontFace*, - bool bVertical, - Int32Vector& rWidths, - Ucs2UIntMap& rUnicodeEnc ); - - virtual sal_Bool GetGlyphBoundRect( sal_GlyphId nIndex, Rectangle& ); - virtual sal_Bool GetGlyphOutline( sal_GlyphId nIndex, basegfx::B2DPolyPolygon& ); - - virtual SalLayout* GetTextLayout( ImplLayoutArgs&, int nFallbackLevel ); - virtual void DrawServerFontLayout( const ServerFontLayout& ); - virtual bool supportsOperation( OutDevSupportType ) const; - - // Query the platform layer for control support - virtual sal_Bool IsNativeControlSupported( ControlType nType, ControlPart nPart ); - - virtual SystemGraphicsData GetGraphicsData() const; - virtual SystemFontData GetSysFontData( int /* nFallbacklevel */ ) const; - -private: - // differences between VCL, Quartz and kHiThemeOrientation coordinate systems - // make some graphics seem to be vertically-mirrored from a VCL perspective - bool IsFlipped() const { return mbWindow; } - - void ApplyXorContext(); - void Pattern50Fill(); - UInt32 getState( ControlState nState ); - UInt32 getTrackState( ControlState nState ); - bool GetRawFontData( const PhysicalFontFace* pFontData, - std::vector& rBuffer, - bool* pJustCFF ); -}; - -// --- some trivial inlines - -#if !defined(__LP64__) && !defined(NS_BUILD_32_LIKE_64) - -inline void AquaSalGraphics::RefreshRect( const CGRect& rRect ) -{ - RefreshRect( rRect.origin.x, rRect.origin.y, rRect.size.width, rRect.size.height ); -} - -#endif - -inline void AquaSalGraphics::RefreshRect( const NSRect& rRect ) -{ - RefreshRect( rRect.origin.x, rRect.origin.y, rRect.size.width, rRect.size.height ); -} - -#endif - -#endif // INCLUDED_VCL_INC_CORETEXT_SALGDI_H - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/headless/svpframe.hxx b/vcl/inc/headless/svpframe.hxx index f5fe6dd55dcd..34bf77b87f0d 100644 --- a/vcl/inc/headless/svpframe.hxx +++ b/vcl/inc/headless/svpframe.hxx @@ -18,6 +18,7 @@ */ #ifndef INCLUDED_VCL_INC_HEADLESS_SVPFRAME_HXX +#define INCLUDED_VCL_INC_HEADLESS_SVPFRAME_HXX #include #include @@ -135,6 +136,7 @@ public: static SvpSalFrame* GetFocusFrame() { return s_pFocusFrame; } }; + #endif // INCLUDED_VCL_INC_HEADLESS_SVPFRAME_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx index fc0e3c5c6e0e..d04f020eeaf5 100644 --- a/vcl/inc/headless/svpgdi.hxx +++ b/vcl/inc/headless/svpgdi.hxx @@ -27,7 +27,7 @@ #include "sallayout.hxx" #ifdef IOS -#include "coretext/salgdi.h" +#include "quartz/salgdi.h" #include #include #include diff --git a/vcl/inc/osx/a11yfactory.h b/vcl/inc/osx/a11yfactory.h new file mode 100644 index 000000000000..c739f3ef6b48 --- /dev/null +++ b/vcl/inc/osx/a11yfactory.h @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_A11YFACTORY_H +#define INCLUDED_VCL_INC_OSX_A11YFACTORY_H + +#include "osxvcltypes.h" +#include "a11ywrapper.h" +#include + +@interface AquaA11yFactory : NSObject +{ +} ++(void)insertIntoWrapperRepository: (NSView *) viewElement forAccessibleContext: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) rxAccessibleContext; ++(AquaA11yWrapper *)wrapperForAccessible: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessible >) rxAccessible; ++(AquaA11yWrapper *)wrapperForAccessibleContext: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) rxAccessibleContext; ++(AquaA11yWrapper *)wrapperForAccessibleContext: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) rxAccessibleContext createIfNotExists:(BOOL) bCreate; ++(AquaA11yWrapper *)wrapperForAccessibleContext: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) rxAccessibleContext createIfNotExists:(BOOL) bCreate asRadioGroup:(BOOL) asRadioGroup; ++(void)removeFromWrapperRepositoryFor: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) rxAccessibleContext; ++(void)registerView: (NSView *) theView; ++(void)revokeView: (NSView *) theViewt; +@end + +#endif // INCLUDED_VCL_INC_OSX_A11YFACTORY_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/a11yfocustracker.hxx b/vcl/inc/osx/a11yfocustracker.hxx new file mode 100644 index 000000000000..22b37d2b64ce --- /dev/null +++ b/vcl/inc/osx/a11yfocustracker.hxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_A11YFOCUSTRACKER_HXX +#define INCLUDED_VCL_INC_OSX_A11YFOCUSTRACKER_HXX + +#include + +#include "keyboardfocuslistener.hxx" + +#include + +#include +#include +#include + +class Window; +class ToolBox; +class DocumentFocusListener; + +// ------------------------ +// - AquaA11yFocusTracker - +// ------------------------ + +class AquaA11yFocusTracker : public rtl::Static< AquaA11yFocusTracker, AquaA11yFocusTracker> +{ + +public: + AquaA11yFocusTracker(); + + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getFocusedObject() { return m_xFocusedObject; }; + + // sets the currently focus object and notifies the FocusEventListener (if any) + void setFocusedObject(const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible); + + // may evolve to add/remove later + void setFocusListener(const rtl::Reference< KeyboardFocusListener >& aFocusListener) { m_aFocusListener = aFocusListener; }; + +protected: + + // received a WINDOW_GETFOCUS event for this window + virtual void window_got_focus(Window *pWindow); + + // received a TOOLBOX_HIGHLIGHT event for this window + virtual void toolbox_highlight_on(Window *pWindow); + + // received a TOOLBOX_HIGHLIGHTOFF event for this window + virtual void toolbox_highlight_off(Window *pWindow); + + // received a TABPAGE_ACTIVATE event for this window + virtual void tabpage_activated(Window *pWindow); + + // received a MENU_HIGHLIGHT event for this window + virtual void menu_highlighted(const ::VclMenuEvent *pEvent); + + // toolbox items are widgets in gtk+ and Cocoa + virtual void notify_toolbox_item_focus(ToolBox *pToolBox); + + // toolbox item opened a floating window (e.g. color chooser) + virtual void toolbox_open_floater(Window *pWindow); + + // callback function for Application::addEventListener + static long WindowEventHandler(AquaA11yFocusTracker *pFocusTracker, ::VclSimpleEvent const *pEvent); + +private: + // the accessible object that has the keyboard focus (if any) + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > m_xFocusedObject; + + // the listener for focus events + rtl::Reference< KeyboardFocusListener > m_aFocusListener; + + // the list of Windows that need deeper (focus) investigation + std::set< Window *> m_aDocumentWindowList; + + // the link object needed for Application::addEventListener + Link m_aWindowEventLink; + + // the UNO XAccessibilityEventListener for Documents and other non VCL objects + const ::com::sun::star::uno::Reference< DocumentFocusListener > m_xDocumentFocusListener; +}; + +#endif // INCLUDED_VCL_INC_OSX_A11YFOCUSTRACKER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/a11ylistener.hxx b/vcl/inc/osx/a11ylistener.hxx new file mode 100644 index 000000000000..8f7176d0766a --- /dev/null +++ b/vcl/inc/osx/a11ylistener.hxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_A11YLISTENER_HXX +#define INCLUDED_VCL_INC_OSX_A11YLISTENER_HXX + +#include +#include + +#include "a11yfocustracker.hxx" +#include "osxvcltypes.h" +#include +#include + +// ------------------------- +// - AquaA11yEventListener - +// ------------------------- + +class AquaA11yEventListener : + public ::cppu::WeakImplHelper1< ::com::sun::star::accessibility::XAccessibleEventListener > +{ + +public: + AquaA11yEventListener(id wrapperObject, sal_Int16 role); + virtual ~AquaA11yEventListener(); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) + throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleEventListener + virtual void SAL_CALL notifyEvent( const ::com::sun::star::accessibility::AccessibleEventObject& aEvent ) + throw( ::com::sun::star::uno::RuntimeException ); + +private: + const id m_wrapperObject; + const sal_Int16 m_role; + ::com::sun::star::awt::Rectangle m_oldBounds; +}; + +#endif // INCLUDED_VCL_INC_OSX_A11YLISTENER_HXX +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/a11ywrapper.h b/vcl/inc/osx/a11ywrapper.h new file mode 100644 index 000000000000..7f291b45ab71 --- /dev/null +++ b/vcl/inc/osx/a11ywrapper.h @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_A11YWRAPPER_H +#define INCLUDED_VCL_INC_OSX_A11YWRAPPER_H + +#include "osxvcltypes.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// rAccessibleXYZ as a field in an Objective-C-Class would not call Con-/Destructor, so use a struct instead +struct ReferenceWrapper +{ + ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleAction > rAccessibleAction; + ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext > rAccessibleContext; + ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleComponent > rAccessibleComponent; + ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleExtendedComponent > rAccessibleExtendedComponent; + ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleSelection > rAccessibleSelection; + ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleTable > rAccessibleTable; + ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleText > rAccessibleText; + ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleEditableText > rAccessibleEditableText; + ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleValue > rAccessibleValue; + ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleTextAttributes > rAccessibleTextAttributes; + ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleMultiLineText > rAccessibleMultiLineText; + ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleTextMarkup > rAccessibleTextMarkup; +}; + +@interface AquaA11yWrapper : NSView +{ + ReferenceWrapper * mpReferenceWrapper; + BOOL mActsAsRadioGroup; + BOOL mIsTableCell; +} +// NSAccessibility Protocol +-(id)accessibilityAttributeValue:(NSString *)attribute; +-(BOOL)accessibilityIsIgnored; +-(NSArray *)accessibilityAttributeNames; +-(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute; +-(NSArray *)accessibilityParameterizedAttributeNames; +-(BOOL)accessibilitySetOverrideValue:(id)value forAttribute:(NSString *)attribute; +-(void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute; +-(id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter; +-(id)accessibilityFocusedUIElement; +-(NSString *)accessibilityActionDescription:(NSString *)action; +-(void)accessibilityPerformAction:(NSString *)action; +-(NSArray *)accessibilityActionNames; +-(id)accessibilityHitTest:(NSPoint)point; +// Attribute values +-(id)parentAttribute; +-(id)valueAttribute; +-(id)titleAttribute; +-(id)helpAttribute; +-(id)numberOfCharactersAttribute; +-(id)selectedTextAttribute; +-(id)selectedTextRangeAttribute; +-(id)visibleCharacterRangeAttribute; +-(id)childrenAttribute; +-(id)orientationAttribute; +-(id)windowAttribute; +// Wrapper-specific +-(void)setActsAsRadioGroup:(BOOL)actsAsRadioGroup; +-(BOOL)actsAsRadioGroup; +-(NSView *)viewElementForParent; +-(id)initWithAccessibleContext: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) anAccessibleContext; +-(void) setDefaults: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) rxAccessibleContext; +-(void) dealloc; ++(void)setPopupMenuOpen:(BOOL)popupMenuOpen; +-(::com::sun::star::accessibility::XAccessibleAction *)accessibleAction; +-(::com::sun::star::accessibility::XAccessibleContext *)accessibleContext; +-(::com::sun::star::accessibility::XAccessibleComponent *)accessibleComponent; +-(::com::sun::star::accessibility::XAccessibleExtendedComponent *)accessibleExtendedComponent; +-(::com::sun::star::accessibility::XAccessibleSelection *)accessibleSelection; +-(::com::sun::star::accessibility::XAccessibleTable *)accessibleTable; +-(::com::sun::star::accessibility::XAccessibleText *)accessibleText; +-(::com::sun::star::accessibility::XAccessibleEditableText *)accessibleEditableText; +-(::com::sun::star::accessibility::XAccessibleValue *)accessibleValue; +-(::com::sun::star::accessibility::XAccessibleTextAttributes *)accessibleTextAttributes; +-(::com::sun::star::accessibility::XAccessibleMultiLineText *)accessibleMultiLineText; +-(::com::sun::star::accessibility::XAccessibleTextMarkup *)accessibleTextMarkup; +@end + +#endif // INCLUDED_VCL_INC_OSX_A11YWRAPPER_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/keyboardfocuslistener.hxx b/vcl/inc/osx/keyboardfocuslistener.hxx new file mode 100644 index 000000000000..3c13f77e5e58 --- /dev/null +++ b/vcl/inc/osx/keyboardfocuslistener.hxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_KEYBOARDFOCUSLISTENER_HXX +#define INCLUDED_VCL_INC_OSX_KEYBOARDFOCUSLISTENER_HXX + +#include + +#include + +// ------------------------- +// - KeyboardFocusListener - +// ------------------------- + +class KeyboardFocusListener : public rtl::IReference +{ +public: + virtual void SAL_CALL focusedObjectChanged(const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible) = 0; +}; + +#endif // INCLUDED_VCL_INC_OSX_KEYBOARDFOCUSLISTENER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/osxvcltypes.h b/vcl/inc/osx/osxvcltypes.h new file mode 100644 index 000000000000..f1659c4fc622 --- /dev/null +++ b/vcl/inc/osx/osxvcltypes.h @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_OSXVCLTYPES_H +#define INCLUDED_VCL_INC_OSX_OSXVCLTYPES_H + +#include "premac.h" +#import +#import +#include "postmac.h" + +#endif // INCLUDED_VCL_INC_OSX_OSXVCLTYPES_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/printview.h b/vcl/inc/osx/printview.h new file mode 100644 index 000000000000..e396bd83775a --- /dev/null +++ b/vcl/inc/osx/printview.h @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_PRINTVIEW_H +#define INCLUDED_VCL_INC_OSX_PRINTVIEW_H + +#include "premac.h" +#include +#include "postmac.h" + +#include "vcl/print.hxx" + +class AquaSalInfoPrinter; + +struct PrintAccessoryViewState +{ + bool bNeedRestart; + sal_Int32 nLastPage; + + PrintAccessoryViewState() + : bNeedRestart( false ), nLastPage( 0 ) {} +}; + +@interface AquaPrintView : NSView +{ + vcl::PrinterController* mpController; + AquaSalInfoPrinter* mpInfoPrinter; +} +-(id)initWithController: (vcl::PrinterController*)pController withInfoPrinter: (AquaSalInfoPrinter*)pInfoPrinter; +-(BOOL)knowsPageRange: (NSRangePointer)range; +-(NSRect)rectForPage: (int)page; +-(NSPoint)locationOfPrintRect: (NSRect)aRect; +-(void)drawRect: (NSRect)rect; +@end + +@interface AquaPrintAccessoryView : NSObject +{ +} ++(NSObject*)setupPrinterPanel: (NSPrintOperation*)pOp withController: (vcl::PrinterController*)pController withState: (PrintAccessoryViewState*)pState; +@end + +#endif // INCLUDED_VCL_INC_OSX_PRINTVIEW_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/saldata.hxx b/vcl/inc/osx/saldata.hxx new file mode 100644 index 000000000000..c9c44bf0fee4 --- /dev/null +++ b/vcl/inc/osx/saldata.hxx @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_SALDATA_HXX +#define INCLUDED_VCL_INC_OSX_SALDATA_HXX + +#include + +#include "premac.h" +#include +#include "postmac.h" + +#include "com/sun/star/uno/Reference.hxx" + +#include "vcl/ptrstyle.hxx" + +#include "svdata.hxx" +#include "salwtype.hxx" + +#include +#include +#include +#include + +#include +#include + +#include "apple_remote/RemoteMainController.h" + +class AquaSalInstance; +class SalObject; +class SalFrame; +class SalVirtualDevice; +class SalPrinter; +class SystemFontList; + +#define SAL_CLIPRECT_COUNT 16 + +class AquaSalFrame; +struct FrameHash : public boost::hash +{ + size_t operator()(const AquaSalFrame* frame) const + { return boost::hash::operator()( reinterpret_cast(frame) ); } +}; + +#define INVALID_CURSOR_PTR (NSCursor*)0xdeadbeef + +class SalData +{ +public: + SALTIMERPROC mpTimerProc; // timer callback proc + AquaSalInstance *mpFirstInstance; // pointer of first instance + std::list maFrames; // list of all frames + boost::unordered_set maFrameCheck; // for fast check of frame existance + std::list maPresentationFrames; // list of frames in presentation mode + SalObject *mpFirstObject; // pointer of first object window + SalVirtualDevice *mpFirstVD; // first VirDev + SalPrinter *mpFirstPrinter; // first printing printer + SystemFontList *mpFontList; + NSStatusItem* mpStatusItem; // one status item that draws all our stati + // at the moment this is only one add menu button + + CGColorSpaceRef mxRGBSpace; + CGColorSpaceRef mxGraySpace; + CGColorSpaceRef mxP50Space; + CGPatternRef mxP50Pattern; + + std::vector< NSCursor* > maCursors; + std::vector< NSMenuItem* > maFallbackMenu; + std::map< NSEvent*, bool > maKeyEventAnswer; + + static oslThreadKey s_aAutoReleaseKey; + + bool mbIsScrollbarDoubleMax; // TODO: support DoubleMin and DoubleBoth too +#if !HAVE_FEATURE_MACOSX_SANDBOX + MainController* mpMainController; // Apple Remote +#endif + NSObject* mpDockIconClickHandler; + long mnDPIX; // #i100617# read DPI only once per office life + long mnDPIY; // #i100617# read DPI only once per office life + + com::sun::star::uno::Reference< com::sun::star::uno::XInterface > + mxClipboard; + + SalData(); + ~SalData(); + + NSCursor* getCursor( PointerStyle i_eStyle ); + + static void ensureThreadAutoreleasePool(); + + static NSStatusItem* getStatusItem(); +}; + +inline void SetSalData( SalData* pData ) { ImplGetSVData()->mpSalData = pData; } +inline SalData *GetSalData() { return ImplGetSVData()->mpSalData; } + +sal_Bool ImplSalYieldMutexTryToAcquire(); +void ImplSalYieldMutexAcquire(); +void ImplSalYieldMutexRelease(); + +#endif // INCLUDED_VCL_INC_OSX_SALDATA_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/salframe.h b/vcl/inc/osx/salframe.h new file mode 100644 index 000000000000..464a54aaf1e9 --- /dev/null +++ b/vcl/inc/osx/salframe.h @@ -0,0 +1,217 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_SALFRAME_H +#define INCLUDED_VCL_INC_OSX_SALFRAME_H + +#include +#include +#include + +#include "vcl/sysdata.hxx" + +#include "osx/salmenu.h" +#include "osx/saldata.hxx" +#include "osx/osxvcltypes.h" + +#include "salframe.hxx" + +#include +#include +#include + +class AquaSalGraphics; +class AquaSalFrame; +class AquaSalTimer; +class AquaSalInstance; +class AquaSalMenu; +class AquaBlinker; + +typedef struct SalFrame::SalPointerState SalPointerState; + +// ---------------- +// - AquaSalFrame - +// ---------------- + +class AquaSalFrame : public SalFrame +{ +public: + NSWindow* mpNSWindow; // Cocoa window + NSView* mpNSView; // Cocoa view (actually a custom view) + NSMenuItem* mpDockMenuEntry; // entry in the dynamic dock menu + NSRect maScreenRect; // for mirroring purposes + AquaSalGraphics* mpGraphics; // current frame graphics + AquaSalFrame* mpParent; // pointer to parent frame + SystemEnvData maSysData; // system data + int mnMinWidth; // min. client width in pixels + int mnMinHeight; // min. client height in pixels + int mnMaxWidth; // max. client width in pixels + int mnMaxHeight; // max. client height in pixels + NSRect maFullScreenRect; // old window size when in FullScreen + bool mbGraphics:1; // is Graphics used? + bool mbFullScreen:1; // is Window in FullScreen? + bool mbShown:1; + bool mbInitShow:1; + bool mbPositioned:1; + bool mbSized:1; + bool mbPresentation:1; + + sal_uLong mnStyle; + unsigned int mnStyleMask; // our style mask from NSWindow creation + + sal_uLong mnLastEventTime; + unsigned int mnLastModifierFlags; + AquaSalMenu* mpMenu; + + SalExtStyle mnExtStyle; // currently document frames are marked this way + + PointerStyle mePointerStyle; // currently active pointer style + + NSTrackingRectTag mnTrackingRectTag; // used to get enter/leave messages + + CGMutablePathRef mrClippingPath; // used for "shaping" + std::vector< CGRect > maClippingRects; + + std::list maBlinkers; + + Rectangle maInvalidRect; + + sal_uLong mnICOptions; + + // To prevent display sleep during presentation + IOPMAssertionID mnAssertionID; + +public: + /** Constructor + + Creates a system window and connects this frame with it. + + @throws std::runtime_error in case window creation fails + */ + AquaSalFrame( SalFrame* pParent, sal_uLong salFrameStyle ); + + virtual ~AquaSalFrame(); + + virtual SalGraphics* GetGraphics(); + virtual void ReleaseGraphics( SalGraphics* pGraphics ); + virtual sal_Bool PostEvent( void* pData ); + virtual void SetTitle( const OUString& rTitle ); + virtual void SetIcon( sal_uInt16 nIcon ); + virtual void SetRepresentedURL( const OUString& ); + virtual void SetMenu( SalMenu* pSalMenu ); + virtual void DrawMenuBar(); + virtual void Show( sal_Bool bVisible, sal_Bool bNoActivate = sal_False ); + virtual void Enable( sal_Bool bEnable ); + virtual void SetMinClientSize( long nWidth, long nHeight ); + virtual void SetMaxClientSize( long nWidth, long nHeight ); + virtual void SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags ); + virtual void GetClientSize( long& rWidth, long& rHeight ); + virtual void GetWorkArea( Rectangle& rRect ); + virtual SalFrame* GetParent() const; + virtual void SetWindowState( const SalFrameState* pState ); + virtual sal_Bool GetWindowState( SalFrameState* pState ); + virtual void ShowFullScreen( sal_Bool bFullScreen, sal_Int32 nDisplay ); + virtual void StartPresentation( sal_Bool bStart ); + virtual void SetAlwaysOnTop( sal_Bool bOnTop ); + virtual void ToTop( sal_uInt16 nFlags ); + virtual void SetPointer( PointerStyle ePointerStyle ); + virtual void CaptureMouse( sal_Bool bMouse ); + virtual void SetPointerPos( long nX, long nY ); + virtual void Flush( void ); + virtual void Flush( const Rectangle& ); + virtual void Sync(); + virtual void SetInputContext( SalInputContext* pContext ); + virtual void EndExtTextInput( sal_uInt16 nFlags ); + virtual OUString GetKeyName( sal_uInt16 nKeyCode ); + virtual sal_Bool MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, KeyCode& rKeyCode ); + virtual LanguageType GetInputLanguage(); + virtual void UpdateSettings( AllSettings& rSettings ); + virtual void Beep(); + virtual const SystemEnvData* GetSystemData() const; + virtual SalPointerState GetPointerState(); + virtual SalIndicatorState GetIndicatorState(); + virtual void SimulateKeyPress( sal_uInt16 nKeyCode ); + virtual void SetParent( SalFrame* pNewParent ); + virtual bool SetPluginParent( SystemParentData* pNewParent ); + virtual void SetExtendedFrameStyle( SalExtStyle ); + virtual void SetScreenNumber(unsigned int); + virtual void SetApplicationID( const OUString &rApplicationID ); + + // shaped system windows + // set clip region to none (-> rectangular windows, normal state) + virtual void ResetClipRegion(); + // start setting the clipregion consisting of nRects rectangles + virtual void BeginSetClipRegion( sal_uLong nRects ); + // add a rectangle to the clip region + virtual void UnionClipRegion( long nX, long nY, long nWidth, long nHeight ); + // done setting up the clipregion + virtual void EndSetClipRegion(); + + virtual void SetClientSize( long nWidth, long nHeight ); + + void UpdateFrameGeometry(); + + // trigger painting of the window + void SendPaintEvent( const Rectangle* pRect = NULL ); + + static bool isAlive( const AquaSalFrame* pFrame ) + { return GetSalData()->maFrameCheck.find( pFrame ) != GetSalData()->maFrameCheck.end(); } + + static AquaSalFrame* GetCaptureFrame() { return s_pCaptureFrame; } + + NSWindow* getNSWindow() const { return mpNSWindow; } + NSView* getNSView() const { return mpNSView; } + unsigned int getStyleMask() const { return mnStyleMask; } + + void getResolution( sal_Int32& o_rDPIX, sal_Int32& o_rDPIY ); + + // actually the follwing methods do the same thing: flipping y coordinates + // but having two of them makes clearer what the coordinate system + // is supposed to be before and after + void VCLToCocoa( NSRect& io_rRect, bool bRelativeToScreen = true ); + void CocoaToVCL( NSRect& io_rRect, bool bRelativeToScreen = true ); + + void VCLToCocoa( NSPoint& io_rPoint, bool bRelativeToScreen = true ); + void CocoaToVCL( NSPoint& io_Point, bool bRelativeToScreen = true ); + + NSCursor* getCurrentCursor() const; + + CGMutablePathRef getClipPath() const { return mrClippingPath; } + + // called by VCL_NSApplication to indicate screen settings have changed + void screenParametersChanged(); + + private: // methods + /** do things on initial show (like centering on parent or on screen) + */ + void initShow(); + + void initWindowAndView(); + + private: // data + static AquaSalFrame* s_pCaptureFrame; + + // make AquaSalFrame non copyable + AquaSalFrame( const AquaSalFrame& ); + AquaSalFrame& operator=(const AquaSalFrame&); +}; + +#endif // INCLUDED_VCL_INC_OSX_SALFRAME_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/salframeview.h b/vcl/inc/osx/salframeview.h new file mode 100644 index 000000000000..3217499b8881 --- /dev/null +++ b/vcl/inc/osx/salframeview.h @@ -0,0 +1,208 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_SALFRAMEVIEW_H +#define INCLUDED_VCL_INC_OSX_SALFRAMEVIEW_H + +#include "osx/a11ywrapper.h" + +@interface SalFrameWindow : NSWindow +{ + AquaSalFrame* mpFrame; + id mDraggingDestinationHandler; +} +-(id)initWithSalFrame: (AquaSalFrame*)pFrame; +-(BOOL)canBecomeKeyWindow; +-(void)displayIfNeeded; +-(void)windowDidBecomeKey: (NSNotification*)pNotification; +-(void)windowDidResignKey: (NSNotification*)pNotification; +-(void)windowDidChangeScreen: (NSNotification*)pNotification; +-(void)windowDidMove: (NSNotification*)pNotification; +-(void)windowDidResize: (NSNotification*)pNotification; +-(void)windowDidMiniaturize: (NSNotification*)pNotification; +-(void)windowDidDeminiaturize: (NSNotification*)pNotification; +-(BOOL)windowShouldClose: (NSNotification*)pNotification; +-(void)dockMenuItemTriggered: (id)sender; +-(AquaSalFrame*)getSalFrame; +-(BOOL)containsMouse; +-(::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >)accessibleContext; + +/* NSDraggingDestination protocol methods + */ +-(NSDragOperation)draggingEntered:(id )sender; +-(NSDragOperation)draggingUpdated:(id )sender; +-(void)draggingExited:(id )sender; +-(BOOL)prepareForDragOperation:(id )sender; +-(BOOL)performDragOperation:(id )sender; +-(void)concludeDragOperation:(id )sender; + +-(void)registerDraggingDestinationHandler:(id)theHandler; +-(void)unregisterDraggingDestinationHandler:(id)theHandler; +@end + +@interface SalFrameView : AquaA11yWrapper +{ + AquaSalFrame* mpFrame; + + // for NSTextInput + NSEvent* mpLastEvent; + BOOL mbNeedSpecialKeyHandle; + BOOL mbInKeyInput; + BOOL mbKeyHandled; + NSRange mMarkedRange; + NSRange mSelectedRange; + id mpMouseEventListener; + id mDraggingDestinationHandler; + NSEvent* mpLastSuperEvent; + + // #i102807# used by magnify event handler + NSTimeInterval mfLastMagnifyTime; + float mfMagnifyDeltaSum; +} ++(void)unsetMouseFrame: (AquaSalFrame*)pFrame; +-(id)initWithSalFrame: (AquaSalFrame*)pFrame; +-(AquaSalFrame*)getSalFrame; +-(BOOL)acceptsFirstResponder; +-(BOOL)acceptsFirstMouse: (NSEvent *)pEvent; +-(BOOL)isOpaque; +-(void)drawRect: (NSRect)aRect; +-(void)mouseDown: (NSEvent*)pEvent; +-(void)mouseDragged: (NSEvent*)pEvent; +-(void)mouseUp: (NSEvent*)pEvent; +-(void)mouseMoved: (NSEvent*)pEvent; +-(void)mouseEntered: (NSEvent*)pEvent; +-(void)mouseExited: (NSEvent*)pEvent; +-(void)rightMouseDown: (NSEvent*)pEvent; +-(void)rightMouseDragged: (NSEvent*)pEvent; +-(void)rightMouseUp: (NSEvent*)pEvent; +-(void)otherMouseDown: (NSEvent*)pEvent; +-(void)otherMouseDragged: (NSEvent*)pEvent; +-(void)otherMouseUp: (NSEvent*)pEvent; +-(void)scrollWheel: (NSEvent*)pEvent; +-(void)magnifyWithEvent: (NSEvent*)pEvent; +-(void)rotateWithEvent: (NSEvent*)pEvent; +-(void)swipeWithEvent: (NSEvent*)pEvent; +-(void)keyDown: (NSEvent*)pEvent; +-(void)flagsChanged: (NSEvent*)pEvent; +-(void)sendMouseEventToFrame:(NSEvent*)pEvent button:(sal_uInt16)nButton eventtype:(sal_uInt16)nEvent; +-(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar; +-(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar modifiers: (unsigned int)nMod; +-(BOOL)sendKeyToFrameDirect: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar modifiers: (unsigned int)nMod; +-(BOOL)sendSingleCharacter:(NSEvent*)pEvent; +-(BOOL)handleKeyDownException:(NSEvent*)pEvent; +-(void)clearLastEvent; +/* + text action methods +*/ +-(void)insertText:(id)aString; +-(void)insertTab: (id)aSender; +-(void)insertBacktab: (id)aSender; +-(void)moveLeft: (id)aSender; +-(void)moveLeftAndModifySelection: (id)aSender; +-(void)moveBackwardAndModifySelection: (id)aSender; +-(void)moveRight: (id)aSender; +-(void)moveRightAndModifySelection: (id)aSender; +-(void)moveForwardAndModifySelection: (id)aSender; +-(void)moveUp: (id)aSender; +-(void)moveDown: (id)aSender; +-(void)moveWordBackward: (id)aSender; +-(void)moveWordBackwardAndModifySelection: (id)aSender; +-(void)moveWordLeftAndModifySelection: (id)aSender; +-(void)moveWordForward: (id)aSender; +-(void)moveWordForwardAndModifySelection: (id)aSender; +-(void)moveWordRightAndModifySelection: (id)aSender; +-(void)moveToEndOfLine: (id)aSender; +-(void)moveToRightEndOfLine: (id)aSender; +-(void)moveToLeftEndOfLine: (id)aSender; +-(void)moveToEndOfLineAndModifySelection: (id)aSender; +-(void)moveToRightEndOfLineAndModifySelection: (id)aSender; +-(void)moveToLeftEndOfLineAndModifySelection: (id)aSender; +-(void)moveToBeginningOfLine: (id)aSender; +-(void)moveToBeginningOfLineAndModifySelection: (id)aSender; +-(void)moveToEndOfParagraph: (id)aSender; +-(void)moveToEndOfParagraphAndModifySelection: (id)aSender; +-(void)moveToBeginningOfParagraph: (id)aSender; +-(void)moveToBeginningOfParagraphAndModifySelection: (id)aSender; +-(void)moveParagraphForward: (id)aSender; +-(void)moveParagraphForwardAndModifySelection: (id)aSender; +-(void)moveParagraphBackward: (id)aSender; +-(void)moveParagraphBackwardAndModifySelection: (id)aSender; +-(void)moveToEndOfDocument: (id)aSender; +-(void)scrollToEndOfDocument: (id)aSender; +-(void)moveToEndOfDocumentAndModifySelection: (id)aSender; +-(void)moveToBeginningOfDocument: (id)aSender; +-(void)scrollToBeginningOfDocument: (id)aSender; +-(void)moveToBeginningOfDocumentAndModifySelection: (id)aSender; +-(void)insertNewline: (id)aSender; +-(void)deleteBackward: (id)aSender; +-(void)deleteForward: (id)aSender; +-(void)cancelOperation: (id)aSender; +-(void)deleteBackwardByDecomposingPreviousCharacter: (id)aSender; +-(void)deleteWordBackward: (id)aSender; +-(void)deleteWordForward: (id)aSender; +-(void)deleteToBeginningOfLine: (id)aSender; +-(void)deleteToEndOfLine: (id)aSender; +-(void)deleteToBeginningOfParagraph: (id)aSender; +-(void)deleteToEndOfParagraph: (id)aSender; +-(void)insertLineBreak: (id)aSender; +-(void)insertParagraphSeparator: (id)aSender; +-(void)selectWord: (id)aSender; +-(void)selectLine: (id)aSender; +-(void)selectParagraph: (id)aSender; +-(void)selectAll: (id)aSender; +-(void)noop: (id)aSender; +/* set the correct pointer for our view */ +-(void)resetCursorRects; +-(::com::sun::star::accessibility::XAccessibleContext *)accessibleContext; +-(id)parentAttribute; +-(NSView *)viewElementForParent; +/* + Event hook for D&D service. + + A drag operation will be invoked on a NSView using + the method 'dragImage'. This method requires the + actual mouse event initiating this drag operation. + Mouse events can only be received by subclassing + NSView and overriding methods like 'mouseDown' etc. + hence we implement a event hook here so that the + D&D service can register as listener for mouse + messages and use the last 'mouseDown' or + 'mouseDragged' message to initiate the drag + operation. +*/ +-(void)registerMouseEventListener: (id)theListener; +-(void)unregisterMouseEventListener: (id)theListener; + +/* NSDraggingDestination protocol methods + */ +-(NSDragOperation)draggingEntered:(id )sender; +-(NSDragOperation)draggingUpdated:(id )sender; +-(void)draggingExited:(id )sender; +-(BOOL)prepareForDragOperation:(id )sender; +-(BOOL)performDragOperation:(id )sender; +-(void)concludeDragOperation:(id )sender; + +-(void)registerDraggingDestinationHandler:(id)theHandler; +-(void)unregisterDraggingDestinationHandler:(id)theHandler; + +@end + +#endif // INCLUDED_VCL_INC_OSX_SALFRAMEVIEW_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h new file mode 100644 index 000000000000..62b7f855a111 --- /dev/null +++ b/vcl/inc/osx/salinst.h @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_SALINST_H +#define INCLUDED_VCL_INC_OSX_SALINST_H + +#include "comphelper/solarmutex.hxx" +#include "osl/thread.hxx" +#include "osl/conditn.h" +#include + +#include "osx/osxvcltypes.h" + +#include "salinst.hxx" + +#include + +class AquaSalFrame; +class ApplicationEvent; +class Image; + +class SalYieldMutex : public vcl::SolarMutexObject +{ + sal_uLong mnCount; + oslThreadIdentifier mnThreadId; + +public: + SalYieldMutex(); + virtual void acquire(); + virtual void release(); + virtual bool tryToAcquire(); + sal_uLong GetAcquireCount() const { return mnCount; } + oslThreadIdentifier GetThreadId() const { return mnThreadId; } +}; + +#define YIELD_GUARD osl::Guard< comphelper::SolarMutex > aGuard( GetSalData()->mpFirstInstance->GetYieldMutex() ) + + +class AquaSalInstance : public SalInstance +{ + struct SalUserEvent + { + AquaSalFrame* mpFrame; + void* mpData; + sal_uInt16 mnType; + + SalUserEvent( AquaSalFrame* pFrame, void* pData, sal_uInt16 nType ) : + mpFrame( pFrame ), mpData( pData ), mnType( nType ) + {} + }; + +public: + SalYieldMutex* mpSalYieldMutex; // Sal-Yield-Mutex + OUString maDefaultPrinter; + oslThreadIdentifier maMainThread; + bool mbWaitingYield; + int mnActivePrintJobs; + std::list< SalUserEvent > maUserEvents; + oslMutex maUserEventListMutex; + oslCondition maWaitingYieldCond; + + typedef std::list AppEventList; + static AppEventList aAppEventList; + +public: + AquaSalInstance(); + virtual ~AquaSalInstance(); + + virtual SalSystem* CreateSystem(); + virtual void DestroySystem(SalSystem*); + virtual SalFrame* CreateChildFrame( SystemParentData* pParent, sal_uLong nStyle ); + virtual SalFrame* CreateFrame( SalFrame* pParent, sal_uLong nStyle ); + virtual void DestroyFrame( SalFrame* pFrame ); + virtual SalObject* CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, sal_Bool bShow = sal_True ); + virtual void DestroyObject( SalObject* pObject ); + virtual SalVirtualDevice* CreateVirtualDevice( SalGraphics* pGraphics, + long nDX, long nDY, + sal_uInt16 nBitCount, const SystemGraphicsData *pData ); + virtual void DestroyVirtualDevice( SalVirtualDevice* pDevice ); + + virtual SalInfoPrinter* CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo, + ImplJobSetup* pSetupData ); + virtual void DestroyInfoPrinter( SalInfoPrinter* pPrinter ); + virtual SalPrinter* CreatePrinter( SalInfoPrinter* pInfoPrinter ); + virtual void DestroyPrinter( SalPrinter* pPrinter ); + virtual void GetPrinterQueueInfo( ImplPrnQueueList* pList ); + virtual void GetPrinterQueueState( SalPrinterQueueInfo* pInfo ); + virtual void DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo ); + virtual OUString GetDefaultPrinter(); + virtual SalTimer* CreateSalTimer(); + virtual SalI18NImeStatus* CreateI18NImeStatus(); + virtual SalSystem* CreateSalSystem(); + virtual SalBitmap* CreateSalBitmap(); + virtual comphelper::SolarMutex* GetYieldMutex(); + virtual sal_uLong ReleaseYieldMutex(); + virtual void AcquireYieldMutex( sal_uLong nCount ); + virtual bool CheckYieldMutex(); + virtual void Yield( bool bWait, bool bHandleAllCurrentEvents ); + virtual bool AnyInput( sal_uInt16 nType ); + virtual SalMenu* CreateMenu( sal_Bool bMenuBar, Menu* pVCLMenu ); + virtual void DestroyMenu( SalMenu* ); + virtual SalMenuItem* CreateMenuItem( const SalItemParams* pItemData ); + virtual void DestroyMenuItem( SalMenuItem* ); + virtual SalSession* CreateSalSession(); + virtual void* GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes ); + virtual void AddToRecentDocumentList(const OUString& rFileUrl, const OUString& rMimeType, const OUString& rDocumentService); + virtual void SetEventCallback( void* pInstance, bool(*pCallback)(void*,void*,int) ); + virtual void SetErrorEventCallback( void* pInstance, bool(*pCallback)(void*,void*,int) ); + + // dtrans implementation + virtual com::sun::star::uno::Reference< com::sun::star::uno::XInterface > + CreateClipboard( const com::sun::star::uno::Sequence< com::sun::star::uno::Any >& i_rArguments ); + virtual com::sun::star::uno::Reference< com::sun::star::uno::XInterface > CreateDragSource(); + virtual com::sun::star::uno::Reference< com::sun::star::uno::XInterface > CreateDropTarget(); + + static void handleAppDefinedEvent( NSEvent* pEvent ); + + // check whether a particular string is passed on the command line + // this is needed to avoid duplicate open events through a) command line and b) NSApp's openFile + static bool isOnCommandLine( const OUString& ); + + void wakeupYield(); + + public: + friend class AquaSalFrame; + + void PostUserEvent( AquaSalFrame* pFrame, sal_uInt16 nType, void* pData ); + void delayedSettingsChanged( bool bInvalidate ); + + bool isNSAppThread() const; + + void startedPrintJob() { mnActivePrintJobs++; } + void endedPrintJob() { mnActivePrintJobs--; } + + // event subtypes for NSApplicationDefined events + static const short AppExecuteSVMain = 0x7fff; + static const short AppEndLoopEvent = 1; + static const short AppStartTimerEvent = 10; + static const short AppleRemoteEvent = 15; + static const short YieldWakeupEvent = 20; + + static NSMenu* GetDynamicDockMenu(); +}; + +// helper class: inverted solar guard +class YieldMutexReleaser +{ + sal_uLong mnCount; + public: + YieldMutexReleaser(); + ~YieldMutexReleaser(); +}; + +CGImageRef CreateCGImage( const Image& ); +NSImage* CreateNSImage( const Image& ); + +#endif // INCLUDED_VCL_INC_OSX_SALINST_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/salmenu.h b/vcl/inc/osx/salmenu.h new file mode 100644 index 000000000000..925a339f7fa5 --- /dev/null +++ b/vcl/inc/osx/salmenu.h @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_SALMENU_H +#define INCLUDED_VCL_INC_OSX_SALMENU_H + +#include "premac.h" +#include +#include "postmac.h" + +#include "salmenu.hxx" + +#include + +class AquaSalFrame; +class AquaSalMenuItem; + +class AquaSalMenu : public SalMenu +{ + std::vector< AquaSalMenuItem* > maItems; + +public: // for OOStatusView + struct MenuBarButtonEntry + { + SalMenuButtonItem maButton; + NSImage* mpNSImage; // cached image + NSString* mpToolTipString; + + MenuBarButtonEntry() : mpNSImage( nil ), mpToolTipString( nil ) {} + MenuBarButtonEntry( const SalMenuButtonItem& i_rItem ) + : maButton( i_rItem), mpNSImage( nil ), mpToolTipString( nil ) {} + }; +private: + std::vector< MenuBarButtonEntry > maButtons; + + MenuBarButtonEntry* findButtonItem( sal_uInt16 i_nItemId ); + void releaseButtonEntry( MenuBarButtonEntry& i_rEntry ); + static void statusLayout(); +public: + AquaSalMenu( bool bMenuBar ); + virtual ~AquaSalMenu(); + + virtual sal_Bool VisibleMenuBar(); // must return TRUE to actually DISPLAY native menu bars + // otherwise only menu messages are processed (eg, OLE on Windows) + + virtual void InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos ); + virtual void RemoveItem( unsigned nPos ); + virtual void SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos ); + virtual void SetFrame( const SalFrame* pFrame ); + virtual void CheckItem( unsigned nPos, sal_Bool bCheck ); + virtual void EnableItem( unsigned nPos, sal_Bool bEnable ); + virtual void SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const OUString& rText ); + virtual void SetItemImage( unsigned nPos, SalMenuItem* pSalMenuItem, const Image& rImage); + virtual void SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const KeyCode& rKeyCode, const OUString& rKeyName ); + virtual void GetSystemMenuData( SystemMenuData* pData ); + virtual bool ShowNativePopupMenu(FloatingWindow * pWin, const Rectangle& rRect, sal_uLong nFlags); + virtual bool AddMenuBarButton( const SalMenuButtonItem& ); + virtual void RemoveMenuBarButton( sal_uInt16 nId ); + virtual Rectangle GetMenuBarButtonRectPixel( sal_uInt16 i_nItemId, SalFrame* i_pReferenceFrame ); + + int getItemIndexByPos( sal_uInt16 nPos ) const; + const AquaSalFrame* getFrame() const; + + void setMainMenu(); + static void unsetMainMenu(); + static void setDefaultMenu(); + static void enableMainMenu( bool bEnable ); + static void addFallbackMenuItem( NSMenuItem* NewItem ); + static void removeFallbackMenuItem( NSMenuItem* pOldItem ); + + const std::vector< MenuBarButtonEntry >& getButtons() const { return maButtons; } + + bool mbMenuBar; // true - Menubar, false - Menu + NSMenu* mpMenu; // The Carbon reference to this menu + Menu* mpVCLMenu; // the corresponding vcl Menu object + const AquaSalFrame* mpFrame; // the frame to dispatch the menu events to + AquaSalMenu* mpParentSalMenu; // the parent menu that contains us (and perhaps has a frame) + + static const AquaSalMenu* pCurrentMenuBar; + +}; + +class AquaSalMenuItem : public SalMenuItem +{ +public: + AquaSalMenuItem( const SalItemParams* ); + virtual ~AquaSalMenuItem(); + + sal_uInt16 mnId; // Item ID + Menu* mpVCLMenu; // VCL Menu into which this MenuItem is inserted + AquaSalMenu* mpParentMenu; // The menu in which this menu item is inserted + AquaSalMenu* mpSubMenu; // Sub menu of this item (if defined) + NSMenuItem* mpMenuItem; // The NSMenuItem +}; + +#endif // INCLUDED_VCL_INC_OSX_SALMENU_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/salnativewidgets.h b/vcl/inc/osx/salnativewidgets.h new file mode 100644 index 000000000000..2a987627e82a --- /dev/null +++ b/vcl/inc/osx/salnativewidgets.h @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_SALNATIVEWIDGETS_H +#define INCLUDED_VCL_INC_OSX_SALNATIVEWIDGETS_H + +// since 10.4 ... no metrics are returned, and we have to fix the values +#define BUTTON_WIDTH 16 +#define BUTTON_HEIGHT 17 + +//standard height of the AHIG +//tabs +#define TAB_HEIGHT_NORMAL 20 +#define TAB_HEIGHT_SMALL 17 +#define TAB_HEIGHT_MINI 15 + +#define TAB_TEXT_OFFSET 12 +#define VCL_TAB_TEXT_OFFSET 2 + +//listboxes, comboboxes (they have the same dimensions) +#define COMBOBOX_HEIGHT_NORMAL 20 +#define DROPDOWN_BUTTON_WIDTH 20 + +//text edit +#define TEXT_EDIT_HEIGHT_NORMAL 22 + +//spin box +#define SPIN_BUTTON_SPACE 2 +#define SPIN_BUTTON_WIDTH 13 +#define SPIN_UPPER_BUTTON_HEIGHT 11 +#define SPIN_LOWER_BUTTON_HEIGHT 10 + +// progress bar +#define INTRO_PROGRESS_HEIGHT 9 + +// for some controls, like spinbuttons + spinboxes, or listboxes +// we need it to adjust text position beside radio and check buttons + +#define TEXT_SEPARATOR 3 + +// extra border for focus ring +#define FOCUS_RING_WIDTH 4 + +#define CLIP_FUZZ 1 + +#endif // INCLUDED_VCL_INC_OSX_SALNATIVEWIDGETS_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/salnsmenu.h b/vcl/inc/osx/salnsmenu.h new file mode 100644 index 000000000000..47c410b6a35e --- /dev/null +++ b/vcl/inc/osx/salnsmenu.h @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_SALNSMENU_H +#define INCLUDED_VCL_INC_OSX_SALNSMENU_H + +class AquaSalMenu; +class AquaSalMenuItem; + +@interface OOStatusItemView : NSView +{ +} +-(void)drawRect: (NSRect)aRect; +-(void)layout; +-(void)mouseUp: (NSEvent *)pEvent; +@end + +@interface SalNSMenu : NSMenu +{ + /* Caution: SalNSMenu instances occasionally are binary copied + in AquaSalMenu::ShowNativePopupMenu. If any members are added, + please take this into account ! + */ + AquaSalMenu* mpMenu; +} +-(id)initWithMenu: (AquaSalMenu*)pMenu; +-(void)menuNeedsUpdate: (NSMenu*)pMenu; +-(void)setSalMenu: (AquaSalMenu*)pMenu; +@end + +@interface SalNSMenuItem : NSMenuItem +{ + /* Caution: SalNSMenuItem instances occasionally are binary copied + in AquaSalMenu::ShowNativePopupMenu. If any members are added, + please take this into account ! + */ + AquaSalMenuItem* mpMenuItem; +} +-(id)initWithMenuItem: (AquaSalMenuItem*)pMenuItem; +-(void)menuItemTriggered: (id)aSender; +@end + +#endif // INCLUDED_VCL_INC_OSX_SALNSMENU_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/salnstimer.h b/vcl/inc/osx/salnstimer.h new file mode 100644 index 000000000000..cce2746c1535 --- /dev/null +++ b/vcl/inc/osx/salnstimer.h @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_SALNSTIMER_H +#define INCLUDED_VCL_INC_OSX_SALNSTIMER_H + +#include "premac.h" +#include "Cocoa/Cocoa.h" +#include "postmac.h" + +@interface TimerCallbackCaller : NSObject +{ +} +-(void)timerElapsed:(NSTimer*)pTimer; +@end + +#endif // INCLUDED_VCL_INC_OSX_SALNSTIMER_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/salobj.h b/vcl/inc/osx/salobj.h new file mode 100644 index 000000000000..397299c15c9d --- /dev/null +++ b/vcl/inc/osx/salobj.h @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_SALOBJ_H +#define INCLUDED_VCL_INC_OSX_SALOBJ_H + +#include "vcl/sysdata.hxx" +#include "salobj.hxx" + +class AquaSalFrame; +class AquaSalObject; + + +// ----------------- +// - SalObjectData - +// ----------------- + +struct SalObjectData +{ +}; + +class AquaSalObject : public SalObject +{ +public: + AquaSalFrame* mpFrame; // parent frame + NSClipView* mpClipView; + SystemEnvData maSysData; + + long mnClipX; + long mnClipY; + long mnClipWidth; + long mnClipHeight; + bool mbClip; + + long mnX; + long mnY; + long mnWidth; + long mnHeight; + + + void setClippedPosSize(); + + + AquaSalObject( AquaSalFrame* pFrame ); + virtual ~AquaSalObject(); + + virtual void ResetClipRegion(); + virtual sal_uInt16 GetClipRegionType(); + virtual void BeginSetClipRegion( sal_uLong nRects ); + virtual void UnionClipRegion( long nX, long nY, long nWidth, long nHeight ); + virtual void EndSetClipRegion(); + virtual void SetPosSize( long nX, long nY, long nWidth, long nHeight ); + virtual void Show( sal_Bool bVisible ); + virtual const SystemEnvData* GetSystemData() const; +}; + +#endif // INCLUDED_VCL_INC_OSX_SALOBJ_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/salprn.h b/vcl/inc/osx/salprn.h new file mode 100644 index 000000000000..906a61dcdfc1 --- /dev/null +++ b/vcl/inc/osx/salprn.h @@ -0,0 +1,165 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_SALPRN_H +#define INCLUDED_VCL_INC_OSX_SALPRN_H + +#include "osx/osxvcltypes.h" + +#include "salprn.hxx" + +#include + + +// --------------------- +// - AquaSalInfoPrinter - +// --------------------- + +class AquaSalGraphics; + +class AquaSalInfoPrinter : public SalInfoPrinter +{ + /// Printer graphics + AquaSalGraphics* mpGraphics; + /// is Graphics used + bool mbGraphics; + /// job active ? + bool mbJob; + + /// cocoa printer object + NSPrinter* mpPrinter; + /// cocoa print info object + NSPrintInfo* mpPrintInfo; + + /// FIXME: get real printer context for infoprinter if possible + /// fake context for info printer + /// graphics context for Quartz 2D + CGContextRef mrContext; + /// memory for graphics bitmap context for querying metrics + boost::shared_array< sal_uInt8 > maContextMemory; + + // since changes to NSPrintInfo during a job are ignored + // we have to care for some settings ourselves + // currently we do this for orientation; + // really needed however is a solution for paper formats + Orientation mePageOrientation; + + int mnStartPageOffsetX; + int mnStartPageOffsetY; + sal_Int32 mnCurPageRangeStart; + sal_Int32 mnCurPageRangeCount; + + public: + AquaSalInfoPrinter( const SalPrinterQueueInfo& pInfo ); + virtual ~AquaSalInfoPrinter(); + + void SetupPrinterGraphics( CGContextRef i_xContext ) const; + + virtual SalGraphics* GetGraphics(); + virtual void ReleaseGraphics( SalGraphics* i_pGraphics ); + virtual sal_Bool Setup( SalFrame* i_pFrame, ImplJobSetup* i_pSetupData ); + virtual sal_Bool SetPrinterData( ImplJobSetup* pSetupData ); + virtual sal_Bool SetData( sal_uLong i_nFlags, ImplJobSetup* i_pSetupData ); + virtual void GetPageInfo( const ImplJobSetup* i_pSetupData, + long& o_rOutWidth, long& o_rOutHeight, + long& o_rPageOffX, long& o_rPageOffY, + long& o_rPageWidth, long& o_rPageHeight ); + virtual sal_uLong GetCapabilities( const ImplJobSetup* i_pSetupData, sal_uInt16 i_nType ); + virtual sal_uLong GetPaperBinCount( const ImplJobSetup* i_pSetupData ); + virtual OUString GetPaperBinName( const ImplJobSetup* i_pSetupData, sal_uLong i_nPaperBin ); + virtual void InitPaperFormats( const ImplJobSetup* i_pSetupData ); + virtual int GetLandscapeAngle( const ImplJobSetup* i_pSetupData ); + + // the artificial separation between InfoPrinter and Printer + // is not really useful for us + // so let's make AquaSalPrinter just a forwarder to AquaSalInfoPrinter + // and concentrate the real work in one class + // implement pull model print system + sal_Bool StartJob( const OUString* i_pFileName, + const OUString& rJobName, + const OUString& i_rAppName, + ImplJobSetup* i_pSetupData, + vcl::PrinterController& i_rController ); + sal_Bool EndJob(); + sal_Bool AbortJob(); + SalGraphics* StartPage( ImplJobSetup* i_pSetupData, sal_Bool i_bNewJobData ); + sal_Bool EndPage(); + sal_uLong GetErrorCode() const; + + NSPrintInfo* getPrintInfo() const { return mpPrintInfo; } + void setStartPageOffset( int nOffsetX, int nOffsetY ) { mnStartPageOffsetX = nOffsetX; mnStartPageOffsetY = nOffsetY; } + sal_Int32 getCurPageRangeStart() const { return mnCurPageRangeStart; } + sal_Int32 getCurPageRangeCount() const { return mnCurPageRangeCount; } + + // match width/height against known paper formats, possibly switching orientation + const PaperInfo* matchPaper( long i_nWidth, long i_nHeight, Orientation& o_rOrientation ) const; + void setPaperSize( long i_nWidth, long i_nHeight, Orientation i_eSetOrientation ); + + private: + AquaSalInfoPrinter( const AquaSalInfoPrinter& ); + AquaSalInfoPrinter& operator=(const AquaSalInfoPrinter&); +}; + +// ----------------- +// - AquaSalPrinter - +// ----------------- + +class AquaSalPrinter : public SalPrinter +{ + AquaSalInfoPrinter* mpInfoPrinter; // pointer to the compatible InfoPrinter + public: + AquaSalPrinter( AquaSalInfoPrinter* i_pInfoPrinter ); + virtual ~AquaSalPrinter(); + + virtual sal_Bool StartJob( const OUString* i_pFileName, + const OUString& i_rJobName, + const OUString& i_rAppName, + sal_uLong i_nCopies, + bool i_bCollate, + bool i_bDirect, + ImplJobSetup* i_pSetupData ); + // implement pull model print system + virtual sal_Bool StartJob( const OUString* i_pFileName, + const OUString& rJobName, + const OUString& i_rAppName, + ImplJobSetup* i_pSetupData, + vcl::PrinterController& i_rListener ); + + virtual sal_Bool EndJob(); + virtual sal_Bool AbortJob(); + virtual SalGraphics* StartPage( ImplJobSetup* i_pSetupData, sal_Bool i_bNewJobData ); + virtual sal_Bool EndPage(); + virtual sal_uLong GetErrorCode(); + + private: + AquaSalPrinter( const AquaSalPrinter& ); + AquaSalPrinter& operator=(const AquaSalPrinter&); +}; + +const double fPtTo100thMM = 35.27777778; + +inline int PtTo10Mu( double nPoints ) { return (int)(((nPoints)*fPtTo100thMM)+0.5); } + +inline double TenMuToPt( double nUnits ) { return floor(((nUnits)/fPtTo100thMM)+0.5); } + + + +#endif // INCLUDED_VCL_INC_OSX_SALPRN_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/salsys.h b/vcl/inc/osx/salsys.h new file mode 100644 index 000000000000..816cffc47ae9 --- /dev/null +++ b/vcl/inc/osx/salsys.h @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_SALSYS_H +#define INCLUDED_VCL_INC_OSX_SALSYS_H + +#include "salsys.hxx" + +#include + +// ----------------- +// - SalSystemData - +// ----------------- + +class VCL_DLLPUBLIC AquaSalSystem : public SalSystem +{ +public: + AquaSalSystem() {} + virtual ~AquaSalSystem(); + + // get info about the display + virtual unsigned int GetDisplayScreenCount(); + virtual Rectangle GetDisplayScreenPosSizePixel( unsigned int nScreen ); + + virtual OUString GetDisplayScreenName( unsigned int nScreen ); + virtual int ShowNativeMessageBox( const OUString& rTitle, + const OUString& rMessage, + int nButtonCombination, + int nDefaultButton, bool bUseResources); +}; + + +#endif // INCLUDED_VCL_INC_OSX_SALSYS_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/saltimer.h b/vcl/inc/osx/saltimer.h new file mode 100644 index 000000000000..993a2efe0c57 --- /dev/null +++ b/vcl/inc/osx/saltimer.h @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_SALTIMER_H +#define INCLUDED_VCL_INC_OSX_SALTIMER_H + +#include "premac.h" +#include +#include "postmac.h" + +#include "saltimer.hxx" + +class AquaSalTimer : public SalTimer +{ + public: + + AquaSalTimer(); + virtual ~AquaSalTimer(); + + void Start( sal_uLong nMS ); + void Stop(); + + static void handleStartTimerEvent( NSEvent* pEvent ); + + + static NSTimer* pRunningTimer; + static bool bDispatchTimer; +}; + +#endif // INCLUDED_VCL_INC_OSX_SALTIMER_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/salvd.h b/vcl/inc/osx/salvd.h new file mode 100644 index 000000000000..1c32ad412379 --- /dev/null +++ b/vcl/inc/osx/salvd.h @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_SALVD_H +#define INCLUDED_VCL_INC_OSX_SALVD_H + +#include "premac.h" +#include +#include "postmac.h" + +#include "quartz/salgdi.h" + +#include "salvd.hxx" + +#if PRAGMA_ONCE + #pragma once +#endif + +// ======================================================================= + +// ======================================================================= + +// ----------------- +// - SalVirDevData - +// ----------------- + +struct SalVirDevData +{ +}; + +typedef struct SalVirDevData SalVirDevData; +typedef SalVirDevData *SalVirDevDataPtr; +typedef SalVirDevDataPtr *SalVirDevDataHandle; + +// ======================================================================= + +class AquaSalGraphics; + +// ----------------- +// - SalVirDevData - +// ----------------- + +class AquaSalVirtualDevice : public SalVirtualDevice +{ +private: + bool mbGraphicsUsed; // is Graphics used + bool mbForeignContext; // is mxContext from outside VCL + CGContextRef mxBitmapContext; + int mnBitmapDepth; + CGLayerRef mxLayer; // Quartz layer + AquaSalGraphics* mpGraphics; // current VirDev graphics + + void Destroy(); + +public: + AquaSalVirtualDevice( AquaSalGraphics* pGraphic, long nDX, long nDY, sal_uInt16 nBitCount, const SystemGraphicsData *pData ); + virtual ~AquaSalVirtualDevice(); + + virtual SalGraphics* GetGraphics(); + virtual void ReleaseGraphics( SalGraphics* pGraphics ); + virtual sal_Bool SetSize( long nNewDX, long nNewDY ); + virtual void GetSize( long& rWidth, long& rHeight ); +}; + +// ======================================================================= + +#endif // INCLUDED_VCL_INC_OSX_SALVD_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/svsys.h b/vcl/inc/osx/svsys.h new file mode 100644 index 000000000000..7c5451c33f2b --- /dev/null +++ b/vcl/inc/osx/svsys.h @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_SVSYS_H +#define INCLUDED_VCL_INC_OSX_SVSYS_H + +#include "premac.h" +#include "Cocoa/Cocoa.h" +#include "postmac.h" + +#endif // INCLUDED_VCL_INC_OSX_SVSYS_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/osx/vclnsapp.h b/vcl/inc/osx/vclnsapp.h new file mode 100644 index 000000000000..38ad251e8bf2 --- /dev/null +++ b/vcl/inc/osx/vclnsapp.h @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OSX_VCLNSAPP_H +#define INCLUDED_VCL_INC_OSX_VCLNSAPP_H + +#include + +#include "premac.h" +#include "Cocoa/Cocoa.h" +#include "postmac.h" + +class AquaSalFrame; + +@interface CocoaThreadEnabler : NSObject +{ +} +-(void)enableCocoaThreads:(id)param; +@end + +// our very own application +@interface VCL_NSApplication : NSApplication +{ +} +-(void)sendEvent:(NSEvent*)pEvent; +-(void)sendSuperEvent:(NSEvent*)pEvent; +-(NSMenu*)applicationDockMenu:(NSApplication *)sender; +-(BOOL)application: (NSApplication*) app openFile: (NSString*)file; +-(void)application: (NSApplication*) app openFiles: (NSArray*)files; +-(BOOL)application: (NSApplication*) app printFile: (NSString*)file; +-(NSApplicationPrintReply)application: (NSApplication *) app printFiles:(NSArray *)files withSettings: (NSDictionary *)printSettings showPrintPanels:(BOOL)bShowPrintPanels; +-(NSApplicationTerminateReply)applicationShouldTerminate: (NSApplication *) app; +-(void)systemColorsChanged: (NSNotification*) pNotification; +-(void)screenParametersChanged: (NSNotification*) pNotification; +-(void)scrollbarVariantChanged: (NSNotification*) pNotification; +-(void)scrollbarSettingsChanged: (NSNotification*) pNotification; +-(void)addFallbackMenuItem: (NSMenuItem*)pNewItem; +-(void)removeFallbackMenuItem: (NSMenuItem*)pOldItem; +-(void)addDockMenuItem: (NSMenuItem*)pNewItem; +#if !HAVE_FEATURE_MACOSX_SANDBOX +-(void)applicationWillBecomeActive: (NSNotification *)pNotification; +-(void)applicationWillResignActive: (NSNotification *)pNotification; +#endif +-(BOOL)applicationShouldHandleReopen: (NSApplication*)pApp hasVisibleWindows: (BOOL)bWinVisible; +-(void)setDockIconClickHandler: (NSObject*)pHandler; +-(void)cycleFrameForward: (AquaSalFrame*)pCurFrame; +-(void)cycleFrameBackward: (AquaSalFrame*)pCurFrame; +@end + +#endif // INCLUDED_VCL_INC_OSX_VCLNSAPP_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/quartz/common.h b/vcl/inc/quartz/common.h new file mode 100644 index 000000000000..2d9b717b5dc6 --- /dev/null +++ b/vcl/inc/quartz/common.h @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_QUARTZ_COMMON_H +#define INCLUDED_VCL_INC_QUARTZ_COMMON_H + +#include + +#include +#ifdef MACOSX +#include +#else +#include +#include +#endif +#include + +#include + +#include + +// CoreFoundation designers, in their wisdom, decided that CFRelease of NULL +// cause a Crash, yet few API can return NULL when asking for the creation +// of an object, which force us to peper the code with egly if construct everywhere +// and open the door to very nasty crash on rare occasion +// this macro hide the mess +#define SafeCFRelease(a) do { if(a) { CFRelease(a); (a)=NULL; } } while(false) + +#define round_to_long(a) ((a) >= 0 ? ((long)((a) + 0.5)) : ((long)((a) - 0.5))) + +#include "vcl/salgtype.hxx" + +std::ostream &operator <<(std::ostream& s, CTFontRef pFont); + +#endif // INCLUDED_VCL_INC_QUARTZ_COMMON_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/quartz/salbmp.h b/vcl/inc/quartz/salbmp.h index f7d8d634c0f2..a645999bbbcd 100644 --- a/vcl/inc/quartz/salbmp.h +++ b/vcl/inc/quartz/salbmp.h @@ -27,7 +27,7 @@ #include "vcl/salbtype.hxx" #ifdef MACOSX -#include "coretext/salgdi.h" +#include "quartz/salgdi.h" #else #include "headless/svpgdi.hxx" #endif diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h new file mode 100644 index 000000000000..49140faf5451 --- /dev/null +++ b/vcl/inc/quartz/salgdi.h @@ -0,0 +1,433 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_QUARTZ_SALGDI_H +#define INCLUDED_VCL_INC_QUARTZ_SALGDI_H + +#include + +#include "basegfx/polygon/b2dpolypolygon.hxx" + +#include "premac.h" +#ifdef MACOSX +#include +#include "osx/osxvcltypes.h" +#include "osx/salframe.h" +#else +#include +#include +#endif +#include "postmac.h" + +#include + +#include "outfont.hxx" +#include "salgdi.hxx" + +#include "quartz/salgdicommon.hxx" + +class AquaSalFrame; +class ImplDevFontAttributes; +class CoreTextStyle; + +typedef sal_uInt32 sal_GlyphId; +typedef std::vector ByteVector; + +// CoreText-specific physically available font face +class CoreTextFontData : public PhysicalFontFace +{ +public: + CoreTextFontData( const ImplDevFontAttributes&, sal_IntPtr nFontID ); + + ~CoreTextFontData(); + + PhysicalFontFace* Clone() const; + ImplFontEntry* CreateFontInstance( FontSelectPattern& ) const; + sal_IntPtr GetFontId() const; + + CoreTextStyle* CreateTextStyle( const FontSelectPattern& ) const; + int GetFontTable( const char pTagName[5], unsigned char* ) const; + + const ImplFontCharMap* GetImplFontCharMap() const; + bool GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const; + bool HasChar( sal_uInt32 cChar ) const; + + void ReadOs2Table() const; + void ReadMacCmapEncoding() const; + +protected: + CoreTextFontData( const CoreTextFontData&); + +private: + const sal_IntPtr mnFontId; + mutable const ImplFontCharMap* mpCharMap; + mutable vcl::FontCapabilities maFontCapabilities; + mutable bool mbOs2Read; // true if OS2-table related info is valid + mutable bool mbHasOs2Table; + mutable bool mbCmapEncodingRead; // true if cmap encoding of Mac font is read + mutable bool mbFontCapabilitiesRead; +}; + +class CoreTextStyle +{ +public: + CoreTextStyle( const FontSelectPattern& ); + ~CoreTextStyle( void ); + + SalLayout* GetTextLayout( void ) const; + + void GetFontMetric( float fPDIY, ImplFontMetricData& ) const; + bool GetGlyphBoundRect( sal_GlyphId, Rectangle& ) const; + bool GetGlyphOutline( sal_GlyphId, basegfx::B2DPolyPolygon& ) const; + + void SetTextColor( const RGBAColor& ); + + const CoreTextFontData* mpFontData; + /// <1.0: font is squeezed, >1.0 font is stretched, else 1.0 + float mfFontStretch; + /// text rotation in radian + float mfFontRotation; + +private: + /// CoreText text style object + CFMutableDictionaryRef mpStyleDict; + + friend class CTLayout; + CFMutableDictionaryRef GetStyleDict( void ) const { return mpStyleDict; } +}; + +// ------------------ +// - SystemFontList - +// TODO: move into cross-platform headers +// ------------------ +class SystemFontList +{ +public: + SystemFontList( void ); + ~SystemFontList( void ); + + bool Init( void ); + void AddFont( CoreTextFontData* ); + + void AnnounceFonts( ImplDevFontList& ) const; + CoreTextFontData* GetFontDataFromId( sal_IntPtr nFontId ) const; + +private: + CTFontCollectionRef mpCTFontCollection; + CFArrayRef mpCTFontArray; + + typedef boost::unordered_map CTFontContainer; + CTFontContainer maFontContainer; +}; + +#ifdef MACOSX + +// ------------------- +// - AquaSalGraphics - +// ------------------- +class AquaSalGraphics : public SalGraphics +{ + friend class CTLayout; +protected: + AquaSalFrame* mpFrame; + CGLayerRef mxLayer; // Quartz graphics layer + CGContextRef mrContext; // Quartz drawing context + class XorEmulation* mpXorEmulation; + int mnXorMode; // 0: off 1: on 2: invert only + int mnWidth; + int mnHeight; + int mnBitmapDepth; // zero unless bitmap + /// device resolution of this graphics + long mnRealDPIX; + long mnRealDPIY; + /// some graphics implementations (e.g. AquaSalInfoPrinter) scale + /// everything down by a factor (see SetupPrinterGraphics for details) + /// so we have to compensate for it with the inverse factor + double mfFakeDPIScale; + + /// path representing current clip region + CGMutablePathRef mxClipPath; + + /// Drawing colors + /// pen color RGBA + RGBAColor maLineColor; + /// brush color RGBA + RGBAColor maFillColor; + + // Device Font settings + const CoreTextFontData* mpFontData; + CoreTextStyle* mpTextStyle; + RGBAColor maTextColor; + /// allows text to be rendered without antialiasing + bool mbNonAntialiasedText; + + // Graphics types + + /// is this a printer graphics + bool mbPrinter; + /// is this a virtual device graphics + bool mbVirDev; + /// is this a window graphics + bool mbWindow; + +public: + AquaSalGraphics(); + virtual ~AquaSalGraphics(); + + bool IsPenVisible() const { return maLineColor.IsVisible(); } + bool IsBrushVisible() const { return maFillColor.IsVisible(); } + + void SetWindowGraphics( AquaSalFrame* pFrame ); + void SetPrinterGraphics( CGContextRef, long nRealDPIX, long nRealDPIY, double fFakeScale ); + void SetVirDevGraphics( CGLayerRef, CGContextRef, int nBitDepth = 0 ); + + void initResolution( NSWindow* ); + void copyResolution( AquaSalGraphics& ); + void updateResolution(); + + bool IsWindowGraphics() const { return mbWindow; } + AquaSalFrame* getGraphicsFrame() const { return mpFrame; } + void setGraphicsFrame( AquaSalFrame* pFrame ) { mpFrame = pFrame; } + + void ImplDrawPixel( long nX, long nY, const RGBAColor& ); // helper to draw single pixels + + bool CheckContext(); + CGContextRef GetContext(); + void UpdateWindow( NSRect& ); // delivered in NSView coordinates +#if !defined(__LP64__) && !defined(NS_BUILD_32_LIKE_64) + void RefreshRect( const CGRect& ); +#endif + void RefreshRect( const NSRect& ); + void RefreshRect(float lX, float lY, float lWidth, float lHeight); + + void SetState(); + void UnsetState(); + // InvalidateContext does an UnsetState and sets mrContext to 0 + void InvalidateContext(); + + virtual bool setClipRegion( const Region& ); + + // draw --> LineColor and FillColor and RasterOp and ClipRegion + virtual void drawPixel( long nX, long nY ); + virtual void drawPixel( long nX, long nY, SalColor nSalColor ); + virtual void drawLine( long nX1, long nY1, long nX2, long nY2 ); + virtual void drawRect( long nX, long nY, long nWidth, long nHeight ); + virtual void drawPolyLine( sal_uLong nPoints, const SalPoint* pPtAry ); + virtual void drawPolygon( sal_uLong nPoints, const SalPoint* pPtAry ); + virtual void drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry ); + virtual bool drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double fTransparency ); + virtual sal_Bool drawPolyLineBezier( sal_uLong nPoints, const SalPoint* pPtAry, const sal_uInt8* pFlgAry ); + virtual sal_Bool drawPolygonBezier( sal_uLong nPoints, const SalPoint* pPtAry, const sal_uInt8* pFlgAry ); + virtual sal_Bool drawPolyPolygonBezier( sal_uInt32 nPoly, const sal_uInt32* pPoints, const SalPoint* const* pPtAry, const sal_uInt8* const* pFlgAry ); + virtual bool drawPolyLine( + const ::basegfx::B2DPolygon&, + double fTransparency, + const ::basegfx::B2DVector& rLineWidths, + basegfx::B2DLineJoin, + com::sun::star::drawing::LineCap eLineCap); + + // CopyArea --> No RasterOp, but ClipRegion + virtual void copyArea( long nDestX, long nDestY, long nSrcX, long nSrcY, long nSrcWidth, + long nSrcHeight, sal_uInt16 nFlags ); + + // CopyBits and DrawBitmap --> RasterOp and ClipRegion + // CopyBits() --> pSrcGraphics == NULL, then CopyBits on same Graphics + virtual void copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ); + virtual void drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap ); + virtual void drawBitmap( const SalTwoRect& rPosAry, + const SalBitmap& rSalBitmap, + SalColor nTransparentColor ); + virtual void drawBitmap( const SalTwoRect& rPosAry, + const SalBitmap& rSalBitmap, + const SalBitmap& rTransparentBitmap ); + virtual void drawMask( const SalTwoRect& rPosAry, + const SalBitmap& rSalBitmap, + SalColor nMaskColor ); + + virtual SalBitmap* getBitmap( long nX, long nY, long nWidth, long nHeight ); + virtual SalColor getPixel( long nX, long nY ); + + // invert --> ClipRegion (only Windows or VirDevs) + virtual void invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags); + virtual void invert( sal_uLong nPoints, const SalPoint* pPtAry, SalInvert nFlags ); + + virtual sal_Bool drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uLong nSize ); + + virtual bool drawAlphaBitmap( const SalTwoRect&, + const SalBitmap& rSourceBitmap, + const SalBitmap& rAlphaBitmap ); + + bool drawTransformedBitmap( + const basegfx::B2DPoint& rNull, + const basegfx::B2DPoint& rX, + const basegfx::B2DPoint& rY, + const SalBitmap& rSourceBitmap, + const SalBitmap* pAlphaBitmap); + + virtual bool drawAlphaRect( long nX, long nY, long nWidth, + long nHeight, sal_uInt8 nTransparency ); + + CGPoint* makeCGptArray(sal_uLong nPoints, const SalPoint* pPtAry); + // native widget rendering methods that require mirroring + virtual sal_Bool hitTestNativeControl( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, + const Point& aPos, sal_Bool& rIsInside ); + virtual sal_Bool drawNativeControl( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, + ControlState nState, const ImplControlValue& aValue, + const OUString& aCaption ); + virtual sal_Bool getNativeControlRegion( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, ControlState nState, + const ImplControlValue& aValue, const OUString& aCaption, + Rectangle &rNativeBoundingRegion, Rectangle &rNativeContentRegion ); + + // get device resolution + virtual void GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY ); + // get the depth of the device + virtual sal_uInt16 GetBitCount() const; + // get the width of the device + virtual long GetGraphicsWidth() const; + + // set the clip region to empty + virtual void ResetClipRegion(); + + // set the line color to transparent (= don't draw lines) + virtual void SetLineColor(); + // set the line color to a specific color + virtual void SetLineColor( SalColor nSalColor ); + // set the fill color to transparent (= don't fill) + virtual void SetFillColor(); + // set the fill color to a specific color, shapes will be + // filled accordingly + virtual void SetFillColor( SalColor nSalColor ); + // enable/disable XOR drawing + virtual void SetXORMode( bool bSet, bool bInvertOnly ); + // set line color for raster operations + virtual void SetROPLineColor( SalROPColor nROPColor ); + // set fill color for raster operations + virtual void SetROPFillColor( SalROPColor nROPColor ); + // set the text color to a specific color + virtual void SetTextColor( SalColor nSalColor ); + // set the font + virtual sal_uInt16 SetFont( FontSelectPattern*, int nFallbackLevel ); + // get the current font's metrics + virtual void GetFontMetric( ImplFontMetricData*, int nFallbackLevel ); + // get the repertoire of the current font + virtual const ImplFontCharMap* GetImplFontCharMap() const; + virtual bool GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const; + // graphics must fill supplied font list + virtual void GetDevFontList( ImplDevFontList* ); + // graphics must drop any cached font info + virtual void ClearDevFontCache(); + virtual bool AddTempDevFont( ImplDevFontList*, const OUString& rFileURL, const OUString& rFontName ); + // CreateFontSubset: a method to get a subset of glyhps of a font + // inside a new valid font file + // returns TRUE if creation of subset was successful + // parameters: rToFile: contains a osl file URL to write the subset to + // pFont: describes from which font to create a subset + // pGlyphIDs: the glyph ids to be extracted + // pEncoding: the character code corresponding to each glyph + // pWidths: the advance widths of the correspoding glyphs (in PS font units) + // nGlyphs: the number of glyphs + // rInfo: additional outgoing information + // implementation note: encoding 0 with glyph id 0 should be added implicitly + // as "undefined character" + virtual sal_Bool CreateFontSubset( const OUString& rToFile, + const PhysicalFontFace* pFont, + sal_Int32* pGlyphIDs, + sal_uInt8* pEncoding, + sal_Int32* pWidths, + int nGlyphs, + FontSubsetInfo& rInfo // out parameter + ); + + // GetFontEncodingVector: a method to get the encoding map Unicode + // to font encoded character; this is only used for type1 fonts and + // may return NULL in case of unknown encoding vector + // if ppNonEncoded is set and non encoded characters (that is type1 + // glyphs with only a name) exist it is set to the corresponding + // map for non encoded glyphs; the encoding vector contains -1 + // as encoding for these cases + virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded ); + + // GetEmbedFontData: gets the font data for a font marked + // embeddable by GetDevFontList or NULL in case of error + // parameters: pFont: describes the font in question + // pWidths: the widths of all glyphs from char code 0 to 255 + // pWidths MUST support at least 256 members; + // rInfo: additional outgoing information + // pDataLen: out parameter, contains the byte length of the returned buffer + virtual const void* GetEmbedFontData( const PhysicalFontFace*, + const sal_Ucs* pUnicodes, + sal_Int32* pWidths, + FontSubsetInfo& rInfo, + long* pDataLen ); + // frees the font data again + virtual void FreeEmbedFontData( const void* pData, long nDataLen ); + + virtual void GetGlyphWidths( const PhysicalFontFace*, + bool bVertical, + Int32Vector& rWidths, + Ucs2UIntMap& rUnicodeEnc ); + + virtual sal_Bool GetGlyphBoundRect( sal_GlyphId nIndex, Rectangle& ); + virtual sal_Bool GetGlyphOutline( sal_GlyphId nIndex, basegfx::B2DPolyPolygon& ); + + virtual SalLayout* GetTextLayout( ImplLayoutArgs&, int nFallbackLevel ); + virtual void DrawServerFontLayout( const ServerFontLayout& ); + virtual bool supportsOperation( OutDevSupportType ) const; + + // Query the platform layer for control support + virtual sal_Bool IsNativeControlSupported( ControlType nType, ControlPart nPart ); + + virtual SystemGraphicsData GetGraphicsData() const; + virtual SystemFontData GetSysFontData( int /* nFallbacklevel */ ) const; + +private: + // differences between VCL, Quartz and kHiThemeOrientation coordinate systems + // make some graphics seem to be vertically-mirrored from a VCL perspective + bool IsFlipped() const { return mbWindow; } + + void ApplyXorContext(); + void Pattern50Fill(); + UInt32 getState( ControlState nState ); + UInt32 getTrackState( ControlState nState ); + bool GetRawFontData( const PhysicalFontFace* pFontData, + std::vector& rBuffer, + bool* pJustCFF ); +}; + +// --- some trivial inlines + +#if !defined(__LP64__) && !defined(NS_BUILD_32_LIKE_64) + +inline void AquaSalGraphics::RefreshRect( const CGRect& rRect ) +{ + RefreshRect( rRect.origin.x, rRect.origin.y, rRect.size.width, rRect.size.height ); +} + +#endif + +inline void AquaSalGraphics::RefreshRect( const NSRect& rRect ) +{ + RefreshRect( rRect.origin.x, rRect.origin.y, rRect.size.width, rRect.size.height ); +} + +#endif + +#endif // INCLUDED_VCL_INC_QUARTZ_SALGDI_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/quartz/salmathutils.hxx b/vcl/inc/quartz/salmathutils.hxx new file mode 100644 index 000000000000..5c6641b94a9f --- /dev/null +++ b/vcl/inc/quartz/salmathutils.hxx @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_QUARTZ_SALMATHUTILS_HXX +#define INCLUDED_VCL_INC_QUARTZ_SALMATHUTILS_HXX + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------------------------------------------------------ +// +// Structures +// +// ------------------------------------------------------------------ + +// LRectCoor is an abreviation for rectangular coordinates +// represented as long integers + +struct LRectCoor +{ + long x; + long y; + long z; +}; + +// ------------------------------------------------------------------ +// +// Type Definitions +// +// ------------------------------------------------------------------ + +// LRectCoorVec is an abreviation for vectors in rectangular +// coordinates represented as long integers + +typedef struct LRectCoor LRectCoor; +typedef LRectCoor *LRectCoorVector; +typedef LRectCoorVector *LRectCoorTensor; + +// ------------------------------------------------------------------ +// +// Function Headers +// +// ------------------------------------------------------------------ + +void CSwap ( char &rX, char &rY ); +void UCSwap ( unsigned char &rX, unsigned char &rY ); +void SSwap ( short &rX, short &rY ); +void USSwap ( unsigned short &rX, unsigned short &rY ); +void LSwap ( long &rX, long &rY ); +void ULSwap ( unsigned long &rX, unsigned long &rY ); + +// ------------------------------------------------------------------ + +unsigned long Euclidian2Norm ( const LRectCoorVector pVec ); + +// ------------------------------------------------------------------ + +#ifdef __cplusplus +} +#endif + +#endif // INCLUDED_VCL_INC_QUARTZ_SALMATHUTILS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/saldatabasic.hxx b/vcl/inc/saldatabasic.hxx index 4ec1a9f25b21..3d2d2c097af7 100644 --- a/vcl/inc/saldatabasic.hxx +++ b/vcl/inc/saldatabasic.hxx @@ -27,7 +27,7 @@ #include "vcl/dllapi.h" #ifdef IOS -#include "coretext/salgdi.h" +#include "quartz/salgdi.h" #endif namespace psp diff --git a/vcl/inc/svsys.h b/vcl/inc/svsys.h index 997b3fb1da0d..9add1a92fc6e 100644 --- a/vcl/inc/svsys.h +++ b/vcl/inc/svsys.h @@ -23,7 +23,7 @@ #ifdef WNT #include "win/svsys.h" #elif defined MACOSX -#include "aqua/svsys.h" +#include "osx/svsys.h" #elif defined IOS #include "ios/svsys.h" #elif defined ANDROID diff --git a/vcl/osx/DataFlavorMapping.cxx b/vcl/osx/DataFlavorMapping.cxx new file mode 100644 index 000000000000..c5a79b368990 --- /dev/null +++ b/vcl/osx/DataFlavorMapping.cxx @@ -0,0 +1,741 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "sal/config.h" + +#include +#include "HtmlFmtFlt.hxx" +#include "PictToBmpFlt.hxx" +#include "com/sun/star/datatransfer/UnsupportedFlavorException.hpp" +#include "com/sun/star/datatransfer/XMimeContentType.hpp" +#include "com/sun/star/datatransfer/MimeContentTypeFactory.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "comphelper/processfactory.hxx" + +#include +#include + +#include +#include + +#include +#include +#include + +using namespace ::com::sun::star::datatransfer; +using namespace ::com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace cppu; +using namespace std; + + +namespace // private +{ + /* Determine whether or not a DataFlavor is valid. + */ + bool isValidFlavor(const DataFlavor& aFlavor) + { + size_t len = aFlavor.MimeType.getLength(); + Type dtype = aFlavor.DataType; + return ((len > 0) && ((dtype == getCppuType((Sequence*)0)) || (dtype == getCppuType( (OUString*)0 )))); + } + + OUString NSStringToOUString(NSString* cfString) + { + BOOST_ASSERT(cfString && "Invalid parameter"); + + const char* utf8Str = [cfString UTF8String]; + unsigned int len = rtl_str_getLength(utf8Str); + + return OUString(utf8Str, len, RTL_TEXTENCODING_UTF8); + } + + NSString* OUStringToNSString(const OUString& ustring) + { + OString utf8Str = OUStringToOString(ustring, RTL_TEXTENCODING_UTF8); + return [NSString stringWithCString: utf8Str.getStr() encoding: NSUTF8StringEncoding]; + } + + NSString* PBTYPE_SODX = @"application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\""; + NSString* PBTYPE_SESX = @"application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\""; + NSString* PBTYPE_SLSDX = @"application/x-openoffice-linksrcdescriptor-xml;windows_formatname=\"Star Link Source Descriptor (XML)\""; + NSString* PBTYPE_ESX = @"application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\""; + NSString* PBTYPE_LSX = @"application/x-openoffice-link-source-xml;windows_formatname=\"Star Link Source (XML)\""; + NSString* PBTYPE_EOX = @"application/x-openoffice-embedded-obj-xml;windows_formatname=\"Star Embedded Object (XML)\""; + NSString* PBTYPE_SVXB = @"application/x-openoffice-svbx;windows_formatname=\"SVXB (StarView Bitmap/Animation)\""; + NSString* PBTYPE_GDIMF = @"application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""; + NSString* PBTYPE_WMF = @"application/x-openoffice-wmf;windows_formatname=\"Image WMF\""; + NSString* PBTYPE_EMF = @"application/x-openoffice-emf;windows_formatname=\"Image EMF\""; + + NSString* PBTYPE_DUMMY_INTERNAL = @"application/x-openoffice-internal"; + + const char* FLAVOR_SODX = "application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\""; + const char* FLAVOR_SESX = "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\""; + const char* FLAVOR_SLSDX = "application/x-openoffice-linksrcdescriptor-xml;windows_formatname=\"Star Link Source Descriptor (XML)\""; + const char* FLAVOR_ESX = "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\""; + const char* FLAVOR_LSX = "application/x-openoffice-link-source-xml;windows_formatname=\"Star Link Source (XML)\""; + const char* FLAVOR_EOX = "application/x-openoffice-embedded-obj-xml;windows_formatname=\"Star Embedded Object (XML)\""; + const char* FLAVOR_SVXB = "application/x-openoffice-svbx;windows_formatname=\"SVXB (StarView Bitmap/Animation)\""; + const char* FLAVOR_GDIMF = "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""; + const char* FLAVOR_WMF = "application/x-openoffice-wmf;windows_formatname=\"Image WMF\""; + const char* FLAVOR_EMF = "application/x-openoffice-emf;windows_formatname=\"Image EMF\""; + + const char* FLAVOR_DUMMY_INTERNAL = "application/x-openoffice-internal"; + + + struct FlavorMap + { + NSString* SystemFlavor; + const char* OOoFlavor; + const char* HumanPresentableName; + bool DataTypeOUString; // sequence otherwise + }; + + /* At the moment it appears as if only MS Office pastes "public.html" to the clipboard. + */ + FlavorMap flavorMap[] = + { + { NSStringPboardType, "text/plain;charset=utf-16", "Unicode Text (UTF-16)", true }, + { NSRTFPboardType, "text/richtext", "Rich Text Format", false }, + { NSTIFFPboardType, "image/png", "Portable Network Graphics", false }, + { NSHTMLPboardType, "text/html", "Plain Html", false }, + { NSFilenamesPboardType, "application/x-openoffice-filelist;windows_formatname=\"FileList\"", "FileList", false }, + { PBTYPE_SESX, FLAVOR_SESX, "Star Embed Source (XML)", false }, + { PBTYPE_SLSDX, FLAVOR_SLSDX, "Star Link Source Descriptor (XML)", false }, + { PBTYPE_ESX, FLAVOR_ESX, "Star Embed Source (XML)", false }, + { PBTYPE_LSX, FLAVOR_LSX, "Star Link Source (XML)", false }, + { PBTYPE_EOX, FLAVOR_EOX, "Star Embedded Object (XML)", false }, + { PBTYPE_SVXB, FLAVOR_SVXB, "SVXB (StarView Bitmap/Animation", false }, + { PBTYPE_GDIMF, FLAVOR_GDIMF, "GDIMetaFile", false }, + { PBTYPE_WMF, FLAVOR_WMF, "Windows MetaFile", false }, + { PBTYPE_EMF, FLAVOR_EMF, "Windows Enhanced MetaFile", false }, + { PBTYPE_SODX, FLAVOR_SODX, "Star Object Descriptor (XML)", false }, + { PBTYPE_DUMMY_INTERNAL, FLAVOR_DUMMY_INTERNAL, "internal data",false } + }; + + + #define SIZE_FLAVOR_MAP (sizeof(flavorMap)/sizeof(FlavorMap)) + + + inline bool isByteSequenceType(const Type& theType) + { + return (theType == getCppuType((Sequence*)0)); + } + + inline bool isOUStringType(const Type& theType) + { + return (theType == getCppuType( (OUString*)0 )); + } + +} // namespace private + + +//########################### + +/* A base class for other data provider. + */ +class DataProviderBaseImpl : public DataProvider +{ +public: + DataProviderBaseImpl(const Any& data); + DataProviderBaseImpl(id data); + virtual ~DataProviderBaseImpl(); + +protected: + Any mData; + //NSData* mSystemData; + id mSystemData; +}; + +DataProviderBaseImpl::DataProviderBaseImpl(const Any& data) : + mData(data), + mSystemData(nil) +{ +} + +DataProviderBaseImpl::DataProviderBaseImpl(id data) : + mSystemData(data) +{ + [mSystemData retain]; +} + + +DataProviderBaseImpl::~DataProviderBaseImpl() +{ + if (mSystemData) + { + [mSystemData release]; + } +} + +//################################# + +class UniDataProvider : public DataProviderBaseImpl +{ +public: + UniDataProvider(const Any& data); + + UniDataProvider(NSData* data); + + virtual NSData* getSystemData(); + + virtual Any getOOoData(); +}; + +UniDataProvider::UniDataProvider(const Any& data) : + DataProviderBaseImpl(data) +{ +} + +UniDataProvider::UniDataProvider(NSData* data) : + DataProviderBaseImpl(data) +{ +} + +NSData* UniDataProvider::getSystemData() +{ + OUString ustr; + mData >>= ustr; + + OString strUtf8; + ustr.convertToString(&strUtf8, RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS); + + return [NSData dataWithBytes: strUtf8.getStr() length: strUtf8.getLength()]; +} + +Any UniDataProvider::getOOoData() +{ + Any oOOData; + + if (mSystemData) + { + oOOData = makeAny(OUString(reinterpret_cast([mSystemData bytes]), + [mSystemData length], + RTL_TEXTENCODING_UTF8)); + } + else + { + oOOData = mData; + } + + return oOOData; +} + +//########################### + +class ByteSequenceDataProvider : public DataProviderBaseImpl +{ +public: + ByteSequenceDataProvider(const Any& data); + + ByteSequenceDataProvider(NSData* data); + + virtual NSData* getSystemData(); + + virtual Any getOOoData(); +}; + +ByteSequenceDataProvider::ByteSequenceDataProvider(const Any& data) : + DataProviderBaseImpl(data) +{ +} + +ByteSequenceDataProvider::ByteSequenceDataProvider(NSData* data) : + DataProviderBaseImpl(data) +{ +} + + +NSData* ByteSequenceDataProvider::getSystemData() +{ + Sequence rawData; + mData >>= rawData; + + return [NSData dataWithBytes: rawData.getArray() length: rawData.getLength()]; +} + +Any ByteSequenceDataProvider::getOOoData() +{ + Any oOOData; + + if (mSystemData) + { + unsigned int flavorDataLength = [mSystemData length]; + Sequence byteSequence; + byteSequence.realloc(flavorDataLength); + memcpy(byteSequence.getArray(), [mSystemData bytes], flavorDataLength); + oOOData = makeAny(byteSequence); + } + else + { + oOOData = mData; + } + + return oOOData; +} + + +//########################### + +class HTMLFormatDataProvider : public DataProviderBaseImpl +{ +public: + HTMLFormatDataProvider(const Any& data); + + HTMLFormatDataProvider(NSData* data); + + virtual NSData* getSystemData(); + + virtual Any getOOoData(); +}; + +HTMLFormatDataProvider::HTMLFormatDataProvider(const Any& data) : + DataProviderBaseImpl(data) +{ +} + +HTMLFormatDataProvider::HTMLFormatDataProvider(NSData* data) : + DataProviderBaseImpl(data) +{ +} + +NSData* HTMLFormatDataProvider::getSystemData() +{ + Sequence textHtmlData; + mData >>= textHtmlData; + + Sequence htmlFormatData = TextHtmlToHTMLFormat(textHtmlData); + + return [NSData dataWithBytes: htmlFormatData.getArray() length: htmlFormatData.getLength()]; +} + +Any HTMLFormatDataProvider::getOOoData() +{ + Any oOOData; + + if (mSystemData) + { + unsigned int flavorDataLength = [mSystemData length]; + Sequence unkHtmlData; + + unkHtmlData.realloc(flavorDataLength); + memcpy(unkHtmlData.getArray(), [mSystemData bytes], flavorDataLength); + + Sequence* pPlainHtml = &unkHtmlData; + Sequence plainHtml; + + if (isHTMLFormat(unkHtmlData)) + { + plainHtml = HTMLFormatToTextHtml(unkHtmlData); + pPlainHtml = &plainHtml; + } + + oOOData = makeAny(*pPlainHtml); + } + else + { + oOOData = mData; + } + + return oOOData; +} + +//########################### + +class PNGDataProvider : public DataProviderBaseImpl +{ + NSBitmapImageFileType meImageType; +public: + PNGDataProvider( const Any&, NSBitmapImageFileType); + + PNGDataProvider( NSData*, NSBitmapImageFileType); + + virtual NSData* getSystemData(); + + virtual Any getOOoData(); +}; + +PNGDataProvider::PNGDataProvider( const Any& data, NSBitmapImageFileType eImageType) : + DataProviderBaseImpl(data), + meImageType( eImageType ) +{ +} + +PNGDataProvider::PNGDataProvider( NSData* data, NSBitmapImageFileType eImageType) : + DataProviderBaseImpl(data), + meImageType( eImageType ) +{ +} + +NSData* PNGDataProvider::getSystemData() +{ + Sequence pngData; + mData >>= pngData; + + Sequence imgData; + NSData* sysData = NULL; + if( PNGToImage( pngData, imgData, meImageType)) + sysData = [NSData dataWithBytes: imgData.getArray() length: imgData.getLength()]; + + return sysData; +} + +/* The AOO 'PCT' filter is not yet good enough to be used + and there is no flavor defined for exchanging 'PCT' with AOO + so we convert 'PCT' to a PNG and provide this to AOO +*/ +Any PNGDataProvider::getOOoData() +{ + Any oOOData; + + if( mSystemData) + { + const unsigned int flavorDataLength = [mSystemData length]; + Sequence imgData( flavorDataLength); + memcpy( imgData.getArray(), [mSystemData bytes], flavorDataLength); + + Sequence pngData; + if( ImageToPNG( imgData, pngData, meImageType)) + oOOData = makeAny( pngData); + } + else + { + oOOData = mData; + } + + return oOOData; +} + +//###################### + +class FileListDataProvider : public DataProviderBaseImpl +{ +public: + FileListDataProvider(const Any& data); + FileListDataProvider(NSArray* data); + + virtual NSData* getSystemData(); + virtual Any getOOoData(); +}; + +FileListDataProvider::FileListDataProvider(const Any& data) : + DataProviderBaseImpl(data) +{ +} + +FileListDataProvider::FileListDataProvider(NSArray* data) : + DataProviderBaseImpl(data) +{ +} + +NSData* FileListDataProvider::getSystemData() +{ + return [NSData data]; +} + +Any FileListDataProvider::getOOoData() +{ + Any oOOData; + + if (mSystemData) + { + size_t length = [mSystemData count]; + size_t lenSeqRequired = 0; + + for (size_t i = 0; i < length; i++) + { + NSString* fname = [mSystemData objectAtIndex: i]; + lenSeqRequired += [fname maximumLengthOfBytesUsingEncoding: NSUnicodeStringEncoding] + sizeof(unichar); + } + + Sequence oOOFileList(lenSeqRequired); + unichar* pBuffer = reinterpret_cast(oOOFileList.getArray()); + memset(pBuffer, 0, lenSeqRequired); + + for (size_t i = 0; i < length; i++) + { + NSString* fname = [mSystemData objectAtIndex: i]; + [fname getCharacters: pBuffer]; + size_t l = [fname length]; + pBuffer += l + 1; + } + + oOOData = makeAny(oOOFileList); + } + else + { + oOOData = mData; + } + + return oOOData; +} + +//########################### + +DataFlavorMapper::DataFlavorMapper() +{ + Reference xContext = comphelper::getProcessComponentContext(); + mrXMimeCntFactory = MimeContentTypeFactory::create( xContext ); +} + +DataFlavorMapper::~DataFlavorMapper() +{ + // release potential NSStrings + for( OfficeOnlyTypes::iterator it = maOfficeOnlyTypes.begin(); it != maOfficeOnlyTypes.end(); ++it ) + { + [it->second release]; + it->second = nil; + } +} + +DataFlavor DataFlavorMapper::systemToOpenOfficeFlavor(NSString* systemDataFlavor) const +{ + DataFlavor oOOFlavor; + + for (size_t i = 0; i < SIZE_FLAVOR_MAP; i++) + { + if ([systemDataFlavor caseInsensitiveCompare: flavorMap[i].SystemFlavor] == NSOrderedSame) + { + oOOFlavor.MimeType = OUString::createFromAscii(flavorMap[i].OOoFlavor); + oOOFlavor.HumanPresentableName = OUString::createFromAscii(flavorMap[i].HumanPresentableName); + oOOFlavor.DataType = flavorMap[i].DataTypeOUString ? getCppuType( (OUString*)0 ) : getCppuType((Sequence*)0); + return oOOFlavor; + } + } // for + + // look if this might be an internal type; if it comes in here it must have + // been through openOfficeToSystemFlavor before, so it should then be in the map + OUString aTryFlavor( NSStringToOUString( systemDataFlavor ) ); + if( maOfficeOnlyTypes.find( aTryFlavor ) != maOfficeOnlyTypes.end() ) + { + oOOFlavor.MimeType = aTryFlavor; + oOOFlavor.HumanPresentableName = OUString(); + oOOFlavor.DataType = getCppuType((Sequence*)0); + } + + return oOOFlavor; +} + +NSString* DataFlavorMapper::openOfficeToSystemFlavor(const DataFlavor& oOOFlavor, bool& rbInternal) const +{ + NSString* sysFlavor = NULL; + rbInternal = false; + + for( size_t i = 0; i < SIZE_FLAVOR_MAP; ++i ) + { + if (oOOFlavor.MimeType.startsWith(OUString::createFromAscii(flavorMap[i].OOoFlavor))) + { + sysFlavor = flavorMap[i].SystemFlavor; + } + } + + if(!sysFlavor) + { + rbInternal = true; + OfficeOnlyTypes::const_iterator it = maOfficeOnlyTypes.find( oOOFlavor.MimeType ); + + if( it == maOfficeOnlyTypes.end() ) + sysFlavor = maOfficeOnlyTypes[ oOOFlavor.MimeType ] = OUStringToNSString( oOOFlavor.MimeType ); + else + sysFlavor = it->second; + } + + return sysFlavor; +} + +NSString* DataFlavorMapper::openOfficeImageToSystemFlavor(NSPasteboard* pPasteboard) const +{ + NSArray *supportedTypes = [NSArray arrayWithObjects: NSTIFFPboardType, nil]; + NSString *sysFlavor = [pPasteboard availableTypeFromArray:supportedTypes]; + return sysFlavor; +} + +DataProviderPtr_t DataFlavorMapper::getDataProvider(NSString* systemFlavor, Reference rTransferable) const +{ + DataProviderPtr_t dp; + + try + { + DataFlavor oOOFlavor = systemToOpenOfficeFlavor(systemFlavor); + + Any data = rTransferable->getTransferData(oOOFlavor); + + if (isByteSequenceType(data.getValueType())) + { + /* + the HTMLFormatDataProvider prepends segment information to HTML + this is useful for exchange with MS Word (which brings this stuff from Windows) + but annoying for other applications. Since this extension is not a standard datatype + on the Mac, let us not provide but provide normal HTML + + if ([systemFlavor caseInsensitiveCompare: NSHTMLPboardType] == NSOrderedSame) + { + dp = DataProviderPtr_t(new HTMLFormatDataProvider(data)); + } + else + */ + if ([systemFlavor caseInsensitiveCompare: NSTIFFPboardType] == NSOrderedSame) + { + dp = DataProviderPtr_t( new PNGDataProvider( data, NSTIFFFileType)); + } + else if ([systemFlavor caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame) + { + dp = DataProviderPtr_t(new FileListDataProvider(data)); + } + else + { + dp = DataProviderPtr_t(new ByteSequenceDataProvider(data)); + } + } + else // Must be OUString type + { + SAL_WARN_IF( + !isOUStringType(data.getValueType()), "vcl", + "must be OUString type"); + dp = DataProviderPtr_t(new UniDataProvider(data)); + } + } + catch(UnsupportedFlavorException&) + { + // Somebody violates the contract of the clipboard + // interface @see XTransferable + } + + return dp; +} + +DataProviderPtr_t DataFlavorMapper::getDataProvider(const NSString* /*systemFlavor*/, NSArray* systemData) const +{ + return DataProviderPtr_t(new FileListDataProvider(systemData)); +} + +DataProviderPtr_t DataFlavorMapper::getDataProvider(const NSString* systemFlavor, NSData* systemData) const +{ + DataProviderPtr_t dp; + + if ([systemFlavor caseInsensitiveCompare: NSStringPboardType] == NSOrderedSame) + { + dp = DataProviderPtr_t(new UniDataProvider(systemData)); + } + else if ([systemFlavor caseInsensitiveCompare: NSHTMLPboardType] == NSOrderedSame) + { + dp = DataProviderPtr_t(new HTMLFormatDataProvider(systemData)); + } + else if ([systemFlavor caseInsensitiveCompare: NSTIFFPboardType] == NSOrderedSame) + { + dp = DataProviderPtr_t( new PNGDataProvider(systemData, NSTIFFFileType)); + } + else if ([systemFlavor caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame) + { + //dp = DataProviderPtr_t(new FileListDataProvider(systemData)); + } + else + { + dp = DataProviderPtr_t(new ByteSequenceDataProvider(systemData)); + } + + return dp; +} + +bool DataFlavorMapper::isValidMimeContentType(const OUString& contentType) const +{ + bool result = true; + + try + { + Reference xCntType(mrXMimeCntFactory->createMimeContentType(contentType)); + } + catch( IllegalArgumentException& ) + { + result = false; + } + + return result; +} + +NSArray* DataFlavorMapper::flavorSequenceToTypesArray(const com::sun::star::uno::Sequence& flavors) const +{ + sal_uInt32 nFlavors = flavors.getLength(); + NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity: 1]; + + bool bNeedDummyInternalFlavor(false); + + for (sal_uInt32 i = 0; i < nFlavors; i++) + { + if( flavors[i].MimeType.startsWith("image/bmp") ) + { + [array addObject: NSTIFFPboardType]; + } + else + { + NSString* str = openOfficeToSystemFlavor(flavors[i], bNeedDummyInternalFlavor); + + if (str != NULL) + { + [str retain]; + [array addObject: str]; + } + } + } + + // #i89462# #i90747# + // in case no system flavor was found to report + // report at least one so D&D between OOo targets works + if( [array count] == 0 || bNeedDummyInternalFlavor) + { + [array addObject: PBTYPE_DUMMY_INTERNAL]; + } + + return [array autorelease]; +} + +com::sun::star::uno::Sequence DataFlavorMapper::typesArrayToFlavorSequence(NSArray* types) const +{ + int nFormats = [types count]; + Sequence flavors; + + for (int i = 0; i < nFormats; i++) + { + NSString* sysFormat = [types objectAtIndex: i]; + DataFlavor oOOFlavor = systemToOpenOfficeFlavor(sysFormat); + + if (isValidFlavor(oOOFlavor)) + { + flavors.realloc(flavors.getLength() + 1); + flavors[flavors.getLength() - 1] = oOOFlavor; + } + } + + return flavors; +} + + +NSArray* DataFlavorMapper::getAllSupportedPboardTypes() const +{ + NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity: SIZE_FLAVOR_MAP]; + + for (sal_uInt32 i = 0; i < SIZE_FLAVOR_MAP; i++) + { + [array addObject: flavorMap[i].SystemFlavor]; + } + + return [array autorelease]; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/DataFlavorMapping.hxx b/vcl/osx/DataFlavorMapping.hxx new file mode 100644 index 000000000000..70f7736b248e --- /dev/null +++ b/vcl/osx/DataFlavorMapping.hxx @@ -0,0 +1,141 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_DATAFLAVORMAPPING_HXX +#define INCLUDED_VCL_OSX_DATAFLAVORMAPPING_HXX + +#include +#include +#include +#include + +#include +#import +#include + +#include +#include +#include + + +/* An interface to get the clipboard data in either + system or OOo format. + */ +class DataProvider +{ +public: + virtual ~DataProvider() {}; + + /* Get the clipboard data in the system format. + The caller has to retain/release the returned + CFDataRef on demand. + */ + virtual NSData* getSystemData() = 0; + + /* Get the clipboard data in OOo format. + */ + virtual com::sun::star::uno::Any getOOoData() = 0; +}; + +typedef std::auto_ptr DataProviderPtr_t; + + +//################################ + + +class DataFlavorMapper +{ +public: + /* Initialialize a DataFavorMapper instance. Throws a RuntimeException in case the XMimeContentTypeFactory service + cannot be created. + */ + DataFlavorMapper(); + ~DataFlavorMapper(); + + + /* Map a system data flavor to an OpenOffice data flavor. + Return an empty string if there is not suiteable + mapping from a system data flavor to a OpenOffice data + flavor. + */ + com::sun::star::datatransfer::DataFlavor systemToOpenOfficeFlavor(NSString* systemDataFlavor) const; + + + /* Map an OpenOffice data flavor to a system data flavor. + If there is no suiteable mapping available NULL will + be returned. + */ + NSString* openOfficeToSystemFlavor(const com::sun::star::datatransfer::DataFlavor& oooDataFlavor, bool& rbInternal) const; + + /* Select the best available image data type + If there is no suiteable mapping available NULL will + be returned. + */ + NSString* openOfficeImageToSystemFlavor(NSPasteboard* pPasteboard) const; + + /* Get a data provider which is able to provide the data 'rTransferable' offers in a format that can + be put on to the system clipboard. + */ + DataProviderPtr_t getDataProvider(NSString* systemFlavor, + const com::sun::star::uno::Reference< com::sun::star::datatransfer::XTransferable > rTransferable) const; + + + + /* Get a data provider which is able to provide 'systemData' in the OOo expected format. + */ + DataProviderPtr_t getDataProvider(const NSString* systemFlavor, NSArray* systemData) const; + + + /* Get a data provider which is able to provide 'systemData' in the OOo expected format. + */ + DataProviderPtr_t getDataProvider(const NSString* systemFlavor, NSData* systemData) const; + + + /* Translate a sequence of DataFlavors into a NSArray of system types. + Only those DataFlavors for which a suitable mapping to a system + type exist will be contained in the returned types array. + */ + NSArray* flavorSequenceToTypesArray(const com::sun::star::uno::Sequence& flavors) const; + + /* Translate a NSArray of system types into a sequence of DataFlavors. + Only those types for which a suitable mapping to a DataFlavor + exist will be contained in the new DataFlavor Sequence. + */ + com::sun::star::uno::Sequence typesArrayToFlavorSequence(NSArray* types) const; + + /* Returns an NSArray containing all pasteboard types supported by OOo + */ + NSArray* getAllSupportedPboardTypes() const; + +private: + /* Determines if the provided Mime content type is valid. + */ + bool isValidMimeContentType(const OUString& contentType) const; + +private: + ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XMimeContentTypeFactory> mrXMimeCntFactory; + typedef boost::unordered_map< OUString, NSString*, OUStringHash > OfficeOnlyTypes; + mutable OfficeOnlyTypes maOfficeOnlyTypes; +}; + +typedef boost::shared_ptr DataFlavorMapperPtr_t; + +#endif // INCLUDED_VCL_OSX_DATAFLAVORMAPPING_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/DragActionConversion.cxx b/vcl/osx/DragActionConversion.cxx new file mode 100644 index 000000000000..d4bb9e5c3c86 --- /dev/null +++ b/vcl/osx/DragActionConversion.cxx @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "DragActionConversion.hxx" +#include + + +using namespace com::sun::star::datatransfer::dnd; + + +/* Convert office drag actions as defined in + com::sun::star::datatransfer::dnd::DNDConstants + into system conform drag actions. + */ +unsigned int OfficeToSystemDragActions(sal_Int8 dragActions) +{ + unsigned int actions = NSDragOperationNone; + + if (dragActions & DNDConstants::ACTION_COPY) + { + actions |= NSDragOperationCopy; + } + + if (dragActions & DNDConstants::ACTION_MOVE) + { + actions |= NSDragOperationMove; + } + + if (dragActions & DNDConstants::ACTION_LINK) + { + actions |= NSDragOperationLink; + } + + return actions; +} + +/* Convert system conform drag actions into office conform + drag actions as defined in + com::sun::star::datatransfer::dnd::DNDConstants. + */ +sal_Int8 SystemToOfficeDragActions(unsigned int dragActions) +{ + sal_Int8 actions = DNDConstants::ACTION_NONE; + + if (dragActions & NSDragOperationCopy) + { + actions |= DNDConstants::ACTION_COPY; + } + + if (dragActions & NSDragOperationMove) + { + actions |= DNDConstants::ACTION_MOVE; + } + + if (dragActions & NSDragOperationLink) + { + actions |= DNDConstants::ACTION_LINK; + } + + // We map NSDragOperationGeneric to ACTION_DEFAULT to + // signal that we have to decide for a drag action + if (dragActions & NSDragOperationGeneric) + { + actions |= DNDConstants::ACTION_DEFAULT; + } + + return actions; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/DragActionConversion.hxx b/vcl/osx/DragActionConversion.hxx new file mode 100644 index 000000000000..8c9b057bff0f --- /dev/null +++ b/vcl/osx/DragActionConversion.hxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include + +#include +#import +#include + + +/* Convert office drag actions as defined in + com::sun::star::datatransfer::dnd::DNDConstants + into system conform drag actions. + */ +unsigned int OfficeToSystemDragActions(sal_Int8 dragActions); + +/* Convert system conform drag actions into office conform + drag actions as defined in + com::sun::star::datatransfer::dnd::DNDConstants. + */ +sal_Int8 SystemToOfficeDragActions(unsigned int dragActions); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/DragSource.cxx b/vcl/osx/DragSource.cxx new file mode 100644 index 000000000000..720292854707 --- /dev/null +++ b/vcl/osx/DragSource.cxx @@ -0,0 +1,372 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include +#include +#include + +#include "rtl/ustring.hxx" + +#include "comphelper/makesequence.hxx" + +#include "DragSource.hxx" +#include "DragSourceContext.hxx" +#include "clipboard.hxx" +#include "DragActionConversion.hxx" + +#include "osx/salframe.h" + +#include + + +using namespace cppu; +using namespace osl; +using namespace com::sun::star; +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::datatransfer::clipboard; +using namespace com::sun::star::datatransfer::dnd; +using namespace com::sun::star::datatransfer::dnd::DNDConstants; +using namespace com::sun::star::uno; +using namespace com::sun::star::awt::MouseButton; +using namespace com::sun::star::awt; +using namespace com::sun::star::lang; +using namespace comphelper; +using namespace std; + + +// For OOo internal D&D we provide the Transferable without NSDragPboard +// interference as a shortcut +uno::Reference DragSource::g_XTransferable; +NSView* DragSource::g_DragSourceView = nil; +bool DragSource::g_DropSuccessSet = false; +bool DragSource::g_DropSuccess = false; + + +OUString dragSource_getImplementationName() +{ + return OUString("com.sun.star.comp.datatransfer.dnd.OleDragSource_V1"); +} + +Sequence dragSource_getSupportedServiceNames() +{ + return makeSequence(OUString("com.sun.star.datatransfer.dnd.OleDragSource")); +} + + +@implementation DragSourceHelper; + +-(DragSourceHelper*)initWithDragSource: (DragSource*) pds +{ + self = [super init]; + + if (self) + { + mDragSource = pds; + } + + return self; +} + + +-(void)mouseDown: (NSEvent*)theEvent +{ + mDragSource->saveMouseEvent(theEvent); +} + + +-(void)mouseDragged: (NSEvent*)theEvent +{ + mDragSource->saveMouseEvent(theEvent); +} + + +-(unsigned int)draggingSourceOperationMaskForLocal: (BOOL)isLocal +{ + return mDragSource->getSupportedDragOperations(isLocal); +} + + +-(void)draggedImage:(NSImage*)anImage beganAt:(NSPoint)aPoint +{ + (void)anImage; + (void)aPoint; + DragSourceDragEvent dsde(static_cast(mDragSource), + new DragSourceContext, + mDragSource, + DNDConstants::ACTION_COPY, + DNDConstants::ACTION_COPY); + + mDragSource->mXDragSrcListener->dragEnter(dsde); +} + + +-(void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation +{ + (void)anImage; + (void)aPoint; + // an internal drop can accept the drop but fail with dropComplete( false ) + // this is different than the Cocoa API + bool bDropSuccess = operation != NSDragOperationNone; + if( DragSource::g_DropSuccessSet ) + bDropSuccess = DragSource::g_DropSuccess; + + DragSourceDropEvent dsde(static_cast(mDragSource), + new DragSourceContext, + static_cast< XDragSource* >(mDragSource), + SystemToOfficeDragActions(operation), + bDropSuccess ); + + mDragSource->mXDragSrcListener->dragDropEnd(dsde); + mDragSource->mXDragSrcListener = uno::Reference(); +} + + +-(void)draggedImage:(NSImage *)draggedImage movedTo:(NSPoint)screenPoint +{ + (void)draggedImage; + (void)screenPoint; + DragSourceDragEvent dsde(static_cast(mDragSource), + new DragSourceContext, + mDragSource, + DNDConstants::ACTION_COPY, + DNDConstants::ACTION_COPY); + + mDragSource->mXDragSrcListener->dragOver(dsde); +} + +@end + + +DragSource::DragSource(): + WeakComponentImplHelper3(m_aMutex), + mView(NULL), + mpFrame(NULL), + mLastMouseEventBeforeStartDrag(nil), + m_MouseButton(0) +{ +} + + +DragSource::~DragSource() +{ + if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) + [(id )mView unregisterMouseEventListener: mDragSourceHelper]; + [mDragSourceHelper release]; +} + + +void SAL_CALL DragSource::initialize(const Sequence< Any >& aArguments) + throw(Exception) +{ + if (aArguments.getLength() < 2) + { + throw Exception("DragSource::initialize: Not enough parameter.", + static_cast(this)); + } + + Any pNSView = aArguments[1]; + sal_uInt64 tmp = 0; + pNSView >>= tmp; + mView = (NSView*)tmp; + + /* All SalFrameView the base class for all VCL system views inherits from + NSView in order to get mouse and other events. This is the only way to + get these events. In order to start a drag operation we need to provide + the mouse event which was the trigger. SalFrameView therefor implements + a hook mechanism so that we can get mouse events for our purpose. + */ + if (![mView respondsToSelector: @selector(registerMouseEventListener:)] || + ![mView respondsToSelector: @selector(unregisterMouseEventListener:)]) + { + throw Exception("DragSource::initialize: Provided view doesn't support mouse listener", + static_cast(this)); + } + NSWindow* pWin = [mView window]; + if( ! pWin || ![pWin respondsToSelector: @selector(getSalFrame)] ) + { + throw Exception("DragSource::initialize: Provided view is not attached to a vcl frame", + static_cast(this)); + } + mpFrame = (AquaSalFrame*)[pWin performSelector: @selector(getSalFrame)]; + + mDragSourceHelper = [[DragSourceHelper alloc] initWithDragSource: this]; + + if (mDragSourceHelper == nil) + { + throw Exception("DragSource::initialize: Cannot initialize DragSource", + static_cast(this)); + } + + [(id )mView registerMouseEventListener: mDragSourceHelper]; +} + + +//---------------------------------------------------- +// XDragSource +//---------------------------------------------------- + +sal_Bool SAL_CALL DragSource::isDragImageSupported( ) + throw(RuntimeException) +{ + return true; +} + + +sal_Int32 SAL_CALL DragSource::getDefaultCursor( sal_Int8 /*dragAction*/ ) + throw( IllegalArgumentException, RuntimeException) +{ + return 0; +} + + +void SAL_CALL DragSource::startDrag(const DragGestureEvent& trigger, + sal_Int8 sourceActions, + sal_Int32 /*cursor*/, + sal_Int32 /*image*/, + const uno::Reference& transferable, + const uno::Reference& listener ) + throw( RuntimeException) +{ + MutexGuard guard(m_aMutex); + + OSL_ASSERT(listener.is() && "DragSource::startDrag: No XDragSourceListener provided\n"); + OSL_ASSERT(transferable.is() && "DragSource::startDrag: No transferable provided\n"); + + trigger.Event >>= mMouseEvent; + m_MouseButton= mMouseEvent.Buttons; + mXDragSrcListener = listener; + mXCurrentContext = static_cast(new DragSourceContext); + auto_ptr clipb(new AquaClipboard(NULL, false)); + g_XTransferable = transferable; + clipb->setContents(g_XTransferable, uno::Reference()); + mDragSourceActions = sourceActions; + g_DragSourceView = mView; + + NSSize sz; + sz.width = 5; + sz.height = 5; + + NSImage* dragImage; + dragImage = [[NSImage alloc] initWithSize: sz]; + + NSRect bounds; + bounds.origin = NSMakePoint(0,0); + bounds.size = sz; + + [dragImage lockFocus]; + [[NSColor blackColor] set]; + [NSBezierPath fillRect: bounds]; + [dragImage unlockFocus]; + + NSPoint pInWnd = [mLastMouseEventBeforeStartDrag locationInWindow]; + NSPoint p; + p = [mView convertPoint: pInWnd fromView: nil]; + p.x = p.x - sz.width/2; + p.y = p.y - sz.height/2; + + // reset drop success flags + g_DropSuccessSet = false; + g_DropSuccess = false; + + [mView dragImage: dragImage + at: p + offset: NSMakeSize(0,0) + event: mLastMouseEventBeforeStartDrag + pasteboard: clipb->getPasteboard() + source: mDragSourceHelper + slideBack: 1]; + + [dragImage release]; + + g_XTransferable = uno::Reference(); + g_DragSourceView = nil; + + // reset drop success flags + g_DropSuccessSet = false; + g_DropSuccess = false; +} + + +// In order to initiate a D&D operation we need to +// provide the triggering mouse event which we get +// from the SalFrameView that is associated with +// this DragSource +void DragSource::saveMouseEvent(NSEvent* theEvent) +{ + if (mLastMouseEventBeforeStartDrag != nil) + { + [mLastMouseEventBeforeStartDrag release]; + } + + mLastMouseEventBeforeStartDrag = theEvent; +} + + +/* isLocal indicates whether or not the DnD operation is OOo + internal. + */ +unsigned int DragSource::getSupportedDragOperations(bool isLocal) const +{ + unsigned int srcActions = OfficeToSystemDragActions(mDragSourceActions); + + if (isLocal) + { + // Support NSDragOperation generic which means we can + // decide which D&D operation to choose. We map + // NSDragOperationGenric to DNDConstants::ACTION_DEFAULT + // in SystemToOfficeDragActions to signal this and + // use it in DropTarget::determineDropAction + srcActions |= NSDragOperationGeneric; + } + else + { + // Mask out link and move operations on external DnD + srcActions &= ~(NSDragOperationMove | NSDragOperationLink); + } + + return srcActions; +} + + +//################################ +// XServiceInfo +//################################ + +OUString SAL_CALL DragSource::getImplementationName( ) throw (RuntimeException) +{ + return dragSource_getImplementationName(); +} + + +sal_Bool SAL_CALL DragSource::supportsService( const OUString& ServiceName ) throw (RuntimeException) +{ + return ServiceName == "com.sun.star.datatransfer.dnd.OleDragSource"; +} + + +Sequence< OUString > SAL_CALL DragSource::getSupportedServiceNames() throw (RuntimeException) +{ + return dragSource_getSupportedServiceNames(); +} + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/DragSource.hxx b/vcl/osx/DragSource.hxx new file mode 100644 index 000000000000..625388e87a69 --- /dev/null +++ b/vcl/osx/DragSource.hxx @@ -0,0 +1,135 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_DRAGSOURCE_HXX +#define INCLUDED_VCL_OSX_DRAGSOURCE_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#import +#include + + +class DragSource; +class AquaSalFrame; + +/* The functions declared in this protocol are actually + declared in vcl/inc/osx/salframe.h. Because we want + to avoid importing VCL headers in UNO services and + on the other hand want to avoid warnings caused by + gcc complaining about unknowness of these functions + we declare them in a protocol here and cast at the + appropriate places. +*/ +@protocol MouseEventListener +-(void)registerMouseEventListener:(id)theHandler; +-(void)unregisterMouseEventListener:(id)theHandler; +@end + + +@interface DragSourceHelper : NSObject +{ + DragSource* mDragSource; +} + +-(DragSourceHelper*)initWithDragSource: (DragSource*) pds; + +-(void)mouseDown: (NSEvent*)theEvent; +-(void)mouseDragged: (NSEvent*)theEvent; + +-(unsigned int)draggingSourceOperationMaskForLocal:(BOOL)isLocal; +-(void)draggedImage:(NSImage*)anImage beganAt:(NSPoint)aPoint; +-(void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation; +-(void)draggedImage:(NSImage *)draggedImage movedTo:(NSPoint)screenPoint; + +@end + + +class DragSource : public ::cppu::BaseMutex, + public ::cppu::WeakComponentImplHelper3< com::sun::star::datatransfer::dnd::XDragSource, + com::sun::star::lang::XInitialization, + com::sun::star::lang::XServiceInfo >, + private ::boost::noncopyable +{ +public: + DragSource(); + virtual ~DragSource(); + + // XInitialization + virtual void SAL_CALL initialize( const com::sun::star::uno::Sequence< com::sun::star::uno::Any >& aArguments ) + throw(com::sun::star::uno::Exception/*, com::sun::star::uno::RuntimeException*/); + + // XDragSource + virtual sal_Bool SAL_CALL isDragImageSupported( ) throw(com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getDefaultCursor(sal_Int8 dragAction) + throw(com::sun::star::lang::IllegalArgumentException, com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL startDrag( const com::sun::star::datatransfer::dnd::DragGestureEvent& trigger, + sal_Int8 sourceActions, + sal_Int32 cursor, + sal_Int32 image, + const com::sun::star::uno::Reference< com::sun::star::datatransfer::XTransferable >& transferable, + const com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDragSourceListener >& listener ) + throw(com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw (com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw (com::sun::star::uno::RuntimeException); + virtual com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() throw (com::sun::star::uno::RuntimeException); + + virtual void saveMouseEvent(NSEvent* theEvent); + virtual unsigned int getSupportedDragOperations(bool isLocal) const; + +public: + // The context notifies the XDragSourceListeners + com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDragSourceContext > mXCurrentContext; + + id mView; + AquaSalFrame* mpFrame; + NSEvent* mLastMouseEventBeforeStartDrag; + DragSourceHelper* mDragSourceHelper; + com::sun::star::awt::MouseEvent mMouseEvent; + com::sun::star::uno::Reference< com::sun::star::datatransfer::XTransferable > mXTransferable; + com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDragSourceListener > mXDragSrcListener; + // The mouse button that set off the drag and drop operation + short m_MouseButton; + sal_Int8 mDragSourceActions; + + static com::sun::star::uno::Reference< com::sun::star::datatransfer::XTransferable > g_XTransferable; + static NSView* g_DragSourceView; + static bool g_DropSuccessSet; + static bool g_DropSuccess; + +}; + +#endif // INCLUDED_VCL_OSX_DRAGSOURCE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/DragSourceContext.cxx b/vcl/osx/DragSourceContext.cxx new file mode 100644 index 000000000000..1eb4fe3ac78e --- /dev/null +++ b/vcl/osx/DragSourceContext.cxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include "DragSourceContext.hxx" + + +using namespace com::sun::star::datatransfer::dnd; +using namespace com::sun::star::datatransfer::dnd::DNDConstants; +using namespace com::sun::star::uno; +using namespace cppu; + +DragSourceContext::DragSourceContext() : + WeakComponentImplHelper1(m_aMutex) +{ +} + +DragSourceContext::~DragSourceContext() +{ +} + +sal_Int32 SAL_CALL DragSourceContext::getCurrentCursor( ) + throw( RuntimeException) +{ + return 0; +} + +void SAL_CALL DragSourceContext::setCursor( sal_Int32 /*cursorId*/ ) + throw( RuntimeException) +{ +} + +void SAL_CALL DragSourceContext::setImage( sal_Int32 /*imageId*/ ) + throw( RuntimeException) +{ +} + +void SAL_CALL DragSourceContext::transferablesFlavorsChanged( ) + throw( RuntimeException) +{ +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/DragSourceContext.hxx b/vcl/osx/DragSourceContext.hxx new file mode 100644 index 000000000000..f27518ee2756 --- /dev/null +++ b/vcl/osx/DragSourceContext.hxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_DRAGSOURCECONTEXT_HXX +#define INCLUDED_VCL_OSX_DRAGSOURCECONTEXT_HXX + +#include +#include +#include +#include + +#include + +// This class fires events to XDragSourceListener implementations. +// Of that interface only dragDropEnd and dropActionChanged are called. +// The functions dragEnter, dragExit and dragOver are not supported +// currently. +// An instance of SourceContext only lives as long as the drag and drop +// operation lasts. +class DragSourceContext: public cppu::BaseMutex, + public cppu::WeakComponentImplHelper1, + private ::boost::noncopyable +{ +public: + DragSourceContext(); + ~DragSourceContext(); + + virtual sal_Int32 SAL_CALL getCurrentCursor( ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL setCursor( sal_Int32 cursorId ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL setImage( sal_Int32 imageId ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL transferablesFlavorsChanged( ) + throw( com::sun::star::uno::RuntimeException); +}; + +#endif // INCLUDED_VCL_OSX_DRAGSOURCECONTEXT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/DropTarget.cxx b/vcl/osx/DropTarget.cxx new file mode 100644 index 000000000000..e4d3a6bc72a4 --- /dev/null +++ b/vcl/osx/DropTarget.cxx @@ -0,0 +1,596 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include + +#include "comphelper/makesequence.hxx" +#include + +#include "clipboard.hxx" +#include "DropTarget.hxx" +#include "DragActionConversion.hxx" + +#include "DragSource.hxx" + +#include +#include + +#include +#include +#include + +#include +#include + +using namespace cppu; +using namespace osl; +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::datatransfer::dnd; +using namespace com::sun::star::datatransfer::dnd::DNDConstants; +using namespace com::sun::star::datatransfer::clipboard; +using namespace com::sun::star::lang; +using namespace com::sun::star::uno; +using namespace com::sun::star; +using namespace comphelper; + + +OUString dropTarget_getImplementationName() +{ + return OUString("com.sun.star.comp.datatransfer.dnd.OleDropTarget_V1"); +} + + +Sequence dropTarget_getSupportedServiceNames() +{ + return makeSequence(OUString("com.sun.star.datatransfer.dnd.OleDropTarget")); +} + + +namespace /* private */ +{ + // Cocoa's coordinate system has its origin lower-left, VCL's + // coordinate system upper-left hence we need to transform + // coordinates + + inline void CocoaToVCL(NSPoint& rPoint, const NSRect& bounds) + { + rPoint.y = bounds.size.height - rPoint.y; + } +} + + +@implementation DropTargetHelper + + +-(DropTargetHelper*)initWithDropTarget:(DropTarget*)pdt +{ + self = [super init]; + + if (self) + { + mDropTarget = pdt; + } + + return self; +} + + +-(NSDragOperation)draggingEntered:(id )sender +{ + return mDropTarget->draggingEntered(sender); +} + + +-(NSDragOperation)draggingUpdated:(id )sender +{ + return mDropTarget->draggingUpdated(sender); +} + + +-(void)draggingExited:(id )sender +{ + mDropTarget->draggingExited(sender); +} + + +-(BOOL)prepareForDragOperation:(id )sender +{ + return mDropTarget->prepareForDragOperation(sender); +} + + +-(BOOL)performDragOperation:(id )sender +{ + return mDropTarget->performDragOperation(sender); +} + + +-(void)concludeDragOperation:(id )sender +{ + mDropTarget->concludeDragOperation(sender); +} + + +@end + + +DropTarget::DropTarget() : + WeakComponentImplHelper5(m_aMutex), + mView(nil), + mpFrame(NULL), + mDropTargetHelper(nil), + mbActive(false), + mDragSourceSupportedActions(DNDConstants::ACTION_NONE), + mSelectedDropAction(DNDConstants::ACTION_NONE), + mDefaultActions(DNDConstants::ACTION_COPY_OR_MOVE | DNDConstants::ACTION_LINK | DNDConstants::ACTION_DEFAULT) +{ + mDataFlavorMapper = DataFlavorMapperPtr_t(new DataFlavorMapper()); +} + + +DropTarget::~DropTarget() +{ + if( AquaSalFrame::isAlive( mpFrame ) ) + [(id )mView unregisterDraggingDestinationHandler:mDropTargetHelper]; + [mDropTargetHelper release]; +} + + +sal_Int8 DropTarget::determineDropAction(sal_Int8 dropActions, id sender) const +{ + sal_Int8 dropAct = dropActions; + bool srcAndDestEqual = false; + + if ([sender draggingSource] != nil) + { + // Internal DnD + NSView* destView = [[sender draggingDestinationWindow] contentView]; + srcAndDestEqual = (DragSource::g_DragSourceView == destView); + } + + // If ACTION_DEFAULT is set this means NSDragOperationGeneric + // has been set and we map this to ACTION_MOVE or ACTION_COPY + // depending on whether or not source and dest are equal, + // this hopefully satisfies all parties + if( (dropActions == DNDConstants::ACTION_DEFAULT) + || ((dropActions == mDragSourceSupportedActions) + && !(~mDragSourceSupportedActions & DNDConstants::ACTION_COPY_OR_MOVE ) ) ) + { + dropAct = srcAndDestEqual ? DNDConstants::ACTION_MOVE : + DNDConstants::ACTION_COPY; + } + // if more than one drop actions have been specified + // set ACTION_DEFAULT in order to let the drop target + // decide which one to use + else if (dropActions != DNDConstants::ACTION_NONE && + dropActions != DNDConstants::ACTION_MOVE && + dropActions != DNDConstants::ACTION_COPY && + dropActions != DNDConstants::ACTION_LINK) + { + if (srcAndDestEqual) + { + dropAct = dropActions; + } + else // source and destination are different + { + if (dropActions & DNDConstants::ACTION_COPY) + dropAct = DNDConstants::ACTION_COPY; + else if (dropActions & DNDConstants::ACTION_MOVE) + dropAct = DNDConstants::ACTION_MOVE; + else if (dropActions & DNDConstants::ACTION_LINK) + dropAct = DNDConstants::ACTION_LINK; + } + + dropAct |= DNDConstants::ACTION_DEFAULT; + } + + return dropAct; +} + + +NSDragOperation DropTarget::draggingEntered(id sender) +{ + // Initially when DnD will be started no modifier key can be pressed yet + // thus we are getting all actions that the drag source supports, we save + // this value because later the system masks the drag source actions if + // a modifier key will be pressed + mDragSourceSupportedActions = SystemToOfficeDragActions([sender draggingSourceOperationMask]); + + // Only if the drop target is really interessted in the drag actions + // supported by the source + if (mDragSourceSupportedActions & mDefaultActions) + { + sal_Int8 currentAction = determineDropAction(mDragSourceSupportedActions, sender); + + NSRect bounds = [mView bounds]; + NSPoint dragLocation = [sender draggedImageLocation]; + + CocoaToVCL(dragLocation, bounds); + + sal_Int32 posX = static_cast(dragLocation.x); + sal_Int32 posY = static_cast(dragLocation.y); + + NSPasteboard* dragPboard = [sender draggingPasteboard]; + mXCurrentDragClipboard = new AquaClipboard(dragPboard, false); + + uno::Reference xTransferable = DragSource::g_XTransferable.is() ? + DragSource::g_XTransferable : mXCurrentDragClipboard->getContents(); + + DropTargetDragEnterEvent dtdee(static_cast(this), + 0, + this, + currentAction, + posX, + posY, + mDragSourceSupportedActions, + xTransferable->getTransferDataFlavors()); + + fire_dragEnter(dtdee); + } + + return OfficeToSystemDragActions(mSelectedDropAction); +} + + +NSDragOperation DropTarget::draggingUpdated(id sender) +{ + sal_Int8 currentDragSourceActions = + SystemToOfficeDragActions([sender draggingSourceOperationMask]); + NSDragOperation dragOp = NSDragOperationNone; + + if (currentDragSourceActions & mDefaultActions) + { + sal_Int8 currentAction = determineDropAction(currentDragSourceActions, sender); + NSRect bounds = [mView bounds]; + NSPoint dragLocation = [sender draggedImageLocation]; + + CocoaToVCL(dragLocation, bounds); + + sal_Int32 posX = static_cast(dragLocation.x); + sal_Int32 posY = static_cast(dragLocation.y); + + DropTargetDragEvent dtde(static_cast(this), + 0, + this, + currentAction, + posX, + posY, + mDragSourceSupportedActions); + + fire_dragOver(dtde); + + // drag over callbacks likely have rendered something + [mView setNeedsDisplay: TRUE]; + + dragOp = OfficeToSystemDragActions(mSelectedDropAction); + + //NSLog(@"Drag update: Source actions: %x proposed action %x selected action %x", mDragSourceSupportedActions, currentAction, mSelectedDropAction); + } + +#ifndef __LP64__ + // Weird but it appears as if there is no method in Cocoa + // to create a kThemeCopyArrowCursor hence we have to use + // Carbon to do it + if (dragOp == NSDragOperationNone) + SetThemeCursor(kThemeNotAllowedCursor); + else if (dragOp == NSDragOperationCopy) + SetThemeCursor(kThemeCopyArrowCursor); + else + SetThemeCursor(kThemeArrowCursor); +#else + // FIXME: SetThemeCursor replacement? +#endif + return dragOp; +} + + +void DropTarget::draggingExited(id /*sender*/) +{ + DropTargetEvent dte(static_cast(this), 0); + fire_dragExit(dte); + mDragSourceSupportedActions = DNDConstants::ACTION_NONE; + mSelectedDropAction = DNDConstants::ACTION_NONE; +#ifndef __LP64__ + SetThemeCursor(kThemeArrowCursor); +#endif +} + + +BOOL DropTarget::prepareForDragOperation(id /*sender*/) +{ + return 1; +} + + +BOOL DropTarget::performDragOperation(id sender) +{ + bool bSuccess = false; + + if (mSelectedDropAction != DNDConstants::ACTION_NONE) + { + uno::Reference xTransferable = DragSource::g_XTransferable; + + if (!DragSource::g_XTransferable.is()) + { + xTransferable = mXCurrentDragClipboard->getContents(); + } + + NSRect bounds = [mView bounds]; + NSPoint dragLocation = [sender draggedImageLocation]; + + CocoaToVCL(dragLocation, bounds); + + sal_Int32 posX = static_cast(dragLocation.x); + sal_Int32 posY = static_cast(dragLocation.y); + + DropTargetDropEvent dtde(static_cast(this), + 0, + this, + mSelectedDropAction, + posX, + posY, + mDragSourceSupportedActions, + xTransferable); + + fire_drop(dtde); + + bSuccess = true; + } + + return bSuccess; +} + + +void DropTarget::concludeDragOperation(id /*sender*/) +{ + mDragSourceSupportedActions = DNDConstants::ACTION_NONE; + mSelectedDropAction = DNDConstants::ACTION_NONE; + mXCurrentDragClipboard = uno::Reference(); +#ifndef __LP64__ + SetThemeCursor(kThemeArrowCursor); +#endif +} + + + // called from WeakComponentImplHelperX::dispose + // WeakComponentImplHelper calls disposing before it destroys + // itself. + void SAL_CALL DropTarget::disposing() + { + } + + + void SAL_CALL DropTarget::initialize(const Sequence< Any >& aArguments) + throw(Exception) + { + if (aArguments.getLength() < 2) + { + throw RuntimeException("DropTarget::initialize: Cannot install window event handler", + static_cast(this)); + } + + Any pNSView = aArguments[0]; + sal_uInt64 tmp = 0; + pNSView >>= tmp; + mView = (id)tmp; + mpFrame = [(SalFrameView*)mView getSalFrame]; + + mDropTargetHelper = [[DropTargetHelper alloc] initWithDropTarget: this]; + + [(id )mView registerDraggingDestinationHandler:mDropTargetHelper]; + [mView registerForDraggedTypes: mDataFlavorMapper->getAllSupportedPboardTypes()]; + + id wnd = [mView window]; + NSWindow* parentWnd = [wnd parentWindow]; + unsigned int topWndStyle = (NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask); + unsigned int wndStyles = [wnd styleMask] & topWndStyle; + + if (parentWnd == nil && (wndStyles == topWndStyle)) + { + [wnd registerDraggingDestinationHandler:mDropTargetHelper]; + [wnd registerForDraggedTypes: [NSArray arrayWithObjects: NSFilenamesPboardType, nil]]; + } + } + + + void SAL_CALL DropTarget::addDropTargetListener(const uno::Reference& dtl) + throw(RuntimeException) + { + rBHelper.addListener(::getCppuType(&dtl), dtl); + } + + + void SAL_CALL DropTarget::removeDropTargetListener(const uno::Reference& dtl) + throw(RuntimeException) + { + rBHelper.removeListener(::getCppuType(&dtl), dtl); + } + + + sal_Bool SAL_CALL DropTarget::isActive( ) throw(RuntimeException) + { + return mbActive; + } + + + void SAL_CALL DropTarget::setActive(sal_Bool active) throw(RuntimeException) + { + mbActive = active; + } + + + sal_Int8 SAL_CALL DropTarget::getDefaultActions() throw(RuntimeException) + { + return mDefaultActions; + } + + + void SAL_CALL DropTarget::setDefaultActions(sal_Int8 actions) throw(RuntimeException) + { + OSL_ENSURE( actions < 8, "No valid default actions"); + mDefaultActions= actions; + } + + + // XDropTargetDragContext + + void SAL_CALL DropTarget::acceptDrag(sal_Int8 dragOperation) throw (RuntimeException) + { + mSelectedDropAction = dragOperation; + } + + + void SAL_CALL DropTarget::rejectDrag() throw (RuntimeException) + { + mSelectedDropAction = DNDConstants::ACTION_NONE; + } + + + //XDropTargetDropContext + + void SAL_CALL DropTarget::acceptDrop(sal_Int8 dropOperation) throw( RuntimeException) + { + mSelectedDropAction = dropOperation; + } + + + void SAL_CALL DropTarget::rejectDrop() throw (RuntimeException) + { + mSelectedDropAction = DNDConstants::ACTION_NONE; + } + + + void SAL_CALL DropTarget::dropComplete(sal_Bool success) throw (RuntimeException) + { + // Reset the internal transferable used as shortcut in case this is + // an internal D&D operation + DragSource::g_XTransferable = uno::Reference(); + DragSource::g_DropSuccessSet = true; + DragSource::g_DropSuccess = success; + } + + + void DropTarget::fire_drop( const DropTargetDropEvent& dte) + { + OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference* )0 ) ); + if( pContainer) + { + OInterfaceIteratorHelper iter( *pContainer); + while( iter.hasMoreElements()) + { + uno::Reference listener( static_cast( iter.next())); + + try { listener->drop( dte); } + catch(RuntimeException&) {} + } + } + } + + + void DropTarget::fire_dragEnter(const DropTargetDragEnterEvent& e) + { + OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference* )0 ) ); + if( pContainer) + { + OInterfaceIteratorHelper iter( *pContainer); + while( iter.hasMoreElements()) + { + uno::Reference listener( static_cast( iter.next())); + + try { listener->dragEnter( e); } + catch (RuntimeException&) {} + } + } + } + + + void DropTarget::fire_dragExit(const DropTargetEvent& dte) + { + OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference* )0 ) ); + + if( pContainer) + { + OInterfaceIteratorHelper iter( *pContainer); + while( iter.hasMoreElements()) + { + uno::Reference listener( static_cast( iter.next())); + + try { listener->dragExit( dte); } + catch (RuntimeException&) {} + } + } + } + + + void DropTarget::fire_dragOver(const DropTargetDragEvent& dtde) + { + OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference* )0 ) ); + if( pContainer) + { + OInterfaceIteratorHelper iter( *pContainer ); + while( iter.hasMoreElements()) + { + uno::Reference listener( static_cast( iter.next())); + + try { listener->dragOver( dtde); } + catch (RuntimeException&) {} + } + } + } + + + void DropTarget::fire_dropActionChanged(const DropTargetDragEvent& dtde) + { + OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference* )0 ) ); + if( pContainer) + { + OInterfaceIteratorHelper iter( *pContainer); + while( iter.hasMoreElements()) + { + uno::Reference listener( static_cast( iter.next())); + + try { listener->dropActionChanged( dtde); } + catch (RuntimeException&) {} + } + } + } + + + // XServiceInfo + + OUString SAL_CALL DropTarget::getImplementationName() throw (RuntimeException) + { + return dropTarget_getImplementationName(); + } + + + sal_Bool SAL_CALL DropTarget::supportsService( const OUString& ServiceName ) throw (RuntimeException) + { + return ServiceName == "com.sun.star.datatransfer.dnd.OleDropTarget"; + } + + + Sequence< OUString > SAL_CALL DropTarget::getSupportedServiceNames( ) throw (RuntimeException) + { + return dropTarget_getSupportedServiceNames(); + } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/DropTarget.hxx b/vcl/osx/DropTarget.hxx new file mode 100644 index 000000000000..0eea030db18b --- /dev/null +++ b/vcl/osx/DropTarget.hxx @@ -0,0 +1,163 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_DROPTARGET_HXX +#define INCLUDED_VCL_OSX_DROPTARGET_HXX + +#include "DataFlavorMapping.hxx" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#import +#include + +class DropTarget; +class AquaSalFrame; + +/* The functions declared in this protocol are actually + declared in vcl/inc/osx/salframe.h. Because we want + to avoid importing VCL headers in UNO services and + on the other hand want to avoid warnings caused by + gcc complaining about unknowness of these functions + we declare them in a protocol here and cast at the + appropriate places. +*/ +@protocol DraggingDestinationHandler +-(void)registerDraggingDestinationHandler:(id)theHandler; +-(void)unregisterDraggingDestinationHandler:(id)theHandler; +@end + + +@interface DropTargetHelper : NSObject +{ + DropTarget* mDropTarget; +} + +-(DropTargetHelper*)initWithDropTarget:(DropTarget*)pdt; + +-(NSDragOperation)draggingEntered:(id )sender; +-(NSDragOperation)draggingUpdated:(id )sender; +-(void)draggingExited:(id )sender; +-(BOOL)prepareForDragOperation:(id )sender; +-(BOOL)performDragOperation:(id )sender; +-(void)concludeDragOperation:(id )sender; + +@end + + +class DropTarget: public cppu::BaseMutex, + public cppu::WeakComponentImplHelper5< com::sun::star::lang::XInitialization, + com::sun::star::datatransfer::dnd::XDropTarget, + com::sun::star::datatransfer::dnd::XDropTargetDragContext, + com::sun::star::datatransfer::dnd::XDropTargetDropContext, + com::sun::star::lang::XServiceInfo >, + private boost::noncopyable +{ +public: + DropTarget(); + virtual ~DropTarget(); + + // Overrides WeakComponentImplHelper::disposing which is called by + // WeakComponentImplHelper::dispose + // Must be called. + virtual void SAL_CALL disposing(); + + // XInitialization + virtual void SAL_CALL initialize( const com::sun::star::uno::Sequence< com::sun::star::uno::Any >& aArguments ) + throw(com::sun::star::uno::Exception); + + // XDropTarget + virtual void SAL_CALL addDropTargetListener( const com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDropTargetListener >& dtl ) + throw(com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL removeDropTargetListener( const com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDropTargetListener >& dtl ) + throw(com::sun::star::uno::RuntimeException); + + // Default is not active + virtual sal_Bool SAL_CALL isActive() throw(com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setActive(sal_Bool isActive) throw(com::sun::star::uno::RuntimeException); + virtual sal_Int8 SAL_CALL getDefaultActions() throw(com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDefaultActions(sal_Int8 actions) throw(com::sun::star::uno::RuntimeException); + + // XDropTargetDragContext + virtual void SAL_CALL acceptDrag(sal_Int8 dragOperation) throw(com::sun::star::uno::RuntimeException); + virtual void SAL_CALL rejectDrag() throw(com::sun::star::uno::RuntimeException); + + // XDropTargetDragContext + virtual void SAL_CALL acceptDrop(sal_Int8 dropOperation) throw (com::sun::star::uno::RuntimeException); + virtual void SAL_CALL rejectDrop() throw (com::sun::star::uno::RuntimeException); + virtual void SAL_CALL dropComplete(sal_Bool success) throw (com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw (com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw (com::sun::star::uno::RuntimeException); + virtual com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() throw (com::sun::star::uno::RuntimeException); + + // NSDraggingDestination protocol functions + virtual NSDragOperation draggingEntered(id sender); + virtual NSDragOperation draggingUpdated(id sender); + virtual void draggingExited(id sender); + virtual BOOL prepareForDragOperation(id sender); + virtual BOOL performDragOperation(id sender); + virtual void concludeDragOperation(id sender); + + /* If multiple actions are supported by the drag source and + the user did not choose a specific action by pressing a + modifier key choose a default action to be proposed to + the application. + */ + sal_Int8 determineDropAction(sal_Int8 dropActions, id sender) const; + +private: + void fire_drop(const com::sun::star::datatransfer::dnd::DropTargetDropEvent& dte); + void fire_dragEnter(const com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& dtdee); + void fire_dragExit(const com::sun::star::datatransfer::dnd::DropTargetEvent& dte); + void fire_dragOver(const com::sun::star::datatransfer::dnd::DropTargetDragEvent& dtde); + void fire_dropActionChanged(const com::sun::star::datatransfer::dnd::DropTargetDragEvent& dtde); + +private: + com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDropTargetDragContext > mXCurrentDragContext; + com::sun::star::uno::Reference< com::sun::star::datatransfer::dnd::XDropTargetDropContext > mXCurrentDropContext; + com::sun::star::uno::Reference< com::sun::star::datatransfer::clipboard::XClipboard > mXCurrentDragClipboard; + DataFlavorMapperPtr_t mDataFlavorMapper; + id mView; + AquaSalFrame* mpFrame; + DropTargetHelper* mDropTargetHelper; + bool mbActive; + sal_Int8 mDragSourceSupportedActions; + sal_Int8 mSelectedDropAction; + sal_Int8 mDefaultActions; +}; + +#endif // INCLUDED_VCL_OSX_DROPTARGET_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/HtmlFmtFlt.cxx b/vcl/osx/HtmlFmtFlt.cxx new file mode 100644 index 000000000000..e629f11e982e --- /dev/null +++ b/vcl/osx/HtmlFmtFlt.cxx @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "HtmlFmtFlt.hxx" + +#include + +#include +#include +#include +#include + +#include + +using namespace com::sun::star::uno; + +//------------------------------------------------------------------------------ +// converts the openoffice text/html clipboard format to the HTML Format +// well known under MS Windows +// the MS HTML Format has a header before the real html data +// +// Version:1.0 Version number of the clipboard. Staring is 0.9 +// StartHTML: Byte count from the beginning of the clipboard to the start +// of the context, or -1 if no context +// EndHTML: Byte count from the beginning of the clipboard to the end +// of the context, or -1 if no context +// StartFragment: Byte count from the beginning of the clipboard to the +// start of the fragment +// EndFragment: Byte count from the beginning of the clipboard to the +// end of the fragment +// StartSelection: Byte count from the beginning of the clipboard to the +// start of the selection +// EndSelection: Byte count from the beginning of the clipboard to the +// end of the selection +// +// StartSelection and EndSelection are optional +// The fragment should be preceded and followed by the HTML comments +// and (no space between !-- and the +// text +//------------------------------------------------------------------------------ + +namespace // private +{ +std::string GetHtmlFormatHeader(size_t startHtml, size_t endHtml, size_t startFragment, size_t endFragment) +{ + std::ostringstream htmlHeader; + htmlHeader << "Version:1.0" << '\r' << '\n'; + htmlHeader << "StartHTML:" << std::setw(10) << std::setfill('0') << std::dec << startHtml << '\r' << '\n'; + htmlHeader << "EndHTML:" << std::setw(10) << std::setfill('0') << std::dec << endHtml << '\r' << '\n'; + htmlHeader << "StartFragment:" << std::setw(10) << std::setfill('0') << std::dec << startFragment << '\r' << '\n'; + htmlHeader << "EndFragment:" << std::setw(10) << std::setfill('0') << std::dec << endFragment << '\r' << '\n'; + return htmlHeader.str(); +} + +} // namespace private + + +// the office always writes the start and end html tag in upper cases and +// without spaces both tags don't allow parameters +const std::string TAG_HTML = std::string(""); +const std::string TAG_END_HTML = std::string(""); + +// The body tag may have parameters so we need to search for the +// closing '>' manually e.g. #92840# +const std::string TAG_BODY = std::string(" SAL_CALL TextHtmlToHTMLFormat(Sequence& aTextHtml) +{ + OSL_ASSERT(aTextHtml.getLength() > 0); + + if (!(aTextHtml.getLength() > 0)) + return Sequence(); + + // fill the buffer with dummy values to calc the exact length + std::string dummyHtmlHeader = GetHtmlFormatHeader(0, 0, 0, 0); + size_t lHtmlFormatHeader = dummyHtmlHeader.length(); + + std::string textHtml( + reinterpret_cast(aTextHtml.getConstArray()), + reinterpret_cast(aTextHtml.getConstArray()) + aTextHtml.getLength()); + + std::string::size_type nStartHtml = textHtml.find(TAG_HTML) + lHtmlFormatHeader - 1; // we start one before '' Word 2000 does also so + std::string::size_type nEndHtml = textHtml.find(TAG_END_HTML) + lHtmlFormatHeader + TAG_END_HTML.length() + 1; // our SOffice 5.2 wants 2 behind ? + + // The body tag may have parameters so we need to search for the + // closing '>' manually e.g. #92840# + std::string::size_type nStartFragment = textHtml.find(">", textHtml.find(TAG_BODY)) + lHtmlFormatHeader + 1; + std::string::size_type nEndFragment = textHtml.find(TAG_END_BODY) + lHtmlFormatHeader; + + std::string htmlFormat = GetHtmlFormatHeader(nStartHtml, nEndHtml, nStartFragment, nEndFragment); + htmlFormat += textHtml; + + Sequence byteSequence(htmlFormat.length() + 1); // space the trailing '\0' + memset(byteSequence.getArray(), 0, byteSequence.getLength()); + + memcpy( + static_cast(byteSequence.getArray()), + static_cast(htmlFormat.c_str()), + htmlFormat.length()); + + return byteSequence; +} + +const char* HtmlStartTag = " HTMLFormatToTextHtml(const Sequence& aHTMLFormat) +{ + BOOST_ASSERT(isHTMLFormat(aHTMLFormat) && "No HTML Format provided"); + + Sequence& nonconstHTMLFormatRef = const_cast< Sequence& >(aHTMLFormat); + sal_Char* dataStart = reinterpret_cast(nonconstHTMLFormatRef.getArray()); + sal_Char* dataEnd = dataStart + nonconstHTMLFormatRef.getLength() - 1; + const sal_Char* htmlStartTag = strcasestr(dataStart, HtmlStartTag); + + BOOST_ASSERT(htmlStartTag && "Seems to be no HTML at all"); + + // It doesn't seem to be HTML? Well then simply return what has been + // provided in non-debug builds + if (htmlStartTag == NULL) + { + return aHTMLFormat; + } + + sal_Int32 len = dataEnd - htmlStartTag; + Sequence plainHtmlData(len); + + memcpy(static_cast(plainHtmlData.getArray()), htmlStartTag, len); + + return plainHtmlData; +} + +/* A simple format detection. We are just comparing the first few bytes + of the provided byte sequence to see whether or not it is the MS + Office Html format. If it shows that this is not reliable enough we + can improve this +*/ +const char HtmlFormatStart[] = "Version:"; +int HtmlFormatStartLen = (sizeof(HtmlFormatStart) - 1); + +bool isHTMLFormat(const Sequence& aHtmlSequence) +{ + if (aHtmlSequence.getLength() < HtmlFormatStartLen) + return false; + + return rtl_str_compareIgnoreAsciiCase_WithLength(HtmlFormatStart, + HtmlFormatStartLen, + reinterpret_cast(aHtmlSequence.getConstArray()), + HtmlFormatStartLen) == 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/HtmlFmtFlt.hxx b/vcl/osx/HtmlFmtFlt.hxx new file mode 100644 index 000000000000..77a92493bad6 --- /dev/null +++ b/vcl/osx/HtmlFmtFlt.hxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_HTMLFMTFLT_HXX +#define INCLUDED_VCL_OSX_HTMLFMTFLT_HXX + +#include + +/* Transform plain HTML into the format expected by MS Office. + */ +com::sun::star::uno::Sequence TextHtmlToHTMLFormat(com::sun::star::uno::Sequence& aTextHtml); + +/* Transform the MS Office HTML format into plain HTML. + */ +com::sun::star::uno::Sequence HTMLFormatToTextHtml(const com::sun::star::uno::Sequence& aHTMLFormat); + +/* Detects whether the given byte sequence contains the MS Office Html format. + + @returns True if the MS Office Html format will be detected False otherwise. + */ +bool isHTMLFormat (const com::sun::star::uno::Sequence& aHtmlSequence); + +#endif // INCLUDED_VCL_OSX_HTMLFMTFLT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/OSXTransferable.cxx b/vcl/osx/OSXTransferable.cxx new file mode 100644 index 000000000000..7cfffcd4d7c5 --- /dev/null +++ b/vcl/osx/OSXTransferable.cxx @@ -0,0 +1,203 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include "OSXTransferable.hxx" + +#include "DataFlavorMapping.hxx" + +using namespace std; +using namespace osl; +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::io; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; + + +namespace // private +{ + bool isValidFlavor( const DataFlavor& aFlavor ) + { + size_t len = aFlavor.MimeType.getLength(); + Type dtype = aFlavor.DataType; + return ((len > 0) && ((dtype == getCppuType((Sequence*)0)) || (dtype == getCppuType((OUString*)0)))); + } + +} // namespace private + + +OSXTransferable::OSXTransferable(const Reference rXMimeCntFactory, + DataFlavorMapperPtr_t pDataFlavorMapper, + NSPasteboard* pasteboard) : + mrXMimeCntFactory(rXMimeCntFactory), + mDataFlavorMapper(pDataFlavorMapper), + mPasteboard(pasteboard) +{ + [mPasteboard retain]; + + initClipboardItemList(); +} + + +OSXTransferable::~OSXTransferable() +{ + [mPasteboard release]; +} + + +Any SAL_CALL OSXTransferable::getTransferData( const DataFlavor& aFlavor ) + throw( UnsupportedFlavorException, IOException, RuntimeException ) +{ + if (!isValidFlavor(aFlavor) || !isDataFlavorSupported(aFlavor)) + { + throw UnsupportedFlavorException("AquaClipboard: Unsupported data flavor", + static_cast(this)); + } + + bool bInternal(false); + NSString* sysFormat = + (aFlavor.MimeType.startsWith("image/png")) + ? mDataFlavorMapper->openOfficeImageToSystemFlavor( mPasteboard ) + : mDataFlavorMapper->openOfficeToSystemFlavor(aFlavor, bInternal); + DataProviderPtr_t dp; + + if ([sysFormat caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame) + { + NSArray* sysData = [mPasteboard propertyListForType: sysFormat]; + dp = mDataFlavorMapper->getDataProvider(sysFormat, sysData); + } + else + { + NSData* sysData = [mPasteboard dataForType: sysFormat]; + dp = mDataFlavorMapper->getDataProvider(sysFormat, sysData); + } + + if (dp.get() == NULL) + { + throw UnsupportedFlavorException("AquaClipboard: Unsupported data flavor", + static_cast(this)); + } + + return dp->getOOoData(); +} + + +bool OSXTransferable::isUnicodeText(const DataFlavor& flavor) +{ + return (flavor.DataType == getCppuType((OUString*)0)); +} + + +Sequence< DataFlavor > SAL_CALL OSXTransferable::getTransferDataFlavors( ) + throw( RuntimeException ) +{ + return mFlavorList; +} + + +sal_Bool SAL_CALL OSXTransferable::isDataFlavorSupported(const DataFlavor& aFlavor) + throw( RuntimeException ) +{ + for (sal_Int32 i = 0; i < mFlavorList.getLength(); i++) + if (compareDataFlavors(aFlavor, mFlavorList[i])) + return sal_True; + + return sal_False; +} + + +void OSXTransferable::initClipboardItemList() +{ + NSArray* pboardFormats = [mPasteboard types]; + + if (pboardFormats == NULL) + { + throw RuntimeException("AquaClipboard: Cannot get clipboard data", + static_cast(this)); + } + + mFlavorList = mDataFlavorMapper->typesArrayToFlavorSequence(pboardFormats); +} + + +/* Compares two DataFlavors. Returns true if both DataFlavor have the same media type + and the number of parameter and all parameter values do match otherwise false + is returned. + */ +bool OSXTransferable::compareDataFlavors(const DataFlavor& lhs, const DataFlavor& rhs ) +{ + try + { + Reference xLhs(mrXMimeCntFactory->createMimeContentType(lhs.MimeType)); + Reference xRhs(mrXMimeCntFactory->createMimeContentType(rhs.MimeType)); + + if (!xLhs->getFullMediaType().equalsIgnoreAsciiCase(xRhs->getFullMediaType()) || + !cmpAllContentTypeParameter(xLhs, xRhs)) + { + return false; + } + } + catch( IllegalArgumentException& ) + { + OSL_FAIL( "Invalid content type detected" ); + return false; + } + + return true; +} + + +bool OSXTransferable::cmpAllContentTypeParameter(const Reference xLhs, + const Reference xRhs) const +{ + Sequence xLhsFlavors = xLhs->getParameters(); + Sequence xRhsFlavors = xRhs->getParameters(); + + // Stop here if the number of parameters is different already + if (xLhsFlavors.getLength() != xRhsFlavors.getLength()) + return false; + + try + { + OUString pLhs; + OUString pRhs; + + for (sal_Int32 i = 0; i < xLhsFlavors.getLength(); i++) + { + pLhs = xLhs->getParameterValue(xLhsFlavors[i]); + pRhs = xRhs->getParameterValue(xLhsFlavors[i]); + + if (!pLhs.equalsIgnoreAsciiCase(pRhs)) + { + return false; + } + } + } + catch(IllegalArgumentException&) + { + return false; + } + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/OSXTransferable.hxx b/vcl/osx/OSXTransferable.hxx new file mode 100644 index 000000000000..27885effd03f --- /dev/null +++ b/vcl/osx/OSXTransferable.hxx @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#ifndef _TRANSFERABLE_HXX_ +#define _TRANSFERABLE_HXX_ + +#include +#include +#include +#include + +#include "DataFlavorMapping.hxx" + +#include +#import +#include + +#include +#include +#include + + +class OSXTransferable : public ::cppu::WeakImplHelper1, + private ::boost::noncopyable +{ +public: + typedef com::sun::star::uno::Sequence< sal_Int8 > ByteSequence_t; + + explicit OSXTransferable(com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XMimeContentTypeFactory> rXMimeCntFactory, + DataFlavorMapperPtr_t pDataFlavorMapper, + NSPasteboard* pasteboard); + + virtual ~OSXTransferable(); + + //------------------------------------------------------------------------ + // XTransferable + //------------------------------------------------------------------------ + + virtual ::com::sun::star::uno::Any SAL_CALL getTransferData( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) + throw( ::com::sun::star::datatransfer::UnsupportedFlavorException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::datatransfer::DataFlavor > SAL_CALL getTransferDataFlavors( ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL isDataFlavorSupported( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------ + // Helper functions not part of the XTransferable interface + //------------------------------------------------------------------------ + + void initClipboardItemList(); + + //com::sun::star::uno::Any getClipboardItemData(ClipboardItemPtr_t clipboardItem); + + bool isUnicodeText(const com::sun::star::datatransfer::DataFlavor& flavor); + + bool compareDataFlavors( const com::sun::star::datatransfer::DataFlavor& lhs, + const com::sun::star::datatransfer::DataFlavor& rhs ); + + bool cmpAllContentTypeParameter( const com::sun::star::uno::Reference< com::sun::star::datatransfer::XMimeContentType > xLhs, + const com::sun::star::uno::Reference< com::sun::star::datatransfer::XMimeContentType > xRhs ) const; + +private: + com::sun::star::uno::Sequence< com::sun::star::datatransfer::DataFlavor > mFlavorList; + ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XMimeContentTypeFactory> mrXMimeCntFactory; + DataFlavorMapperPtr_t mDataFlavorMapper; + NSPasteboard* mPasteboard; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/PictToBmpFlt.cxx b/vcl/osx/PictToBmpFlt.cxx new file mode 100644 index 000000000000..91ed2bc5f177 --- /dev/null +++ b/vcl/osx/PictToBmpFlt.cxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include + +#include + +#include "PictToBmpFlt.hxx" + +bool ImageToPNG( com::sun::star::uno::Sequence& rImgData, + com::sun::star::uno::Sequence& rPngData, + NSBitmapImageFileType eInFormat) +{ + (void) eInFormat; // Really not needed? Weird. + + NSData* pData = [NSData dataWithBytesNoCopy: (void*)rImgData.getConstArray() length: rImgData.getLength() freeWhenDone: 0]; + if( !pData) + return false; + + NSBitmapImageRep* pRep =[NSBitmapImageRep imageRepWithData: pData]; + if( !pRep) + return false; + + NSData* pOut = [pRep representationUsingType: NSPNGFileType properties: nil]; + if( !pOut) + return false; + + const size_t nPngSize = [pOut length]; + rPngData.realloc( nPngSize); + [pOut getBytes: rPngData.getArray() length: nPngSize]; + return (nPngSize > 0); +} + +bool PNGToImage( com::sun::star::uno::Sequence& rPngData, + com::sun::star::uno::Sequence& rImgData, + NSBitmapImageFileType eOutFormat + ) +{ + NSData* pData = [NSData dataWithBytesNoCopy: const_cast(rPngData.getConstArray()) length: rPngData.getLength() freeWhenDone: 0]; + if( !pData) + return false; + + NSBitmapImageRep* pRep = [NSBitmapImageRep imageRepWithData: pData]; + if( !pRep) + return false; + + NSData* pOut = [pRep representationUsingType: eOutFormat properties: nil]; + if( !pOut) + return false; + + const size_t nImgSize = [pOut length]; + rImgData.realloc( nImgSize); + [pOut getBytes: rImgData.getArray() length: nImgSize]; + return (nImgSize > 0); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/PictToBmpFlt.hxx b/vcl/osx/PictToBmpFlt.hxx new file mode 100644 index 000000000000..59f1f2d3fa99 --- /dev/null +++ b/vcl/osx/PictToBmpFlt.hxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_PICTTOBMPFLT_HXX +#define INCLUDED_VCL_OSX_PICTTOBMPFLT_HXX + +#include + +#include +#include +#include + +bool ImageToPNG( com::sun::star::uno::Sequence& rImgData, + com::sun::star::uno::Sequence& rPngData, + NSBitmapImageFileType eInFormat); + +bool PNGToImage( com::sun::star::uno::Sequence& rPngData, + com::sun::star::uno::Sequence& rImgData, + NSBitmapImageFileType eOutFormat); + +#endif // INCLUDED_VCL_OSX_PICTTOBMPFLT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/README.a11y b/vcl/osx/README.a11y new file mode 100644 index 000000000000..4422713bc4fa --- /dev/null +++ b/vcl/osx/README.a11y @@ -0,0 +1,7 @@ +Naming scheme: + +a11yXYZhelper: Helper class providing static methods + +a11yXYZwrapper: Wrapper around one (or two) UNO-interfaces + +a11ywrapperXYZ: Subclass of a11ywrapper for a specific AXRole diff --git a/vcl/osx/a11yactionwrapper.h b/vcl/osx/a11yactionwrapper.h new file mode 100644 index 000000000000..0fda9a32ae21 --- /dev/null +++ b/vcl/osx/a11yactionwrapper.h @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YACTIONWRAPPER_H +#define INCLUDED_VCL_OSX_A11YACTIONWRAPPER_H + +#include "osx/osxvcltypes.h" +#include "osx/a11ywrapper.h" + +@interface AquaA11yActionWrapper : NSObject +{ +} ++(NSArray *)actionNamesForElement:(AquaA11yWrapper *)wrapper; ++(void)doAction:(NSString *)action ofElement:(AquaA11yWrapper *)wrapper; +@end + +#endif // INCLUDED_VCL_OSX_A11YACTIONWRAPPER_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11yactionwrapper.mm b/vcl/osx/a11yactionwrapper.mm new file mode 100644 index 000000000000..31dc39527ecd --- /dev/null +++ b/vcl/osx/a11yactionwrapper.mm @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" +#include "quartz/utils.h" + +#include "a11yactionwrapper.h" + +// Wrapper for XAccessibleAction + +@implementation AquaA11yActionWrapper : NSObject + ++(NSString *)nativeActionNameFor:(NSString *)actionName { + // TODO: Optimize ? + // Use NSAccessibilityActionDescription + if ( [ actionName isEqualToString: @"click" ] ) { + return NSAccessibilityPressAction; + } else if ( [ actionName isEqualToString: @"togglePopup" ] ) { + return NSAccessibilityShowMenuAction; + } else if ( [ actionName isEqualToString: @"select" ] ) { + return NSAccessibilityPickAction; + } else if ( [ actionName isEqualToString: @"incrementLine" ] ) { + return NSAccessibilityIncrementAction; + } else if ( [ actionName isEqualToString: @"decrementLine" ] ) { + return NSAccessibilityDecrementAction; + } else if ( [ actionName isEqualToString: @"incrementBlock" ] ) { + return NSAccessibilityIncrementAction; // TODO ? + } else if ( [ actionName isEqualToString: @"decrementBlock" ] ) { + return NSAccessibilityDecrementAction; // TODO ? + } else if ( [ actionName isEqualToString: @"Browse" ] ) { + return NSAccessibilityPressAction; // TODO ? + } else { + return [ NSString string ]; + } +} + ++(NSArray *)actionNamesForElement:(AquaA11yWrapper *)wrapper { + NSMutableArray * actionNames = [ [ NSMutableArray alloc ] init ]; + if ( [ wrapper accessibleAction ] != nil ) { + for ( int cnt = 0; cnt < [ wrapper accessibleAction ] -> getAccessibleActionCount(); cnt++ ) { + [ actionNames addObject: [ AquaA11yActionWrapper nativeActionNameFor: CreateNSString ( [ wrapper accessibleAction ] -> getAccessibleActionDescription ( cnt ) ) ] ]; + } + } + return actionNames; +} + ++(void)doAction:(NSString *)action ofElement:(AquaA11yWrapper *)wrapper { + if ( [ wrapper accessibleAction ] != nil ) { + for ( int cnt = 0; cnt < [ wrapper accessibleAction ] -> getAccessibleActionCount(); cnt++ ) { + if ( [ action isEqualToString: [ AquaA11yActionWrapper nativeActionNameFor: CreateNSString ( [ wrapper accessibleAction ] -> getAccessibleActionDescription ( cnt ) ) ] ] ) { + [ wrapper accessibleAction ] -> doAccessibleAction ( cnt ); + break; + } + } + } +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ycomponentwrapper.h b/vcl/osx/a11ycomponentwrapper.h new file mode 100644 index 000000000000..450f0688155e --- /dev/null +++ b/vcl/osx/a11ycomponentwrapper.h @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YCOMPONENTWRAPPER_H +#define INCLUDED_VCL_OSX_A11YCOMPONENTWRAPPER_H + +#include "osx/osxvcltypes.h" +#include "osx/a11ywrapper.h" + +@interface AquaA11yComponentWrapper : NSObject +{ +} ++(id)sizeAttributeForElement:(AquaA11yWrapper *)wrapper; ++(id)positionAttributeForElement:(AquaA11yWrapper *)wrapper; ++(id)descriptionAttributeForElement:(AquaA11yWrapper *)wrapper; ++(void)addAttributeNamesTo:(NSMutableArray *)attributeNames; ++(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper; ++(void)setFocusedAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value; +@end + +#endif // INCLUDED_VCL_OSX_A11YCOMPONENTWRAPPER_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ycomponentwrapper.mm b/vcl/osx/a11ycomponentwrapper.mm new file mode 100644 index 000000000000..b91029d6aca8 --- /dev/null +++ b/vcl/osx/a11ycomponentwrapper.mm @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "quartz/utils.h" +#include "a11ycomponentwrapper.h" +#include "a11yrolehelper.h" +#include + +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::uno; + +// Wrapper for XAccessibleComponent and XAccessibleExtendedComponent + +@implementation AquaA11yComponentWrapper : NSObject + ++(id)sizeAttributeForElement:(AquaA11yWrapper *)wrapper { + Size size = [ wrapper accessibleComponent ] -> getSize(); + NSSize nsSize = NSMakeSize ( (float) size.Width, (float) size.Height ); + return [ NSValue valueWithSize: nsSize ]; +} + +// TODO: should be merged with AquaSalFrame::VCLToCocoa... to a general helper method ++(id)positionAttributeForElement:(AquaA11yWrapper *)wrapper { + // VCL coordinates are in upper-left-notation, Cocoa likes it the Cartesian way (lower-left) + NSRect screenRect = [ [ NSScreen mainScreen ] frame ]; + Size size = [ wrapper accessibleComponent ] -> getSize(); + Point location = [ wrapper accessibleComponent ] -> getLocationOnScreen(); + NSPoint nsPoint = NSMakePoint ( (float) location.X, (float) ( screenRect.size.height - size.Height - location.Y ) ); + return [ NSValue valueWithPoint: nsPoint ]; +} + ++(id)descriptionAttributeForElement:(AquaA11yWrapper *)wrapper { + if ( [ wrapper accessibleExtendedComponent ] != nil ) { + return CreateNSString ( [ wrapper accessibleExtendedComponent ] -> getToolTipText() ); + } else { + return nil; + } +} + ++(void)addAttributeNamesTo:(NSMutableArray *)attributeNames { + NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; + [ attributeNames addObjectsFromArray: [ NSArray arrayWithObjects: + NSAccessibilitySizeAttribute, + NSAccessibilityPositionAttribute, + NSAccessibilityFocusedAttribute, + NSAccessibilityEnabledAttribute, + nil ] ]; + [ pool release ]; +} + ++(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper { + BOOL isSettable = NO; + NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; + if ( [ attribute isEqualToString: NSAccessibilityFocusedAttribute ] + && ! [ [ AquaA11yRoleHelper getNativeRoleFrom: [ wrapper accessibleContext ] ] isEqualToString: NSAccessibilityScrollBarRole ] + && ! [ [ AquaA11yRoleHelper getNativeRoleFrom: [ wrapper accessibleContext ] ] isEqualToString: NSAccessibilityStaticTextRole ] ) { + isSettable = YES; + } + [ pool release ]; + return isSettable; +} + ++(void)setFocusedAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value { + if ( [ value boolValue ] == YES ) { + if ( [ wrapper accessibleContext ] -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) { + // special treatment for comboboxes: find the corresponding PANEL and set focus to it + Reference < XAccessible > rxParent = [ wrapper accessibleContext ] -> getAccessibleParent(); + if ( rxParent.is() ) { + Reference < XAccessibleContext > rxContext = rxParent->getAccessibleContext(); + if ( rxContext.is() && rxContext -> getAccessibleRole() == AccessibleRole::PANEL ) { + Reference < XAccessibleComponent > rxComponent = Reference < XAccessibleComponent > ( rxParent -> getAccessibleContext(), UNO_QUERY ); + if ( rxComponent.is() ) { + rxComponent -> grabFocus(); + } + } + } + } else { + [ wrapper accessibleComponent ] -> grabFocus(); + } + } +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11yfactory.mm b/vcl/osx/a11yfactory.mm new file mode 100644 index 000000000000..30437a837936 --- /dev/null +++ b/vcl/osx/a11yfactory.mm @@ -0,0 +1,219 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" +#include "osx/a11yfactory.h" +#include "osx/a11yfocustracker.hxx" + +#include "a11yfocuslistener.hxx" +#include "a11yrolehelper.h" +#include "a11ywrapperbutton.h" +#include "a11ywrapperstatictext.h" +#include "a11ywrappertextarea.h" +#include "a11ywrappercheckbox.h" +#include "a11ywrappercombobox.h" +#include "a11ywrappergroup.h" +#include "a11ywrapperlist.h" +#include "a11ywrapperradiobutton.h" +#include "a11ywrapperradiogroup.h" +#include "a11ywrapperrow.h" +#include "a11ywrapperscrollarea.h" +#include "a11ywrapperscrollbar.h" +#include "a11ywrappersplitter.h" +#include "a11ywrappertabgroup.h" +#include "a11ywrappertoolbar.h" +#include "a11ytablewrapper.h" + +#include + +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::uno; + +static bool enabled = false; + +@implementation AquaA11yFactory : NSObject + +#pragma mark - +#pragma mark Wrapper Repository + ++(NSMutableDictionary *)allWrapper { + static NSMutableDictionary * mdAllWrapper = nil; + if ( mdAllWrapper == nil ) { + mdAllWrapper = [ [ [ NSMutableDictionary alloc ] init ] retain ]; + // initialize keyboard focus tracker + rtl::Reference< AquaA11yFocusListener > listener( AquaA11yFocusListener::get() ); + AquaA11yFocusTracker::get().setFocusListener(listener.get()); + enabled = true; + } + return mdAllWrapper; +} + ++(NSValue *)keyForAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext { + return [ NSValue valueWithPointer: rxAccessibleContext.get() ]; +} + ++(NSValue *)keyForAccessibleContextAsRadioGroup: (Reference < XAccessibleContext >) rxAccessibleContext { + return [ NSValue valueWithPointer: ( rxAccessibleContext.get() + 2 ) ]; +} + ++(AquaA11yWrapper *)wrapperForAccessible: (Reference < XAccessible >) rxAccessible { + if ( rxAccessible.is() ) { + Reference< XAccessibleContext > xAccessibleContext = rxAccessible->getAccessibleContext(); + if( xAccessibleContext.is() ) { + return [ AquaA11yFactory wrapperForAccessibleContext: xAccessibleContext ]; + } + } + return nil; +} + ++(AquaA11yWrapper *)wrapperForAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext { + return [ AquaA11yFactory wrapperForAccessibleContext: rxAccessibleContext createIfNotExists: YES asRadioGroup: NO ]; +} + ++(AquaA11yWrapper *)wrapperForAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext createIfNotExists:(BOOL) bCreate { + return [ AquaA11yFactory wrapperForAccessibleContext: rxAccessibleContext createIfNotExists: bCreate asRadioGroup: NO ]; +} + ++(AquaA11yWrapper *)wrapperForAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext createIfNotExists:(BOOL) bCreate asRadioGroup:(BOOL) asRadioGroup{ + NSMutableDictionary * dAllWrapper = [ AquaA11yFactory allWrapper ]; + NSValue * nKey = nil; + if ( asRadioGroup ) { + nKey = [ AquaA11yFactory keyForAccessibleContextAsRadioGroup: rxAccessibleContext ]; + } else { + nKey = [ AquaA11yFactory keyForAccessibleContext: rxAccessibleContext ]; + } + AquaA11yWrapper * aWrapper = (AquaA11yWrapper *) [ dAllWrapper objectForKey: nKey ]; + if ( aWrapper != nil ) { + [ aWrapper retain ]; + } else if ( bCreate ) { + NSString * nativeRole = [ AquaA11yRoleHelper getNativeRoleFrom: rxAccessibleContext.get() ]; + // TODO: reflection + if ( [ nativeRole isEqualToString: NSAccessibilityButtonRole ] ) { + aWrapper = [ [ AquaA11yWrapperButton alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } else if ( [ nativeRole isEqualToString: NSAccessibilityTextAreaRole ] ) { + aWrapper = [ [ AquaA11yWrapperTextArea alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } else if ( [ nativeRole isEqualToString: NSAccessibilityStaticTextRole ] ) { + aWrapper = [ [ AquaA11yWrapperStaticText alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } else if ( [ nativeRole isEqualToString: NSAccessibilityComboBoxRole ] ) { + aWrapper = [ [ AquaA11yWrapperComboBox alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } else if ( [ nativeRole isEqualToString: NSAccessibilityGroupRole ] ) { + aWrapper = [ [ AquaA11yWrapperGroup alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } else if ( [ nativeRole isEqualToString: NSAccessibilityToolbarRole ] ) { + aWrapper = [ [ AquaA11yWrapperToolbar alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } else if ( [ nativeRole isEqualToString: NSAccessibilityScrollAreaRole ] ) { + aWrapper = [ [ AquaA11yWrapperScrollArea alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } else if ( [ nativeRole isEqualToString: NSAccessibilityTabGroupRole ] ) { + aWrapper = [ [ AquaA11yWrapperTabGroup alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } else if ( [ nativeRole isEqualToString: NSAccessibilityScrollBarRole ] ) { + aWrapper = [ [ AquaA11yWrapperScrollBar alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } else if ( [ nativeRole isEqualToString: NSAccessibilityCheckBoxRole ] ) { + aWrapper = [ [ AquaA11yWrapperCheckBox alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } else if ( [ nativeRole isEqualToString: NSAccessibilityRadioGroupRole ] ) { + aWrapper = [ [ AquaA11yWrapperRadioGroup alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } else if ( [ nativeRole isEqualToString: NSAccessibilityRadioButtonRole ] ) { + aWrapper = [ [ AquaA11yWrapperRadioButton alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } else if ( [ nativeRole isEqualToString: NSAccessibilityRowRole ] ) { + aWrapper = [ [ AquaA11yWrapperRow alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } else if ( [ nativeRole isEqualToString: NSAccessibilityListRole ] ) { + aWrapper = [ [ AquaA11yWrapperList alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } else if ( [ nativeRole isEqualToString: NSAccessibilitySplitterRole ] ) { + aWrapper = [ [ AquaA11yWrapperSplitter alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } else if ( [ nativeRole isEqualToString: NSAccessibilityTableRole ] ) { + aWrapper = [ [ AquaA11yTableWrapper alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } else { + aWrapper = [ [ AquaA11yWrapper alloc ] initWithAccessibleContext: rxAccessibleContext ]; + } + [ nativeRole release ]; + [ aWrapper setActsAsRadioGroup: asRadioGroup ]; + #if 0 + /* #i102033# NSAccessibility does not seemt to know an equivalent for transient children. + That means we need to cache this, else e.g. tree list boxes are not accessible (moreover + it crashes by notifying dead objects - which would seemt o be another bug) + + FIXME: + Unfortunately this can increase memory consumption drastically until the non transient parent + is destroyed an finally all the transients are released. + */ + if ( ! rxAccessibleContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::TRANSIENT ) ) + #endif + { + [ dAllWrapper setObject: aWrapper forKey: nKey ]; + /* fdo#67410: Accessibility notifications are not delivered on NSView subclasses that do not + "reasonably" participate in NSView hierarchy (perhaps the only important point is + that the view is a transitive subview of the NSWindow's content view, but I + did not try to verify that). + + So let the superview-subviews relationship mirror the AXParent-AXChildren relationship. + */ + id parent = [aWrapper accessibilityAttributeValue:NSAccessibilityParentAttribute]; + if (parent) { + if ([parent isKindOfClass:[NSView class]]) { + // SAL_DEBUG("Wrapper INIT: " << [[aWrapper description] UTF8String] << " ==> " << [[parent description] UTF8String]); + NSView *parentView = (NSView *)parent; + [parentView addSubview:aWrapper positioned:NSWindowBelow relativeTo:nil]; + } else if ([parent isKindOfClass:NSClassFromString(@"SalFrameWindow")]) { + NSWindow *window = (NSWindow *)parent; + NSView *salView = [window contentView]; + // SAL_DEBUG("Wrapper INIT SAL: " << [[aWrapper description] UTF8String] << " ==> " << [[salView description] UTF8String]); + [salView addSubview:aWrapper positioned:NSWindowBelow relativeTo:nil]; + } else { + // SAL_DEBUG("Wrapper INIT: !! " << [[aWrapper description] UTF8String] << " !==>! " << [[parent description] UTF8String] << "!!"); + } + } else { + // SAL_DEBUG("Wrapper INIT: " << [[aWrapper description] UTF8String] << " ==> NO PARENT"); + } + } + } + return aWrapper; +} + ++(void)insertIntoWrapperRepository: (NSView *) viewElement forAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext { + NSMutableDictionary * dAllWrapper = [ AquaA11yFactory allWrapper ]; + [ dAllWrapper setObject: viewElement forKey: [ AquaA11yFactory keyForAccessibleContext: rxAccessibleContext ] ]; +} + ++(void)removeFromWrapperRepositoryFor: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) rxAccessibleContext { + // TODO: when RADIO_BUTTON search for associated RadioGroup-wrapper and delete that as well + AquaA11yWrapper * theWrapper = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessibleContext createIfNotExists: NO ]; + if ( theWrapper != nil ) { + if (![theWrapper isKindOfClass:NSClassFromString(@"SalFrameView")]) { + [theWrapper removeFromSuperview]; + } + [ [ AquaA11yFactory allWrapper ] removeObjectForKey: [ AquaA11yFactory keyForAccessibleContext: rxAccessibleContext ] ]; + [ theWrapper release ]; + } +} + ++(void)registerView: (NSView *) theView { + if ( enabled && [ theView isKindOfClass: [ AquaA11yWrapper class ] ] ) { + // insertIntoWrapperRepository gets called from SalFrameView itself to bootstrap the bridge initially + [ (AquaA11yWrapper *) theView accessibleContext ]; + } +} + ++(void)revokeView: (NSView *) theView { + if ( enabled && [ theView isKindOfClass: [ AquaA11yWrapper class ] ] ) { + [ AquaA11yFactory removeFromWrapperRepositoryFor: [ (AquaA11yWrapper *) theView accessibleContext ] ]; + } +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11yfocuslistener.cxx b/vcl/osx/a11yfocuslistener.cxx new file mode 100644 index 000000000000..c4e296072868 --- /dev/null +++ b/vcl/osx/a11yfocuslistener.cxx @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include + +#include "osx/a11yfocustracker.hxx" +#include "osx/a11yfactory.h" + +#include "a11yfocuslistener.hxx" + +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::uno; + + +rtl::Reference< AquaA11yFocusListener > AquaA11yFocusListener::theListener; + +//------------------------------------------------------------------------------ + +rtl::Reference< AquaA11yFocusListener > AquaA11yFocusListener::get() +{ + if ( ! theListener.is() ) + theListener = new AquaA11yFocusListener(); + + return theListener; +} + +//------------------------------------------------------------------------------ + +AquaA11yFocusListener::AquaA11yFocusListener() : m_focusedObject(nil) +{ +} + +//------------------------------------------------------------------------------ + +id AquaA11yFocusListener::getFocusedUIElement() +{ + if ( nil == m_focusedObject ) { + Reference< XAccessible > xAccessible( AquaA11yFocusTracker::get().getFocusedObject() ); + try { + if( xAccessible.is() ) { + Reference< XAccessibleContext > xContext(xAccessible->getAccessibleContext()); + if( xContext.is() ) + m_focusedObject = [ AquaA11yFactory wrapperForAccessibleContext: xContext ]; + } + } catch(const RuntimeException &) { + // intentionally do nothing .. + } + } + + return m_focusedObject; +} + +//------------------------------------------------------------------------------ + +void SAL_CALL +AquaA11yFocusListener::focusedObjectChanged(const Reference< XAccessible >& xAccessible) +{ + if ( nil != m_focusedObject ) { + [ m_focusedObject release ]; + m_focusedObject = nil; + } + + try { + if( xAccessible.is() ) { + Reference< XAccessibleContext > xContext(xAccessible->getAccessibleContext()); + if( xContext.is() ) + { + m_focusedObject = [ AquaA11yFactory wrapperForAccessibleContext: xContext ]; + NSAccessibilityPostNotification(m_focusedObject, NSAccessibilityFocusedUIElementChangedNotification); + } + } + } catch(const RuntimeException &) { + // intentionally do nothing .. + } +} + +//------------------------------------------------------------------------------ + +oslInterlockedCount SAL_CALL +AquaA11yFocusListener::acquire() SAL_THROW(()) +{ + return ReferenceObject::acquire(); +} + +//------------------------------------------------------------------------------ + +oslInterlockedCount SAL_CALL +AquaA11yFocusListener::release() SAL_THROW(()) +{ + return ReferenceObject::release(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11yfocuslistener.hxx b/vcl/osx/a11yfocuslistener.hxx new file mode 100644 index 000000000000..42d5c358b4cd --- /dev/null +++ b/vcl/osx/a11yfocuslistener.hxx @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YFOCUSLISTENER_HXX +#define INCLUDED_VCL_OSX_A11YFOCUSLISTENER_HXX + +#include + +#include "osx/keyboardfocuslistener.hxx" +#include "osx/osxvcltypes.h" + +class AquaA11yFocusListener : + public KeyboardFocusListener, + public salhelper::ReferenceObject +{ + id m_focusedObject; + + static rtl::Reference< AquaA11yFocusListener > theListener; + + AquaA11yFocusListener(); + virtual ~AquaA11yFocusListener() {}; +public: + + static rtl::Reference< AquaA11yFocusListener > get(); + + id getFocusedUIElement(); + + // KeyboardFocusListener + virtual void SAL_CALL focusedObjectChanged(const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible); + + // rtl::IReference + virtual oslInterlockedCount SAL_CALL acquire() SAL_THROW(()); + virtual oslInterlockedCount SAL_CALL release() SAL_THROW(()); +}; + +#endif // INCLUDED_VCL_OSX_A11YFOCUSLISTENER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11yfocustracker.cxx b/vcl/osx/a11yfocustracker.cxx new file mode 100644 index 000000000000..1017969c879a --- /dev/null +++ b/vcl/osx/a11yfocustracker.cxx @@ -0,0 +1,284 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "vcl/svapp.hxx" +#include "vcl/window.hxx" +#include "vcl/toolbox.hxx" +#include "vcl/menu.hxx" + +#include "osx/a11yfocustracker.hxx" + +#include "documentfocuslistener.hxx" + +#include +#include +#include +#include +#include + +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::uno; + +//------------------------------------------------------------------------------ + +static inline Window * +getWindow(const ::VclSimpleEvent *pEvent) +{ + return static_cast< const ::VclWindowEvent *> (pEvent)->GetWindow(); +} + + +//------------------------------------------------------------------------------ + +// callback function for Application::addEventListener + +long AquaA11yFocusTracker::WindowEventHandler(AquaA11yFocusTracker *pFocusTracker, ::VclSimpleEvent const *pEvent) +{ + switch (pEvent->GetId()) + { + case VCLEVENT_WINDOW_PAINT: + pFocusTracker-> toolbox_open_floater( getWindow(pEvent) ); + break; + case VCLEVENT_WINDOW_GETFOCUS: + pFocusTracker->window_got_focus( getWindow(pEvent) ); + break; + case VCLEVENT_OBJECT_DYING: + pFocusTracker->m_aDocumentWindowList.erase( getWindow(pEvent) ); + // intentional pass through .. + case VCLEVENT_TOOLBOX_HIGHLIGHTOFF: + pFocusTracker->toolbox_highlight_off( getWindow(pEvent) ); + break; + case VCLEVENT_TOOLBOX_HIGHLIGHT: + pFocusTracker->toolbox_highlight_on( getWindow(pEvent) ); + break; + case VCLEVENT_TABPAGE_ACTIVATE: + pFocusTracker->tabpage_activated( getWindow(pEvent) ); + break; + case VCLEVENT_MENU_HIGHLIGHT: + // Inspired by code in WindowEventHandler in + // vcl/unx/gtk/a11y/atkutil.cxx, find out what kind of event + // it is to avoid blindly using a static_cast and crash, + // fdo#47275. + if( const VclMenuEvent* pMenuEvent = dynamic_cast < const VclMenuEvent* > (pEvent) ) + { + pFocusTracker->menu_highlighted( pMenuEvent ); + } + else if( const VclAccessibleEvent* pAccEvent = dynamic_cast < const VclAccessibleEvent* > (pEvent) ) + { + Reference< XAccessible > xAccessible = pAccEvent->GetAccessible(); + if( xAccessible.is() ) + pFocusTracker->setFocusedObject( xAccessible ); + } + break; + default: + break; + }; + + return 0; +} + +//------------------------------------------------------------------------------ + +AquaA11yFocusTracker::AquaA11yFocusTracker() : + m_aWindowEventLink(this, (PSTUB) WindowEventHandler), + m_xDocumentFocusListener(new DocumentFocusListener(*this)) +{ + Application::AddEventListener(m_aWindowEventLink); + window_got_focus(Application::GetFocusWindow()); +} + +//------------------------------------------------------------------------------ + +void AquaA11yFocusTracker::setFocusedObject(const Reference< XAccessible >& xAccessible) +{ + if( xAccessible != m_xFocusedObject ) + { + m_xFocusedObject = xAccessible; + + if( m_aFocusListener.is() ) + m_aFocusListener->focusedObjectChanged(xAccessible); + } +} + +//------------------------------------------------------------------------------ + +void AquaA11yFocusTracker::notify_toolbox_item_focus(ToolBox *pToolBox) +{ + Reference< XAccessible > xAccessible( pToolBox->GetAccessible() ); + + if( xAccessible.is() ) + { + Reference< XAccessibleContext > xContext(xAccessible->getAccessibleContext()); + + if( xContext.is() ) + { + sal_Int32 nPos = pToolBox->GetItemPos( pToolBox->GetHighlightItemId() ); + if( nPos != TOOLBOX_ITEM_NOTFOUND ) + setFocusedObject( xContext->getAccessibleChild( nPos ) ); + } + } +} + +//------------------------------------------------------------------------------ + +void AquaA11yFocusTracker::toolbox_open_floater(Window *pWindow) +{ + bool bToolboxFound = false; + bool bFloatingWindowFound = false; + Window * pFloatingWindow = NULL; + while ( pWindow != NULL ) { + if ( pWindow->GetType() == WINDOW_TOOLBOX ) { + bToolboxFound = true; + } else if ( pWindow->GetType() == WINDOW_FLOATINGWINDOW ) { + bFloatingWindowFound = true; + pFloatingWindow = pWindow; + } + pWindow = pWindow->GetParent(); + } + if ( bToolboxFound && bFloatingWindowFound ) { + Reference < XAccessible > rxAccessible = pFloatingWindow -> GetAccessible(); + if ( ! rxAccessible.is() ) { + return; + } + Reference < XAccessibleContext > rxContext = rxAccessible -> getAccessibleContext(); + if ( ! rxContext.is() ) { + return; + } + if ( rxContext -> getAccessibleChildCount() > 0 ) { + Reference < XAccessible > rxAccessibleChild = rxContext -> getAccessibleChild( 0 ); + if ( ! rxAccessibleChild.is() ) { + return; + } + setFocusedObject ( rxAccessibleChild ); + } + } +} + +//------------------------------------------------------------------------------ + +void AquaA11yFocusTracker::toolbox_highlight_on(Window *pWindow) +{ + // Make sure either the toolbox or its parent toolbox has the focus + if ( ! pWindow->HasFocus() ) + { + ToolBox* pToolBoxParent = dynamic_cast< ToolBox * >( pWindow->GetParent() ); + if ( ! pToolBoxParent || ! pToolBoxParent->HasFocus() ) + return; + } + + notify_toolbox_item_focus(static_cast (pWindow)); +} + +//------------------------------------------------------------------------------ + +void AquaA11yFocusTracker::toolbox_highlight_off(Window *pWindow) +{ + ToolBox* pToolBoxParent = dynamic_cast< ToolBox * >( pWindow->GetParent() ); + + // Notify when leaving sub toolboxes + if( pToolBoxParent && pToolBoxParent->HasFocus() ) + notify_toolbox_item_focus( pToolBoxParent ); +} + +//------------------------------------------------------------------------------ + +void AquaA11yFocusTracker::tabpage_activated(Window *pWindow) +{ + Reference< XAccessible > xAccessible( pWindow->GetAccessible() ); + + if( xAccessible.is() ) + { + Reference< XAccessibleSelection > xSelection(xAccessible->getAccessibleContext(), UNO_QUERY); + + if( xSelection.is() ) + setFocusedObject( xSelection->getSelectedAccessibleChild(0) ); + } +} + +//------------------------------------------------------------------------------ + +void AquaA11yFocusTracker::menu_highlighted(const VclMenuEvent *pEvent) +{ + Menu * pMenu = pEvent->GetMenu(); + + if( pMenu ) + { + Reference< XAccessible > xAccessible( pMenu->GetAccessible() ); + + if( xAccessible.is() ) + setFocusedObject( xAccessible ); + } +} + +//------------------------------------------------------------------------------ + +void AquaA11yFocusTracker::window_got_focus(Window *pWindow) +{ + // The menu bar is handled through VCLEVENT_MENU_HIGHLIGHTED + if( ! pWindow || !pWindow->IsReallyVisible() || pWindow->GetType() == WINDOW_MENUBARWINDOW ) + return; + + // ToolBoxes are handled through VCLEVENT_TOOLBOX_HIGHLIGHT + if( pWindow->GetType() == WINDOW_TOOLBOX ) + return; + + if( pWindow->GetType() == WINDOW_TABCONTROL ) + { + tabpage_activated( pWindow ); + return; + } + + Reference< XAccessible > xAccessible(pWindow->GetAccessible()); + + if( ! xAccessible.is() ) + return; + + Reference< XAccessibleContext > xContext = xAccessible->getAccessibleContext(); + + if( ! xContext.is() ) + return; + + Reference< XAccessibleStateSet > xStateSet = xContext->getAccessibleStateSet(); + + if( ! xStateSet.is() ) + return; + +/* the UNO ToolBox wrapper does not (yet?) support XAccessibleSelection, so we + * need to add listeners to the children instead of re-using the tabpage stuff + */ + if( xStateSet->contains(AccessibleStateType::FOCUSED) && (pWindow->GetType() != WINDOW_TREELISTBOX) ) + { + setFocusedObject( xAccessible ); + } + else + { + if( m_aDocumentWindowList.find(pWindow) == m_aDocumentWindowList.end() ) + { + m_aDocumentWindowList.insert(pWindow); + m_xDocumentFocusListener->attachRecursive(xAccessible, xContext, xStateSet); + } +#ifdef ENABLE_TRACING + else + fprintf(stderr, "Window %p already in the list\n", pWindow ); +#endif + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ylistener.cxx b/vcl/osx/a11ylistener.cxx new file mode 100644 index 000000000000..dafabb7133c2 --- /dev/null +++ b/vcl/osx/a11ylistener.cxx @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "osx/salinst.h" +#include "osx/a11ylistener.hxx" +#include "osx/a11yfactory.h" +#include "osx/a11yfocustracker.hxx" +#include "osx/a11ywrapper.h" + +#include "a11ytextwrapper.h" + +#include +#include +#include +#include + +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; + +NSString * getTableNotification( const AccessibleEventObject& aEvent ) +{ + AccessibleTableModelChange aChange; + NSString * notification = nil; + + if( (aEvent.NewValue >>= aChange) && + ( AccessibleTableModelChangeType::INSERT == aChange.Type || AccessibleTableModelChangeType::DELETE == aChange.Type ) && + aChange.FirstRow != aChange.LastRow ) + { + notification = NSAccessibilityRowCountChangedNotification; + } + + return notification; +} + +//------------------------------------------------------------------------------ + +AquaA11yEventListener::AquaA11yEventListener(id wrapperObject, sal_Int16 role) : m_wrapperObject(wrapperObject), m_role(role) +{ + [ m_wrapperObject retain ]; +} + +//------------------------------------------------------------------------------ + +AquaA11yEventListener::~AquaA11yEventListener() +{ + [ m_wrapperObject release ]; +} + +//------------------------------------------------------------------------------ + +void SAL_CALL +AquaA11yEventListener::disposing( const EventObject& ) throw( RuntimeException ) +{ + [ AquaA11yFactory removeFromWrapperRepositoryFor: [ (AquaA11yWrapper *) m_wrapperObject accessibleContext ] ]; +} + +//------------------------------------------------------------------------------ + +void SAL_CALL +AquaA11yEventListener::notifyEvent( const AccessibleEventObject& aEvent ) throw( RuntimeException ) +{ + NSString * notification = nil; + id element = m_wrapperObject; + Rectangle bounds; + + // TODO: NSAccessibilityValueChanged, NSAccessibilitySelectedRowsChangedNotification + switch( aEvent.EventId ) + { + case AccessibleEventId::ACTIVE_DESCENDANT_CHANGED: + if( m_role != AccessibleRole::LIST ) { + Reference< XAccessible > xAccessible; + if( aEvent.NewValue >>= xAccessible ) + AquaA11yFocusTracker::get().setFocusedObject( xAccessible ); + } + break; + + case AccessibleEventId::NAME_CHANGED: + notification = NSAccessibilityTitleChangedNotification; + break; + + case AccessibleEventId::CHILD: + // only needed for tooltips (says Apple) + if ( m_role == AccessibleRole::TOOL_TIP ) { + if(aEvent.NewValue.hasValue()) { + notification = NSAccessibilityCreatedNotification; + } else if(aEvent.OldValue.hasValue()) { + notification = NSAccessibilityUIElementDestroyedNotification; + } + } + break; + + case AccessibleEventId::INVALIDATE_ALL_CHILDREN: + // TODO: depricate or remember all children + break; + + case AccessibleEventId::BOUNDRECT_CHANGED: + bounds = [ element accessibleComponent ] -> getBounds(); + if ( m_oldBounds.X != 0 && ( bounds.X != m_oldBounds.X || bounds.Y != m_oldBounds.Y ) ) { + NSAccessibilityPostNotification(element, NSAccessibilityMovedNotification); // post directly since both cases can happen simultaneously + } + if ( m_oldBounds.X != 0 && ( bounds.Width != m_oldBounds.Width || bounds.Height != m_oldBounds.Height ) ) { + NSAccessibilityPostNotification(element, NSAccessibilityResizedNotification); // post directly since both cases can happen simultaneously + } + m_oldBounds = bounds; + break; + + case AccessibleEventId::SELECTION_CHANGED: + notification = NSAccessibilitySelectedChildrenChangedNotification; + break; + + case AccessibleEventId::TEXT_SELECTION_CHANGED: + notification = NSAccessibilitySelectedTextChangedNotification; + break; + + case AccessibleEventId::TABLE_MODEL_CHANGED: + notification = getTableNotification(aEvent); + break; + + case AccessibleEventId::CARET_CHANGED: + notification = NSAccessibilitySelectedTextChangedNotification; + break; + + case AccessibleEventId::TEXT_CHANGED: + notification = NSAccessibilityValueChangedNotification; + break; + + default: + break; + } + + if( nil != notification ) + NSAccessibilityPostNotification(element, notification); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11yrolehelper.h b/vcl/osx/a11yrolehelper.h new file mode 100644 index 000000000000..21b2ff5b960a --- /dev/null +++ b/vcl/osx/a11yrolehelper.h @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YROLEHELPER_H +#define INCLUDED_VCL_OSX_A11YROLEHELPER_H + +#include "osx/salinst.h" +#include + +@interface AquaA11yRoleHelper : NSObject +{ +} ++(id)getNativeRoleFrom: (::com::sun::star::accessibility::XAccessibleContext *) accessibleContext; ++(id)getNativeSubroleFrom: (sal_Int16) nRole; ++(id)getRoleDescriptionFrom: (NSString *) role with: (NSString *) subRole; +@end + +#endif // INCLUDED_VCL_OSX_A11YROLEHELPER_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11yrolehelper.mm b/vcl/osx/a11yrolehelper.mm new file mode 100644 index 000000000000..2940a4b2f7aa --- /dev/null +++ b/vcl/osx/a11yrolehelper.mm @@ -0,0 +1,270 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/a11yfactory.h" + +#include "a11yrolehelper.h" + +#include +#include + +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::uno; + +@implementation AquaA11yRoleHelper + ++(id)simpleMapNativeRoleFrom: (XAccessibleContext *) accessibleContext { + id nativeRole = nil; + + if (accessibleContext == NULL) + return nativeRole; + + switch( accessibleContext -> getAccessibleRole() ) { +#define MAP(a,b) \ + case a: nativeRole = b; break + + MAP( AccessibleRole::UNKNOWN, NSAccessibilityUnknownRole ); + MAP( AccessibleRole::ALERT, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::COLUMN_HEADER, NSAccessibilityColumnRole ); + MAP( AccessibleRole::CANVAS, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::CHECK_BOX, NSAccessibilityCheckBoxRole ); + MAP( AccessibleRole::CHECK_MENU_ITEM, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::COLOR_CHOOSER, NSAccessibilityColorWellRole ); // FIXME + MAP( AccessibleRole::COMBO_BOX, NSAccessibilityComboBoxRole ); + MAP( AccessibleRole::DATE_EDITOR, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::DESKTOP_ICON, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::DESKTOP_PANE, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::DIRECTORY_PANE, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::DIALOG, NSAccessibilityGroupRole ); + MAP( AccessibleRole::DOCUMENT, NSAccessibilityGroupRole ); + MAP( AccessibleRole::EMBEDDED_OBJECT, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::END_NOTE, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::FILE_CHOOSER, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::FILLER, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::FONT_CHOOSER, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::FOOTER, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::FOOTNOTE, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::FRAME, NSAccessibilityWindowRole ); + MAP( AccessibleRole::GLASS_PANE, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::GRAPHIC, NSAccessibilityImageRole ); + MAP( AccessibleRole::GROUP_BOX, NSAccessibilityGroupRole ); + MAP( AccessibleRole::HEADER, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::HEADING, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::HYPER_LINK, NSAccessibilityLinkRole ); + MAP( AccessibleRole::ICON, NSAccessibilityImageRole ); + MAP( AccessibleRole::INTERNAL_FRAME, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::LABEL, NSAccessibilityStaticTextRole ); + MAP( AccessibleRole::LAYERED_PANE, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::LIST, NSAccessibilityMenuRole ); + MAP( AccessibleRole::LIST_ITEM, NSAccessibilityMenuItemRole ); + MAP( AccessibleRole::MENU, NSAccessibilityMenuRole ); + MAP( AccessibleRole::MENU_BAR, NSAccessibilityMenuBarRole ); + MAP( AccessibleRole::MENU_ITEM, NSAccessibilityMenuItemRole ); + MAP( AccessibleRole::OPTION_PANE, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::PAGE_TAB, NSAccessibilityButtonRole ); + MAP( AccessibleRole::PAGE_TAB_LIST, NSAccessibilityTabGroupRole ); + MAP( AccessibleRole::PANEL, NSAccessibilityGroupRole ); + MAP( AccessibleRole::PARAGRAPH, NSAccessibilityTextAreaRole ); + MAP( AccessibleRole::PASSWORD_TEXT, NSAccessibilityTextFieldRole ); + MAP( AccessibleRole::POPUP_MENU, NSAccessibilityMenuRole ); + MAP( AccessibleRole::PUSH_BUTTON, NSAccessibilityButtonRole ); + MAP( AccessibleRole::PROGRESS_BAR, NSAccessibilityProgressIndicatorRole ); + MAP( AccessibleRole::RADIO_BUTTON, NSAccessibilityRadioButtonRole ); + MAP( AccessibleRole::RADIO_MENU_ITEM, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::ROW_HEADER, NSAccessibilityRowRole ); + MAP( AccessibleRole::ROOT_PANE, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::SCROLL_BAR, NSAccessibilityScrollBarRole ); + MAP( AccessibleRole::SCROLL_PANE, NSAccessibilityScrollAreaRole ); + MAP( AccessibleRole::SHAPE, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::SEPARATOR, NSAccessibilitySplitterRole ); // FIXME + MAP( AccessibleRole::SLIDER, NSAccessibilitySliderRole ); + MAP( AccessibleRole::SPIN_BOX, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::SPLIT_PANE, NSAccessibilitySplitterRole ); + MAP( AccessibleRole::STATUS_BAR, NSAccessibilityGroupRole ); // FIXME + MAP( AccessibleRole::TABLE, NSAccessibilityTableRole ); + MAP( AccessibleRole::TABLE_CELL, NSAccessibilityTextFieldRole ); + MAP( AccessibleRole::TEXT, NSAccessibilityTextAreaRole ); + MAP( AccessibleRole::TEXT_FRAME, NSAccessibilityGroupRole ); + MAP( AccessibleRole::TOGGLE_BUTTON, NSAccessibilityCheckBoxRole ); + MAP( AccessibleRole::TOOL_BAR, NSAccessibilityToolbarRole ); + MAP( AccessibleRole::TOOL_TIP, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::TREE, NSAccessibilityGroupRole ); + MAP( AccessibleRole::VIEW_PORT, NSAccessibilityUnknownRole ); // FIXME + MAP( AccessibleRole::WINDOW, NSAccessibilityWindowRole ); + + MAP( AccessibleRole::BUTTON_DROPDOWN, NSAccessibilityMenuButtonRole ); + MAP( AccessibleRole::BUTTON_MENU, NSAccessibilityMenuButtonRole ); + MAP( AccessibleRole::CAPTION, NSAccessibilityUnknownRole ); + MAP( AccessibleRole::CHART, NSAccessibilityUnknownRole ); + MAP( AccessibleRole::FORM, NSAccessibilityUnknownRole ); + MAP( AccessibleRole::IMAGE_MAP, NSAccessibilityUnknownRole ); + MAP( AccessibleRole::NOTE, NSAccessibilityUnknownRole ); + MAP( AccessibleRole::PAGE, NSAccessibilityUnknownRole ); + MAP( AccessibleRole::RULER, NSAccessibilityUnknownRole ); + MAP( AccessibleRole::SECTION, NSAccessibilityUnknownRole ); + MAP( AccessibleRole::TREE_ITEM, NSAccessibilityUnknownRole ); + MAP( AccessibleRole::TREE_TABLE, NSAccessibilityUnknownRole ); + +#undef MAP + default: + break; + } + return nativeRole; +} + ++(id)getNativeRoleFrom: (XAccessibleContext *) accessibleContext { + id nativeRole = [ AquaA11yRoleHelper simpleMapNativeRoleFrom: accessibleContext ]; + if ( accessibleContext -> getAccessibleRole() == AccessibleRole::LABEL ) { + if ( accessibleContext -> getAccessibleChildCount() > 0 ) { + [ nativeRole release ]; + nativeRole = NSAccessibilityOutlineRole; + } else if ( accessibleContext -> getAccessibleParent().is() ) { + Reference < XAccessibleContext > rxParentContext = accessibleContext -> getAccessibleParent() -> getAccessibleContext(); + if ( rxParentContext.is() ) { + NSString * roleParent = (NSString *) [ AquaA11yRoleHelper simpleMapNativeRoleFrom: rxParentContext.get() ]; + if ( [ roleParent isEqualToString: NSAccessibilityOutlineRole ] ) { + [ nativeRole release ]; + nativeRole = NSAccessibilityRowRole; + } + [ roleParent release ]; + } + } + } else if ( accessibleContext -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) { + Reference < XAccessible > rxAccessible = accessibleContext -> getAccessibleChild(0); + if ( rxAccessible.is() ) { + Reference < XAccessibleContext > rxAccessibleContext = rxAccessible -> getAccessibleContext(); + if ( rxAccessibleContext.is() && rxAccessibleContext -> getAccessibleRole() == AccessibleRole::TEXT ) { + if ( ! rxAccessibleContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::EDITABLE ) ) { + [ nativeRole release ]; + nativeRole = NSAccessibilityPopUpButtonRole; + } + } + } + } + return nativeRole; +} + ++(id)getNativeSubroleFrom: (sal_Int16) nRole { + id nativeSubrole = nil; + switch( nRole ) { +#define MAP(a,b) \ + case a: nativeSubrole = b; break + + MAP( AccessibleRole::UNKNOWN, NSAccessibilityUnknownSubrole ); + MAP( AccessibleRole::ALERT, NSAccessibilitySystemDialogSubrole ); + MAP( AccessibleRole::COLUMN_HEADER, @"" ); + MAP( AccessibleRole::CANVAS, @"" ); + MAP( AccessibleRole::CHECK_BOX, @"" ); + MAP( AccessibleRole::CHECK_MENU_ITEM, @"" ); + MAP( AccessibleRole::COLOR_CHOOSER, @"" ); + MAP( AccessibleRole::COMBO_BOX, @"" ); + MAP( AccessibleRole::DATE_EDITOR, @"" ); + MAP( AccessibleRole::DESKTOP_ICON, @"" ); + MAP( AccessibleRole::DESKTOP_PANE, @"" ); + MAP( AccessibleRole::DIRECTORY_PANE, @"" ); + MAP( AccessibleRole::DIALOG, NSAccessibilityDialogSubrole ); + MAP( AccessibleRole::DOCUMENT, @"" ); + MAP( AccessibleRole::EMBEDDED_OBJECT, @"" ); + MAP( AccessibleRole::END_NOTE, @"" ); + MAP( AccessibleRole::FILE_CHOOSER, @"" ); + MAP( AccessibleRole::FILLER, @"" ); + MAP( AccessibleRole::FONT_CHOOSER, @"" ); + MAP( AccessibleRole::FOOTER, @"" ); + MAP( AccessibleRole::FOOTNOTE, @"" ); + MAP( AccessibleRole::FRAME, @"" ); + MAP( AccessibleRole::GLASS_PANE, @"" ); + MAP( AccessibleRole::GRAPHIC, @"" ); + MAP( AccessibleRole::GROUP_BOX, @"" ); + MAP( AccessibleRole::HEADER, @"" ); + MAP( AccessibleRole::HEADING, @"" ); + MAP( AccessibleRole::HYPER_LINK, NSAccessibilityTextLinkSubrole ); + MAP( AccessibleRole::ICON, @"" ); + MAP( AccessibleRole::INTERNAL_FRAME, @"" ); + MAP( AccessibleRole::LABEL, @"" ); + MAP( AccessibleRole::LAYERED_PANE, @"" ); + MAP( AccessibleRole::LIST, @"" ); + MAP( AccessibleRole::LIST_ITEM, NSAccessibilityOutlineRowSubrole ); + MAP( AccessibleRole::MENU, @"" ); + MAP( AccessibleRole::MENU_BAR, @"" ); + MAP( AccessibleRole::MENU_ITEM, @"" ); + MAP( AccessibleRole::OPTION_PANE, @"" ); + MAP( AccessibleRole::PAGE_TAB, @"" ); + MAP( AccessibleRole::PAGE_TAB_LIST, @"" ); + MAP( AccessibleRole::PANEL, @"" ); + MAP( AccessibleRole::PARAGRAPH, @"" ); + MAP( AccessibleRole::PASSWORD_TEXT, NSAccessibilitySecureTextFieldSubrole ); + MAP( AccessibleRole::POPUP_MENU, @"" ); + MAP( AccessibleRole::PUSH_BUTTON, @"" ); + MAP( AccessibleRole::PROGRESS_BAR, @"" ); + MAP( AccessibleRole::RADIO_BUTTON, @"" ); + MAP( AccessibleRole::RADIO_MENU_ITEM, @"" ); + MAP( AccessibleRole::ROW_HEADER, @"" ); + MAP( AccessibleRole::ROOT_PANE, @"" ); + MAP( AccessibleRole::SCROLL_BAR, @"" ); + MAP( AccessibleRole::SCROLL_PANE, @"" ); + MAP( AccessibleRole::SHAPE, @"" ); + MAP( AccessibleRole::SEPARATOR, @"" ); + MAP( AccessibleRole::SLIDER, @"" ); + MAP( AccessibleRole::SPIN_BOX, @"" ); + MAP( AccessibleRole::SPLIT_PANE, @"" ); + MAP( AccessibleRole::STATUS_BAR, @"" ); + MAP( AccessibleRole::TABLE, @"" ); + MAP( AccessibleRole::TABLE_CELL, @"" ); + MAP( AccessibleRole::TEXT, @"" ); + MAP( AccessibleRole::TEXT_FRAME, @"" ); + MAP( AccessibleRole::TOGGLE_BUTTON, @"" ); + MAP( AccessibleRole::TOOL_BAR, @"" ); + MAP( AccessibleRole::TOOL_TIP, @"" ); + MAP( AccessibleRole::TREE, @"" ); + MAP( AccessibleRole::VIEW_PORT, @"" ); + MAP( AccessibleRole::WINDOW, NSAccessibilityStandardWindowSubrole ); + + MAP( AccessibleRole::BUTTON_DROPDOWN, @"" ); + MAP( AccessibleRole::BUTTON_MENU, @"" ); + MAP( AccessibleRole::CAPTION, @"" ); + MAP( AccessibleRole::CHART, @"" ); + MAP( AccessibleRole::FORM, @"" ); + MAP( AccessibleRole::IMAGE_MAP, @"" ); + MAP( AccessibleRole::NOTE, @"" ); + MAP( AccessibleRole::PAGE, @"" ); + MAP( AccessibleRole::RULER, @"" ); + MAP( AccessibleRole::SECTION, @"" ); + MAP( AccessibleRole::TREE_ITEM, @"" ); + MAP( AccessibleRole::TREE_TABLE, @"" ); + +#undef MAP + default: + break; + } + return nativeSubrole; +} + ++(id)getRoleDescriptionFrom: (NSString *) role with: (NSString *) subRole { + id roleDescription; + if ( [ subRole length ] == 0 ) + roleDescription = NSAccessibilityRoleDescription( role, nil ); + else + roleDescription = NSAccessibilityRoleDescription( role, subRole ); + return roleDescription; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11yselectionwrapper.h b/vcl/osx/a11yselectionwrapper.h new file mode 100644 index 000000000000..9b254d7df1f6 --- /dev/null +++ b/vcl/osx/a11yselectionwrapper.h @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YSELECTIONWRAPPER_H +#define INCLUDED_VCL_OSX_A11YSELECTIONWRAPPER_H + +#include "osx/osxvcltypes.h" +#include "osx/a11ywrapper.h" + +@interface AquaA11ySelectionWrapper : NSObject +{ +} ++(id)selectedChildrenAttributeForElement:(AquaA11yWrapper *)wrapper; ++(void)addAttributeNamesTo:(NSMutableArray *)attributeNames; ++(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper; ++(void)setSelectedChildrenAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value; +@end + +#endif // INCLUDED_VCL_OSX_A11YSELECTIONWRAPPER_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11yselectionwrapper.mm b/vcl/osx/a11yselectionwrapper.mm new file mode 100644 index 000000000000..e341aedacfe0 --- /dev/null +++ b/vcl/osx/a11yselectionwrapper.mm @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" +#include "osx/a11yfactory.h" + +#include "a11yselectionwrapper.h" + +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::uno; + +@implementation AquaA11ySelectionWrapper : NSObject + ++(id)selectedChildrenAttributeForElement:(AquaA11yWrapper *)wrapper +{ + Reference< XAccessibleSelection > xAccessibleSelection = [ wrapper accessibleSelection ]; + if( xAccessibleSelection.is() ) + { + NSMutableArray * children = [ [ NSMutableArray alloc ] init ]; + try { + sal_Int32 n = xAccessibleSelection -> getSelectedAccessibleChildCount(); + for ( sal_Int32 i=0 ; i < n ; ++i ) { + [ children addObject: [ AquaA11yFactory wrapperForAccessible: xAccessibleSelection -> getSelectedAccessibleChild( i ) ] ]; + } + + return children; + + } catch ( Exception& e) + { + } + } + + return nil; +} + + ++(void)addAttributeNamesTo:(NSMutableArray *)attributeNames +{ + [ attributeNames addObject: NSAccessibilitySelectedChildrenAttribute ]; +} + ++(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper +{ + (void)wrapper; + if ( [ attribute isEqualToString: NSAccessibilitySelectedChildrenAttribute ] ) + { + return YES; + } + else + { + return NO; + } +} + ++(void)setSelectedChildrenAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value +{ + Reference< XAccessibleSelection > xAccessibleSelection = [ wrapper accessibleSelection ]; + try { + xAccessibleSelection -> clearAccessibleSelection(); + + unsigned c = [ value count ]; + for ( unsigned i = 0 ; i < c ; ++i ) { + xAccessibleSelection -> selectAccessibleChild( [ [ value objectAtIndex: i ] accessibleContext ] -> getAccessibleIndexInParent() ); + } + } catch ( Exception& e) { + } +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ytablewrapper.h b/vcl/osx/a11ytablewrapper.h new file mode 100644 index 000000000000..94b29bd44c78 --- /dev/null +++ b/vcl/osx/a11ytablewrapper.h @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YTABLEWRAPPER_H +#define INCLUDED_VCL_OSX_A11YTABLEWRAPPER_H + +#include "osx/a11ywrapper.h" + +#define MAXIMUM_ACCESSIBLE_TABLE_CELLS 1000 + +@interface AquaA11yTableWrapper : AquaA11yWrapper +{ +} ++(id)childrenAttributeForElement:(AquaA11yTableWrapper *)wrapper; ++(void)addAttributeNamesTo: (NSMutableArray *)attributeNames object: (AquaA11yWrapper*)pObject; + +-(id)rowsAttribute; +-(id)columnsAttribute; +@end +#endif // INCLUDED_VCL_OSX_A11YTABLEWRAPPER_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ytablewrapper.mm b/vcl/osx/a11ytablewrapper.mm new file mode 100644 index 000000000000..f772efcce4b1 --- /dev/null +++ b/vcl/osx/a11ytablewrapper.mm @@ -0,0 +1,204 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/a11yfactory.h" + +#include "a11ytablewrapper.h" + +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::uno; + +@implementation AquaA11yTableWrapper : AquaA11yWrapper + ++(id)childrenAttributeForElement:(AquaA11yTableWrapper *)wrapper +{ + XAccessibleTable * accessibleTable = [ wrapper accessibleTable ]; + NSArray* pResult = nil; + if( accessibleTable ) + { + NSMutableArray * cells = [ [ NSMutableArray alloc ] init ]; + try + { + sal_Int32 nRows = accessibleTable->getAccessibleRowCount(); + sal_Int32 nCols = accessibleTable->getAccessibleColumnCount(); + + if( nRows * nCols < MAXIMUM_ACCESSIBLE_TABLE_CELLS ) + { + // make all children visible to the hierarchy + for ( sal_Int32 rowCount = 0; rowCount < nRows; rowCount++ ) + { + for ( sal_Int32 columnCount = 0; columnCount < nCols; columnCount++ ) + { + Reference < XAccessible > rAccessibleCell = accessibleTable -> getAccessibleCellAt ( rowCount, columnCount ); + if ( rAccessibleCell.is() ) + { + id cell_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rAccessibleCell -> getAccessibleContext() ]; + [ cells addObject: cell_wrapper ]; + [ cell_wrapper release ]; + } + } + } + } + else + { + XAccessibleComponent * accessibleComponent = [ wrapper accessibleComponent ]; + // find out which cells are actually visible by determining the top-left-cell and the bottom-right-cell + Size tableSize = accessibleComponent -> getSize(); + Point point; + point.X = 0; + point.Y = 0; + Reference < XAccessible > rAccessibleTopLeft = accessibleComponent -> getAccessibleAtPoint ( point ); + point.X = tableSize.Width - 1; + point.Y = tableSize.Height - 1; + Reference < XAccessible > rAccessibleBottomRight = accessibleComponent -> getAccessibleAtPoint ( point ); + if ( rAccessibleTopLeft.is() && rAccessibleBottomRight.is() ) + { + sal_Int32 idxTopLeft = rAccessibleTopLeft -> getAccessibleContext() -> getAccessibleIndexInParent(); + sal_Int32 idxBottomRight = rAccessibleBottomRight -> getAccessibleContext() -> getAccessibleIndexInParent(); + sal_Int32 rowTopLeft = accessibleTable -> getAccessibleRow ( idxTopLeft ); + sal_Int32 columnTopLeft = accessibleTable -> getAccessibleColumn ( idxTopLeft ); + sal_Int32 rowBottomRight = accessibleTable -> getAccessibleRow ( idxBottomRight ); + sal_Int32 columnBottomRight = accessibleTable -> getAccessibleColumn ( idxBottomRight ); + // create an array containing the visible cells + for ( sal_Int32 rowCount = rowTopLeft; rowCount <= rowBottomRight; rowCount++ ) + { + for ( sal_Int32 columnCount = columnTopLeft; columnCount <= columnBottomRight; columnCount++ ) + { + Reference < XAccessible > rAccessibleCell = accessibleTable -> getAccessibleCellAt ( rowCount, columnCount ); + if ( rAccessibleCell.is() ) + { + id cell_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rAccessibleCell -> getAccessibleContext() ]; + [ cells addObject: cell_wrapper ]; + [ cell_wrapper release ]; + } + } + } + } + } + pResult = NSAccessibilityUnignoredChildren( cells ); + } + catch (const Exception &e) + { + } + [cells autorelease]; + } + + return pResult; +} + ++(void)addAttributeNamesTo: (NSMutableArray *)attributeNames object: (AquaA11yWrapper*)pObject +{ + XAccessibleTable * accessibleTable = [ pObject accessibleTable ]; + if( accessibleTable ) + { + sal_Int32 nRows = accessibleTable->getAccessibleRowCount(); + sal_Int32 nCols = accessibleTable->getAccessibleColumnCount(); + + + if( nRows*nCols < MAXIMUM_ACCESSIBLE_TABLE_CELLS ) + { + [ attributeNames addObject: NSAccessibilityRowsAttribute ]; + [ attributeNames addObject: NSAccessibilityColumnsAttribute ]; + } + } +} + +-(id)rowsAttribute +{ + NSArray* pResult = nil; + + XAccessibleTable * accessibleTable = [ self accessibleTable ]; + if( accessibleTable ) + { + sal_Int32 nRows = accessibleTable->getAccessibleRowCount(); + sal_Int32 nCols = accessibleTable->getAccessibleColumnCount(); + if( nRows * nCols < MAXIMUM_ACCESSIBLE_TABLE_CELLS ) + { + NSMutableArray * cells = [ [ NSMutableArray alloc ] init ]; + try + { + // find out number of rows + sal_Int32 nRows = accessibleTable->getAccessibleRowCount(); + for( sal_Int32 n = 0; n < nRows; n++ ) + { + Reference < XAccessible > rAccessibleCell = accessibleTable -> getAccessibleCellAt ( n, 0 ); + if ( rAccessibleCell.is() ) + { + id cell_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rAccessibleCell -> getAccessibleContext() ]; + [ cells addObject: cell_wrapper ]; + [ cell_wrapper release ]; + } + } + pResult = NSAccessibilityUnignoredChildren( cells ); + } + catch (const Exception &e) + { + pResult = nil; + } + [ cells autorelease ]; + } + } + + return pResult; +} + +-(id)columnsAttribute +{ + NSArray* pResult = nil; + + XAccessibleTable * accessibleTable = [ self accessibleTable ]; + + if( accessibleTable ) + { + sal_Int32 nRows = accessibleTable->getAccessibleRowCount(); + sal_Int32 nCols = accessibleTable->getAccessibleColumnCount(); + if( nRows * nCols < MAXIMUM_ACCESSIBLE_TABLE_CELLS ) + { + NSMutableArray * cells = [ [ NSMutableArray alloc ] init ]; + try + { + // find out number of columns + for( sal_Int32 n = 0; n < nCols; n++ ) + { + Reference < XAccessible > rAccessibleCell = accessibleTable -> getAccessibleCellAt ( 0, n ); + if ( rAccessibleCell.is() ) + { + id cell_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rAccessibleCell -> getAccessibleContext() ]; + [ cells addObject: cell_wrapper ]; + [ cell_wrapper release ]; + } + } + pResult = NSAccessibilityUnignoredChildren( cells ); + } + catch (const Exception &e) + { + pResult = nil; + } + [ cells autorelease ]; + } + } + + return pResult; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ytextattributeswrapper.h b/vcl/osx/a11ytextattributeswrapper.h new file mode 100644 index 000000000000..03e3b3a82eef --- /dev/null +++ b/vcl/osx/a11ytextattributeswrapper.h @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YTEXTATTRIBUTESWRAPPER_H +#define INCLUDED_VCL_OSX_A11YTEXTATTRIBUTESWRAPPER_H + +#include "osx/a11ywrapper.h" + +@interface AquaA11yTextAttributesWrapper : NSObject +{ +} ++(NSMutableAttributedString *)createAttributedStringForElement:(AquaA11yWrapper *)wrapper inOrigRange:(id)origRange; +@end +#endif // INCLUDED_VCL_OSX_A11YTEXTATTRIBUTESWRAPPER_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ytextattributeswrapper.mm b/vcl/osx/a11ytextattributeswrapper.mm new file mode 100644 index 000000000000..339103740be0 --- /dev/null +++ b/vcl/osx/a11ytextattributeswrapper.mm @@ -0,0 +1,355 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" +#include "quartz/utils.h" +#include "quartz/salgdi.h" + +#include "a11ytextattributeswrapper.h" + +#include +#include +#include +#include +#include +#include + +namespace css_awt = ::com::sun::star::awt; +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::rtl; + +// cannot use NSFontDescriptor as it has no notion of explicit NSUn{bold,italic}FontMask +@interface AquaA11yFontDescriptor : NSObject +{ + NSString *_name; + NSFontTraitMask _traits; + CGFloat _size; +} +-(void)setName:(NSString*)name; +-(void)setBold:(NSFontTraitMask)bold; +-(void)setItalic:(NSFontTraitMask)italic; +-(void)setSize:(CGFloat)size; +-(NSFont*)font; +@end + +@implementation AquaA11yFontDescriptor +- (id)init +{ + if((self = [super init])) + { + _name = nil; + _traits = 0; + _size = 0.0; + } + return self; +} + +- (id)initWithDescriptor:(AquaA11yFontDescriptor*)descriptor { + if((self = [super init])) + { + _name = [descriptor->_name retain]; + _traits = descriptor->_traits; + _size = descriptor->_size; + } + return self; +} + +- (void)dealloc { + [_name release]; + [super dealloc]; +} + +-(void)setName:(NSString*)name { + if (_name != name) { + [name retain]; + [_name release]; + _name = name; + } +} + +-(void)setBold:(NSFontTraitMask)bold { + _traits &= ~(NSBoldFontMask | NSUnboldFontMask); + _traits |= bold & (NSBoldFontMask | NSUnboldFontMask); +}; + +-(void)setItalic:(NSFontTraitMask)italic { + _traits &= ~(NSItalicFontMask | NSUnitalicFontMask); + _traits |= italic & (NSItalicFontMask | NSUnitalicFontMask); +}; + +-(void)setSize:(CGFloat)size { _size = size; } + +-(NSFont*)font { + return [[NSFontManager sharedFontManager] fontWithFamily:_name traits:_traits weight:0 size:_size]; +} +@end + +@implementation AquaA11yTextAttributesWrapper : NSObject + ++(int)convertUnderlineStyle:(PropertyValue)property { + int underlineStyle = NSNoUnderlineStyle; + sal_Int16 value = 0; + property.Value >>= value; + if ( value != ::css_awt::FontUnderline::NONE + && value != ::css_awt::FontUnderline::DONTKNOW) { + underlineStyle = NSSingleUnderlineStyle; + } + return underlineStyle; +} + ++(int)convertBoldStyle:(PropertyValue)property { + int boldStyle = NSUnboldFontMask; + float value = 0; + property.Value >>= value; + if ( value == ::css_awt::FontWeight::SEMIBOLD + || value == ::css_awt::FontWeight::BOLD + || value == ::css_awt::FontWeight::ULTRABOLD + || value == ::css_awt::FontWeight::BLACK ) { + boldStyle = NSBoldFontMask; + } + return boldStyle; +} + ++(int)convertItalicStyle:(PropertyValue)property { + int italicStyle = NSUnitalicFontMask; + sal_Int16 value = property.Value.get< ::css_awt::FontSlant>(); + if ( value == ::css_awt::FontSlant_ITALIC ) { + italicStyle = NSItalicFontMask; + } + return italicStyle; +} + ++(BOOL)isStrikethrough:(PropertyValue)property { + BOOL strikethrough = NO; + sal_Int16 value = 0; + property.Value >>= value; + if ( value != ::css_awt::FontStrikeout::NONE + && value != ::css_awt::FontStrikeout::DONTKNOW ) { + strikethrough = YES; + } + return strikethrough; +} + ++(BOOL)convertBoolean:(PropertyValue)property { + BOOL myBoolean = NO; + bool value = sal_False; + property.Value >>= value; + if ( value ) { + myBoolean = YES; + } + return myBoolean; +} + ++(NSNumber *)convertShort:(PropertyValue)property { + sal_Int16 value = 0; + property.Value >>= value; + return [ NSNumber numberWithShort: value ]; +} + ++(void)addColor:(SalColor)nSalColor forAttribute:(NSString *)attribute andRange:(NSRange)range toString:(NSMutableAttributedString *)string { + if( nSalColor == COL_TRANSPARENT ) + return; + const RGBAColor aRGBAColor( nSalColor); + CGColorRef aColorRef = CGColorCreate ( CGColorSpaceCreateWithName ( kCGColorSpaceGenericRGB ), aRGBAColor.AsArray() ); + [ string addAttribute: attribute value: (id) aColorRef range: range ]; + CGColorRelease( aColorRef ); +} + ++(void)addFont:(NSFont *)font toString:(NSMutableAttributedString *)string forRange:(NSRange)range { + if ( font != nil ) { + NSDictionary * fontDictionary = [ NSDictionary dictionaryWithObjectsAndKeys: + [ font fontName ], NSAccessibilityFontNameKey, + [ font familyName ], NSAccessibilityFontFamilyKey, + [ font displayName ], NSAccessibilityVisibleNameKey, + [ NSNumber numberWithFloat: [ font pointSize ] ], NSAccessibilityFontSizeKey, + nil + ]; + [ string addAttribute: NSAccessibilityFontTextAttribute + value: fontDictionary + range: range + ]; + } +} + ++(void)applyAttributesFrom:(Sequence < PropertyValue >)attributes toString:(NSMutableAttributedString *)string forRange:(NSRange)range fontDescriptor:(AquaA11yFontDescriptor*)fontDescriptor { + NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; + // constants + static const OUString attrUnderline("CharUnderline"); + static const OUString attrBold("CharWeight"); + static const OUString attrFontname("CharFontName"); + static const OUString attrItalic("CharPosture"); + static const OUString attrHeight("CharHeight"); + static const OUString attrStrikethrough("CharStrikeout"); + static const OUString attrShadow("CharShadowed"); + static const OUString attrUnderlineColor("CharUnderlineColor"); + static const OUString attrUnderlineHasColor("CharUnderlineHasColor"); + static const OUString attrForegroundColor("CharColor"); + static const OUString attrBackgroundColor("CharBackColor"); + static const OUString attrSuperscript("CharEscapement"); + static const OUString attrTextAlignment("ParaAdjust"); + // vars + sal_Int32 underlineColor = 0; + BOOL underlineHasColor = NO; + // add attributes to string + for ( int attrIndex = 0; attrIndex < attributes.getLength(); attrIndex++ ) { + PropertyValue property = attributes [ attrIndex ]; + // TODO: NSAccessibilityMisspelledTextAttribute, NSAccessibilityAttachmentTextAttribute, NSAccessibilityLinkTextAttribute + // NSAccessibilityStrikethroughColorTextAttribute is unsupported by UNP-API + if ( property.Value.hasValue() ) { + if ( property.Name.equals ( attrUnderline ) ) { + int style = [ AquaA11yTextAttributesWrapper convertUnderlineStyle: property ]; + if ( style != NSNoUnderlineStyle ) { + [ string addAttribute: NSAccessibilityUnderlineTextAttribute value: [ NSNumber numberWithInt: style ] range: range ]; + } + } else if ( property.Name.equals ( attrFontname ) ) { + OUString fontname; + property.Value >>= fontname; + [fontDescriptor setName:CreateNSString(fontname)]; + } else if ( property.Name.equals ( attrBold ) ) { + [fontDescriptor setBold:[AquaA11yTextAttributesWrapper convertBoldStyle:property]]; + } else if ( property.Name.equals ( attrItalic ) ) { + [fontDescriptor setItalic:[AquaA11yTextAttributesWrapper convertItalicStyle:property]]; + } else if ( property.Name.equals ( attrHeight ) ) { + float size; + property.Value >>= size; + [fontDescriptor setSize:size]; + } else if ( property.Name.equals ( attrStrikethrough ) ) { + if ( [ AquaA11yTextAttributesWrapper isStrikethrough: property ] ) { + [ string addAttribute: NSAccessibilityStrikethroughTextAttribute value: [ NSNumber numberWithBool: YES ] range: range ]; + } + } else if ( property.Name.equals ( attrShadow ) ) { + if ( [ AquaA11yTextAttributesWrapper convertBoolean: property ] ) { + [ string addAttribute: NSAccessibilityShadowTextAttribute value: [ NSNumber numberWithBool: YES ] range: range ]; + } + } else if ( property.Name.equals ( attrUnderlineColor ) ) { + property.Value >>= underlineColor; + } else if ( property.Name.equals ( attrUnderlineHasColor ) ) { + underlineHasColor = [ AquaA11yTextAttributesWrapper convertBoolean: property ]; + } else if ( property.Name.equals ( attrForegroundColor ) ) { + [ AquaA11yTextAttributesWrapper addColor: property.Value.get() forAttribute: NSAccessibilityForegroundColorTextAttribute andRange: range toString: string ]; + } else if ( property.Name.equals ( attrBackgroundColor ) ) { + [ AquaA11yTextAttributesWrapper addColor: property.Value.get() forAttribute: NSAccessibilityBackgroundColorTextAttribute andRange: range toString: string ]; + } else if ( property.Name.equals ( attrSuperscript ) ) { + // values < zero mean subscript + // values > zero mean superscript + // this is true for both NSAccessibility-API and UNO-API + NSNumber * number = [ AquaA11yTextAttributesWrapper convertShort: property ]; + if ( [ number shortValue ] != 0 ) { + [ string addAttribute: NSAccessibilitySuperscriptTextAttribute value: number range: range ]; + } + } else if ( property.Name.equals ( attrTextAlignment ) ) { + sal_Int32 alignment; + property.Value >>= alignment; + NSNumber *textAlignment = nil; + switch(alignment) { + case ::com::sun::star::style::ParagraphAdjust_RIGHT : textAlignment = [NSNumber numberWithInteger:NSRightTextAlignment] ; break; + case ::com::sun::star::style::ParagraphAdjust_CENTER: textAlignment = [NSNumber numberWithInteger:NSCenterTextAlignment] ; break; + case ::com::sun::star::style::ParagraphAdjust_BLOCK : textAlignment = [NSNumber numberWithInteger:NSJustifiedTextAlignment]; break; + case ::com::sun::star::style::ParagraphAdjust_LEFT : + default : textAlignment = [NSNumber numberWithInteger:NSLeftTextAlignment] ; break; + } + NSDictionary *paragraphStyle = [NSDictionary dictionaryWithObjectsAndKeys:textAlignment, @"AXTextAlignment", textAlignment, @"AXVisualTextAlignment", nil]; + [string addAttribute:@"AXParagraphStyle" value:paragraphStyle range:range]; + } + } + } + // add underline information + if ( underlineHasColor ) { + [ AquaA11yTextAttributesWrapper addColor: underlineColor forAttribute: NSAccessibilityUnderlineColorTextAttribute andRange: range toString: string ]; + } + // add font information + NSFont * font = [fontDescriptor font]; + [AquaA11yTextAttributesWrapper addFont:font toString:string forRange:range]; + [ pool release ]; +} + ++(void)addMarkup:(XAccessibleTextMarkup*)markup withType:(long)type toString:(NSMutableAttributedString*)string inRange:(NSRange)range { + const long markupCount = markup->getTextMarkupCount(type); + for (long markupIndex = 0; markupIndex < markupCount; ++markupIndex) { + TextSegment markupSegment = markup->getTextMarkup(markupIndex, type); + NSRange markupRange = NSMakeRange(markupSegment.SegmentStart, markupSegment.SegmentEnd - markupSegment.SegmentStart); + markupRange = NSIntersectionRange(range, markupRange); + if (markupRange.length > 0) { + markupRange.location -= range.location; + switch(type) { + case ::com::sun::star::text::TextMarkupType::SPELLCHECK: { + [string addAttribute:NSAccessibilityMisspelledTextAttribute value:[NSNumber numberWithBool:YES] range:markupRange]; + [string addAttribute:@"AXMarkedMisspelled" value:[NSNumber numberWithBool:YES] range:markupRange]; + break; + } + } + } + } +} + ++(void)addMarkup:(XAccessibleTextMarkup*)markup toString:(NSMutableAttributedString*)string inRange:(NSRange)range { + [AquaA11yTextAttributesWrapper addMarkup:markup withType:(::com::sun::star::text::TextMarkupType::SPELLCHECK) toString:string inRange:range]; +} + ++(NSMutableAttributedString *)createAttributedStringForElement:(AquaA11yWrapper *)wrapper inOrigRange:(id)origRange { + static const Sequence < OUString > emptySequence; + // vars + NSMutableAttributedString * string = nil; + int loc = [ origRange rangeValue ].location; + int len = [ origRange rangeValue ].length; + int endIndex = loc + len; + int currentIndex = loc; + try { + NSString * myString = CreateNSString ( [ wrapper accessibleText ] -> getText() ); // TODO: dirty fix for i87817 + string = [ [ NSMutableAttributedString alloc ] initWithString: CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) ]; + if ( [ wrapper accessibleTextAttributes ] != nil && [myString characterAtIndex:0] != 57361) { // TODO: dirty fix for i87817 + [ string beginEditing ]; + // add default attributes for whole string + Sequence < PropertyValue > defaultAttributes = [ wrapper accessibleTextAttributes ] -> getDefaultAttributes ( emptySequence ); + AquaA11yFontDescriptor *defaultFontDescriptor = [[AquaA11yFontDescriptor alloc] init]; + [ AquaA11yTextAttributesWrapper applyAttributesFrom: defaultAttributes toString: string forRange: NSMakeRange ( 0, len ) fontDescriptor: defaultFontDescriptor ]; + // add attributes for attribute run(s) + while ( currentIndex < endIndex ) { + TextSegment textSegment = [ wrapper accessibleText ] -> getTextAtIndex ( currentIndex, AccessibleTextType::ATTRIBUTE_RUN ); + int endOfRange = endIndex > textSegment.SegmentEnd ? textSegment.SegmentEnd : endIndex; + NSRange rangeForAttributeRun = NSMakeRange ( currentIndex - loc , endOfRange - currentIndex ); + // add run attributes + Sequence < PropertyValue > attributes = [ wrapper accessibleTextAttributes ] -> getRunAttributes ( currentIndex, emptySequence ); + AquaA11yFontDescriptor *fontDescriptor = [[AquaA11yFontDescriptor alloc] initWithDescriptor:defaultFontDescriptor]; + [ AquaA11yTextAttributesWrapper applyAttributesFrom: attributes toString: string forRange: rangeForAttributeRun fontDescriptor: fontDescriptor ]; + [fontDescriptor release]; + currentIndex = textSegment.SegmentEnd; + } + [defaultFontDescriptor release]; + if ([wrapper accessibleTextMarkup]) + [AquaA11yTextAttributesWrapper addMarkup:[wrapper accessibleTextMarkup] toString:string inRange:[origRange rangeValue]]; + [ string endEditing ]; + } + } catch ( IllegalArgumentException & e ) { + // empty + } catch ( IndexOutOfBoundsException & e ) { + // empty + } catch ( RuntimeException& ) { + // at least don't crash + } + return string; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ytextwrapper.h b/vcl/osx/a11ytextwrapper.h new file mode 100644 index 000000000000..c1830a2072c6 --- /dev/null +++ b/vcl/osx/a11ytextwrapper.h @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YTEXTWRAPPER_H +#define INCLUDED_VCL_OSX_A11YTEXTWRAPPER_H + +#include "osx/osxvcltypes.h" +#include "osx/a11ywrapper.h" + +@interface AquaA11yTextWrapper : NSObject +{ +} ++(id)valueAttributeForElement:(AquaA11yWrapper *)wrapper; ++(id)numberOfCharactersAttributeForElement:(AquaA11yWrapper *)wrapper; ++(id)selectedTextAttributeForElement:(AquaA11yWrapper *)wrapper; ++(id)selectedTextRangeAttributeForElement:(AquaA11yWrapper *)wrapper; ++(id)visibleCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper; ++(id)sharedTextUIElementsAttributeForElement:(AquaA11yWrapper *)wrapper; ++(id)sharedCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper; ++(id)stringForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range; ++(id)attributedStringForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range; ++(id)rangeForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index; ++(id)rangeForPositionAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)point; ++(id)boundsForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range; ++(id)styleRangeForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index; ++(id)rTFForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range; ++(id)lineForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index; ++(id)rangeForLineAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)line; ++(void)addAttributeNamesTo:(NSMutableArray *)attributeNames; ++(void)addParameterizedAttributeNamesTo:(NSMutableArray *)attributeNames; ++(NSArray *)specialAttributeNames; ++(NSArray *)specialParameterizedAttributeNames; ++(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper; ++(void)setVisibleCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value; ++(void)setSelectedTextRangeAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value; ++(void)setSelectedTextAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value; ++(void)setValueAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value; +@end + +#endif // INCLUDED_VCL_OSX_A11YTEXTWRAPPER_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ytextwrapper.mm b/vcl/osx/a11ytextwrapper.mm new file mode 100644 index 000000000000..29d525d8b7bf --- /dev/null +++ b/vcl/osx/a11ytextwrapper.mm @@ -0,0 +1,293 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" +#include "quartz/utils.h" +#include "a11ytextwrapper.h" +#include "a11ytextattributeswrapper.h" +#include "a11yutil.h" + +#include +#include + +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::rtl; + +// Wrapper for XAccessibleText, XAccessibleEditableText and XAccessibleMultiLineText + +@implementation AquaA11yTextWrapper : NSObject + ++(id)valueAttributeForElement:(AquaA11yWrapper *)wrapper { + return CreateNSString ( [ wrapper accessibleText ] -> getText() ); +} + ++(void)setValueAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value +{ + // TODO + (void)wrapper; + (void)value; +} + ++(id)numberOfCharactersAttributeForElement:(AquaA11yWrapper *)wrapper { + return [ NSNumber numberWithLong: [ wrapper accessibleText ] -> getCharacterCount() ]; +} + ++(id)selectedTextAttributeForElement:(AquaA11yWrapper *)wrapper { + return CreateNSString ( [ wrapper accessibleText ] -> getSelectedText() ); +} + ++(void)setSelectedTextAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value { + if ( [ wrapper accessibleEditableText ] != nil ) { + NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; + OUString newText = GetOUString ( (NSString *) value ); + NSRange selectedTextRange = [ [ AquaA11yTextWrapper selectedTextRangeAttributeForElement: wrapper ] rangeValue ]; + try { + [ wrapper accessibleEditableText ] -> replaceText ( selectedTextRange.location, selectedTextRange.location + selectedTextRange.length, newText ); + } catch ( const Exception & e ) { + // empty + } + [ pool release ]; + } +} + ++(id)selectedTextRangeAttributeForElement:(AquaA11yWrapper *)wrapper { + sal_Int32 start = [ wrapper accessibleText ] -> getSelectionStart(); + sal_Int32 end = [ wrapper accessibleText ] -> getSelectionEnd(); + if ( start != end ) { + return [ NSValue valueWithRange: NSMakeRange ( start, end - start ) ]; // true selection + } else { + long caretPos = [ wrapper accessibleText ] -> getCaretPosition(); + if ( caretPos < 0 || caretPos > [ wrapper accessibleText ] -> getCharacterCount() ) { + return nil; + } + return [ NSValue valueWithRange: NSMakeRange ( caretPos, 0 ) ]; // insertion point + } +} + ++(void)setSelectedTextRangeAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value { + NSRange range = [ value rangeValue ]; + try { + [ wrapper accessibleText ] -> setSelection ( range.location, range.location + range.length ); + } catch ( const Exception & e ) { + // empty + } +} + ++(id)visibleCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper { + // the OOo a11y API returns only the visible portion... + return [ NSValue valueWithRange: NSMakeRange ( 0, [ wrapper accessibleText ] -> getCharacterCount() ) ]; +} + ++(void)setVisibleCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value +{ + // do nothing + (void)wrapper; + (void)value; +} + ++(id)sharedTextUIElementsAttributeForElement:(AquaA11yWrapper *)wrapper +{ + (void)wrapper; + return [NSArray arrayWithObject:wrapper]; +} + ++(id)sharedCharacterRangeAttributeForElement:(AquaA11yWrapper *)wrapper +{ + (void)wrapper; + return [ NSValue valueWithRange: NSMakeRange ( 0, [wrapper accessibleText]->getCharacterCount() ) ]; +} + ++(void)addAttributeNamesTo:(NSMutableArray *)attributeNames { + [ attributeNames addObjectsFromArray: [ AquaA11yTextWrapper specialAttributeNames ] ]; +} + ++(NSArray *)specialAttributeNames { + return [ NSArray arrayWithObjects: + NSAccessibilityValueAttribute, + NSAccessibilityNumberOfCharactersAttribute, + NSAccessibilitySelectedTextAttribute, + NSAccessibilitySelectedTextRangeAttribute, + NSAccessibilityVisibleCharacterRangeAttribute, + NSAccessibilitySharedTextUIElementsAttribute, + NSAccessibilitySharedCharacterRangeAttribute, + nil ]; +} + ++(void)addParameterizedAttributeNamesTo:(NSMutableArray *)attributeNames { + [ attributeNames addObjectsFromArray: [ AquaA11yTextWrapper specialParameterizedAttributeNames ] ]; +} + ++(NSArray *)specialParameterizedAttributeNames { + return [ NSArray arrayWithObjects: + NSAccessibilityStringForRangeParameterizedAttribute, + NSAccessibilityAttributedStringForRangeParameterizedAttribute, + NSAccessibilityRangeForIndexParameterizedAttribute, + NSAccessibilityRangeForPositionParameterizedAttribute, + NSAccessibilityBoundsForRangeParameterizedAttribute, + NSAccessibilityStyleRangeForIndexParameterizedAttribute, + NSAccessibilityRTFForRangeParameterizedAttribute, + NSAccessibilityLineForIndexParameterizedAttribute, + NSAccessibilityRangeForLineParameterizedAttribute, + nil ]; +} + ++(id)lineForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index { + NSNumber * lineNumber = nil; + try { + sal_Int32 line = [ wrapper accessibleMultiLineText ] -> getLineNumberAtIndex ( (sal_Int32) [ index intValue ] ); + lineNumber = [ NSNumber numberWithInt: line ]; + } catch ( IndexOutOfBoundsException & e ) { + // empty + } + return lineNumber; +} + ++(id)rangeForLineAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)line { + NSValue * range = nil; + try { + TextSegment textSegment = [ wrapper accessibleMultiLineText ] -> getTextAtLineNumber ( [ line intValue ] ); + range = [ NSValue valueWithRange: NSMakeRange ( textSegment.SegmentStart, textSegment.SegmentEnd - textSegment.SegmentStart ) ]; + } catch ( IndexOutOfBoundsException & e ) { + // empty + } + return range; +} + ++(id)stringForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range { + int loc = [ range rangeValue ].location; + int len = [ range rangeValue ].length; + NSMutableString * textRange = [ [ NSMutableString alloc ] init ]; + try { + [ textRange appendString: CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) ]; + } catch ( IndexOutOfBoundsException & e ) { + // empty + } + return textRange; +} + ++(id)attributedStringForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range { + return [ AquaA11yTextAttributesWrapper createAttributedStringForElement: wrapper inOrigRange: range ]; +} + ++(id)rangeForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index { + NSValue * range = nil; + try { + TextSegment textSegment = [ wrapper accessibleText ] -> getTextBeforeIndex ( [ index intValue ], AccessibleTextType::GLYPH ); + range = [ NSValue valueWithRange: NSMakeRange ( textSegment.SegmentStart, textSegment.SegmentEnd - textSegment.SegmentStart ) ]; + } catch ( IndexOutOfBoundsException & e ) { + // empty + } catch ( IllegalArgumentException & e ) { + // empty + } + return range; +} + ++(id)rangeForPositionAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)point { + NSValue * value = nil; + sal_Int32 index = [ wrapper accessibleText ] -> getIndexAtPoint ( [ AquaA11yUtil nsPointToVclPoint: point ] ); + if ( index > -1 ) { + value = [ AquaA11yTextWrapper rangeForIndexAttributeForElement: wrapper forParameter: [ NSNumber numberWithLong: index ] ]; + } + return value; +} + ++(id)boundsForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range { + NSValue * rect = nil; + try { + // TODO: this is ugly!!! + // the UNP-API can only return the bounds for a single character, not for a range + int loc = [ range rangeValue ].location; + int len = [ range rangeValue ].length; + int minx = 0x7fffffff, miny = 0x7fffffff, maxx = 0, maxy = 0; + for ( int i = 0; i < len; i++ ) { + Rectangle vclRect = [ wrapper accessibleText ] -> getCharacterBounds ( loc + i ); + if ( vclRect.X < minx ) { + minx = vclRect.X; + } + if ( vclRect.Y < miny ) { + miny = vclRect.Y; + } + if ( vclRect.Width + vclRect.X > maxx ) { + maxx = vclRect.Width + vclRect.X; + } + if ( vclRect.Height + vclRect.Y > maxy ) { + maxy = vclRect.Height + vclRect.Y; + } + } + if ( [ wrapper accessibleComponent ] != nil ) { + // get location on screen (must be added since get CharacterBounds returns values relative to parent) + Point screenPos = [ wrapper accessibleComponent ] -> getLocationOnScreen(); + Point pos ( minx + screenPos.X, miny + screenPos.Y ); + Point size ( maxx - minx, maxy - miny ); + NSValue * nsPos = [ AquaA11yUtil vclPointToNSPoint: pos ]; + rect = [ NSValue valueWithRect: NSMakeRect ( [ nsPos pointValue ].x, [ nsPos pointValue ].y - size.Y, size.X, size.Y ) ]; + //printf("Range: %s --- Rect: %s\n", [ NSStringFromRange ( [ range rangeValue ] ) UTF8String ], [ NSStringFromRect ( [ rect rectValue ] ) UTF8String ]); + } + } catch ( IndexOutOfBoundsException & e ) { + // empty + } + return rect; +} + ++(id)styleRangeForIndexAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)index { + NSValue * range = nil; + try { + TextSegment textSegment = [ wrapper accessibleText ] -> getTextAtIndex ( [ index intValue ], AccessibleTextType::ATTRIBUTE_RUN ); + range = [ NSValue valueWithRange: NSMakeRange ( textSegment.SegmentStart, textSegment.SegmentEnd - textSegment.SegmentStart ) ]; + } catch ( IndexOutOfBoundsException & e ) { + // empty + } catch ( IllegalArgumentException & e ) { + // empty + } + return range; +} + ++(id)rTFForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range { + NSData * rtfData = nil; + NSAttributedString * attrString = (NSAttributedString *) [ AquaA11yTextWrapper attributedStringForRangeAttributeForElement: wrapper forParameter: range ]; + if ( attrString != nil ) { + @try { + rtfData = [ attrString RTFFromRange: [ range rangeValue ] documentAttributes: nil ]; + } @catch ( NSException * e) { + // emtpy + } + } + return rtfData; +} + ++(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper { + BOOL isSettable = NO; + if ( [ attribute isEqualToString: NSAccessibilityValueAttribute ] + || [ attribute isEqualToString: NSAccessibilitySelectedTextAttribute ] + || [ attribute isEqualToString: NSAccessibilitySelectedTextRangeAttribute ] + || [ attribute isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute ] ) { + if ( ! [ [ wrapper accessibilityAttributeValue: NSAccessibilityRoleAttribute ] isEqualToString: NSAccessibilityStaticTextRole ] ) { + isSettable = YES; + } + } + return isSettable; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11yutil.h b/vcl/osx/a11yutil.h new file mode 100644 index 000000000000..5cc5dc4582f9 --- /dev/null +++ b/vcl/osx/a11yutil.h @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YUTIL_H +#define INCLUDED_VCL_OSX_A11YUTIL_H + +#include + +@interface AquaA11yUtil : NSObject { +} ++(NSValue *)vclPointToNSPoint:(::com::sun::star::awt::Point)vclPoint; ++(::com::sun::star::awt::Point)nsPointToVclPoint:(NSValue *)nsPoint; +@end + +#endif // INCLUDED_VCL_OSX_A11YUTIL_H +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11yutil.mm b/vcl/osx/a11yutil.mm new file mode 100644 index 000000000000..68438643ace7 --- /dev/null +++ b/vcl/osx/a11yutil.mm @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/osxvcltypes.h" + +#include "a11yutil.h" + +using namespace ::com::sun::star::awt; + +@implementation AquaA11yUtil : NSObject + +// TODO: should be merged with AquaSalFrame::VCLToCocoa... to a general helper method ++(NSValue *)vclPointToNSPoint:(Point)vclPoint { + // VCL coordinates are in upper-left-notation, Cocoa likes it the Cartesian way (lower-left) + NSRect screenRect = [ [ NSScreen mainScreen ] frame ]; + NSPoint nsPoint = NSMakePoint ( (float) vclPoint.X, (float) ( screenRect.size.height - vclPoint.Y ) ); + return [ NSValue valueWithPoint: nsPoint ]; +} + +// TODO: should be merged with AquaSalFrame::VCLToCocoa... to a general helper method ++(Point)nsPointToVclPoint:(NSValue *)nsPoint { + // VCL coordinates are in upper-left-notation, Cocoa likes it the Cartesian way (lower-left) + NSRect screenRect = [ [ NSScreen mainScreen ] frame ]; + return Point ( static_cast([ nsPoint pointValue ].x), static_cast(screenRect.size.height - [ nsPoint pointValue ].y) ); +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11yvaluewrapper.h b/vcl/osx/a11yvaluewrapper.h new file mode 100644 index 000000000000..3ff33d491424 --- /dev/null +++ b/vcl/osx/a11yvaluewrapper.h @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YVALUEWRAPPER_H +#define INCLUDED_VCL_OSX_A11YVALUEWRAPPER_H + +#include "osx/salinst.h" +#include "osx/osxvcltypes.h" +#include "osx/a11ywrapper.h" + +@interface AquaA11yValueWrapper : NSObject +{ +} ++(id)valueAttributeForElement:(AquaA11yWrapper *)wrapper; ++(id)minValueAttributeForElement:(AquaA11yWrapper *)wrapper; ++(id)maxValueAttributeForElement:(AquaA11yWrapper *)wrapper; ++(void)addAttributeNamesTo:(NSMutableArray *)attributeNames; ++(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper; ++(void)setValueAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value; +@end + +#endif // INCLUDED_VCL_OSX_A11YVALUEWRAPPER_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11yvaluewrapper.mm b/vcl/osx/a11yvaluewrapper.mm new file mode 100644 index 000000000000..539eb9124f67 --- /dev/null +++ b/vcl/osx/a11yvaluewrapper.mm @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "a11yvaluewrapper.h" +#include "a11ywrapperstatictext.h" + +using namespace ::com::sun::star::uno; + +// Wrapper for XAccessibleValue +// Remember: A UNO-Value is a single numeric value. Regarding the Mac A11y-API, a value can be anything! + +@implementation AquaA11yValueWrapper : NSObject + ++(id)valueAttributeForElement:(AquaA11yWrapper *)wrapper { + // TODO: Detect Type from Any + if ( [ wrapper accessibleValue ] != nil ) { + long value = 0; + [ wrapper accessibleValue ] -> getCurrentValue() >>= value; + return [ NSNumber numberWithLong: value ]; + } + return [ NSNumber numberWithLong: 0 ]; +} + ++(id)minValueAttributeForElement:(AquaA11yWrapper *)wrapper { + // TODO: Detect Type from Any + if ( [ wrapper accessibleValue ] != nil ) { + long value = 0; + [ wrapper accessibleValue ] -> getMinimumValue() >>= value; + return [ NSNumber numberWithLong: value ]; + } + return [ NSNumber numberWithLong: 0 ]; +} + ++(id)maxValueAttributeForElement:(AquaA11yWrapper *)wrapper { + // TODO: Detect Type from Any + if ( [ wrapper accessibleValue ] != nil ) { + long value = 0; + [ wrapper accessibleValue ] -> getMaximumValue() >>= value; + return [ NSNumber numberWithLong: value ]; + } + return [ NSNumber numberWithLong: 0 ]; +} + ++(void)setValueAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value { + // TODO: Detect Type from NSNumber + if ( [ value isKindOfClass: [ NSNumber class ] ] + && [ wrapper accessibleValue ] != nil ) { + NSNumber * number = (NSNumber *) value; + Any numberAny ( [ number longValue ] ); + [ wrapper accessibleValue ] -> setCurrentValue ( numberAny ); + } +} + ++(void)addAttributeNamesTo:(NSMutableArray *)attributeNames { + [ attributeNames addObject: NSAccessibilityValueAttribute ]; +} + ++(BOOL)isAttributeSettable:(NSString *)attribute forElement:(AquaA11yWrapper *)wrapper { + BOOL isSettable = NO; + if ( [ wrapper accessibleValue ] != nil + && [ attribute isEqualToString: NSAccessibilityValueAttribute ] + && ! [ wrapper isKindOfClass: [ AquaA11yWrapperStaticText class ] ] ) { + isSettable = YES; + } + return isSettable; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapper.mm b/vcl/osx/a11ywrapper.mm new file mode 100644 index 000000000000..85ee3ff3ab05 --- /dev/null +++ b/vcl/osx/a11ywrapper.mm @@ -0,0 +1,1150 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" +#include "osx/saldata.hxx" + +#include "osx/a11ywrapper.h" +#include "osx/a11ylistener.hxx" +#include "osx/a11yfactory.h" +#include "osx/a11yfocustracker.hxx" + +#include "quartz/utils.h" + +#include "a11yfocuslistener.hxx" +#include "a11yactionwrapper.h" +#include "a11ycomponentwrapper.h" +#include "a11yselectionwrapper.h" +#include "a11ytablewrapper.h" +#include "a11ytextwrapper.h" +#include "a11yvaluewrapper.h" +#include "a11yrolehelper.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; + +@interface SalFrameWindow : NSWindow +{ +} +-(Reference)accessibleContext; +@end + +static BOOL isPopupMenuOpen = NO; + +static std::ostream &operator<<(std::ostream &s, NSObject *obj) { + return s << [[obj description] UTF8String]; +} + +#ifndef _LP64 + +// In 64-bit code NSPoint == CGPoint, and CGPoint already has +// an operator<< in vcl/inc/quartz/util.h + +static std::ostream &operator<<(std::ostream &s, NSPoint point) { + return s << NSStringFromPoint(point); +} + +#endif + +@implementation AquaA11yWrapper : NSView + +#pragma mark - +#pragma mark Init and dealloc + +-(id)initWithAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext { + self = [ super init ]; + if ( self != nil ) { + [ self setDefaults: rxAccessibleContext ]; + } + return self; +} + +-(void) setDefaults: (Reference < XAccessibleContext >) rxAccessibleContext { + mpReferenceWrapper = new ReferenceWrapper; + mActsAsRadioGroup = NO; + mpReferenceWrapper -> rAccessibleContext = rxAccessibleContext; + mIsTableCell = NO; + // Querying all supported interfaces + try { + // XAccessibleComponent + mpReferenceWrapper -> rAccessibleComponent = Reference < XAccessibleComponent > ( rxAccessibleContext, UNO_QUERY ); + // XAccessibleExtendedComponent + mpReferenceWrapper -> rAccessibleExtendedComponent = Reference < XAccessibleExtendedComponent > ( rxAccessibleContext, UNO_QUERY ); + // XAccessibleSelection + mpReferenceWrapper -> rAccessibleSelection = Reference< XAccessibleSelection > ( rxAccessibleContext, UNO_QUERY ); + // XAccessibleTable + mpReferenceWrapper -> rAccessibleTable = Reference < XAccessibleTable > ( rxAccessibleContext, UNO_QUERY ); + // XAccessibleText + mpReferenceWrapper -> rAccessibleText = Reference < XAccessibleText > ( rxAccessibleContext, UNO_QUERY ); + // XAccessibleEditableText + mpReferenceWrapper -> rAccessibleEditableText = Reference < XAccessibleEditableText > ( rxAccessibleContext, UNO_QUERY ); + // XAccessibleValue + mpReferenceWrapper -> rAccessibleValue = Reference < XAccessibleValue > ( rxAccessibleContext, UNO_QUERY ); + // XAccessibleAction + mpReferenceWrapper -> rAccessibleAction = Reference < XAccessibleAction > ( rxAccessibleContext, UNO_QUERY ); + // XAccessibleTextAttributes + mpReferenceWrapper -> rAccessibleTextAttributes = Reference < XAccessibleTextAttributes > ( rxAccessibleContext, UNO_QUERY ); + // XAccessibleMultiLineText + mpReferenceWrapper -> rAccessibleMultiLineText = Reference < XAccessibleMultiLineText > ( rxAccessibleContext, UNO_QUERY ); + // XAccessibleTextMarkup + mpReferenceWrapper -> rAccessibleTextMarkup = Reference < XAccessibleTextMarkup > ( rxAccessibleContext, UNO_QUERY ); + // XAccessibleEventBroadcaster + #if 0 + /* #i102033# NSAccessibility does not seemt to know an equivalent for transient children. + That means we need to cache this, else e.g. tree list boxes are not accessible (moreover + it crashes by notifying dead objects - which would seemt o be another bug) + + FIXME: + Unfortunately this can increase memory consumption drastically until the non transient parent + is destroyed an finally all the transients are released. + */ + if ( ! rxAccessibleContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::TRANSIENT ) ) + #endif + { + Reference< XAccessibleEventBroadcaster > xBroadcaster(rxAccessibleContext, UNO_QUERY); + if( xBroadcaster.is() ) { + /* + * We intentionally do not hold a reference to the event listener in the wrapper object, + * but let the listener control the life cycle of the wrapper instead .. + */ + xBroadcaster->addAccessibleEventListener( new AquaA11yEventListener( self, rxAccessibleContext -> getAccessibleRole() ) ); + } + } + // TABLE_CELL + if ( rxAccessibleContext -> getAccessibleRole() == AccessibleRole::TABLE_CELL ) { + mIsTableCell = YES; + } + } catch ( const Exception ) { + } +} + +-(void)dealloc { + if ( mpReferenceWrapper != nil ) { + delete mpReferenceWrapper; + } + [ super dealloc ]; +} + +#pragma mark - +#pragma mark Utility Section + +// generates selectors for attribute name AXAttributeNameHere +// (getter without parameter) attributeNameHereAttribute +// (getter with parameter) attributeNameHereAttributeForParameter: +// (setter) setAttributeNameHereAttributeForElement:to: +-(SEL)selectorForAttribute:(NSString *)attribute asGetter:(BOOL)asGetter withGetterParameter:(BOOL)withGetterParameter { + SEL selector = nil; + NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; + @try { + // step 1: create method name from attribute name + NSMutableString * methodName = [ NSMutableString string ]; + if ( ! asGetter ) { + [ methodName appendString: @"set" ]; + } + NSRange aRange = { 2, 1 }; + NSString * firstChar = [ attribute substringWithRange: aRange ]; // drop leading "AX" and get first char + if ( asGetter ) { + [ methodName appendString: [ firstChar lowercaseString ] ]; + } else { + [ methodName appendString: firstChar ]; + } + [ methodName appendString: [ attribute substringFromIndex: 3 ] ]; // append rest of attribute name + // append rest of method name + [ methodName appendString: @"Attribute" ]; + if ( ! asGetter ) { + [ methodName appendString: @"ForElement:to:" ]; + } else if ( asGetter && withGetterParameter ) { + [ methodName appendString: @"ForParameter:" ]; + } + // step 2: create selector + selector = NSSelectorFromString ( methodName ); + } @catch ( id exception ) { + selector = nil; + } + [ pool release ]; + return selector; +} + +-(Reference < XAccessible >)getFirstRadioButtonInGroup { + Reference < XAccessibleRelationSet > rxAccessibleRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet(); + if( rxAccessibleRelationSet.is() ) + { + AccessibleRelation relationMemberOf = rxAccessibleRelationSet -> getRelationByType ( AccessibleRelationType::MEMBER_OF ); + if ( relationMemberOf.RelationType == AccessibleRelationType::MEMBER_OF && relationMemberOf.TargetSet.hasElements() ) + return Reference < XAccessible > ( relationMemberOf.TargetSet[0], UNO_QUERY ); + } + return Reference < XAccessible > (); +} + +-(BOOL)isFirstRadioButtonInGroup { + Reference < XAccessible > rFirstMateAccessible = [ self getFirstRadioButtonInGroup ]; + if ( rFirstMateAccessible.is() && rFirstMateAccessible -> getAccessibleContext().get() == [ self accessibleContext ] ) { + return YES; + } + return NO; +} + +#pragma mark - +#pragma mark Attribute Value Getters +// ( called via Reflection by accessibilityAttributeValue ) + +/* + Radiobutton grouping is done differently in NSAccessibility and the UNO-API. In UNO related radio buttons share an entry in their + RelationSet. In NSAccessibility the relationship is axpressed through the hierarchy. A AXRadioGroup contains two or more AXRadioButton + objects. Since this group is not available in the UNO hierarchy, an extra wrapper is used for it. This wrapper shares almost all + attributes with the first radio button of the group, except for the role, subrole, role description, parent and children attributes. + So in this five methods there is a special treatment for radio buttons and groups. +*/ + +-(id)roleAttribute { + if ( mActsAsRadioGroup ) { + return NSAccessibilityRadioGroupRole; + } + else { + return [ AquaA11yRoleHelper getNativeRoleFrom: [ self accessibleContext ] ]; + } +} + +-(id)subroleAttribute { + if ( mActsAsRadioGroup ) { + return @""; + } else { + NSString * subRole = [ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ]; + if ( ! [ subRole isEqualToString: @"" ] ) { + return subRole; + } else { + [ subRole release ]; + return [ super accessibilityAttributeValue: NSAccessibilitySubroleAttribute ]; + } + } +} + +-(id)titleAttribute { + return CreateNSString ( [ self accessibleContext ] -> getAccessibleName() ); +} + +-(id)descriptionAttribute { + if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) { + return [ self titleAttribute ]; + } else if ( [ self accessibleExtendedComponent ] != nil ) { + return [ AquaA11yComponentWrapper descriptionAttributeForElement: self ]; + } else { + return CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() ); + } +} + +-(id)enabledAttribute { + if ( [ self accessibleContext ] -> getAccessibleStateSet().is() ) { + return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::ENABLED ) ]; + } else { + return nil; + } +} + +-(id)focusedAttribute { + if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) { + id isFocused = nil; + Reference < XAccessible > rxParent = [ self accessibleContext ] -> getAccessibleParent(); + if ( rxParent.is() ) { + Reference < XAccessibleContext > rxContext = rxParent -> getAccessibleContext(); + if ( rxContext.is() && rxContext -> getAccessibleStateSet().is() ) { + isFocused = [ NSNumber numberWithBool: rxContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::FOCUSED ) ]; + } + } + return isFocused; + } else if ( [ self accessibleContext ] -> getAccessibleStateSet().is() ) { + return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::FOCUSED ) ]; + } else { + return nil; + } +} + +-(id)parentAttribute { + if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::RADIO_BUTTON && ! mActsAsRadioGroup ) { + Reference < XAccessible > rxAccessible = [ self getFirstRadioButtonInGroup ]; + if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() ) { + Reference < XAccessibleContext > rxAccessibleContext = rxAccessible -> getAccessibleContext(); + id parent_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessibleContext createIfNotExists: YES asRadioGroup: YES ]; + [ parent_wrapper autorelease ]; + return NSAccessibilityUnignoredAncestor( parent_wrapper ); + } + return nil; + } + try { + Reference< XAccessible > xParent( [ self accessibleContext ] -> getAccessibleParent() ); + if ( xParent.is() ) { + Reference< XAccessibleContext > xContext( xParent -> getAccessibleContext() ); + if ( xContext.is() ) { + id parent_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: xContext ]; + [ parent_wrapper autorelease ]; + return NSAccessibilityUnignoredAncestor( parent_wrapper ); + } + } + } catch (const Exception&) { + } + + OSL_ASSERT( 0 ); + return nil; +} + +-(id)childrenAttribute { + if ( mActsAsRadioGroup ) { + NSMutableArray * children = [ [ NSMutableArray alloc ] init ]; + Reference < XAccessibleRelationSet > rxAccessibleRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet(); + AccessibleRelation relationMemberOf = rxAccessibleRelationSet -> getRelationByType ( AccessibleRelationType::MEMBER_OF ); + if ( relationMemberOf.RelationType == AccessibleRelationType::MEMBER_OF && relationMemberOf.TargetSet.hasElements() ) { + for ( int index = 0; index < relationMemberOf.TargetSet.getLength(); index++ ) { + Reference < XAccessible > rMateAccessible = Reference < XAccessible > ( relationMemberOf.TargetSet[index], UNO_QUERY ); + if ( rMateAccessible.is() ) { + Reference< XAccessibleContext > rMateAccessibleContext( rMateAccessible -> getAccessibleContext() ); + if ( rMateAccessibleContext.is() ) { + id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rMateAccessibleContext ]; + [ children addObject: wrapper ]; + [ wrapper release ]; + } + } + } + } + return children; + } else if ( [ self accessibleTable ] != nil ) + { + AquaA11yTableWrapper* pTable = [self isKindOfClass: [AquaA11yTableWrapper class]] ? (AquaA11yTableWrapper*)self : nil; + return [ AquaA11yTableWrapper childrenAttributeForElement: pTable ]; + } else { + try { + NSMutableArray * children = [ [ NSMutableArray alloc ] init ]; + Reference< XAccessibleContext > xContext( [ self accessibleContext ] ); + + sal_Int32 cnt = xContext -> getAccessibleChildCount(); + for ( sal_Int32 i = 0; i < cnt; i++ ) { + Reference< XAccessible > xChild( xContext -> getAccessibleChild( i ) ); + if( xChild.is() ) { + Reference< XAccessibleContext > xChildContext( xChild -> getAccessibleContext() ); + // the menubar is already accessible (including Apple- and Application-Menu) through NSApplication => omit it here + if ( xChildContext.is() && AccessibleRole::MENU_BAR != xChildContext -> getAccessibleRole() ) { + id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: xChildContext ]; + [ children addObject: wrapper ]; + [ wrapper release ]; + } + } + } + + // if not already acting as RadioGroup now is the time to replace RadioButtons with RadioGroups and remove RadioButtons + if ( ! mActsAsRadioGroup ) { + NSEnumerator * enumerator = [ children objectEnumerator ]; + AquaA11yWrapper * element; + while ( ( element = ( (AquaA11yWrapper *) [ enumerator nextObject ] ) ) ) { + if ( [ element accessibleContext ] -> getAccessibleRole() == AccessibleRole::RADIO_BUTTON ) { + if ( [ element isFirstRadioButtonInGroup ] ) { + id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: [ element accessibleContext ] createIfNotExists: YES asRadioGroup: YES ]; + [ children replaceObjectAtIndex: [ children indexOfObjectIdenticalTo: element ] withObject: wrapper ]; + } + [ children removeObject: element ]; + } + } + } + + [ children autorelease ]; + return NSAccessibilityUnignoredChildren( children ); + } catch (const Exception &e) { + // TODO: Log + return nil; + } + } +} + +-(id)windowAttribute { + // go upstairs until reaching the broken connection + AquaA11yWrapper * aWrapper = self; + int loops = 0; + while ( [ aWrapper accessibleContext ] -> getAccessibleParent().is() ) { + AquaA11yWrapper *aTentativeParentWrapper = [ AquaA11yFactory wrapperForAccessibleContext: [ aWrapper accessibleContext ] -> getAccessibleParent() -> getAccessibleContext() ]; + // Quick-and-dirty fix for infinite loop after fixing crash in + // fdo#47275 + if ( aTentativeParentWrapper == aWrapper ) + break; + // Even dirtier fix for infinite loop in fdo#55156 + if ( loops++ == 100 ) + break; + aWrapper = aTentativeParentWrapper; + [ aWrapper autorelease ]; + } + // get associated NSWindow + NSView * theView = [ aWrapper viewElementForParent ]; + return theView; +} + +-(id)topLevelUIElementAttribute { + return [ self windowAttribute ]; +} + +-(id)sizeAttribute { + if ( [ self accessibleComponent ] != nil ) { + return [ AquaA11yComponentWrapper sizeAttributeForElement: self ]; + } else { + return nil; + } +} + +-(id)positionAttribute { + if ( [ self accessibleComponent ] != nil ) { + return [ AquaA11yComponentWrapper positionAttributeForElement: self ]; + } else { + return nil; + } +} + +-(id)helpAttribute { + return CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() ); +} + +-(id)roleDescriptionAttribute { + if ( mActsAsRadioGroup ) { + return [ AquaA11yRoleHelper getRoleDescriptionFrom: NSAccessibilityRadioGroupRole with: @"" ]; + } else if( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::RADIO_BUTTON ) { + // FIXME: VO should read this because of hierarchy, this is just a workaround + // get parent and its children + AquaA11yWrapper * parent = [ self parentAttribute ]; + NSArray * children = [ parent childrenAttribute ]; + // find index of self + int index = 1; + NSEnumerator * enumerator = [ children objectEnumerator ]; + AquaA11yWrapper * child = nil; + while ( ( child = [ enumerator nextObject ] ) ) { + if ( self == child ) { + break; + } + index++; + } + // build string + NSNumber * nIndex = [ NSNumber numberWithInt: index ]; + NSNumber * nGroupsize = [ NSNumber numberWithInt: [ children count ] ]; + NSMutableString * value = [ [ NSMutableString alloc ] init ]; + [ value appendString: @"radio button " ]; + [ value appendString: [ nIndex stringValue ] ]; + [ value appendString: @" of " ]; + [ value appendString: [ nGroupsize stringValue ] ]; + // clean up and return string + [ nIndex release ]; + [ nGroupsize release ]; + [ children release ]; + return value; + } else { + return [ AquaA11yRoleHelper getRoleDescriptionFrom: + [ AquaA11yRoleHelper getNativeRoleFrom: [ self accessibleContext ] ] + with: [ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ] ]; + } +} + +-(id)valueAttribute { + if ( [ [ self roleAttribute ] isEqualToString: NSAccessibilityMenuItemRole ] ) { + return nil; + } else if ( [ self accessibleText ] != nil ) { + return [ AquaA11yTextWrapper valueAttributeForElement: self ]; + } else if ( [ self accessibleValue ] != nil ) { + return [ AquaA11yValueWrapper valueAttributeForElement: self ]; + } else { + return nil; + } +} + +-(id)minValueAttribute { + if ( [ self accessibleValue ] != nil ) { + return [ AquaA11yValueWrapper minValueAttributeForElement: self ]; + } else { + return nil; + } +} + +-(id)maxValueAttribute { + if ( [ self accessibleValue ] != nil ) { + return [ AquaA11yValueWrapper maxValueAttributeForElement: self ]; + } else { + return nil; + } +} + +-(id)contentsAttribute { + return [ self childrenAttribute ]; +} + +-(id)selectedChildrenAttribute { + return [ AquaA11ySelectionWrapper selectedChildrenAttributeForElement: self ]; +} + +-(id)numberOfCharactersAttribute { + if ( [ self accessibleText ] != nil ) { + return [ AquaA11yTextWrapper numberOfCharactersAttributeForElement: self ]; + } else { + return nil; + } +} + +-(id)selectedTextAttribute { + if ( [ self accessibleText ] != nil ) { + return [ AquaA11yTextWrapper selectedTextAttributeForElement: self ]; + } else { + return nil; + } +} + +-(id)selectedTextRangeAttribute { + if ( [ self accessibleText ] != nil ) { + return [ AquaA11yTextWrapper selectedTextRangeAttributeForElement: self ]; + } else { + return nil; + } +} + +-(id)visibleCharacterRangeAttribute { + if ( [ self accessibleText ] != nil ) { + return [ AquaA11yTextWrapper visibleCharacterRangeAttributeForElement: self ]; + } else { + return nil; + } +} + +-(id)tabsAttribute { + return self; // TODO ??? +} + +-(id)sharedTextUIElementsAttribute { + if ( [ self accessibleText ] != nil ) { + return [ AquaA11yTextWrapper sharedTextUIElementsAttributeForElement: self ]; + } else { + return nil; + } +} + +-(id)sharedCharacterRangeAttribute { + if ( [ self accessibleText ] != nil ) { + return [ AquaA11yTextWrapper sharedCharacterRangeAttributeForElement: self ]; + } else { + return nil; + } +} + +-(id)expandedAttribute { + return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::EXPANDED ) ]; +} + +-(id)selectedAttribute { + return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::SELECTED ) ]; +} + +-(id)stringForRangeAttributeForParameter:(id)range { + if ( [ self accessibleText ] != nil ) { + return [ AquaA11yTextWrapper stringForRangeAttributeForElement: self forParameter: range ]; + } else { + return nil; + } +} + +-(id)attributedStringForRangeAttributeForParameter:(id)range { + if ( [ self accessibleText ] != nil ) { + return [ AquaA11yTextWrapper attributedStringForRangeAttributeForElement: self forParameter: range ]; + } else { + return nil; + } +} + +-(id)rangeForIndexAttributeForParameter:(id)index { + if ( [ self accessibleText ] != nil ) { + return [ AquaA11yTextWrapper rangeForIndexAttributeForElement: self forParameter: index ]; + } else { + return nil; + } +} + +-(id)rangeForPositionAttributeForParameter:(id)point { + if ( [ self accessibleText ] != nil ) { + return [ AquaA11yTextWrapper rangeForPositionAttributeForElement: self forParameter: point ]; + } else { + return nil; + } +} + +-(id)boundsForRangeAttributeForParameter:(id)range { + if ( [ self accessibleText ] != nil ) { + return [ AquaA11yTextWrapper boundsForRangeAttributeForElement: self forParameter: range ]; + } else { + return nil; + } +} + +-(id)styleRangeForIndexAttributeForParameter:(id)index { + if ( [ self accessibleText ] != nil ) { + return [ AquaA11yTextWrapper styleRangeForIndexAttributeForElement: self forParameter: index ]; + } else { + return nil; + } +} + +-(id)rTFForRangeAttributeForParameter:(id)range { + if ( [ self accessibleText ] != nil ) { + return [ AquaA11yTextWrapper rTFForRangeAttributeForElement: self forParameter: range ]; + } else { + return nil; + } +} + +-(id)orientationAttribute { + NSString * orientation = nil; + Reference < XAccessibleStateSet > stateSet = [ self accessibleContext ] -> getAccessibleStateSet(); + if ( stateSet -> contains ( AccessibleStateType::HORIZONTAL ) ) { + orientation = NSAccessibilityHorizontalOrientationValue; + } else if ( stateSet -> contains ( AccessibleStateType::VERTICAL ) ) { + orientation = NSAccessibilityVerticalOrientationValue; + } + return orientation; +} + +-(id)titleUIElementAttribute { + if ( [ self accessibleContext ] -> getAccessibleRelationSet().is() ) { + NSString * title = [ self titleAttribute ]; + id titleElement = nil; + if ( [ title length ] == 0 ) { + AccessibleRelation relationLabeledBy = [ self accessibleContext ] -> getAccessibleRelationSet() -> getRelationByType ( AccessibleRelationType::LABELED_BY ); + if ( relationLabeledBy.RelationType == AccessibleRelationType::LABELED_BY && relationLabeledBy.TargetSet.hasElements() ) { + Reference < XAccessible > rxAccessible ( relationLabeledBy.TargetSet[0], UNO_QUERY ); + titleElement = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessible -> getAccessibleContext() ]; + } + } + if ( title != nil ) { + [ title release ]; + } + return titleElement; + } else { + return nil; + } +} + +-(id)servesAsTitleForUIElementsAttribute { + if ( [ self accessibleContext ] -> getAccessibleRelationSet().is() ) { + id titleForElement = nil; + AccessibleRelation relationLabelFor = [ self accessibleContext ] -> getAccessibleRelationSet() -> getRelationByType ( AccessibleRelationType::LABEL_FOR ); + if ( relationLabelFor.RelationType == AccessibleRelationType::LABEL_FOR && relationLabelFor.TargetSet.hasElements() ) { + Reference < XAccessible > rxAccessible ( relationLabelFor.TargetSet[0], UNO_QUERY ); + titleForElement = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessible -> getAccessibleContext() ]; + } + return titleForElement; + } else { + return nil; + } +} + +-(id)lineForIndexAttributeForParameter:(id)index { + if ( [ self accessibleMultiLineText ] != nil ) { + return [ AquaA11yTextWrapper lineForIndexAttributeForElement: self forParameter: index ]; + } else { + return nil; + } +} + +-(id)rangeForLineAttributeForParameter:(id)line { + if ( [ self accessibleMultiLineText ] != nil ) { + return [ AquaA11yTextWrapper rangeForLineAttributeForElement: self forParameter: line ]; + } else { + return nil; + } +} + +#pragma mark - +#pragma mark Accessibility Protocol + +-(id)accessibilityAttributeValue:(NSString *)attribute { + SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeValue:" << attribute << "]"); + // #i90575# guard NSAccessibility protocol against unwanted access + if ( isPopupMenuOpen ) { + return nil; + } + + id value = nil; + // if we are no longer in the wrapper repository, we have been disposed + AquaA11yWrapper * theWrapper = [ AquaA11yFactory wrapperForAccessibleContext: [ self accessibleContext ] createIfNotExists: NO ]; + if ( theWrapper != nil || mIsTableCell ) { + try { + SEL methodSelector = [ self selectorForAttribute: attribute asGetter: YES withGetterParameter: NO ]; + if ( [ self respondsToSelector: methodSelector ] ) { + value = [ self performSelector: methodSelector ]; + } + } catch ( const DisposedException & e ) { + mIsTableCell = NO; // just to be sure + [ AquaA11yFactory removeFromWrapperRepositoryFor: [ self accessibleContext ] ]; + return nil; + } catch ( const Exception & e ) { + // empty + } + } + if ( theWrapper != nil ) { + [ theWrapper release ]; // the above called method calls retain on the returned Wrapper + } + return value; +} + +-(BOOL)accessibilityIsIgnored { + SAL_INFO("vcl.a11y", "[" << self << " accessibilityIsIgnored]"); + // #i90575# guard NSAccessibility protocol against unwanted access + if ( isPopupMenuOpen ) { + return NO; + } + BOOL ignored = NO; + sal_Int16 nRole = [ self accessibleContext ] -> getAccessibleRole(); + switch ( nRole ) { + case AccessibleRole::PANEL: + case AccessibleRole::FRAME: + case AccessibleRole::ROOT_PANE: + case AccessibleRole::SEPARATOR: + case AccessibleRole::FILLER: + case AccessibleRole::DIALOG: + ignored = YES; + break; + default: + ignored = ! ( [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::VISIBLE ) ); + break; + } + return ignored; // TODO: to be completed +} + +-(NSArray *)accessibilityAttributeNames { + SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeNames]"); + // #i90575# guard NSAccessibility protocol against unwanted access + if ( isPopupMenuOpen ) { + return nil; + } + NSString * nativeSubrole = nil; + NSString * title = nil; + NSMutableArray * attributeNames = nil; + sal_Int32 nAccessibleChildren = 0; + try { + // Default Attributes + attributeNames = [ NSMutableArray arrayWithObjects: + NSAccessibilityRoleAttribute, + NSAccessibilityDescriptionAttribute, + NSAccessibilityParentAttribute, + NSAccessibilityWindowAttribute, + NSAccessibilityHelpAttribute, + NSAccessibilityTopLevelUIElementAttribute, + NSAccessibilityRoleDescriptionAttribute, + nil ]; + nativeSubrole = (NSString *) [ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ]; + title = (NSString *) [ self titleAttribute ]; + Reference < XAccessibleRelationSet > rxRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet(); + // Special Attributes depending on attribute values + if ( nativeSubrole != nil && ! [ nativeSubrole isEqualToString: @"" ] ) { + [ attributeNames addObject: NSAccessibilitySubroleAttribute ]; + } + try + { + nAccessibleChildren = [ self accessibleContext ] -> getAccessibleChildCount(); + if ( nAccessibleChildren > 0 ) { + [ attributeNames addObject: NSAccessibilityChildrenAttribute ]; + } + } + catch( DisposedException& ) {} + catch( RuntimeException& ) {} + + if ( title != nil && ! [ title isEqualToString: @"" ] ) { + [ attributeNames addObject: NSAccessibilityTitleAttribute ]; + } + if ( [ title length ] == 0 && rxRelationSet.is() && rxRelationSet -> containsRelation ( AccessibleRelationType::LABELED_BY ) ) { + [ attributeNames addObject: NSAccessibilityTitleUIElementAttribute ]; + } + if ( rxRelationSet.is() && rxRelationSet -> containsRelation ( AccessibleRelationType::LABEL_FOR ) ) { + [ attributeNames addObject: NSAccessibilityServesAsTitleForUIElementsAttribute ]; + } + // Special Attributes depending on interface + if( [self accessibleContext ] -> getAccessibleRole() == AccessibleRole::TABLE ) + [AquaA11yTableWrapper addAttributeNamesTo: attributeNames object: self]; + + if ( [ self accessibleText ] != nil ) { + [ AquaA11yTextWrapper addAttributeNamesTo: attributeNames ]; + } + if ( [ self accessibleComponent ] != nil ) { + [ AquaA11yComponentWrapper addAttributeNamesTo: attributeNames ]; + } + if ( [ self accessibleSelection ] != nil ) { + [ AquaA11ySelectionWrapper addAttributeNamesTo: attributeNames ]; + } + if ( [ self accessibleValue ] != nil ) { + [ AquaA11yValueWrapper addAttributeNamesTo: attributeNames ]; + } + [ nativeSubrole release ]; + [ title release ]; + return attributeNames; + } catch ( DisposedException & e ) { // Object is no longer available + if ( nativeSubrole != nil ) { + [ nativeSubrole release ]; + } + if ( title != nil ) { + [ title release ]; + } + if ( attributeNames != nil ) { + [ attributeNames release ]; + } + [ AquaA11yFactory removeFromWrapperRepositoryFor: [ self accessibleContext ] ]; + return [ [ NSArray alloc ] init ]; + } +} + +-(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { + SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeIsSettable:" << attribute << "]"); + BOOL isSettable = NO; + if ( [ self accessibleText ] != nil ) { + isSettable = [ AquaA11yTextWrapper isAttributeSettable: attribute forElement: self ]; + } + if ( ! isSettable && [ self accessibleComponent ] != nil ) { + isSettable = [ AquaA11yComponentWrapper isAttributeSettable: attribute forElement: self ]; + } + if ( ! isSettable && [ self accessibleSelection ] != nil ) { + isSettable = [ AquaA11ySelectionWrapper isAttributeSettable: attribute forElement: self ]; + } + if ( ! isSettable && [ self accessibleValue ] != nil ) { + isSettable = [ AquaA11yValueWrapper isAttributeSettable: attribute forElement: self ]; + } + return isSettable; // TODO: to be completed +} + +-(NSArray *)accessibilityParameterizedAttributeNames { + SAL_INFO("vcl.a11y", "[" << self << " accessibilityParameterizedAttributeNames]"); + NSMutableArray * attributeNames = [ [ NSMutableArray alloc ] init ]; + // Special Attributes depending on interface + if ( [ self accessibleText ] != nil ) { + [ AquaA11yTextWrapper addParameterizedAttributeNamesTo: attributeNames ]; + } + return attributeNames; // TODO: to be completed +} + +-(id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter { + SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeValue:" << attribute << " forParameter:" << ((NSObject*)parameter) << "]"); + SEL methodSelector = [ self selectorForAttribute: attribute asGetter: YES withGetterParameter: YES ]; + if ( [ self respondsToSelector: methodSelector ] ) { + return [ self performSelector: methodSelector withObject: parameter ]; + } + return nil; // TODO: to be completed +} + +-(BOOL)accessibilitySetOverrideValue:(id)value forAttribute:(NSString *)attribute +{ + SAL_INFO("vcl.a11y", "[" << self << " accessibilitySetOverrideValue:" << ((NSObject*)value) << " forAttribute:" << attribute << "]"); + (void)value; + (void)attribute; + return NO; // TODO +} + +-(void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute { + SAL_INFO("vcl.a11y", "[" << self << " accessibilitySetValue:" << ((NSObject*)value) << " forAttribute:" << attribute << "]"); + SEL methodSelector = [ self selectorForAttribute: attribute asGetter: NO withGetterParameter: NO ]; + if ( [ AquaA11yComponentWrapper respondsToSelector: methodSelector ] ) { + [ AquaA11yComponentWrapper performSelector: methodSelector withObject: self withObject: value ]; + } + if ( [ AquaA11yTextWrapper respondsToSelector: methodSelector ] ) { + [ AquaA11yTextWrapper performSelector: methodSelector withObject: self withObject: value ]; + } + if ( [ AquaA11ySelectionWrapper respondsToSelector: methodSelector ] ) { + [ AquaA11ySelectionWrapper performSelector: methodSelector withObject: self withObject: value ]; + } + if ( [ AquaA11yValueWrapper respondsToSelector: methodSelector ] ) { + [ AquaA11yValueWrapper performSelector: methodSelector withObject: self withObject: value ]; + } +} + +-(id)accessibilityFocusedUIElement { + SAL_INFO("vcl.a11y", "[" << self << " accessibilityFocusedUIElement]"); + // #i90575# guard NSAccessibility protocol against unwanted access + if ( isPopupMenuOpen ) { + return nil; + } + + // as this seems to be the first API call on a newly created SalFrameView object, + // make sure self gets registered in the repository .. + [ self accessibleContext ]; + + AquaA11yWrapper * focusedUIElement = AquaA11yFocusListener::get()->getFocusedUIElement(); +// AquaA11yWrapper * ancestor = focusedUIElement; + + // Make sure the focused object is a descendant of self +// do { +// if( self == ancestor ) + return focusedUIElement; + +// ancestor = [ ancestor accessibilityAttributeValue: NSAccessibilityParentAttribute ]; +// } while( nil != ancestor ); + + return self; +} + +-(NSString *)accessibilityActionDescription:(NSString *)action { + SAL_INFO("vcl.a11y", "[" << self << " accessibilityActionDescription:" << action << "]"); + return NSAccessibilityActionDescription(action); +} + +-(AquaA11yWrapper *)actionResponder { + AquaA11yWrapper * wrapper = nil; + // get some information + NSString * role = (NSString *) [ self accessibilityAttributeValue: NSAccessibilityRoleAttribute ]; + id enabledAttr = [ self enabledAttribute ]; + BOOL enabled = [ enabledAttr boolValue ]; + NSView * parent = (NSView *) [ self accessibilityAttributeValue: NSAccessibilityParentAttribute ]; + AquaA11yWrapper * parentAsWrapper = nil; + if ( [ parent isKindOfClass: [ AquaA11yWrapper class ] ] ) { + parentAsWrapper = (AquaA11yWrapper *) parent; + } + NSString * parentRole = (NSString *) [ parent accessibilityAttributeValue: NSAccessibilityRoleAttribute ]; + // if we are a textarea inside a combobox, then the combobox is the action responder + if ( enabled + && [ role isEqualToString: NSAccessibilityTextAreaRole ] + && [ parentRole isEqualToString: NSAccessibilityComboBoxRole ] + && parentAsWrapper != nil ) { + wrapper = parentAsWrapper; + } else if ( enabled && [ self accessibleAction ] != nil ) { + wrapper = self ; + } + [ parentRole release ]; + [ enabledAttr release ]; + [ role release ]; + return wrapper; +} + +-(void)accessibilityPerformAction:(NSString *)action { + SAL_INFO("vcl.a11y", "[" << self << " accessibilityPerformAction:" << action << "]"); + AquaA11yWrapper * actionResponder = [ self actionResponder ]; + if ( actionResponder != nil ) { + [ AquaA11yActionWrapper doAction: action ofElement: actionResponder ]; + } +} + +-(NSArray *)accessibilityActionNames { + SAL_INFO("vcl.a11y", "[" << self << " accessibilityActionNames]"); + NSArray * actionNames = nil; + AquaA11yWrapper * actionResponder = [ self actionResponder ]; + if ( actionResponder != nil ) { + actionNames = [ AquaA11yActionWrapper actionNamesForElement: actionResponder ]; + } else { + actionNames = [ [ NSArray alloc ] init ]; + } + return actionNames; +} + +#pragma mark - +#pragma mark Hit Test + +-(BOOL)isViewElement:(NSObject *)viewElement hitByPoint:(NSPoint)point { + BOOL hit = NO; + NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; + NSValue * position = [ viewElement accessibilityAttributeValue: NSAccessibilityPositionAttribute ]; + NSValue * size = [ viewElement accessibilityAttributeValue: NSAccessibilitySizeAttribute ]; + if ( position != nil && size != nil ) { + float minX = [ position pointValue ].x; + float minY = [ position pointValue ].y; + float maxX = minX + [ size sizeValue ].width; + float maxY = minY + [ size sizeValue ].height; + if ( minX < point.x && maxX > point.x && minY < point.y && maxY > point.y ) { + hit = YES; + } + } + [ pool release ]; + return hit; +} + +Reference < XAccessibleContext > hitTestRunner ( com::sun::star::awt::Point point, + Reference < XAccessibleContext > rxAccessibleContext ) { + Reference < XAccessibleContext > hitChild; + Reference < XAccessibleContext > emptyReference; + try { + Reference < XAccessibleComponent > rxAccessibleComponent ( rxAccessibleContext, UNO_QUERY ); + if ( rxAccessibleComponent.is() ) { + com::sun::star::awt::Point location = rxAccessibleComponent -> getLocationOnScreen(); + com::sun::star::awt::Point hitPoint ( point.X - location.X , point.Y - location.Y); + Reference < XAccessible > rxAccessible = rxAccessibleComponent -> getAccessibleAtPoint ( hitPoint ); + if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() && + rxAccessible -> getAccessibleContext() -> getAccessibleChildCount() == 0 ) { + hitChild = rxAccessible -> getAccessibleContext(); + } + } + + // iterate the hirerachy looking doing recursive hit testing. + // apparently necessary as a special treatment for e.g. comboboxes + if ( !hitChild.is() ) { + bool bSafeToIterate = true; + sal_Int32 nCount = rxAccessibleContext -> getAccessibleChildCount(); + + if ( nCount < 0 || nCount > SAL_MAX_UINT16 /* slow enough for anyone */ ) + bSafeToIterate = false; + else { // manages descendants is an horror from the a11y standards guys. + Reference< XAccessibleStateSet > xStateSet; + xStateSet = rxAccessibleContext -> getAccessibleStateSet(); + if (xStateSet.is() && xStateSet -> contains(AccessibleStateType::MANAGES_DESCENDANTS ) ) + bSafeToIterate = false; + } + + if( bSafeToIterate ) { + for ( int i = 0; i < rxAccessibleContext -> getAccessibleChildCount(); i++ ) { + Reference < XAccessible > rxAccessibleChild = rxAccessibleContext -> getAccessibleChild ( i ); + if ( rxAccessibleChild.is() && rxAccessibleChild -> getAccessibleContext().is() && rxAccessibleChild -> getAccessibleContext() -> getAccessibleRole() != AccessibleRole::LIST ) { + Reference < XAccessibleContext > myHitChild = hitTestRunner ( point, rxAccessibleChild -> getAccessibleContext() ); + if ( myHitChild.is() ) { + hitChild = myHitChild; + break; + } + } + } + } + } + } catch ( RuntimeException ) { + return emptyReference; + } + return hitChild; +} + +-(id)accessibilityHitTest:(NSPoint)point { + SAL_INFO("vcl.a11y", "[" << self << " accessibilityHitTest:" << point << "]"); + static id wrapper = nil; + if ( nil != wrapper ) { + [ wrapper release ]; + wrapper = nil; + } + Reference < XAccessibleContext > hitChild; + NSRect screenRect = [ [ NSScreen mainScreen ] frame ]; + com::sun::star::awt::Point hitPoint ( static_cast(point.x) , static_cast(screenRect.size.height - point.y) ); + // check child windows first + NSWindow * window = (NSWindow *) [ self accessibilityAttributeValue: NSAccessibilityWindowAttribute ]; + NSArray * childWindows = [ window childWindows ]; + if ( [ childWindows count ] > 0 ) { + NSWindow * element = nil; + NSEnumerator * enumerator = [ childWindows objectEnumerator ]; + while ( ( element = [ enumerator nextObject ] ) && hitChild == nil ) { + if ( [ element isKindOfClass: [ SalFrameWindow class ] ] && [ self isViewElement: element hitByPoint: point ] ) { + // we have a child window that is hit + Reference < XAccessibleRelationSet > relationSet = [ ( ( SalFrameWindow * ) element ) accessibleContext ] -> getAccessibleRelationSet(); + if ( relationSet.is() && relationSet -> containsRelation ( AccessibleRelationType::SUB_WINDOW_OF )) { + // we have a valid relation to the parent element + AccessibleRelation relation = relationSet -> getRelationByType ( AccessibleRelationType::SUB_WINDOW_OF ); + for ( int i = 0; i < relation.TargetSet.getLength() && !hitChild.is(); i++ ) { + Reference < XAccessible > rxAccessible ( relation.TargetSet [ i ], UNO_QUERY ); + if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() ) { + // hit test for children of parent + hitChild = hitTestRunner ( hitPoint, rxAccessible -> getAccessibleContext() ); + } + } + } + } + } + } + // nothing hit yet, so check ourself + if ( ! hitChild.is() ) { + if ( mpReferenceWrapper == nil ) { + [ self setDefaults: [ self accessibleContext ] ]; + } + hitChild = hitTestRunner ( hitPoint, mpReferenceWrapper -> rAccessibleContext ); + } + if ( hitChild.is() ) { + wrapper = [ AquaA11yFactory wrapperForAccessibleContext: hitChild ]; + } + if ( wrapper != nil ) { + [ wrapper retain ]; // TODO: retain only when transient ? + } + return wrapper; +} + +#pragma mark - +#pragma mark Access Methods + +-(XAccessibleAction *)accessibleAction { + return mpReferenceWrapper -> rAccessibleAction.get(); +} + +-(XAccessibleContext *)accessibleContext { + return mpReferenceWrapper -> rAccessibleContext.get(); +} + +-(XAccessibleComponent *)accessibleComponent { + return mpReferenceWrapper -> rAccessibleComponent.get(); +} + +-(XAccessibleExtendedComponent *)accessibleExtendedComponent { + return mpReferenceWrapper -> rAccessibleExtendedComponent.get(); +} + +-(XAccessibleSelection *)accessibleSelection { + return mpReferenceWrapper -> rAccessibleSelection.get(); +} + +-(XAccessibleTable *)accessibleTable { + return mpReferenceWrapper -> rAccessibleTable.get(); +} + +-(XAccessibleText *)accessibleText { + return mpReferenceWrapper -> rAccessibleText.get(); +} + +-(XAccessibleEditableText *)accessibleEditableText { + return mpReferenceWrapper -> rAccessibleEditableText.get(); +} + +-(XAccessibleValue *)accessibleValue { + return mpReferenceWrapper -> rAccessibleValue.get(); +} + +-(XAccessibleTextAttributes *)accessibleTextAttributes { + return mpReferenceWrapper -> rAccessibleTextAttributes.get(); +} + +-(XAccessibleMultiLineText *)accessibleMultiLineText { + return mpReferenceWrapper -> rAccessibleMultiLineText.get(); +} + +-(XAccessibleTextMarkup *)accessibleTextMarkup { + return mpReferenceWrapper -> rAccessibleTextMarkup.get(); +} + +-(NSView *)viewElementForParent { + return self; +} + +// These four are for AXTextAreas only. They are needed, because bold and italic +// attributes have to be bound to a font on the Mac. Our UNO-API instead handles +// and reports them independently. When they occur we bundle them to a font with +// this information here to create a according NSFont. +-(void)setActsAsRadioGroup:(BOOL)actsAsRadioGroup { + mActsAsRadioGroup = actsAsRadioGroup; +} + +-(BOOL)actsAsRadioGroup { + return mActsAsRadioGroup; +} + ++(void)setPopupMenuOpen:(BOOL)popupMenuOpen { + isPopupMenuOpen = popupMenuOpen; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapperbutton.h b/vcl/osx/a11ywrapperbutton.h new file mode 100644 index 000000000000..0bf115f130be --- /dev/null +++ b/vcl/osx/a11ywrapperbutton.h @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YWRAPPERBUTTON_H +#define INCLUDED_VCL_OSX_A11YWRAPPERBUTTON_H + +#include "osx/a11ywrapper.h" + +@interface AquaA11yWrapperButton : AquaA11yWrapper +{ +} +-(id)valueAttribute; +-(id)descriptionAttribute; +-(NSArray *)accessibilityAttributeNames; +@end + +#endif // INCLUDED_VCL_OSX_A11YWRAPPERBUTTON_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapperbutton.mm b/vcl/osx/a11ywrapperbutton.mm new file mode 100644 index 000000000000..eab7e07d00e3 --- /dev/null +++ b/vcl/osx/a11ywrapperbutton.mm @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" + +#include "a11ywrapperbutton.h" +#include "a11ytextwrapper.h" + +// Wrapper for AXButton role + +@implementation AquaA11yWrapperButton : AquaA11yWrapper + +-(id)valueAttribute { + return [ NSString string ]; // we propagate AXTitle, that's enough +} + +-(id)descriptionAttribute { + return [ NSString string ]; // we propagate AXTitle, that's enough +} + +-(NSArray *)accessibilityAttributeNames { + // Default Attributes + NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; + // Special Attributes and removing unwanted attributes depending on role + if ( [ attributeNames containsObject: NSAccessibilityTitleAttribute ] ) { + [ attributeNames removeObject: NSAccessibilityDescriptionAttribute ]; + } else { + [ attributeNames addObject: NSAccessibilityTitleAttribute ]; + } + // Remove text-specific attributes + [ attributeNames removeObjectsInArray: [ AquaA11yTextWrapper specialAttributeNames ] ]; + return attributeNames; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrappercheckbox.h b/vcl/osx/a11ywrappercheckbox.h new file mode 100644 index 000000000000..58cd2986e41e --- /dev/null +++ b/vcl/osx/a11ywrappercheckbox.h @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YWRAPPERCHECKBOX_H +#define INCLUDED_VCL_OSX_A11YWRAPPERCHECKBOX_H + +#include "osx/a11ywrapper.h" + +@interface AquaA11yWrapperCheckBox : AquaA11yWrapper +{ +} +-(id)valueAttribute; +-(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute; +-(NSArray *)accessibilityAttributeNames; +@end + +#endif // INCLUDED_VCL_OSX_A11YWRAPPERCHECKBOX_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrappercheckbox.mm b/vcl/osx/a11ywrappercheckbox.mm new file mode 100644 index 000000000000..e8ea2a00b9d6 --- /dev/null +++ b/vcl/osx/a11ywrappercheckbox.mm @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" + +#include "a11ywrappercheckbox.h" +#include "a11yvaluewrapper.h" +#include "a11ytextwrapper.h" + +// Wrapper for AXCheckbox role + +@implementation AquaA11yWrapperCheckBox : AquaA11yWrapper + +-(id)valueAttribute { + if ( [ self accessibleValue ] != nil ) { + return [ AquaA11yValueWrapper valueAttributeForElement: self ]; + } + return [ NSNumber numberWithInt: 0 ]; +} + +-(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { + if ( [ attribute isEqualToString: NSAccessibilityValueAttribute ] ) { + return NO; + } + return [ super accessibilityIsAttributeSettable: attribute ]; +} + +-(NSArray *)accessibilityAttributeNames { + // Default Attributes + NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; + // Remove text-specific attributes + [ attributeNames removeObjectsInArray: [ AquaA11yTextWrapper specialAttributeNames ] ]; + [ attributeNames addObject: NSAccessibilityValueAttribute ]; + [ attributeNames addObject: NSAccessibilityMinValueAttribute ]; + [ attributeNames addObject: NSAccessibilityMaxValueAttribute ]; + return attributeNames; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrappercombobox.h b/vcl/osx/a11ywrappercombobox.h new file mode 100644 index 000000000000..13058844b746 --- /dev/null +++ b/vcl/osx/a11ywrappercombobox.h @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YWRAPPERCOMBOBOX_H +#define INCLUDED_VCL_OSX_A11YWRAPPERCOMBOBOX_H + +#include "osx/a11ywrapper.h" +#include + +@interface AquaA11yWrapperComboBox : AquaA11yWrapper +{ + AquaA11yWrapper * textArea; +} +-(id)initWithAccessibleContext: (::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >) anAccessibleContext; +-(id)valueAttribute; +-(id)numberOfCharactersAttribute; +-(id)selectedTextAttribute; +-(id)selectedTextRangeAttribute; +-(id)visibleCharacterRangeAttribute; +// Accessibility Protocol +-(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute; +-(void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute; +-(NSArray *)accessibilityAttributeNames; +@end + +#endif // INCLUDED_VCL_OSX_A11YWRAPPERCOMBOBOX_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrappercombobox.mm b/vcl/osx/a11ywrappercombobox.mm new file mode 100644 index 000000000000..2467718c79d4 --- /dev/null +++ b/vcl/osx/a11ywrappercombobox.mm @@ -0,0 +1,155 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" + +#include "a11ywrappercombobox.h" +#include "a11yrolehelper.h" + +#include + +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::uno; + +// Wrapper for AXCombobox role + +@implementation AquaA11yWrapperComboBox : AquaA11yWrapper + +#pragma mark - +#pragma mark Specialized Init Method + +-(id)initWithAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext { + self = [ super initWithAccessibleContext: rxAccessibleContext ]; + if ( self != nil ) + { + textArea = nil; + } + return self; +} + +#pragma mark - +#pragma mark Private Helper Method + +-(AquaA11yWrapper *)textArea { + // FIXME: May cause problems when stored. Then get dynamically each time (bad performance!) + if ( textArea == nil ) { + NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; + NSArray * elementChildren = [ super childrenAttribute ]; + if ( [ elementChildren count ] > 0 ) { + NSEnumerator * enumerator = [ elementChildren objectEnumerator ]; + id child; + while ( ( child = [ enumerator nextObject ] ) ) { + AquaA11yWrapper * element = ( AquaA11yWrapper * ) child; + if ( [ [ AquaA11yRoleHelper getNativeRoleFrom: [ element accessibleContext ] ] isEqualToString: NSAccessibilityTextAreaRole ] ) { + textArea = element; + break; + } + } + } + [ pool release ]; + } + return textArea; +} + +#pragma mark - +#pragma mark Wrapped Attributes From Contained Text Area + +-(id)valueAttribute { + if ( [ self textArea ] != nil ) { + return [ [ self textArea ] valueAttribute ]; + } + return @""; +} + +-(id)numberOfCharactersAttribute { + if ( [ self textArea ] != nil ) { + return [ [ self textArea ] numberOfCharactersAttribute ]; + } + return [ NSNumber numberWithInt: 0 ]; +} + +-(id)selectedTextAttribute { + if ( [ self textArea ] != nil ) { + return [ [ self textArea ] selectedTextAttribute ]; + } + return @""; +} + +-(id)selectedTextRangeAttribute { + if ( [ self textArea ] != nil ) { + return [ [ self textArea ] selectedTextRangeAttribute ]; + } + return [ NSValue valueWithRange: NSMakeRange ( 0, 0 ) ]; +} + +-(id)visibleCharacterRangeAttribute { + if ( [ self textArea ] != nil ) { + return [ [ self textArea ] visibleCharacterRangeAttribute ]; + } + return [ NSValue valueWithRange: NSMakeRange ( 0, 0 ) ]; +} + +#pragma mark - +#pragma mark Accessibility Protocol + +-(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { + if ( [ self textArea ] != nil && ( + [ attribute isEqualToString: NSAccessibilitySelectedTextAttribute ] + || [ attribute isEqualToString: NSAccessibilitySelectedTextRangeAttribute ] + || [ attribute isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute ] ) ) { + return [ [ self textArea ] accessibilityIsAttributeSettable: attribute ]; + } + return [ super accessibilityIsAttributeSettable: attribute ]; +} + +-(void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute { + if ( [ self textArea ] != nil && ( + [ attribute isEqualToString: NSAccessibilitySelectedTextAttribute ] + || [ attribute isEqualToString: NSAccessibilitySelectedTextRangeAttribute ] + || [ attribute isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute ] ) ) { + return [ [ self textArea ] accessibilitySetValue: value forAttribute: attribute ]; + } + return [ super accessibilitySetValue: value forAttribute: attribute ]; +} + +-(NSArray *)accessibilityAttributeNames { + // Default Attributes + NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; + // Special Attributes and removing unwanted attributes depending on role + [ attributeNames removeObjectsInArray: [ NSArray arrayWithObjects: + NSAccessibilityTitleAttribute, + NSAccessibilityChildrenAttribute, + nil ] + ]; + [ attributeNames addObjectsFromArray: [ NSArray arrayWithObjects: + NSAccessibilityExpandedAttribute, + NSAccessibilityValueAttribute, + NSAccessibilityNumberOfCharactersAttribute, + NSAccessibilitySelectedTextAttribute, + NSAccessibilitySelectedTextRangeAttribute, + NSAccessibilityVisibleCharacterRangeAttribute, + nil ] + ]; + return attributeNames; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrappergroup.h b/vcl/osx/a11ywrappergroup.h new file mode 100644 index 000000000000..af2baea63e11 --- /dev/null +++ b/vcl/osx/a11ywrappergroup.h @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YWRAPPERGROUP_H +#define INCLUDED_VCL_OSX_A11YWRAPPERGROUP_H + +#include "osx/a11ywrapper.h" + +@interface AquaA11yWrapperGroup : AquaA11yWrapper +{ +} +-(id)titleUIElementAttribute; +-(NSArray *)accessibilityAttributeNames; +@end + +#endif // INCLUDED_VCL_OSX_A11YWRAPPERGROUP_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrappergroup.mm b/vcl/osx/a11ywrappergroup.mm new file mode 100644 index 000000000000..3eb864fc7eb8 --- /dev/null +++ b/vcl/osx/a11ywrappergroup.mm @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" +#include "a11ywrappergroup.h" + +// Wrapper for AXGroup role + +@implementation AquaA11yWrapperGroup : AquaA11yWrapper + +-(id)titleUIElementAttribute { + return self; // TODO +} + +-(NSArray *)accessibilityAttributeNames { + // Default Attributes + NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; + // Special Attributes and removing unwanted attributes depending on role + [ attributeNames removeObjectsInArray: [ NSArray arrayWithObjects: + NSAccessibilityTitleAttribute, + NSAccessibilityEnabledAttribute, + NSAccessibilitySelectedChildrenAttribute, + nil ] + ]; + [ attributeNames addObject: NSAccessibilityContentsAttribute ]; + [ attributeNames addObject: NSAccessibilityTitleUIElementAttribute ]; + return attributeNames; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapperlist.h b/vcl/osx/a11ywrapperlist.h new file mode 100644 index 000000000000..65f605a173b1 --- /dev/null +++ b/vcl/osx/a11ywrapperlist.h @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YWRAPPERLIST_H +#define INCLUDED_VCL_OSX_A11YWRAPPERLIST_H + +#include "osx/a11ywrapper.h" + +@interface AquaA11yWrapperList : AquaA11yWrapper +{ +} +-(NSArray *)accessibilityAttributeNames; +@end + +#endif // INCLUDED_VCL_OSX_A11YWRAPPERLIST_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapperlist.mm b/vcl/osx/a11ywrapperlist.mm new file mode 100644 index 000000000000..e10bf727858f --- /dev/null +++ b/vcl/osx/a11ywrapperlist.mm @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" +#include "a11ywrapperlist.h" + +using namespace ::com::sun::star::accessibility; + +// Wrapper for AXList role + +@implementation AquaA11yWrapperList : AquaA11yWrapper + +-(NSArray *)accessibilityAttributeNames { + // Default Attributes + NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; + // Special Attributes and removing unwanted attributes depending on role + [ attributeNames addObject: NSAccessibilityOrientationAttribute ]; + return attributeNames; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapperradiobutton.h b/vcl/osx/a11ywrapperradiobutton.h new file mode 100644 index 000000000000..83e3f5fc9e89 --- /dev/null +++ b/vcl/osx/a11ywrapperradiobutton.h @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YWRAPPERRADIOBUTTON_H +#define INCLUDED_VCL_OSX_A11YWRAPPERRADIOBUTTON_H + +#include "osx/a11ywrapper.h" + +@interface AquaA11yWrapperRadioButton : AquaA11yWrapper +{ +} +-(id)valueAttribute; +-(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute; +-(NSArray *)accessibilityAttributeNames; +@end + +#endif // INCLUDED_VCL_OSX_A11YWRAPPERRADIOBUTTON_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapperradiobutton.mm b/vcl/osx/a11ywrapperradiobutton.mm new file mode 100644 index 000000000000..cfd8dbd23871 --- /dev/null +++ b/vcl/osx/a11ywrapperradiobutton.mm @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" +#include "a11ywrapperradiobutton.h" +#include "a11ytextwrapper.h" +#include "a11yvaluewrapper.h" + +// Wrapper for AXRadioButton role + +@implementation AquaA11yWrapperRadioButton : AquaA11yWrapper + +-(id)valueAttribute { + if ( [ self accessibleValue ] != nil ) { + return [ AquaA11yValueWrapper valueAttributeForElement: self ]; + } + return [ NSNumber numberWithInt: 0 ]; +} + +-(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { + if ( [ attribute isEqualToString: NSAccessibilityValueAttribute ] ) { + return NO; + } + return [ super accessibilityIsAttributeSettable: attribute ]; +} + +-(NSArray *)accessibilityAttributeNames { + // Default Attributes + NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; + // Special Attributes and removing unwanted attributes depending on role + [ attributeNames removeObjectsInArray: [ AquaA11yTextWrapper specialAttributeNames ] ]; + [ attributeNames addObject: NSAccessibilityMinValueAttribute ]; + [ attributeNames addObject: NSAccessibilityMaxValueAttribute ]; + [ attributeNames addObject: NSAccessibilityValueAttribute ]; + return attributeNames; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapperradiogroup.h b/vcl/osx/a11ywrapperradiogroup.h new file mode 100644 index 000000000000..6ae98cbfd583 --- /dev/null +++ b/vcl/osx/a11ywrapperradiogroup.h @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YWRAPPERRADIOGROUP_H +#define INCLUDED_VCL_OSX_A11YWRAPPERRADIOGROUP_H + +#include "osx/a11ywrapper.h" + +@interface AquaA11yWrapperRadioGroup : AquaA11yWrapper +{ +} +-(NSArray *)accessibilityAttributeNames; +@end + +#endif // INCLUDED_VCL_OSX_A11YWRAPPERRADIOGROUP_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapperradiogroup.mm b/vcl/osx/a11ywrapperradiogroup.mm new file mode 100644 index 000000000000..d66192df67bb --- /dev/null +++ b/vcl/osx/a11ywrapperradiogroup.mm @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" +#include "a11ywrapperradiogroup.h" +#include "a11ytextwrapper.h" + +// Wrapper for AXRadioGroup role + +@implementation AquaA11yWrapperRadioGroup : AquaA11yWrapper + +-(NSArray *)accessibilityAttributeNames { + // Default Attributes + NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; + // Special Attributes and removing unwanted attributes depending on role + [ attributeNames removeObjectsInArray: [ AquaA11yTextWrapper specialAttributeNames ] ]; + [ attributeNames removeObject: NSAccessibilityTitleAttribute ]; + return attributeNames; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapperrow.h b/vcl/osx/a11ywrapperrow.h new file mode 100644 index 000000000000..45cd7477d6ec --- /dev/null +++ b/vcl/osx/a11ywrapperrow.h @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YWRAPPERROW_H +#define INCLUDED_VCL_OSX_A11YWRAPPERROW_H + +#include "osx/a11ywrapper.h" + +@interface AquaA11yWrapperRow : AquaA11yWrapper +{ +} +-(id)disclosingAttribute; +-(NSArray *)accessibilityAttributeNames; +@end + +#endif // INCLUDED_VCL_OSX_A11YWRAPPERROW_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapperrow.mm b/vcl/osx/a11ywrapperrow.mm new file mode 100644 index 000000000000..8bcef8032cd3 --- /dev/null +++ b/vcl/osx/a11ywrapperrow.mm @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" + +#include "a11ywrapperrow.h" +#include "a11ytextwrapper.h" + +// Wrapper for AXRow role + +@implementation AquaA11yWrapperRow : AquaA11yWrapper + +-(id)disclosingAttribute { + return NULL; // TODO +} + +-(NSArray *)accessibilityAttributeNames { + // Default Attributes + NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; + // Special Attributes and removing unwanted attributes depending on role + [ attributeNames removeObjectsInArray: [ AquaA11yTextWrapper specialAttributeNames ] ]; + [ attributeNames removeObject: NSAccessibilityTitleAttribute ]; + [ attributeNames removeObject: NSAccessibilityEnabledAttribute ]; + [ attributeNames removeObject: NSAccessibilityFocusedAttribute ]; + [ attributeNames addObject: NSAccessibilitySelectedAttribute ]; + [ attributeNames addObject: NSAccessibilityDisclosingAttribute ]; + return attributeNames; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapperscrollarea.h b/vcl/osx/a11ywrapperscrollarea.h new file mode 100644 index 000000000000..35a2aa15a028 --- /dev/null +++ b/vcl/osx/a11ywrapperscrollarea.h @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YWRAPPERSCROLLAREA_H +#define INCLUDED_VCL_OSX_A11YWRAPPERSCROLLAREA_H + +#include "osx/a11ywrapper.h" + +@interface AquaA11yWrapperScrollArea : AquaA11yWrapper +{ +} +-(id)verticalScrollBarAttribute; +-(id)horizontalScrollBarAttribute; +-(NSArray *)accessibilityAttributeNames; +@end + +#endif // INCLUDED_VCL_OSX_A11YWRAPPERSCROLLAREA_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapperscrollarea.mm b/vcl/osx/a11ywrapperscrollarea.mm new file mode 100644 index 000000000000..f70f44962ddb --- /dev/null +++ b/vcl/osx/a11ywrapperscrollarea.mm @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" + +#include "a11ywrapperscrollarea.h" +#include "a11ywrapperscrollbar.h" +#include "a11yrolehelper.h" + +// Wrapper for AXScrollArea role + +@implementation AquaA11yWrapperScrollArea : AquaA11yWrapper + +-(id)scrollBarWithOrientation:(NSString *)orientation { + AquaA11yWrapper * theScrollBar = nil; + NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; + NSArray * elementChildren = [ self accessibilityAttributeValue: NSAccessibilityChildrenAttribute ]; + if ( [ elementChildren count ] > 0 ) { + NSEnumerator * enumerator = [ elementChildren objectEnumerator ]; + id child; + while ( ( child = [ enumerator nextObject ] ) ) { + AquaA11yWrapper * element = ( AquaA11yWrapper * ) child; + if ( [ element isKindOfClass: [ AquaA11yWrapperScrollBar class ] ] ) { + AquaA11yWrapperScrollBar * scrollBar = (AquaA11yWrapperScrollBar *) element; + if ( [ [ scrollBar orientationAttribute ] isEqualToString: orientation ] ) { + theScrollBar = scrollBar; + break; + } + } + } + } + [ pool release ]; + return theScrollBar; +} + +-(id)verticalScrollBarAttribute { + return [ self scrollBarWithOrientation: NSAccessibilityVerticalOrientationValue ]; +} + +-(id)horizontalScrollBarAttribute { + return [ self scrollBarWithOrientation: NSAccessibilityHorizontalOrientationValue ]; +} + +-(NSArray *)accessibilityAttributeNames { + // Default Attributes + NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; + // Special Attributes and removing unwanted attributes depending on role + [ attributeNames removeObject: NSAccessibilityEnabledAttribute ]; + [ attributeNames addObjectsFromArray: [ NSArray arrayWithObjects: + NSAccessibilityContentsAttribute, + NSAccessibilityVerticalScrollBarAttribute, + NSAccessibilityHorizontalScrollBarAttribute, + nil ] + ]; + return attributeNames; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapperscrollbar.h b/vcl/osx/a11ywrapperscrollbar.h new file mode 100644 index 000000000000..a6d87079a31b --- /dev/null +++ b/vcl/osx/a11ywrapperscrollbar.h @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YWRAPPERSCROLLBAR_H +#define INCLUDED_VCL_OSX_A11YWRAPPERSCROLLBAR_H + +#include "osx/a11ywrapper.h" + +@interface AquaA11yWrapperScrollBar : AquaA11yWrapper +{ +} +-(NSArray *)accessibilityAttributeNames; +@end + +#endif // INCLUDED_VCL_OSX_A11YWRAPPERSCROLLBAR_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapperscrollbar.mm b/vcl/osx/a11ywrapperscrollbar.mm new file mode 100644 index 000000000000..3717cafc883b --- /dev/null +++ b/vcl/osx/a11ywrapperscrollbar.mm @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" + +#include "a11ywrapperscrollbar.h" + +#include + +using namespace ::com::sun::star::accessibility; + +// Wrapper for AXScrollBar role + +@implementation AquaA11yWrapperScrollBar : AquaA11yWrapper + +-(NSArray *)accessibilityAttributeNames { + // Default Attributes + NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; + // Special Attributes and removing unwanted attributes depending on role + [ attributeNames addObject: NSAccessibilityOrientationAttribute ]; + return attributeNames; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrappersplitter.h b/vcl/osx/a11ywrappersplitter.h new file mode 100644 index 000000000000..18cdb6e0cdca --- /dev/null +++ b/vcl/osx/a11ywrappersplitter.h @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YWRAPPERSPLITTER_H +#define INCLUDED_VCL_OSX_A11YWRAPPERSPLITTER_H + +#include "osx/a11ywrapper.h" + +@interface AquaA11yWrapperSplitter : AquaA11yWrapper +{ +} +-(NSArray *)accessibilityAttributeNames; +@end + +#endif // INCLUDED_VCL_OSX_A11YWRAPPERSPLITTER_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrappersplitter.mm b/vcl/osx/a11ywrappersplitter.mm new file mode 100644 index 000000000000..66db6dc92f36 --- /dev/null +++ b/vcl/osx/a11ywrappersplitter.mm @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" +#include "a11ywrappersplitter.h" + +using namespace ::com::sun::star::accessibility; + +// Wrapper for AXSplitter role + +@implementation AquaA11yWrapperSplitter : AquaA11yWrapper + +-(NSArray *)accessibilityAttributeNames { + // Default Attributes + NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; + // Special Attributes and removing unwanted attributes depending on role + [ attributeNames addObject: NSAccessibilityOrientationAttribute ]; + return attributeNames; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapperstatictext.h b/vcl/osx/a11ywrapperstatictext.h new file mode 100644 index 000000000000..a210d80b7550 --- /dev/null +++ b/vcl/osx/a11ywrapperstatictext.h @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YWRAPPERSTATICTEXT_H +#define INCLUDED_VCL_OSX_A11YWRAPPERSTATICTEXT_H + +#include "osx/a11ywrapper.h" + +@interface AquaA11yWrapperStaticText : AquaA11yWrapper +{ +} +-(id)titleAttribute; +-(NSArray *)accessibilityAttributeNames; +@end + +#endif // INCLUDED_VCL_OSX_A11YWRAPPERSTATICTEXT_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrapperstatictext.mm b/vcl/osx/a11ywrapperstatictext.mm new file mode 100644 index 000000000000..ce0d7c425d92 --- /dev/null +++ b/vcl/osx/a11ywrapperstatictext.mm @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" +#include "a11ywrapperstatictext.h" + +// Wrapper for AXStaticText role + +@implementation AquaA11yWrapperStaticText : AquaA11yWrapper + +-(id)titleAttribute { + NSString * title = [ super titleAttribute ]; + if ( [ title isEqualToString: [ super valueAttribute ] ] ) { + return [ NSString string ]; + } + return title; +} + +-(NSArray *)accessibilityAttributeNames { + // Default Attributes + NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; + // Special Attributes and removing unwanted attributes depending on role + [ attributeNames removeObject: NSAccessibilityTitleAttribute ]; + [ attributeNames removeObject: NSAccessibilitySharedTextUIElementsAttribute ]; + [ attributeNames removeObject: NSAccessibilitySharedCharacterRangeAttribute ]; + return attributeNames; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrappertabgroup.h b/vcl/osx/a11ywrappertabgroup.h new file mode 100644 index 000000000000..b340d7506995 --- /dev/null +++ b/vcl/osx/a11ywrappertabgroup.h @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YWRAPPERTABGROUP_H +#define INCLUDED_VCL_OSX_A11YWRAPPERTABGROUP_H + +#include "osx/a11ywrapper.h" + +@interface AquaA11yWrapperTabGroup : AquaA11yWrapper +{ +} +-(NSArray *)accessibilityAttributeNames; +@end + +#endif // INCLUDED_VCL_OSX_A11YWRAPPERTABGROUP_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrappertabgroup.mm b/vcl/osx/a11ywrappertabgroup.mm new file mode 100644 index 000000000000..0174e43093e2 --- /dev/null +++ b/vcl/osx/a11ywrappertabgroup.mm @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" +#include "a11ywrappertabgroup.h" + +// Wrapper for AXTabGroup role + +@implementation AquaA11yWrapperTabGroup : AquaA11yWrapper + +-(NSArray *)accessibilityAttributeNames { + // Default Attributes + NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; + // Special Attributes and removing unwanted attributes depending on role + [ attributeNames addObjectsFromArray: [ NSArray arrayWithObjects: + NSAccessibilityContentsAttribute, + NSAccessibilityTabsAttribute, + nil ] + ]; + return attributeNames; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrappertextarea.h b/vcl/osx/a11ywrappertextarea.h new file mode 100644 index 000000000000..a0cf4f68d6af --- /dev/null +++ b/vcl/osx/a11ywrappertextarea.h @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YWRAPPERTEXTAREA_H +#define INCLUDED_VCL_OSX_A11YWRAPPERTEXTAREA_H + +#include "osx/a11ywrapper.h" + +@interface AquaA11yWrapperTextArea : AquaA11yWrapper +{ +} +-(NSArray *)accessibilityAttributeNames; +@end + +#endif // INCLUDED_VCL_OSX_A11YWRAPPERTEXTAREA_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrappertextarea.mm b/vcl/osx/a11ywrappertextarea.mm new file mode 100644 index 000000000000..9b4fbf995733 --- /dev/null +++ b/vcl/osx/a11ywrappertextarea.mm @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" +#include "a11ywrappertextarea.h" + +// Wrapper for AXTextArea role + +@implementation AquaA11yWrapperTextArea : AquaA11yWrapper + +-(NSArray *)accessibilityAttributeNames { + // Default Attributes + NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; + // Special Attributes and removing unwanted attributes depending on role + [ attributeNames removeObject: NSAccessibilityTitleAttribute ]; + [ attributeNames removeObject: NSAccessibilityEnabledAttribute ]; + [ attributeNames addObject: NSAccessibilityChildrenAttribute ]; + return attributeNames; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrappertoolbar.h b/vcl/osx/a11ywrappertoolbar.h new file mode 100644 index 000000000000..64bd14250e9e --- /dev/null +++ b/vcl/osx/a11ywrappertoolbar.h @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_A11YWRAPPERTOOLBAR_H +#define INCLUDED_VCL_OSX_A11YWRAPPERTOOLBAR_H + +#include "osx/a11ywrapper.h" + +@interface AquaA11yWrapperToolbar : AquaA11yWrapper +{ +} +-(NSArray *)accessibilityAttributeNames; +@end + +#endif // INCLUDED_VCL_OSX_A11YWRAPPERTOOLBAR_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/a11ywrappertoolbar.mm b/vcl/osx/a11ywrappertoolbar.mm new file mode 100644 index 000000000000..9636d7882705 --- /dev/null +++ b/vcl/osx/a11ywrappertoolbar.mm @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" +#include "a11ywrappertoolbar.h" + +// Wrapper for AXToolbar role + +@implementation AquaA11yWrapperToolbar : AquaA11yWrapper + +-(NSArray *)accessibilityAttributeNames { + // Default Attributes + NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; + // Special Attributes and removing unwanted attributes depending on role + [ attributeNames removeObjectsInArray: [ NSArray arrayWithObjects: + NSAccessibilityTitleAttribute, + NSAccessibilityEnabledAttribute, + nil ] + ]; + return attributeNames; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/clipboard.cxx b/vcl/osx/clipboard.cxx new file mode 100644 index 000000000000..72feefe5bdb6 --- /dev/null +++ b/vcl/osx/clipboard.cxx @@ -0,0 +1,372 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "clipboard.hxx" + +#include "DataFlavorMapping.hxx" +#include "OSXTransferable.hxx" +#include +#include "comphelper/makesequence.hxx" +#include "comphelper/processfactory.hxx" + +#include + +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::datatransfer::clipboard; +using namespace com::sun::star::lang; +using namespace com::sun::star::uno; +using namespace cppu; +using namespace osl; +using namespace std; +using namespace comphelper; + + +@implementation EventListener; + +-(EventListener*)initWithAquaClipboard: (AquaClipboard*) pcb +{ + self = [super init]; + + if (self) + pAquaClipboard = pcb; + + return self; +} + +-(void)pasteboard:(NSPasteboard*)sender provideDataForType:(NSString*)type +{ + if( pAquaClipboard ) + pAquaClipboard->provideDataForType(sender, type); +} + +-(void)applicationDidBecomeActive:(NSNotification*)aNotification +{ + if( pAquaClipboard ) + pAquaClipboard->applicationDidBecomeActive(aNotification); +} + +-(void)disposing +{ + pAquaClipboard = NULL; +} + +@end + + +OUString clipboard_getImplementationName() +{ + return OUString("com.sun.star.datatransfer.clipboard.AquaClipboard"); +} + +Sequence clipboard_getSupportedServiceNames() +{ + return makeSequence(OUString("com.sun.star.datatransfer.clipboard.SystemClipboard")); +} + + +AquaClipboard::AquaClipboard(NSPasteboard* pasteboard, bool bUseSystemPasteboard) : + WeakComponentImplHelper3(m_aMutex), + mIsSystemPasteboard(bUseSystemPasteboard) +{ + Reference xContext = comphelper::getProcessComponentContext(); + + mrXMimeCntFactory = MimeContentTypeFactory::create(xContext); + + mpDataFlavorMapper = DataFlavorMapperPtr_t(new DataFlavorMapper()); + + if (pasteboard != NULL) + { + mPasteboard = pasteboard; + mIsSystemPasteboard = false; + } + else + { + mPasteboard = bUseSystemPasteboard ? [NSPasteboard generalPasteboard] : + [NSPasteboard pasteboardWithName: NSDragPboard]; + + if (mPasteboard == nil) + { + throw RuntimeException("AquaClipboard: Cannot create Cocoa pasteboard", + static_cast(this)); + } + } + + [mPasteboard retain]; + + mEventListener = [[EventListener alloc] initWithAquaClipboard: this]; + + if (mEventListener == nil) + { + [mPasteboard release]; + + throw RuntimeException( + OUString("AquaClipboard: Cannot create pasteboard change listener"), + static_cast(this)); + } + + if (mIsSystemPasteboard) + { + NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter]; + + [notificationCenter addObserver: mEventListener + selector: @selector(applicationDidBecomeActive:) + name: @"NSApplicationDidBecomeActiveNotification" + object: [NSApplication sharedApplication]]; + } + + mPasteboardChangeCount = [mPasteboard changeCount]; +} + + +AquaClipboard::~AquaClipboard() +{ + if (mIsSystemPasteboard) + { + [[NSNotificationCenter defaultCenter] removeObserver: mEventListener]; + } + + [mEventListener disposing]; + [mEventListener release]; + [mPasteboard release]; +} + + +Reference SAL_CALL AquaClipboard::getContents() throw(RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + + // Shortcut: If we are clipboard owner already we don't need + // to drag the data through the system clipboard + if (mXClipboardContent.is()) + { + return mXClipboardContent; + } + + return Reference(new OSXTransferable(mrXMimeCntFactory, + mpDataFlavorMapper, + mPasteboard)); +} + + +void SAL_CALL AquaClipboard::setContents(const Reference& xTransferable, + const Reference& xClipboardOwner) + throw( RuntimeException ) +{ + NSArray* types = xTransferable.is() ? + mpDataFlavorMapper->flavorSequenceToTypesArray(xTransferable->getTransferDataFlavors()) : + [NSArray array]; + + ClearableMutexGuard aGuard(m_aMutex); + + Reference oldOwner(mXClipboardOwner); + mXClipboardOwner = xClipboardOwner; + + Reference oldContent(mXClipboardContent); + mXClipboardContent = xTransferable; + + mPasteboardChangeCount = [mPasteboard declareTypes: types owner: mEventListener]; + + aGuard.clear(); + + // if we are already the owner of the clipboard + // then fire lost ownership event + if (oldOwner.is()) + { + fireLostClipboardOwnershipEvent(oldOwner, oldContent); + } + + fireClipboardChangedEvent(); +} + + +OUString SAL_CALL AquaClipboard::getName() throw( RuntimeException ) +{ + return OUString(); +} + + +sal_Int8 SAL_CALL AquaClipboard::getRenderingCapabilities() throw( RuntimeException ) +{ + return 0; +} + + +void SAL_CALL AquaClipboard::addClipboardListener(const Reference< XClipboardListener >& listener) + throw( RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + + if (!listener.is()) + throw IllegalArgumentException("empty reference", + static_cast(this), 1); + + mClipboardListeners.push_back(listener); +} + + +void SAL_CALL AquaClipboard::removeClipboardListener(const Reference< XClipboardListener >& listener) + throw( RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + + if (!listener.is()) + throw IllegalArgumentException("empty reference", + static_cast(this), 1); + + mClipboardListeners.remove(listener); +} + + +void AquaClipboard::applicationDidBecomeActive(NSNotification*) +{ + ClearableMutexGuard aGuard(m_aMutex); + + int currentPboardChgCount = [mPasteboard changeCount]; + + if (currentPboardChgCount != mPasteboardChangeCount) + { + mPasteboardChangeCount = currentPboardChgCount; + + // Clear clipboard content and owner and send lostOwnership + // notification to the old clipboard owner as well as + // ClipboardChanged notification to any clipboard listener + Reference oldOwner(mXClipboardOwner); + mXClipboardOwner.clear(); + + Reference oldContent(mXClipboardContent); + mXClipboardContent.clear(); + + aGuard.clear(); + + if (oldOwner.is()) + { + fireLostClipboardOwnershipEvent(oldOwner, oldContent); + } + + fireClipboardChangedEvent(); + } +} + + +void AquaClipboard::fireClipboardChangedEvent() +{ + ClearableMutexGuard aGuard(m_aMutex); + + list > listeners(mClipboardListeners); + ClipboardEvent aEvent; + + if (listeners.begin() != listeners.end()) + { + aEvent = ClipboardEvent(static_cast(this), getContents()); + } + + aGuard.clear(); + + while (listeners.begin() != listeners.end()) + { + if (listeners.front().is()) + { + try { listeners.front()->changedContents(aEvent); } + catch (RuntimeException&) { } + } + listeners.pop_front(); + } +} + + +void AquaClipboard::fireLostClipboardOwnershipEvent(Reference oldOwner, Reference oldContent) +{ + BOOST_ASSERT(oldOwner.is()); + + try { oldOwner->lostOwnership(static_cast(this), oldContent); } + catch(RuntimeException&) { } +} + + +void AquaClipboard::provideDataForType(NSPasteboard* sender, NSString* type) +{ + if( mXClipboardContent.is() ) + { + DataProviderPtr_t dp = mpDataFlavorMapper->getDataProvider(type, mXClipboardContent); + NSData* pBoardData = NULL; + + if (dp.get() != NULL) + { + pBoardData = (NSData*)dp->getSystemData(); + [sender setData: pBoardData forType: type]; + } + } +} + + +//------------------------------------------------ +// XFlushableClipboard +//------------------------------------------------ + +void SAL_CALL AquaClipboard::flushClipboard() + throw(RuntimeException) +{ + if (mXClipboardContent.is()) + { + Sequence flavorList = mXClipboardContent->getTransferDataFlavors(); + sal_uInt32 nFlavors = flavorList.getLength(); + bool bInternal(false); + + for (sal_uInt32 i = 0; i < nFlavors; i++) + { + NSString* sysType = mpDataFlavorMapper->openOfficeToSystemFlavor(flavorList[i], bInternal); + + if (sysType != NULL) + { + provideDataForType(mPasteboard, sysType); + } + } + mXClipboardContent.clear(); + } +} + + +NSPasteboard* AquaClipboard::getPasteboard() const +{ + return mPasteboard; +} + + +//------------------------------------------------- +// XServiceInfo +//------------------------------------------------- + +OUString SAL_CALL AquaClipboard::getImplementationName() throw( RuntimeException ) +{ + return clipboard_getImplementationName(); +} + + +sal_Bool SAL_CALL AquaClipboard::supportsService( const OUString& /*ServiceName*/ ) throw( RuntimeException ) +{ + return sal_False; +} + + +Sequence< OUString > SAL_CALL AquaClipboard::getSupportedServiceNames() throw( RuntimeException ) +{ + return clipboard_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/clipboard.hxx b/vcl/osx/clipboard.hxx new file mode 100644 index 000000000000..1424e34fc4d4 --- /dev/null +++ b/vcl/osx/clipboard.hxx @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_CLIPBOARD_HXX +#define INCLUDED_VCL_OSX_CLIPBOARD_HXX + +#include "DataFlavorMapping.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#import +#include + +class AquaClipboard; + +@interface EventListener : NSObject +{ + AquaClipboard* pAquaClipboard; +} + +// Init the pasteboard change listener with a reference to the OfficeClipboard +// instance +- (EventListener*)initWithAquaClipboard: (AquaClipboard*) pcb; + +// Promiss resolver function +- (void)pasteboard:(NSPasteboard*)sender provideDataForType:(NSString *)type; + +-(void)applicationDidBecomeActive:(NSNotification*)aNotification; + +-(void)disposing; +@end + + +class AquaClipboard : public ::cppu::BaseMutex, + public ::cppu::WeakComponentImplHelper3< com::sun::star::datatransfer::clipboard::XSystemClipboard, + com::sun::star::datatransfer::clipboard::XFlushableClipboard, + com::sun::star::lang::XServiceInfo >, + private ::boost::noncopyable +{ +public: + /* Create a clipboard instance. + + @param pasteboard + If not equal NULL the instance will be instantiated with the provided + pasteboard reference and 'bUseSystemClipboard' will be ignored + + @param bUseSystemClipboard + If 'pasteboard' is NULL 'bUseSystemClipboard' determines whether the + system clipboard will be created (bUseSystemClipboard == true) or if + the DragPasteboard if bUseSystemClipboard == false + */ + AquaClipboard(NSPasteboard* pasteboard = NULL, + bool bUseSystemClipboard = true); + + ~AquaClipboard(); + + //------------------------------------------------ + // XClipboard + //------------------------------------------------ + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > SAL_CALL getContents() + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setContents( const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable >& xTransferable, + const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardOwner >& xClipboardOwner ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual OUString SAL_CALL getName() + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------ + // XClipboardEx + //------------------------------------------------ + + virtual sal_Int8 SAL_CALL getRenderingCapabilities() + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------ + // XClipboardNotifier + //------------------------------------------------ + + virtual void SAL_CALL addClipboardListener( const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardListener >& listener ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL removeClipboardListener( const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardListener >& listener ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------ + // XFlushableClipboard + //------------------------------------------------ + + virtual void SAL_CALL flushClipboard( ) throw( com::sun::star::uno::RuntimeException ); + + //------------------------------------------------ + // XServiceInfo + //------------------------------------------------ + + virtual OUString SAL_CALL getImplementationName() + throw(::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) + throw(::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() + throw(::com::sun::star::uno::RuntimeException); + + /* Get a reference to the used pastboard. + */ + NSPasteboard* getPasteboard() const; + + /* Notify the current clipboard owner that he is no longer the clipboard owner. + */ + void fireLostClipboardOwnershipEvent(::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardOwner> oldOwner, + ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > oldContent); + + void pasteboardChangedOwner(); + + void provideDataForType(NSPasteboard* sender, NSString* type); + + void applicationDidBecomeActive(NSNotification* aNotification); + +private: + + /* Notify all registered XClipboardListener that the clipboard content + has changed. + */ + void fireClipboardChangedEvent(); + +private: + ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XMimeContentTypeFactory > mrXMimeCntFactory; + ::std::list< ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardListener > > mClipboardListeners; + ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > mXClipboardContent; + com::sun::star::uno::Reference< com::sun::star::datatransfer::clipboard::XClipboardOwner > mXClipboardOwner; + DataFlavorMapperPtr_t mpDataFlavorMapper; + bool mIsSystemPasteboard; + NSPasteboard* mPasteboard; + int mPasteboardChangeCount; + EventListener* mEventListener; +}; + +#endif // INCLUDED_VCL_OSX_CLIPBOARD_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/documentfocuslistener.cxx b/vcl/osx/documentfocuslistener.cxx new file mode 100644 index 000000000000..ac65f1e84338 --- /dev/null +++ b/vcl/osx/documentfocuslistener.cxx @@ -0,0 +1,241 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "documentfocuslistener.hxx" + +#include + +#include + +#include + +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; + + +//------------------------------------------------------------------------------ + +DocumentFocusListener::DocumentFocusListener(AquaA11yFocusTracker& rTracker) : + m_aFocusTracker(rTracker) +{ +} + +//------------------------------------------------------------------------------ + +void SAL_CALL +DocumentFocusListener::disposing( const EventObject& aEvent ) + throw (RuntimeException) +{ + // Unref the object here, but do not remove as listener since the object + // might no longer be in a state that safely allows this. + if( aEvent.Source.is() ) + m_aRefList.erase(aEvent.Source); +} + +//------------------------------------------------------------------------------ + +void SAL_CALL +DocumentFocusListener::notifyEvent( const AccessibleEventObject& aEvent ) + throw( RuntimeException ) +{ + switch( aEvent.EventId ) + { + case AccessibleEventId::STATE_CHANGED: + try + { + sal_Int16 nState = AccessibleStateType::INVALID; + aEvent.NewValue >>= nState; + + if( AccessibleStateType::FOCUSED == nState ) + m_aFocusTracker.setFocusedObject( getAccessible(aEvent) ); + } + catch(const IndexOutOfBoundsException &) + { + OSL_TRACE("Focused object has invalid index in parent"); + } + break; + + case AccessibleEventId::CHILD: + { + Reference< XAccessible > xChild; + if( (aEvent.OldValue >>= xChild) && xChild.is() ) + detachRecursive(xChild); + + if( (aEvent.NewValue >>= xChild) && xChild.is() ) + attachRecursive(xChild); + } + break; + + case AccessibleEventId::INVALIDATE_ALL_CHILDREN: + { + Reference< XAccessible > xAccessible( getAccessible(aEvent) ); + detachRecursive(xAccessible); + attachRecursive(xAccessible); + } + + OSL_TRACE( "Invalidate all children called" ); + break; + default: + break; + } +} + +//------------------------------------------------------------------------------ + +Reference< XAccessible > DocumentFocusListener::getAccessible(const EventObject& aEvent ) + throw (IndexOutOfBoundsException, RuntimeException) +{ + Reference< XAccessible > xAccessible(aEvent.Source, UNO_QUERY); + + if( xAccessible.is() ) + return xAccessible; + + Reference< XAccessibleContext > xContext(aEvent.Source, UNO_QUERY); + + if( xContext.is() ) + { + Reference< XAccessible > xParent( xContext->getAccessibleParent() ); + if( xParent.is() ) + { + Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() ); + if( xParentContext.is() ) + { + return xParentContext->getAccessibleChild( xContext->getAccessibleIndexInParent() ); + } + } + } + + return Reference< XAccessible >(); +} + +//------------------------------------------------------------------------------ + +void DocumentFocusListener::attachRecursive(const Reference< XAccessible >& xAccessible) + throw (IndexOutOfBoundsException, RuntimeException) +{ + Reference< XAccessibleContext > xContext = xAccessible->getAccessibleContext(); + + if( xContext.is() ) + attachRecursive(xAccessible, xContext); +} + +//------------------------------------------------------------------------------ + +void DocumentFocusListener::attachRecursive( + const Reference< XAccessible >& xAccessible, + const Reference< XAccessibleContext >& xContext +) throw (IndexOutOfBoundsException, RuntimeException) +{ + if( xContext.is() ) + { + Reference< XAccessibleStateSet > xStateSet = xContext->getAccessibleStateSet(); + + if( xStateSet.is() ) + attachRecursive(xAccessible, xContext, xStateSet); + } +} + +//------------------------------------------------------------------------------ + +void DocumentFocusListener::attachRecursive( + const Reference< XAccessible >& xAccessible, + const Reference< XAccessibleContext >& xContext, + const Reference< XAccessibleStateSet >& xStateSet +) throw (IndexOutOfBoundsException,RuntimeException) +{ + if( xStateSet->contains(AccessibleStateType::FOCUSED ) ) + m_aFocusTracker.setFocusedObject( xAccessible ); + + Reference< XAccessibleEventBroadcaster > xBroadcaster = + Reference< XAccessibleEventBroadcaster >(xContext, UNO_QUERY); + + // If not already done, add the broadcaster to the list and attach as listener. + if( xBroadcaster.is() && m_aRefList.insert(xBroadcaster).second ) + { + xBroadcaster->addAccessibleEventListener(static_cast< XAccessibleEventListener *>(this)); + + if( ! xStateSet->contains(AccessibleStateType::MANAGES_DESCENDANTS ) ) + { + sal_Int32 n, nmax = xContext->getAccessibleChildCount(); + for( n = 0; n < nmax; n++ ) + { + Reference< XAccessible > xChild( xContext->getAccessibleChild( n ) ); + + if( xChild.is() ) + attachRecursive(xChild); + } + } + } +} + +//------------------------------------------------------------------------------ + +void DocumentFocusListener::detachRecursive(const Reference< XAccessible >& xAccessible) + throw (IndexOutOfBoundsException, RuntimeException) +{ + Reference< XAccessibleContext > xContext = xAccessible->getAccessibleContext(); + + if( xContext.is() ) + detachRecursive(xAccessible, xContext); +} + +//------------------------------------------------------------------------------ + +void DocumentFocusListener::detachRecursive( + const Reference< XAccessible >& xAccessible, + const Reference< XAccessibleContext >& xContext +) throw (IndexOutOfBoundsException, RuntimeException) +{ + Reference< XAccessibleStateSet > xStateSet = xContext->getAccessibleStateSet(); + + if( xStateSet.is() ) + detachRecursive(xAccessible, xContext, xStateSet); +} + +//------------------------------------------------------------------------------ + +void DocumentFocusListener::detachRecursive( + const Reference< XAccessible >&, + const Reference< XAccessibleContext >& xContext, + const Reference< XAccessibleStateSet >& xStateSet +) throw (IndexOutOfBoundsException, RuntimeException) +{ + Reference< XAccessibleEventBroadcaster > xBroadcaster = + Reference< XAccessibleEventBroadcaster >(xContext, UNO_QUERY); + + if( xBroadcaster.is() && 0 < m_aRefList.erase(xBroadcaster) ) + { + xBroadcaster->removeAccessibleEventListener(static_cast< XAccessibleEventListener *>(this)); + + if( ! xStateSet->contains(AccessibleStateType::MANAGES_DESCENDANTS ) ) + { + sal_Int32 n, nmax = xContext->getAccessibleChildCount(); + for( n = 0; n < nmax; n++ ) + { + Reference< XAccessible > xChild( xContext->getAccessibleChild( n ) ); + + if( xChild.is() ) + detachRecursive(xChild); + } + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/documentfocuslistener.hxx b/vcl/osx/documentfocuslistener.hxx new file mode 100644 index 000000000000..1a604a677df5 --- /dev/null +++ b/vcl/osx/documentfocuslistener.hxx @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_DOCUMENTFOCUSLISTENER_HXX +#define INCLUDED_VCL_OSX_DOCUMENTFOCUSLISTENER_HXX + +#include + +#include + +#include "osx/a11yfocustracker.hxx" + +#include + +// ------------------------- +// - DocumentFocusListener - +// ------------------------- + +class DocumentFocusListener : + public ::cppu::WeakImplHelper1< ::com::sun::star::accessibility::XAccessibleEventListener > +{ + +public: + + DocumentFocusListener(AquaA11yFocusTracker& rTracker); + + void attachRecursive( + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible + ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + void attachRecursive( + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible, + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& xContext + ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + void attachRecursive( + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible, + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& xContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet >& xStateSet + ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + void detachRecursive( + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible + ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + void detachRecursive( + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible, + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& xContext + ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + void detachRecursive( + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xAccessible, + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& xContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet >& xStateSet + ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + static ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getAccessible(const ::com::sun::star::lang::EventObject& aEvent ) + throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) + throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleEventListener + virtual void SAL_CALL notifyEvent( const ::com::sun::star::accessibility::AccessibleEventObject& aEvent ) + throw( ::com::sun::star::uno::RuntimeException ); + +private: + std::set< ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > > m_aRefList; + + AquaA11yFocusTracker& m_aFocusTracker; +}; + +#endif // INCLUDED_VCL_OSX_DOCUMENTFOCUSLISTENER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/printaccessoryview.mm b/vcl/osx/printaccessoryview.mm new file mode 100644 index 000000000000..517dcc09975f --- /dev/null +++ b/vcl/osx/printaccessoryview.mm @@ -0,0 +1,1381 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "sal/config.h" + +#include "tools/resary.hxx" + +#include "vcl/print.hxx" +#include "vcl/image.hxx" +#include "vcl/virdev.hxx" +#include "vcl/svapp.hxx" +#include "vcl/unohelp.hxx" + +#include "osx/printview.h" +#include "osx/salinst.h" +#include "quartz/utils.h" + +#include "svdata.hxx" +#include "svids.hrc" + +#include "com/sun/star/i18n/XBreakIterator.hpp" +#include "com/sun/star/i18n/WordType.hpp" + +#include + +using namespace vcl; +using namespace com::sun::star; +using namespace com::sun::star::beans; +using namespace com::sun::star::uno; + +/* Note: the accesory view as implemented here is already deprecated in Leopard. Unfortunately + as long as our baseline is Tiger we cannot gain the advantages over multiple accessory views + as well havs having accessory views AND a preview (as long as you are linked vs. 10.4 libraries + the preview insists on not being present. This is unfortunate. +*/ + +class ControllerProperties; + +@interface ControlTarget : NSObject +{ + ControllerProperties* mpController; +} +-(id)initWithControllerMap: (ControllerProperties*)pController; +-(void)triggered:(id)pSender; +-(void)triggeredNumeric:(id)pSender; +-(void)triggeredPreview:(id)pSender; +-(void)dealloc; +@end + + +class ControllerProperties +{ + vcl::PrinterController* mpController; + std::map< int, rtl::OUString > maTagToPropertyName; + std::map< int, sal_Int32 > maTagToValueInt; + std::map< NSView*, NSView* > maViewPairMap; + std::vector< NSObject* > maViews; + int mnNextTag; + sal_Int32 mnLastPageCount; + PrintAccessoryViewState* mpState; + NSPrintOperation* mpOp; + NSView* mpAccessoryView; + NSTabView* mpTabView; + NSBox* mpPreviewBox; + NSImageView* mpPreview; + NSTextField* mpPageEdit; + NSStepper* mpStepper; + NSTextView* mpPagesLabel; + ResStringArray maLocalizedStrings; + + public: + ControllerProperties( vcl::PrinterController* i_pController, + NSPrintOperation* i_pOp, + NSView* i_pAccessoryView, + NSTabView* i_pTabView, + PrintAccessoryViewState* i_pState ) + : mpController( i_pController ), + mnNextTag( 0 ), + mnLastPageCount( i_pController->getFilteredPageCount() ), + mpState( i_pState ), + mpOp( i_pOp ), + mpAccessoryView( i_pAccessoryView ), + mpTabView( i_pTabView ), + mpPreviewBox( nil ), + mpPreview( nil ), + mpPageEdit( nil ), + mpStepper( nil ), + mpPagesLabel( nil ), + maLocalizedStrings( VclResId( SV_PRINT_NATIVE_STRINGS ) ) + { + mpState->bNeedRestart = false; + DBG_ASSERT( maLocalizedStrings.Count() >= 5, "resources not found !" ); + } + + rtl::OUString getMoreString() + { + return maLocalizedStrings.Count() >= 4 + ? OUString( maLocalizedStrings.GetString( 3 ) ) + : OUString( "More" ); + } + + rtl::OUString getPrintSelectionString() + { + return maLocalizedStrings.Count() >= 5 + ? OUString( maLocalizedStrings.GetString( 4 ) ) + : OUString( "Print selection only" ); + } + + void updatePrintJob() + { + // TODO: refresh page count etc from mpController + + // page range may have changed depending on options + sal_Int32 nPages = mpController->getFilteredPageCount(); + #if OSL_DEBUG_LEVEL > 1 + if( nPages != mnLastPageCount ) + fprintf( stderr, "trouble: number of pages changed from %ld to %ld !\n", mnLastPageCount, nPages ); + #endif + mpState->bNeedRestart = (nPages != mnLastPageCount); + NSTabViewItem* pItem = [mpTabView selectedTabViewItem]; + if( pItem ) + mpState->nLastPage = [mpTabView indexOfTabViewItem: pItem]; + else + mpState->nLastPage = 0; + mnLastPageCount = nPages; + if( mpState->bNeedRestart ) + { + // Warning: bad hack ahead + // Apple does not give us a chance of changing the page count, + // and they don't let us cancel the dialog either + // hack: send a cancel message to the window displaying our views. + // this is ugly. + NSWindow* pNSWindow = [NSApp modalWindow]; + if( pNSWindow ) + [pNSWindow cancelOperation: nil]; + [[mpOp printInfo] setJobDisposition: NSPrintCancelJob]; + } + else + { + sal_Int32 nPage = [mpStepper intValue]; + updatePreviewImage( nPage-1 ); + } + } + + int addNameTag( const rtl::OUString& i_rPropertyName ) + { + int nNewTag = mnNextTag++; + maTagToPropertyName[ nNewTag ] = i_rPropertyName; + return nNewTag; + } + + int addNameAndValueTag( const rtl::OUString& i_rPropertyName, sal_Int32 i_nValue ) + { + int nNewTag = mnNextTag++; + maTagToPropertyName[ nNewTag ] = i_rPropertyName; + maTagToValueInt[ nNewTag ] = i_nValue; + return nNewTag; + } + + void addObservedControl( NSObject* i_pView ) + { + maViews.push_back( i_pView ); + } + + void addViewPair( NSView* i_pLeft, NSView* i_pRight ) + { + maViewPairMap[ i_pLeft ] = i_pRight; + maViewPairMap[ i_pRight ] = i_pLeft; + } + + NSView* getPair( NSView* i_pLeft ) const + { + NSView* pRight = nil; + std::map< NSView*, NSView* >::const_iterator it = maViewPairMap.find( i_pLeft ); + if( it != maViewPairMap.end() ) + pRight = it->second; + return pRight; + } + + void changePropertyWithIntValue( int i_nTag ) + { + std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); + std::map< int, sal_Int32 >::const_iterator value_it = maTagToValueInt.find( i_nTag ); + if( name_it != maTagToPropertyName.end() && value_it != maTagToValueInt.end() ) + { + PropertyValue* pVal = mpController->getValue( name_it->second ); + if( pVal ) + { + pVal->Value <<= value_it->second; + updatePrintJob(); + } + } + } + + void changePropertyWithIntValue( int i_nTag, sal_Int64 i_nValue ) + { + std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); + if( name_it != maTagToPropertyName.end() ) + { + PropertyValue* pVal = mpController->getValue( name_it->second ); + if( pVal ) + { + pVal->Value <<= i_nValue; + updatePrintJob(); + } + } + } + + void changePropertyWithBoolValue( int i_nTag, sal_Bool i_bValue ) + { + std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); + if( name_it != maTagToPropertyName.end() ) + { + PropertyValue* pVal = mpController->getValue( name_it->second ); + if( pVal ) + { + // ugly + if( name_it->second.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrintContent")) ) + pVal->Value <<= i_bValue ? sal_Int32(2) : sal_Int32(0); + else + pVal->Value <<= i_bValue; + updatePrintJob(); + } + } + } + + void changePropertyWithStringValue( int i_nTag, const rtl::OUString& i_rValue ) + { + std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); + if( name_it != maTagToPropertyName.end() ) + { + PropertyValue* pVal = mpController->getValue( name_it->second ); + if( pVal ) + { + pVal->Value <<= i_rValue; + updatePrintJob(); + } + } + } + + void updateEnableState() + { + for( std::vector< NSObject* >::iterator it = maViews.begin(); it != maViews.end(); ++it ) + { + NSObject* pObj = *it; + NSControl* pCtrl = nil; + NSCell* pCell = nil; + if( [pObj isKindOfClass: [NSControl class]] ) + pCtrl = (NSControl*)pObj; + else if( [pObj isKindOfClass: [NSCell class]] ) + pCell = (NSCell*)pObj; + + int nTag = pCtrl ? [pCtrl tag] : + pCell ? [pCell tag] : + -1; + + std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( nTag ); + if( name_it != maTagToPropertyName.end() && ! name_it->second.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrintContent")) ) + { + BOOL bEnabled = mpController->isUIOptionEnabled( name_it->second ) ? YES : NO; + if( pCtrl ) + { + [pCtrl setEnabled: bEnabled]; + NSView* pOther = getPair( pCtrl ); + if( pOther && [pOther isKindOfClass: [NSControl class]] ) + [(NSControl*)pOther setEnabled: bEnabled]; + } + else if( pCell ) + [pCell setEnabled: bEnabled]; + + } + } + } + + void updatePreviewImage( sal_Int32 i_nPage ) + { + sal_Int32 nPages = mpController->getFilteredPageCount(); + NSRect aViewFrame = [mpPreview frame]; + Size aPixelSize( static_cast(aViewFrame.size.width), + static_cast(aViewFrame.size.height) ); + if( i_nPage >= 0 && nPages > i_nPage ) + { + GDIMetaFile aMtf; + PrinterController::PageSize aPageSize( mpController->getFilteredPageFile( i_nPage, aMtf, false ) ); + VirtualDevice aDev; + if( mpController->getPrinter()->GetPrinterOptions().IsConvertToGreyscales() ) + aDev.SetDrawMode( aDev.GetDrawMode() | ( DRAWMODE_GRAYLINE | DRAWMODE_GRAYFILL | DRAWMODE_GRAYTEXT | + DRAWMODE_GRAYBITMAP | DRAWMODE_GRAYGRADIENT ) ); + // see salprn.cxx, currently we pretend to be a 720dpi device on printers + aDev.SetReferenceDevice( 720, 720 ); + aDev.EnableOutput( TRUE ); + Size aLogicSize( aDev.PixelToLogic( aPixelSize, MapMode( MAP_100TH_MM ) ) ); + double fScaleX = double(aLogicSize.Width())/double(aPageSize.aSize.Width()); + double fScaleY = double(aLogicSize.Height())/double(aPageSize.aSize.Height()); + double fScale = (fScaleX < fScaleY) ? fScaleX : fScaleY; + // #i104784# if we render the page too small then rounding issues result in + // layout artifacts looking really bad. So scale the page unto a device that is not + // full page size but not too small either. This also results in much better visual + // quality of the preview, e.g. when its height approaches the number of text lines + if( fScale < 0.1 ) + fScale = 0.1; + aMtf.WindStart(); + aMtf.Scale( fScale, fScale ); + aMtf.WindStart(); + aLogicSize.Width() = long(double(aPageSize.aSize.Width()) * fScale); + aLogicSize.Height() = long(double(aPageSize.aSize.Height()) * fScale); + aPixelSize = aDev.LogicToPixel( aLogicSize, MapMode( MAP_100TH_MM ) ); + aDev.SetOutputSizePixel( aPixelSize ); + aMtf.WindStart(); + aDev.SetMapMode( MapMode( MAP_100TH_MM ) ); + aMtf.Play( &aDev, Point( 0, 0 ), aLogicSize ); + aDev.EnableMapMode( FALSE ); + Image aImage( aDev.GetBitmap( Point( 0, 0 ), aPixelSize ) ); + NSImage* pImage = CreateNSImage( aImage ); + [mpPreview setImage: [pImage autorelease]]; + } + else + [mpPreview setImage: nil]; + } + + void setupPreview( ControlTarget* i_pCtrlTarget ) + { + if( maLocalizedStrings.Count() < 3 ) + return; + + // get the preview control + NSRect aPreviewFrame = [mpAccessoryView frame]; + aPreviewFrame.origin.x = 0; + aPreviewFrame.origin.y = 5; + aPreviewFrame.size.width = 190; + aPreviewFrame.size.height -= 7; + + // create a box to put the preview controls in + mpPreviewBox = [[NSBox alloc] initWithFrame: aPreviewFrame]; + [mpPreviewBox setTitle: [CreateNSString( maLocalizedStrings.GetString( 0 ) ) autorelease]]; + [mpAccessoryView addSubview: [mpPreviewBox autorelease]]; + + // now create the image view of the preview + NSSize aMargins = [mpPreviewBox contentViewMargins]; + aPreviewFrame.origin.x = 0; + aPreviewFrame.origin.y = 34; + aPreviewFrame.size.width -= 2*(aMargins.width+1); + aPreviewFrame.size.height -= 61; + mpPreview = [[NSImageView alloc] initWithFrame: aPreviewFrame]; + [mpPreview setImageScaling: NSScaleProportionally]; + [mpPreview setImageAlignment: NSImageAlignCenter]; + [mpPreview setImageFrameStyle: NSImageFrameNone]; + [mpPreviewBox addSubview: [mpPreview autorelease]]; + + // add a label + sal_Int32 nPages = mpController->getFilteredPageCount(); + rtl::OUStringBuffer aBuf( 16 ); + aBuf.appendAscii( "/ " ); + aBuf.append( rtl::OUString::number( nPages ) ); + + NSString* pText = CreateNSString( aBuf.makeStringAndClear() ); + NSRect aTextRect = { { 100, 5 }, { 100, 22 } }; + mpPagesLabel = [[NSTextView alloc] initWithFrame: aTextRect]; + [mpPagesLabel setFont: [NSFont controlContentFontOfSize: 0]]; + [mpPagesLabel setEditable: NO]; + [mpPagesLabel setSelectable: NO]; + [mpPagesLabel setDrawsBackground: NO]; + [mpPagesLabel setString: [pText autorelease]]; + [mpPagesLabel setToolTip: [CreateNSString( maLocalizedStrings.GetString( 2 ) ) autorelease]]; + [mpPreviewBox addSubview: [mpPagesLabel autorelease]]; + + NSRect aFieldRect = { { 45, 5 }, { 35, 25 } }; + mpPageEdit = [[NSTextField alloc] initWithFrame: aFieldRect]; + [mpPageEdit setEditable: YES]; + [mpPageEdit setSelectable: YES]; + [mpPageEdit setDrawsBackground: YES]; + [mpPageEdit setToolTip: [CreateNSString( maLocalizedStrings.GetString( 1 ) ) autorelease]]; + [mpPreviewBox addSubview: [mpPageEdit autorelease]]; + + // add a stepper control + NSRect aStepFrame = { { 85, 5 }, { 15, 25 } }; + mpStepper = [[NSStepper alloc] initWithFrame: aStepFrame]; + [mpStepper setIncrement: 1]; + [mpStepper setValueWraps: NO]; + [mpPreviewBox addSubview: [mpStepper autorelease]]; + + // constrain the text field to decimal numbers + NSNumberFormatter* pFormatter = [[NSNumberFormatter alloc] init]; + [pFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4]; + [pFormatter setMinimum: [[NSNumber numberWithInt: 1] autorelease]]; + [pFormatter setMaximum: [[NSNumber numberWithInt: nPages] autorelease]]; + [pFormatter setNumberStyle: NSNumberFormatterDecimalStyle]; + [pFormatter setAllowsFloats: NO]; + [pFormatter setMaximumFractionDigits: 0]; + [mpPageEdit setFormatter: pFormatter]; + [mpStepper setMinValue: 1]; + [mpStepper setMaxValue: nPages]; + + [mpPageEdit setIntValue: 1]; + [mpStepper setIntValue: 1]; + + // connect target and action + [mpStepper setTarget: i_pCtrlTarget]; + [mpStepper setAction: @selector(triggeredPreview:)]; + [mpPageEdit setTarget: i_pCtrlTarget]; + [mpPageEdit setAction: @selector(triggeredPreview:)]; + + // set first preview image + updatePreviewImage( 0 ); + } + + void changePreview( NSObject* i_pSender ) + { + if( [i_pSender isMemberOfClass: [NSTextField class]] ) + { + NSTextField* pField = (NSTextField*)i_pSender; + if( pField == mpPageEdit ) // sanity check + { + sal_Int32 nPage = [pField intValue]; + [mpStepper setIntValue: nPage]; + updatePreviewImage( nPage-1 ); + } + } + else if( [i_pSender isMemberOfClass: [NSStepper class]] ) + { + NSStepper* pStepper = (NSStepper*)i_pSender; + if( pStepper == mpStepper ) // sanity check + { + sal_Int32 nPage = [pStepper intValue]; + [mpPageEdit setIntValue: nPage]; + updatePreviewImage( nPage-1 ); + } + } + } +}; + +static void filterAccelerator( rtl::OUString& io_rText ) +{ + rtl::OUStringBuffer aBuf( io_rText.getLength() ); + for( sal_Int32 nIndex = 0; nIndex != -1; ) + aBuf.append( io_rText.getToken( 0, '~', nIndex ) ); + io_rText = aBuf.makeStringAndClear(); +} + +@implementation ControlTarget +-(id)initWithControllerMap: (ControllerProperties*)pController +{ + if( (self = [super init]) ) + { + mpController = pController; + } + return self; +} +-(void)triggered:(id)pSender +{ + if( [pSender isMemberOfClass: [NSPopUpButton class]] ) + { + NSPopUpButton* pBtn = (NSPopUpButton*)pSender; + NSMenuItem* pSelected = [pBtn selectedItem]; + if( pSelected ) + { + int nTag = [pSelected tag]; + mpController->changePropertyWithIntValue( nTag ); + } + } + else if( [pSender isMemberOfClass: [NSButton class]] ) + { + NSButton* pBtn = (NSButton*)pSender; + int nTag = [pBtn tag]; + mpController->changePropertyWithBoolValue( nTag, [pBtn state] == NSOnState ); + } + else if( [pSender isMemberOfClass: [NSMatrix class]] ) + { + NSObject* pObj = [(NSMatrix*)pSender selectedCell]; + if( [pObj isMemberOfClass: [NSButtonCell class]] ) + { + NSButtonCell* pCell = (NSButtonCell*)pObj; + int nTag = [pCell tag]; + mpController->changePropertyWithIntValue( nTag ); + } + } + else if( [pSender isMemberOfClass: [NSTextField class]] ) + { + NSTextField* pField = (NSTextField*)pSender; + int nTag = [pField tag]; + rtl::OUString aValue = GetOUString( [pSender stringValue] ); + mpController->changePropertyWithStringValue( nTag, aValue ); + } + else + { + SAL_INFO( "vcl.osx.print", "Unsupported class" << ([pSender class] ? [NSStringFromClass([pSender class]) UTF8String] : "nil")); + } + mpController->updateEnableState(); +} +-(void)triggeredNumeric:(id)pSender +{ + if( [pSender isMemberOfClass: [NSTextField class]] ) + { + NSTextField* pField = (NSTextField*)pSender; + int nTag = [pField tag]; + sal_Int64 nValue = [pField intValue]; + + NSView* pOther = mpController->getPair( pField ); + if( pOther ) + [(NSControl*)pOther setIntValue: nValue]; + + mpController->changePropertyWithIntValue( nTag, nValue ); + } + else if( [pSender isMemberOfClass: [NSStepper class]] ) + { + NSStepper* pStep = (NSStepper*)pSender; + int nTag = [pStep tag]; + sal_Int64 nValue = [pStep intValue]; + + NSView* pOther = mpController->getPair( pStep ); + if( pOther ) + [(NSControl*)pOther setIntValue: nValue]; + + mpController->changePropertyWithIntValue( nTag, nValue ); + } + else + { + SAL_INFO( "vcl.osx.print", "Unsupported class" << ([pSender class] ? [NSStringFromClass([pSender class]) UTF8String] : "nil")); + } + mpController->updateEnableState(); +} +-(void)triggeredPreview:(id)pSender +{ + mpController->changePreview( pSender ); +} +-(void)dealloc +{ + delete mpController; + [super dealloc]; +} +@end + +struct ColumnItem +{ + NSControl* pControl; + long nOffset; + NSControl* pSubControl; + + ColumnItem( NSControl* i_pControl = nil, long i_nOffset = 0, NSControl* i_pSub = nil ) + : pControl( i_pControl ) + , nOffset( i_nOffset ) + , pSubControl( i_pSub ) + {} + + long getWidth() const + { + long nWidth = 0; + if( pControl ) + { + NSRect aCtrlRect = [pControl frame]; + nWidth = aCtrlRect.size.width; + nWidth += nOffset; + if( pSubControl ) + { + NSRect aSubRect = [pSubControl frame]; + nWidth += aSubRect.size.width; + nWidth += aSubRect.origin.x - (aCtrlRect.origin.x + aCtrlRect.size.width); + } + } + return nWidth; + } +}; + +static void adjustViewAndChildren( NSView* pNSView, NSSize& rMaxSize, + std::vector< ColumnItem >& rLeftColumn, + std::vector< ColumnItem >& rRightColumn + ) +{ + // balance columns + + // first get overall column widths + long nLeftWidth = 0; + long nRightWidth = 0; + for( size_t i = 0; i < rLeftColumn.size(); i++ ) + { + long nW = rLeftColumn[i].getWidth(); + if( nW > nLeftWidth ) + nLeftWidth = nW; + } + for( size_t i = 0; i < rRightColumn.size(); i++ ) + { + long nW = rRightColumn[i].getWidth(); + if( nW > nRightWidth ) + nRightWidth = nW; + } + + // right align left column + for( size_t i = 0; i < rLeftColumn.size(); i++ ) + { + if( rLeftColumn[i].pControl ) + { + NSRect aCtrlRect = [rLeftColumn[i].pControl frame]; + long nX = nLeftWidth - aCtrlRect.size.width; + if( rLeftColumn[i].pSubControl ) + { + NSRect aSubRect = [rLeftColumn[i].pSubControl frame]; + nX -= aSubRect.size.width + (aSubRect.origin.x - (aCtrlRect.origin.x + aCtrlRect.size.width)); + aSubRect.origin.x = nLeftWidth - aSubRect.size.width; + [rLeftColumn[i].pSubControl setFrame: aSubRect]; + } + aCtrlRect.origin.x = nX; + [rLeftColumn[i].pControl setFrame: aCtrlRect]; + } + } + + // left align right column + for( size_t i = 0; i < rRightColumn.size(); i++ ) + { + if( rRightColumn[i].pControl ) + { + NSRect aCtrlRect = [rRightColumn[i].pControl frame]; + long nX = nLeftWidth + 3; + if( rRightColumn[i].pSubControl ) + { + NSRect aSubRect = [rRightColumn[i].pSubControl frame]; + aSubRect.origin.x = nX + aSubRect.origin.x - aCtrlRect.origin.x; + [rRightColumn[i].pSubControl setFrame: aSubRect]; + } + aCtrlRect.origin.x = nX; + [rRightColumn[i].pControl setFrame: aCtrlRect]; + } + } + + NSArray* pSubViews = [pNSView subviews]; + unsigned int nViews = [pSubViews count]; + NSRect aUnion = { { 0, 0 }, { 0, 0 } }; + + // get the combined frame of all subviews + for( unsigned int n = 0; n < nViews; n++ ) + { + aUnion = NSUnionRect( aUnion, [[pSubViews objectAtIndex: n] frame] ); + } + + // move everything so it will fit + for( unsigned int n = 0; n < nViews; n++ ) + { + NSView* pCurSubView = [pSubViews objectAtIndex: n]; + NSRect aFrame = [pCurSubView frame]; + aFrame.origin.x -= aUnion.origin.x - 5; + aFrame.origin.y -= aUnion.origin.y - 5; + [pCurSubView setFrame: aFrame]; + } + + // resize the view itself + aUnion.size.height += 10; + aUnion.size.width += 20; + [pNSView setFrameSize: aUnion.size]; + + if( aUnion.size.width > rMaxSize.width ) + rMaxSize.width = aUnion.size.width; + if( aUnion.size.height > rMaxSize.height ) + rMaxSize.height = aUnion.size.height; +} + +static void adjustTabViews( NSTabView* pTabView, NSSize aTabSize ) +{ + // loop over all contained tab pages + NSArray* pTabbedViews = [pTabView tabViewItems]; + int nViews = [pTabbedViews count]; + for( int i = 0; i < nViews; i++ ) + { + NSTabViewItem* pItem = (NSTabViewItem*)[pTabbedViews objectAtIndex: i]; + NSView* pNSView = [pItem view]; + if( pNSView ) + { + NSRect aRect = [pNSView frame]; + double nDiff = aTabSize.height - aRect.size.height; + aRect.size = aTabSize; + [pNSView setFrame: aRect]; + + NSArray* pSubViews = [pNSView subviews]; + unsigned int nSubViews = [pSubViews count]; + + // move everything up + for( unsigned int n = 0; n < nSubViews; n++ ) + { + NSView* pCurSubView = [pSubViews objectAtIndex: n]; + NSRect aFrame = [pCurSubView frame]; + aFrame.origin.y += nDiff; + // give separators the correct width + // separators are currently the only NSBoxes we use + if( [pCurSubView isMemberOfClass: [NSBox class]] ) + { + aFrame.size.width = aTabSize.width - aFrame.origin.x - 10; + } + [pCurSubView setFrame: aFrame]; + } + } + } +} + +static NSControl* createLabel( const rtl::OUString& i_rText ) +{ + NSString* pText = CreateNSString( i_rText ); + NSRect aTextRect = { { 0, 0 }, {20, 15} }; + NSTextField* pTextView = [[NSTextField alloc] initWithFrame: aTextRect]; + [pTextView setFont: [NSFont controlContentFontOfSize: 0]]; + [pTextView setEditable: NO]; + [pTextView setSelectable: NO]; + [pTextView setDrawsBackground: NO]; + [pTextView setBordered: NO]; + [pTextView setStringValue: pText]; + [pTextView sizeToFit]; + [pText release]; + return pTextView; +} + +static sal_Int32 findBreak( const rtl::OUString& i_rText, sal_Int32 i_nPos ) +{ + sal_Int32 nRet = i_rText.getLength(); + Reference< i18n::XBreakIterator > xBI( vcl::unohelper::CreateBreakIterator() ); + if( xBI.is() ) + { + i18n::Boundary aBoundary = xBI->getWordBoundary( i_rText, i_nPos, + Application::GetSettings().GetLanguageTag().getLocale(), + i18n::WordType::ANYWORD_IGNOREWHITESPACES, + sal_True ); + nRet = aBoundary.endPos; + } + return nRet; +} + +static void linebreakCell( NSCell* pBtn, const rtl::OUString& i_rText ) +{ + NSString* pText = CreateNSString( i_rText ); + [pBtn setTitle: pText]; + [pText release]; + NSSize aSize = [pBtn cellSize]; + if( aSize.width > 280 ) + { + // need two lines + sal_Int32 nLen = i_rText.getLength(); + sal_Int32 nIndex = nLen / 2; + nIndex = findBreak( i_rText, nIndex ); + if( nIndex < nLen ) + { + rtl::OUStringBuffer aBuf( i_rText ); + aBuf[nIndex] = '\n'; + pText = CreateNSString( aBuf.makeStringAndClear() ); + [pBtn setTitle: pText]; + [pText release]; + } + } +} + +static void addSubgroup( NSView* pCurParent, long& rCurY, const rtl::OUString& rText ) +{ + NSControl* pTextView = createLabel( rText ); + [pCurParent addSubview: [pTextView autorelease]]; + NSRect aTextRect = [pTextView frame]; + // move to nCurY + aTextRect.origin.y = rCurY - aTextRect.size.height; + [pTextView setFrame: aTextRect]; + + NSRect aSepRect = { { aTextRect.size.width + 1, aTextRect.origin.y }, { 100, 6 } }; + NSBox* pBox = [[NSBox alloc] initWithFrame: aSepRect]; + [pBox setBoxType: NSBoxSeparator]; + [pCurParent addSubview: [pBox autorelease]]; + + // update nCurY + rCurY = aTextRect.origin.y - 5; +} + +static void addBool( NSView* pCurParent, long& rCurX, long& rCurY, long nAttachOffset, + const rtl::OUString& rText, sal_Bool bEnabled, + const rtl::OUString& rProperty, sal_Bool bValue, + std::vector& rRightColumn, + ControllerProperties* pControllerProperties, + ControlTarget* pCtrlTarget + ) +{ + NSRect aCheckRect = { { static_cast(rCurX + nAttachOffset), 0 }, { 0, 15 } }; + NSButton* pBtn = [[NSButton alloc] initWithFrame: aCheckRect]; + [pBtn setButtonType: NSSwitchButton]; + [pBtn setState: bValue ? NSOnState : NSOffState]; + if( ! bEnabled ) + [pBtn setEnabled: NO]; + linebreakCell( [pBtn cell], rText ); + [pBtn sizeToFit]; + + rRightColumn.push_back( ColumnItem( pBtn ) ); + + // connect target + [pBtn setTarget: pCtrlTarget]; + [pBtn setAction: @selector(triggered:)]; + int nTag = pControllerProperties->addNameTag( rProperty ); + pControllerProperties->addObservedControl( pBtn ); + [pBtn setTag: nTag]; + + aCheckRect = [pBtn frame]; + // #i115837# add a murphy factor; it can apparently occasionally happen + // that sizeToFit does not a perfect job and that the button linebreaks again + // if - and only if - there is already a '\n' contained in the text and the width + // is minimally of + aCheckRect.size.width += 1; + + // move to rCurY + aCheckRect.origin.y = rCurY - aCheckRect.size.height; + [pBtn setFrame: aCheckRect]; + + [pCurParent addSubview: [pBtn autorelease]]; + + // update rCurY + rCurY = aCheckRect.origin.y - 5; +} + +static void addRadio( NSView* pCurParent, long& rCurX, long& rCurY, long nAttachOffset, + const rtl::OUString& rText, + const rtl::OUString& rProperty, Sequence< rtl::OUString > rChoices, sal_Int32 nSelectValue, + std::vector& rLeftColumn, + std::vector& rRightColumn, + ControllerProperties* pControllerProperties, + ControlTarget* pCtrlTarget + ) +{ + sal_Int32 nOff = 0; + if( rText.getLength() ) + { + // add a label + NSControl* pTextView = createLabel( rText ); + NSRect aTextRect = [pTextView frame]; + aTextRect.origin.x = rCurX + nAttachOffset; + [pCurParent addSubview: [pTextView autorelease]]; + + rLeftColumn.push_back( ColumnItem( pTextView ) ); + + // move to nCurY + aTextRect.origin.y = rCurY - aTextRect.size.height; + [pTextView setFrame: aTextRect]; + + // update nCurY + rCurY = aTextRect.origin.y - 5; + + // indent the radio group relative to the text + // nOff = 20; + } + + // setup radio matrix + NSButtonCell* pProto = [[NSButtonCell alloc] init]; + + NSRect aRadioRect = { { static_cast(rCurX + nOff), 0 }, { static_cast(280 - rCurX), static_cast(5*rChoices.getLength()) } }; + [pProto setTitle: @"RadioButtonGroup"]; + [pProto setButtonType: NSRadioButton]; + NSMatrix* pMatrix = [[NSMatrix alloc] initWithFrame: aRadioRect + mode: NSRadioModeMatrix + prototype: (NSCell*)pProto + numberOfRows: rChoices.getLength() + numberOfColumns: 1]; + // set individual titles + NSArray* pCells = [pMatrix cells]; + for( sal_Int32 m = 0; m < rChoices.getLength(); m++ ) + { + NSCell* pCell = [pCells objectAtIndex: m]; + filterAccelerator( rChoices[m] ); + linebreakCell( pCell, rChoices[m] ); + // connect target and action + [pCell setTarget: pCtrlTarget]; + [pCell setAction: @selector(triggered:)]; + int nTag = pControllerProperties->addNameAndValueTag( rProperty, m ); + pControllerProperties->addObservedControl( pCell ); + [pCell setTag: nTag]; + // set current selection + if( nSelectValue == m ) + [pMatrix selectCellAtRow: m column: 0]; + } + [pMatrix sizeToFit]; + aRadioRect = [pMatrix frame]; + + // move it down, so it comes to the correct position + aRadioRect.origin.y = rCurY - aRadioRect.size.height; + [pMatrix setFrame: aRadioRect]; + [pCurParent addSubview: [pMatrix autorelease]]; + + rRightColumn.push_back( ColumnItem( pMatrix ) ); + + // update nCurY + rCurY = aRadioRect.origin.y - 5; + + [pProto release]; +} + +static void addList( NSView* pCurParent, long& rCurX, long& rCurY, long /*nAttachOffset*/, + const rtl::OUString& rText, + const rtl::OUString& rProperty, const Sequence< rtl::OUString > rChoices, sal_Int32 nSelectValue, + std::vector& rLeftColumn, + std::vector& rRightColumn, + ControllerProperties* pControllerProperties, + ControlTarget* pCtrlTarget + ) +{ + // don't indent attached lists, looks bad in the existing cases + NSControl* pTextView = createLabel( rText ); + [pCurParent addSubview: [pTextView autorelease]]; + rLeftColumn.push_back( ColumnItem( pTextView ) ); + NSRect aTextRect = [pTextView frame]; + aTextRect.origin.x = rCurX /* + nAttachOffset*/; + + // don't indent attached lists, looks bad in the existing cases + NSRect aBtnRect = { { rCurX /*+ nAttachOffset*/ + aTextRect.size.width, 0 }, { 0, 15 } }; + NSPopUpButton* pBtn = [[NSPopUpButton alloc] initWithFrame: aBtnRect pullsDown: NO]; + + // iterate options + for( sal_Int32 m = 0; m < rChoices.getLength(); m++ ) + { + NSString* pItemText = CreateNSString( rChoices[m] ); + [pBtn addItemWithTitle: pItemText]; + NSMenuItem* pItem = [pBtn itemWithTitle: pItemText]; + int nTag = pControllerProperties->addNameAndValueTag( rProperty, m ); + [pItem setTag: nTag]; + [pItemText release]; + } + + [pBtn selectItemAtIndex: nSelectValue]; + + // add the button to observed controls for enabled state changes + // also add a tag just for this purpose + pControllerProperties->addObservedControl( pBtn ); + [pBtn setTag: pControllerProperties->addNameTag( rProperty )]; + + [pBtn sizeToFit]; + [pCurParent addSubview: [pBtn autorelease]]; + + rRightColumn.push_back( ColumnItem( pBtn ) ); + + // connect target and action + [pBtn setTarget: pCtrlTarget]; + [pBtn setAction: @selector(triggered:)]; + + // move to nCurY + aBtnRect = [pBtn frame]; + aBtnRect.origin.y = rCurY - aBtnRect.size.height; + [pBtn setFrame: aBtnRect]; + + // align label + aTextRect.origin.y = aBtnRect.origin.y + (aBtnRect.size.height - aTextRect.size.height)/2; + [pTextView setFrame: aTextRect]; + + // update rCurY + rCurY = aBtnRect.origin.y - 5; +} + +static void addEdit( NSView* pCurParent, long& rCurX, long& rCurY, long nAttachOffset, + const rtl::OUString rCtrlType, + const rtl::OUString& rText, + const rtl::OUString& rProperty, const PropertyValue* pValue, + sal_Int64 nMinValue, sal_Int64 nMaxValue, + std::vector& rLeftColumn, + std::vector& rRightColumn, + ControllerProperties* pControllerProperties, + ControlTarget* pCtrlTarget + ) +{ + sal_Int32 nOff = 0; + if( rText.getLength() ) + { + // add a label + NSControl* pTextView = createLabel( rText ); + [pCurParent addSubview: [pTextView autorelease]]; + + rLeftColumn.push_back( ColumnItem( pTextView ) ); + + // move to nCurY + NSRect aTextRect = [pTextView frame]; + aTextRect.origin.x = rCurX + nAttachOffset; + aTextRect.origin.y = rCurY - aTextRect.size.height; + [pTextView setFrame: aTextRect]; + + // update nCurY + rCurY = aTextRect.origin.y - 5; + + // and set the offset for the real edit field + nOff = aTextRect.size.width + 5; + } + + NSRect aFieldRect = { { static_cast(rCurX + nOff + nAttachOffset), 0 }, { 100, 25 } }; + NSTextField* pFieldView = [[NSTextField alloc] initWithFrame: aFieldRect]; + [pFieldView setEditable: YES]; + [pFieldView setSelectable: YES]; + [pFieldView setDrawsBackground: YES]; + [pFieldView sizeToFit]; // FIXME: this does nothing + [pCurParent addSubview: [pFieldView autorelease]]; + + rRightColumn.push_back( ColumnItem( pFieldView ) ); + + // add the field to observed controls for enabled state changes + // also add a tag just for this purpose + pControllerProperties->addObservedControl( pFieldView ); + int nTag = pControllerProperties->addNameTag( rProperty ); + [pFieldView setTag: nTag]; + // pControllerProperties->addNamedView( pFieldView, aPropertyName ); + + // move to nCurY + aFieldRect.origin.y = rCurY - aFieldRect.size.height; + [pFieldView setFrame: aFieldRect]; + + if( rCtrlType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Range" ) ) ) + { + // add a stepper control + NSRect aStepFrame = { { aFieldRect.origin.x + aFieldRect.size.width + 5, + aFieldRect.origin.y }, + { 15, aFieldRect.size.height } }; + NSStepper* pStep = [[NSStepper alloc] initWithFrame: aStepFrame]; + [pStep setIncrement: 1]; + [pStep setValueWraps: NO]; + [pStep setTag: nTag]; + [pCurParent addSubview: [pStep autorelease]]; + + rRightColumn.back().pSubControl = pStep; + + pControllerProperties->addObservedControl( pStep ); + [pStep setTarget: pCtrlTarget]; + [pStep setAction: @selector(triggered:)]; + + // constrain the text field to decimal numbers + NSNumberFormatter* pFormatter = [[NSNumberFormatter alloc] init]; + [pFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4]; + [pFormatter setNumberStyle: NSNumberFormatterDecimalStyle]; + [pFormatter setAllowsFloats: NO]; + [pFormatter setMaximumFractionDigits: 0]; + if( nMinValue != nMaxValue ) + { + [pFormatter setMinimum: [[NSNumber numberWithInt: nMinValue] autorelease]]; + [pStep setMinValue: nMinValue]; + [pFormatter setMaximum: [[NSNumber numberWithInt: nMaxValue] autorelease]]; + [pStep setMaxValue: nMaxValue]; + } + [pFieldView setFormatter: pFormatter]; + + sal_Int64 nSelectVal = 0; + if( pValue && pValue->Value.hasValue() ) + pValue->Value >>= nSelectVal; + + [pFieldView setIntValue: nSelectVal]; + [pStep setIntValue: nSelectVal]; + + pControllerProperties->addViewPair( pFieldView, pStep ); + // connect target and action + [pFieldView setTarget: pCtrlTarget]; + [pFieldView setAction: @selector(triggeredNumeric:)]; + [pStep setTarget: pCtrlTarget]; + [pStep setAction: @selector(triggeredNumeric:)]; + } + else + { + // connect target and action + [pFieldView setTarget: pCtrlTarget]; + [pFieldView setAction: @selector(triggered:)]; + + if( pValue && pValue->Value.hasValue() ) + { + rtl::OUString aValue; + pValue->Value >>= aValue; + if( aValue.getLength() ) + { + NSString* pText = CreateNSString( aValue ); + [pFieldView setStringValue: pText]; + [pText release]; + } + } + } + + // update nCurY + rCurY = aFieldRect.origin.y - 5; +} + +// In 10.5 and later: +// 'setAccessoryView:' is deprecated + +// Make deprecation warnings just warnings in a -Werror compilation. + +#if HAVE_GCC_PRAGMA_DIAGNOSTIC_MODIFY +// #pragma GCC diagnostic push +#pragma GCC diagnostic warning "-Wdeprecated-declarations" +#endif + +@implementation AquaPrintAccessoryView ++(NSObject*)setupPrinterPanel: (NSPrintOperation*)pOp withController: (vcl::PrinterController*)pController withState: (PrintAccessoryViewState*)pState +{ + const Sequence< PropertyValue >& rOptions( pController->getUIOptions() ); + if( rOptions.getLength() == 0 ) + return nil; + + NSView* pCurParent = 0; + long nCurY = 0; + long nCurX = 0; + NSRect aViewFrame = { { 0, 0 }, {600, 400 } }; + NSRect aTabViewFrame = { { 190, 0 }, {410, 400 } }; + NSSize aMaxTabSize = { 0, 0 }; + NSView* pAccessoryView = [[NSView alloc] initWithFrame: aViewFrame]; + NSTabView* pTabView = [[NSTabView alloc] initWithFrame: aTabViewFrame]; + [pAccessoryView addSubview: [pTabView autorelease]]; + + sal_Bool bIgnoreSubgroup = sal_False; + + ControllerProperties* pControllerProperties = new ControllerProperties( pController, pOp, pAccessoryView, pTabView, pState ); + ControlTarget* pCtrlTarget = [[ControlTarget alloc] initWithControllerMap: pControllerProperties]; + + std::vector< ColumnItem > aLeftColumn, aRightColumn; + + // ugly: + // prepend a "selection" checkbox if the properties have such a selection in PrintContent + bool bAddSelectionCheckBox = false, bSelectionBoxEnabled = false, bSelectionBoxChecked = false; + for( int i = 0; i < rOptions.getLength(); i++ ) + { + Sequence< beans::PropertyValue > aOptProp; + rOptions[i].Value >>= aOptProp; + + rtl::OUString aCtrlType; + rtl::OUString aPropertyName; + Sequence< rtl::OUString > aChoices; + Sequence< sal_Bool > aChoicesDisabled; + sal_Int32 aSelectionChecked = 0; + for( int n = 0; n < aOptProp.getLength(); n++ ) + { + const beans::PropertyValue& rEntry( aOptProp[ n ] ); + if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ControlType")) ) + { + rEntry.Value >>= aCtrlType; + } + else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Choices")) ) + { + rEntry.Value >>= aChoices; + } + else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ChoicesDisabled")) ) + { + rEntry.Value >>= aChoicesDisabled; + } + else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Property")) ) + { + PropertyValue aVal; + rEntry.Value >>= aVal; + aPropertyName = aVal.Name; + if( aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrintContent")) ) + aVal.Value >>= aSelectionChecked; + } + } + if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Radio")) && + aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrintContent")) && + aChoices.getLength() > 2 ) + { + bAddSelectionCheckBox = true; + bSelectionBoxEnabled = aChoicesDisabled.getLength() < 2 || ! aChoicesDisabled[2]; + bSelectionBoxChecked = (aSelectionChecked==2); + break; + } + } + + for( int i = 0; i < rOptions.getLength(); i++ ) + { + Sequence< beans::PropertyValue > aOptProp; + rOptions[i].Value >>= aOptProp; + + // extract ui element + bool bEnabled = true; + rtl::OUString aCtrlType; + rtl::OUString aText; + rtl::OUString aPropertyName; + rtl::OUString aGroupHint; + Sequence< rtl::OUString > aChoices; + sal_Int64 nMinValue = 0, nMaxValue = 0; + long nAttachOffset = 0; + sal_Bool bIgnore = sal_False; + + for( int n = 0; n < aOptProp.getLength(); n++ ) + { + const beans::PropertyValue& rEntry( aOptProp[ n ] ); + if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Text")) ) + { + rEntry.Value >>= aText; + filterAccelerator( aText ); + } + else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ControlType")) ) + { + rEntry.Value >>= aCtrlType; + } + else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Choices")) ) + { + rEntry.Value >>= aChoices; + } + else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Property")) ) + { + PropertyValue aVal; + rEntry.Value >>= aVal; + aPropertyName = aVal.Name; + } + else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Enabled")) ) + { + sal_Bool bValue = sal_True; + rEntry.Value >>= bValue; + bEnabled = bValue; + } + else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("MinValue")) ) + { + rEntry.Value >>= nMinValue; + } + else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("MaxValue")) ) + { + rEntry.Value >>= nMaxValue; + } + else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("AttachToDependency")) ) + { + nAttachOffset = 20; + } + else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("InternalUIOnly")) ) + { + rEntry.Value >>= bIgnore; + } + else if( rEntry.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("GroupingHint")) ) + { + rEntry.Value >>= aGroupHint; + } + } + + if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Group")) || + aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Subgroup")) || + aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Radio")) || + aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("List")) || + aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Edit")) || + aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Range")) || + aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Bool")) ) + { + // since our build target is MacOSX 10.4 we can have only one accessory view + // so we have a single accessory view that is tabbed for grouping + if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Group")) + || ! pCurParent + || ( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Subgroup")) && nCurY < -250 && ! bIgnore ) + ) + { + rtl::OUString aGroupTitle( aText ); + if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Subgroup")) ) + aGroupTitle = pControllerProperties->getMoreString(); + // set size of current parent + if( pCurParent ) + adjustViewAndChildren( pCurParent, aMaxTabSize, aLeftColumn, aRightColumn ); + + // new tab item + if( ! aText.getLength() ) + aText = OUString( "OOo" ); + NSString* pLabel = CreateNSString( aGroupTitle ); + NSTabViewItem* pItem = [[NSTabViewItem alloc] initWithIdentifier: pLabel ]; + [pItem setLabel: pLabel]; + [pTabView addTabViewItem: pItem]; + pCurParent = [[NSView alloc] initWithFrame: aTabViewFrame]; + [pItem setView: pCurParent]; + [pLabel release]; + + // reset indent + nCurX = 20; + // reset Y + nCurY = 0; + // clear columns + aLeftColumn.clear(); + aRightColumn.clear(); + + if( bAddSelectionCheckBox ) + { + addBool( pCurParent, nCurX, nCurY, 0, + pControllerProperties->getPrintSelectionString(), bSelectionBoxEnabled, + OUString( "PrintContent" ), bSelectionBoxChecked, + aRightColumn, pControllerProperties, pCtrlTarget ); + bAddSelectionCheckBox = false; + } + } + + if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Subgroup")) && pCurParent ) + { + bIgnoreSubgroup = bIgnore; + if( bIgnore ) + continue; + + addSubgroup( pCurParent, nCurY, aText ); + } + else if( bIgnoreSubgroup || bIgnore ) + { + continue; + } + else if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Bool")) && pCurParent ) + { + sal_Bool bVal = sal_False; + PropertyValue* pVal = pController->getValue( aPropertyName ); + if( pVal ) + pVal->Value >>= bVal; + addBool( pCurParent, nCurX, nCurY, nAttachOffset, + aText, true, aPropertyName, bVal, + aRightColumn, pControllerProperties, pCtrlTarget ); + } + else if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Radio")) && pCurParent ) + { + // get currently selected value + sal_Int32 nSelectVal = 0; + PropertyValue* pVal = pController->getValue( aPropertyName ); + if( pVal && pVal->Value.hasValue() ) + pVal->Value >>= nSelectVal; + + addRadio( pCurParent, nCurX, nCurY, nAttachOffset, + aText, aPropertyName, aChoices, nSelectVal, + aLeftColumn, aRightColumn, + pControllerProperties, pCtrlTarget ); + } + else if( aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("List")) && pCurParent ) + { + PropertyValue* pVal = pController->getValue( aPropertyName ); + sal_Int32 aSelectVal = 0; + if( pVal && pVal->Value.hasValue() ) + pVal->Value >>= aSelectVal; + + addList( pCurParent, nCurX, nCurY, nAttachOffset, + aText, aPropertyName, aChoices, aSelectVal, + aLeftColumn, aRightColumn, + pControllerProperties, pCtrlTarget ); + } + else if( (aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Edit")) || aCtrlType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Range"))) && pCurParent ) + { + // current value + PropertyValue* pVal = pController->getValue( aPropertyName ); + addEdit( pCurParent, nCurX, nCurY, nAttachOffset, + aCtrlType, aText, aPropertyName, pVal, + nMinValue, nMaxValue, + aLeftColumn, aRightColumn, + pControllerProperties, pCtrlTarget ); + } + } + else + { + SAL_INFO( "vcl.osx.print", "Unsupported UI option \"" << aCtrlType << "\""); + } + } + + pControllerProperties->updateEnableState(); + adjustViewAndChildren( pCurParent, aMaxTabSize, aLeftColumn, aRightColumn ); + + // leave some space for the preview + if( aMaxTabSize.height < 200 ) + aMaxTabSize.height = 200; + + // now reposition everything again so it is upper bound + adjustTabViews( pTabView, aMaxTabSize ); + + // find the minimum needed tab size + NSSize aTabCtrlSize = [pTabView minimumSize]; + aTabCtrlSize.height += aMaxTabSize.height + 10; + if( aTabCtrlSize.width < aMaxTabSize.width + 10 ) + aTabCtrlSize.width = aMaxTabSize.width + 10; + [pTabView setFrameSize: aTabCtrlSize]; + aViewFrame.size.width = aTabCtrlSize.width + aTabViewFrame.origin.x; + aViewFrame.size.height = aTabCtrlSize.height + aTabViewFrame.origin.y; + [pAccessoryView setFrameSize: aViewFrame.size]; + + pControllerProperties->setupPreview( pCtrlTarget ); + + // set the accessory view + [pOp setAccessoryView: [pAccessoryView autorelease]]; + + // set the current selecte tab item + if( pState->nLastPage >= 0 && pState->nLastPage < [pTabView numberOfTabViewItems] ) + [pTabView selectTabViewItemAtIndex: pState->nLastPage]; + + return pCtrlTarget; +} + +// #pragma GCC diagnostic pop + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/printview.mm b/vcl/osx/printview.mm new file mode 100644 index 000000000000..d2f4ac006d71 --- /dev/null +++ b/vcl/osx/printview.mm @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "vcl/print.hxx" + +#include "osx/printview.h" +#include "osx/salprn.h" + +@implementation AquaPrintView +-(id)initWithController: (vcl::PrinterController*)pController withInfoPrinter: (AquaSalInfoPrinter*)pInfoPrinter +{ + NSRect aRect = { { 0, 0 }, [pInfoPrinter->getPrintInfo() paperSize] }; + if( (self = [super initWithFrame: aRect]) != nil ) + { + mpController = pController; + mpInfoPrinter = pInfoPrinter; + } + return self; +} + +-(BOOL)knowsPageRange: (NSRangePointer)range +{ + range->location = 1; + range->length = mpInfoPrinter->getCurPageRangeCount(); + return YES; +} + +-(NSRect)rectForPage: (int)page +{ + NSSize aPaperSize = [mpInfoPrinter->getPrintInfo() paperSize]; + int nWidth = (int)aPaperSize.width; + // #i101108# sanity check + if( nWidth < 1 ) + nWidth = 1; + NSRect aRect = { { static_cast(page % nWidth), static_cast(page / nWidth) }, aPaperSize }; + return aRect; +} + +-(NSPoint)locationOfPrintRect: (NSRect)aRect +{ + (void)aRect; + NSPoint aPoint = { 0, 0 }; + return aPoint; +} + +-(void)drawRect: (NSRect)rect +{ + mpInfoPrinter->setStartPageOffset( static_cast(rect.origin.x), static_cast(rect.origin.y) ); + NSSize aPaperSize = [mpInfoPrinter->getPrintInfo() paperSize]; + int nPage = (int)(aPaperSize.width * rect.origin.y + rect.origin.x); + + // page count is 1 based + if( nPage - 1 < (mpInfoPrinter->getCurPageRangeStart() + mpInfoPrinter->getCurPageRangeCount() ) ) + mpController->printFilteredPage( nPage-1 ); +} +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/res/MainMenu.nib/classes.nib b/vcl/osx/res/MainMenu.nib/classes.nib new file mode 100644 index 000000000000..b9b4b09f6b0d --- /dev/null +++ b/vcl/osx/res/MainMenu.nib/classes.nib @@ -0,0 +1,4 @@ +{ + IBClasses = ({CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }); + IBVersion = 1; +} \ No newline at end of file diff --git a/vcl/osx/res/MainMenu.nib/info.nib b/vcl/osx/res/MainMenu.nib/info.nib new file mode 100644 index 000000000000..856429aee5bd --- /dev/null +++ b/vcl/osx/res/MainMenu.nib/info.nib @@ -0,0 +1,21 @@ + + + + + IBDocumentLocation + 135 107 356 240 0 0 1680 1028 + IBEditorPositions + + 29 + 132 352 141 44 0 0 1680 1028 + + IBFramework Version + 446.1 + IBOpenObjects + + 29 + + IBSystem Version + 8R2218 + + diff --git a/vcl/osx/res/MainMenu.nib/keyedobjects.nib b/vcl/osx/res/MainMenu.nib/keyedobjects.nib new file mode 100644 index 000000000000..d39d10119c0c Binary files /dev/null and b/vcl/osx/res/MainMenu.nib/keyedobjects.nib differ diff --git a/vcl/osx/res/cursors/airbrush.png b/vcl/osx/res/cursors/airbrush.png new file mode 100644 index 000000000000..7ec780c4f9f9 Binary files /dev/null and b/vcl/osx/res/cursors/airbrush.png differ diff --git a/vcl/osx/res/cursors/ase.png b/vcl/osx/res/cursors/ase.png new file mode 100644 index 000000000000..a3a30e0bcdce Binary files /dev/null and b/vcl/osx/res/cursors/ase.png differ diff --git a/vcl/osx/res/cursors/asn.png b/vcl/osx/res/cursors/asn.png new file mode 100644 index 000000000000..7a140b1ec926 Binary files /dev/null and b/vcl/osx/res/cursors/asn.png differ diff --git a/vcl/osx/res/cursors/asne.png b/vcl/osx/res/cursors/asne.png new file mode 100644 index 000000000000..311506aeb349 Binary files /dev/null and b/vcl/osx/res/cursors/asne.png differ diff --git a/vcl/osx/res/cursors/asns.png b/vcl/osx/res/cursors/asns.png new file mode 100644 index 000000000000..1c8950eb28bc Binary files /dev/null and b/vcl/osx/res/cursors/asns.png differ diff --git a/vcl/osx/res/cursors/asnswe.png b/vcl/osx/res/cursors/asnswe.png new file mode 100644 index 000000000000..aae5246fbbc0 Binary files /dev/null and b/vcl/osx/res/cursors/asnswe.png differ diff --git a/vcl/osx/res/cursors/asnw.png b/vcl/osx/res/cursors/asnw.png new file mode 100644 index 000000000000..9fd0036df077 Binary files /dev/null and b/vcl/osx/res/cursors/asnw.png differ diff --git a/vcl/osx/res/cursors/ass.png b/vcl/osx/res/cursors/ass.png new file mode 100644 index 000000000000..bee09e736ad1 Binary files /dev/null and b/vcl/osx/res/cursors/ass.png differ diff --git a/vcl/osx/res/cursors/asse.png b/vcl/osx/res/cursors/asse.png new file mode 100644 index 000000000000..d7883211d44f Binary files /dev/null and b/vcl/osx/res/cursors/asse.png differ diff --git a/vcl/osx/res/cursors/assw.png b/vcl/osx/res/cursors/assw.png new file mode 100644 index 000000000000..0b0a496a52ec Binary files /dev/null and b/vcl/osx/res/cursors/assw.png differ diff --git a/vcl/osx/res/cursors/asw.png b/vcl/osx/res/cursors/asw.png new file mode 100644 index 000000000000..5a4b9519e075 Binary files /dev/null and b/vcl/osx/res/cursors/asw.png differ diff --git a/vcl/osx/res/cursors/aswe.png b/vcl/osx/res/cursors/aswe.png new file mode 100644 index 000000000000..b9c5afaac043 Binary files /dev/null and b/vcl/osx/res/cursors/aswe.png differ diff --git a/vcl/osx/res/cursors/chain.png b/vcl/osx/res/cursors/chain.png new file mode 100644 index 000000000000..dbf069924d73 Binary files /dev/null and b/vcl/osx/res/cursors/chain.png differ diff --git a/vcl/osx/res/cursors/chainnot.png b/vcl/osx/res/cursors/chainnot.png new file mode 100644 index 000000000000..547703edf12c Binary files /dev/null and b/vcl/osx/res/cursors/chainnot.png differ diff --git a/vcl/osx/res/cursors/chart.png b/vcl/osx/res/cursors/chart.png new file mode 100644 index 000000000000..de5514006e1f Binary files /dev/null and b/vcl/osx/res/cursors/chart.png differ diff --git a/vcl/osx/res/cursors/copydata.png b/vcl/osx/res/cursors/copydata.png new file mode 100644 index 000000000000..b6202fd9144f Binary files /dev/null and b/vcl/osx/res/cursors/copydata.png differ diff --git a/vcl/osx/res/cursors/copydlnk.png b/vcl/osx/res/cursors/copydlnk.png new file mode 100644 index 000000000000..fab24c9f8f7c Binary files /dev/null and b/vcl/osx/res/cursors/copydlnk.png differ diff --git a/vcl/osx/res/cursors/copyf.png b/vcl/osx/res/cursors/copyf.png new file mode 100644 index 000000000000..70546d0c0c22 Binary files /dev/null and b/vcl/osx/res/cursors/copyf.png differ diff --git a/vcl/osx/res/cursors/copyf2.png b/vcl/osx/res/cursors/copyf2.png new file mode 100644 index 000000000000..b6f76051f10f Binary files /dev/null and b/vcl/osx/res/cursors/copyf2.png differ diff --git a/vcl/osx/res/cursors/copyflnk.png b/vcl/osx/res/cursors/copyflnk.png new file mode 100644 index 000000000000..23561e484e36 Binary files /dev/null and b/vcl/osx/res/cursors/copyflnk.png differ diff --git a/vcl/osx/res/cursors/crook.png b/vcl/osx/res/cursors/crook.png new file mode 100644 index 000000000000..4378f8df8351 Binary files /dev/null and b/vcl/osx/res/cursors/crook.png differ diff --git a/vcl/osx/res/cursors/crop.png b/vcl/osx/res/cursors/crop.png new file mode 100644 index 000000000000..92a778ada31a Binary files /dev/null and b/vcl/osx/res/cursors/crop.png differ diff --git a/vcl/osx/res/cursors/darc.png b/vcl/osx/res/cursors/darc.png new file mode 100644 index 000000000000..9772a1c6b85a Binary files /dev/null and b/vcl/osx/res/cursors/darc.png differ diff --git a/vcl/osx/res/cursors/dbezier.png b/vcl/osx/res/cursors/dbezier.png new file mode 100644 index 000000000000..988498137e9a Binary files /dev/null and b/vcl/osx/res/cursors/dbezier.png differ diff --git a/vcl/osx/res/cursors/dcapt.png b/vcl/osx/res/cursors/dcapt.png new file mode 100644 index 000000000000..d1ef82818735 Binary files /dev/null and b/vcl/osx/res/cursors/dcapt.png differ diff --git a/vcl/osx/res/cursors/dcirccut.png b/vcl/osx/res/cursors/dcirccut.png new file mode 100644 index 000000000000..cb4ed0e85ecd Binary files /dev/null and b/vcl/osx/res/cursors/dcirccut.png differ diff --git a/vcl/osx/res/cursors/dconnect.png b/vcl/osx/res/cursors/dconnect.png new file mode 100644 index 000000000000..e4a43bdbe021 Binary files /dev/null and b/vcl/osx/res/cursors/dconnect.png differ diff --git a/vcl/osx/res/cursors/dellipse.png b/vcl/osx/res/cursors/dellipse.png new file mode 100644 index 000000000000..319c4574c7c1 Binary files /dev/null and b/vcl/osx/res/cursors/dellipse.png differ diff --git a/vcl/osx/res/cursors/detectiv.png b/vcl/osx/res/cursors/detectiv.png new file mode 100644 index 000000000000..abe93f263d4d Binary files /dev/null and b/vcl/osx/res/cursors/detectiv.png differ diff --git a/vcl/osx/res/cursors/dfree.png b/vcl/osx/res/cursors/dfree.png new file mode 100644 index 000000000000..2de92942adde Binary files /dev/null and b/vcl/osx/res/cursors/dfree.png differ diff --git a/vcl/osx/res/cursors/dline.png b/vcl/osx/res/cursors/dline.png new file mode 100644 index 000000000000..6afb670ef8a8 Binary files /dev/null and b/vcl/osx/res/cursors/dline.png differ diff --git a/vcl/osx/res/cursors/dpie.png b/vcl/osx/res/cursors/dpie.png new file mode 100644 index 000000000000..44a9474846b9 Binary files /dev/null and b/vcl/osx/res/cursors/dpie.png differ diff --git a/vcl/osx/res/cursors/dpolygon.png b/vcl/osx/res/cursors/dpolygon.png new file mode 100644 index 000000000000..847e6ad9bea5 Binary files /dev/null and b/vcl/osx/res/cursors/dpolygon.png differ diff --git a/vcl/osx/res/cursors/drect.png b/vcl/osx/res/cursors/drect.png new file mode 100644 index 000000000000..ff3dcbba07b4 Binary files /dev/null and b/vcl/osx/res/cursors/drect.png differ diff --git a/vcl/osx/res/cursors/dtext.png b/vcl/osx/res/cursors/dtext.png new file mode 100644 index 000000000000..ee375f0e47a0 Binary files /dev/null and b/vcl/osx/res/cursors/dtext.png differ diff --git a/vcl/osx/res/cursors/fill.png b/vcl/osx/res/cursors/fill.png new file mode 100644 index 000000000000..220641b9beb4 Binary files /dev/null and b/vcl/osx/res/cursors/fill.png differ diff --git a/vcl/osx/res/cursors/help.png b/vcl/osx/res/cursors/help.png new file mode 100644 index 000000000000..e29c19eccd22 Binary files /dev/null and b/vcl/osx/res/cursors/help.png differ diff --git a/vcl/osx/res/cursors/hourglass.png b/vcl/osx/res/cursors/hourglass.png new file mode 100644 index 000000000000..07bb5af73e6e Binary files /dev/null and b/vcl/osx/res/cursors/hourglass.png differ diff --git a/vcl/osx/res/cursors/hshear.png b/vcl/osx/res/cursors/hshear.png new file mode 100644 index 000000000000..b45beded2d93 Binary files /dev/null and b/vcl/osx/res/cursors/hshear.png differ diff --git a/vcl/osx/res/cursors/linkdata.png b/vcl/osx/res/cursors/linkdata.png new file mode 100644 index 000000000000..6432db0155b6 Binary files /dev/null and b/vcl/osx/res/cursors/linkdata.png differ diff --git a/vcl/osx/res/cursors/linkf.png b/vcl/osx/res/cursors/linkf.png new file mode 100644 index 000000000000..e17107fec9ff Binary files /dev/null and b/vcl/osx/res/cursors/linkf.png differ diff --git a/vcl/osx/res/cursors/magnify.png b/vcl/osx/res/cursors/magnify.png new file mode 100644 index 000000000000..4e73146b91e4 Binary files /dev/null and b/vcl/osx/res/cursors/magnify.png differ diff --git a/vcl/osx/res/cursors/mirror.png b/vcl/osx/res/cursors/mirror.png new file mode 100644 index 000000000000..8fac93f0b6df Binary files /dev/null and b/vcl/osx/res/cursors/mirror.png differ diff --git a/vcl/osx/res/cursors/movebw.png b/vcl/osx/res/cursors/movebw.png new file mode 100644 index 000000000000..63bf76ad3942 Binary files /dev/null and b/vcl/osx/res/cursors/movebw.png differ diff --git a/vcl/osx/res/cursors/movedata.png b/vcl/osx/res/cursors/movedata.png new file mode 100644 index 000000000000..60ece8a53e59 Binary files /dev/null and b/vcl/osx/res/cursors/movedata.png differ diff --git a/vcl/osx/res/cursors/movedlnk.png b/vcl/osx/res/cursors/movedlnk.png new file mode 100644 index 000000000000..6951cd718d97 Binary files /dev/null and b/vcl/osx/res/cursors/movedlnk.png differ diff --git a/vcl/osx/res/cursors/movef.png b/vcl/osx/res/cursors/movef.png new file mode 100644 index 000000000000..97a01c88fa4d Binary files /dev/null and b/vcl/osx/res/cursors/movef.png differ diff --git a/vcl/osx/res/cursors/movef2.png b/vcl/osx/res/cursors/movef2.png new file mode 100644 index 000000000000..2cdddb410aae Binary files /dev/null and b/vcl/osx/res/cursors/movef2.png differ diff --git a/vcl/osx/res/cursors/moveflnk.png b/vcl/osx/res/cursors/moveflnk.png new file mode 100644 index 000000000000..53301ba58c50 Binary files /dev/null and b/vcl/osx/res/cursors/moveflnk.png differ diff --git a/vcl/osx/res/cursors/movept.png b/vcl/osx/res/cursors/movept.png new file mode 100644 index 000000000000..41945deb1916 Binary files /dev/null and b/vcl/osx/res/cursors/movept.png differ diff --git a/vcl/osx/res/cursors/neswsize.png b/vcl/osx/res/cursors/neswsize.png new file mode 100644 index 000000000000..91b89b5803ec Binary files /dev/null and b/vcl/osx/res/cursors/neswsize.png differ diff --git a/vcl/osx/res/cursors/notallow.png b/vcl/osx/res/cursors/notallow.png new file mode 100644 index 000000000000..df770a495194 Binary files /dev/null and b/vcl/osx/res/cursors/notallow.png differ diff --git a/vcl/osx/res/cursors/nullptr.png b/vcl/osx/res/cursors/nullptr.png new file mode 100644 index 000000000000..489636595bec Binary files /dev/null and b/vcl/osx/res/cursors/nullptr.png differ diff --git a/vcl/osx/res/cursors/nwsesize.png b/vcl/osx/res/cursors/nwsesize.png new file mode 100644 index 000000000000..fc6a33288ef2 Binary files /dev/null and b/vcl/osx/res/cursors/nwsesize.png differ diff --git a/vcl/osx/res/cursors/pen.png b/vcl/osx/res/cursors/pen.png new file mode 100644 index 000000000000..81b583086778 Binary files /dev/null and b/vcl/osx/res/cursors/pen.png differ diff --git a/vcl/osx/res/cursors/pivotcol.png b/vcl/osx/res/cursors/pivotcol.png new file mode 100644 index 000000000000..1c38b915b886 Binary files /dev/null and b/vcl/osx/res/cursors/pivotcol.png differ diff --git a/vcl/osx/res/cursors/pivotdel.png b/vcl/osx/res/cursors/pivotdel.png new file mode 100644 index 000000000000..fbd663ee36c1 Binary files /dev/null and b/vcl/osx/res/cursors/pivotdel.png differ diff --git a/vcl/osx/res/cursors/pivotfld.png b/vcl/osx/res/cursors/pivotfld.png new file mode 100644 index 000000000000..04375de1efe6 Binary files /dev/null and b/vcl/osx/res/cursors/pivotfld.png differ diff --git a/vcl/osx/res/cursors/pivotrow.png b/vcl/osx/res/cursors/pivotrow.png new file mode 100644 index 000000000000..18ef0e8e59ba Binary files /dev/null and b/vcl/osx/res/cursors/pivotrow.png differ diff --git a/vcl/osx/res/cursors/pntbrsh.png b/vcl/osx/res/cursors/pntbrsh.png new file mode 100644 index 000000000000..ec8d799f66c2 Binary files /dev/null and b/vcl/osx/res/cursors/pntbrsh.png differ diff --git a/vcl/osx/res/cursors/rotate.png b/vcl/osx/res/cursors/rotate.png new file mode 100644 index 000000000000..a8137e077e56 Binary files /dev/null and b/vcl/osx/res/cursors/rotate.png differ diff --git a/vcl/osx/res/cursors/tblsele.png b/vcl/osx/res/cursors/tblsele.png new file mode 100644 index 000000000000..a2da05e009d1 Binary files /dev/null and b/vcl/osx/res/cursors/tblsele.png differ diff --git a/vcl/osx/res/cursors/tblsels.png b/vcl/osx/res/cursors/tblsels.png new file mode 100644 index 000000000000..ba20589c794f Binary files /dev/null and b/vcl/osx/res/cursors/tblsels.png differ diff --git a/vcl/osx/res/cursors/tblselse.png b/vcl/osx/res/cursors/tblselse.png new file mode 100644 index 000000000000..4ee7f62b304b Binary files /dev/null and b/vcl/osx/res/cursors/tblselse.png differ diff --git a/vcl/osx/res/cursors/tblselsw.png b/vcl/osx/res/cursors/tblselsw.png new file mode 100644 index 000000000000..11d7cb34d64d Binary files /dev/null and b/vcl/osx/res/cursors/tblselsw.png differ diff --git a/vcl/osx/res/cursors/tblselw.png b/vcl/osx/res/cursors/tblselw.png new file mode 100644 index 000000000000..62813a975855 Binary files /dev/null and b/vcl/osx/res/cursors/tblselw.png differ diff --git a/vcl/osx/res/cursors/timemove.png b/vcl/osx/res/cursors/timemove.png new file mode 100644 index 000000000000..3dae038a2011 Binary files /dev/null and b/vcl/osx/res/cursors/timemove.png differ diff --git a/vcl/osx/res/cursors/timesize.png b/vcl/osx/res/cursors/timesize.png new file mode 100644 index 000000000000..22178c9b8d0e Binary files /dev/null and b/vcl/osx/res/cursors/timesize.png differ diff --git a/vcl/osx/res/cursors/vshear.png b/vcl/osx/res/cursors/vshear.png new file mode 100644 index 000000000000..b01cb6c935e1 Binary files /dev/null and b/vcl/osx/res/cursors/vshear.png differ diff --git a/vcl/osx/res/cursors/vtext.png b/vcl/osx/res/cursors/vtext.png new file mode 100644 index 000000000000..2d6c847c9fc7 Binary files /dev/null and b/vcl/osx/res/cursors/vtext.png differ diff --git a/vcl/osx/saldata.cxx b/vcl/osx/saldata.cxx new file mode 100644 index 000000000000..55a5e6493782 --- /dev/null +++ b/vcl/osx/saldata.cxx @@ -0,0 +1,265 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include "osx/saldata.hxx" +#include "osx/salnsmenu.h" +#include "osx/salinst.h" + +#import "apple_remote/RemoteMainController.h" + +oslThreadKey SalData::s_aAutoReleaseKey = 0; + +static void SAL_CALL releasePool( void* pPool ) +{ + if( pPool ) + [(NSAutoreleasePool*)pPool release]; +} + +SalData::SalData() +: + mpTimerProc( NULL ), + mpFirstInstance( NULL ), + mpFirstObject( NULL ), + mpFirstVD( NULL ), + mpFirstPrinter( NULL ), + mpFontList( NULL ), + mpStatusItem( nil ), + mxRGBSpace( CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB) ), + mxGraySpace( CGColorSpaceCreateWithName(kCGColorSpaceGenericGray) ), + mxP50Space( NULL ), + mxP50Pattern( NULL ), + maCursors( POINTER_COUNT, INVALID_CURSOR_PTR ), + mbIsScrollbarDoubleMax( false ), +#if !HAVE_FEATURE_MACOSX_SANDBOX + mpMainController( NULL ), +#endif + mpDockIconClickHandler( nil ), + mnDPIX( 0 ), + mnDPIY( 0 ) +{ + if( s_aAutoReleaseKey == 0 ) + s_aAutoReleaseKey = osl_createThreadKey( releasePool ); +} + +SalData::~SalData() +{ + CGPatternRelease( mxP50Pattern ); + CGColorSpaceRelease( mxP50Space ); + CGColorSpaceRelease( mxRGBSpace ); + CGColorSpaceRelease( mxGraySpace ); + for( unsigned int i = 0; i < maCursors.size(); i++ ) + { + NSCursor* pCurs = maCursors[i]; + if( pCurs && pCurs != INVALID_CURSOR_PTR ) + [pCurs release]; + } + if( s_aAutoReleaseKey ) + { + // release the last pool + NSAutoreleasePool* pPool = nil; + pPool = reinterpret_cast( osl_getThreadKeyData( s_aAutoReleaseKey ) ); + if( pPool ) + { + osl_setThreadKeyData( s_aAutoReleaseKey, NULL ); + [pPool release]; + } + + osl_destroyThreadKey( s_aAutoReleaseKey ); + s_aAutoReleaseKey = 0; + } +#if !HAVE_FEATURE_MACOSX_SANDBOX + if ( mpMainController ) + [mpMainController release]; +#endif +} + +void SalData::ensureThreadAutoreleasePool() +{ + NSAutoreleasePool* pPool = nil; + if( s_aAutoReleaseKey ) + { + pPool = reinterpret_cast( osl_getThreadKeyData( s_aAutoReleaseKey ) ); + if( ! pPool ) + { + pPool = [[NSAutoreleasePool alloc] init]; + osl_setThreadKeyData( s_aAutoReleaseKey, pPool ); + } + } + else + { + OSL_FAIL( "no autorelease key" ); + } +} + +struct curs_ent +{ + const char* pBaseName; + const NSPoint aHotSpot; +} +const aCursorTab[ POINTER_COUNT ] = +{ +{ NULL, { 0, 0 } }, //POINTER_ARROW +{ "nullptr", { 16, 16 } }, //POINTER_NULL +{ "hourglass", { 15, 15 } }, //POINTER_WAIT +{ NULL, { 0, 0 } }, //POINTER_TEXT +{ "help", { 0, 0 } }, //POINTER_HELP +{ NULL, { 0, 0 } }, //POINTER_CROSS +{ NULL, { 0, 0 } }, //POINTER_MOVE +{ NULL, { 0, 0 } }, //POINTER_NSIZE +{ NULL, { 0, 0 } }, //POINTER_SSIZE +{ NULL, { 0, 0 } }, //POINTER_WSIZE +{ NULL, { 0, 0 } }, //POINTER_ESIZE +{ "nwsesize", { 15, 15 } }, //POINTER_NWSIZE +{ "neswsize", { 15, 15 } }, //POINTER_NESIZE +{ "neswsize", { 15, 15 } }, //POINTER_SWSIZE +{ "nwsesize", { 15, 15 } }, //POINTER_SESIZE +{ NULL, { 0, 0 } }, //POINTER_WINDOW_NSIZE +{ NULL, { 0, 0 } }, //POINTER_WINDOW_SSIZE +{ NULL, { 0, 0 } }, //POINTER_WINDOW_WSIZE +{ NULL, { 0, 0 } }, //POINTER_WINDOW_ESIZE +{ "nwsesize", { 15, 15 } }, //POINTER_WINDOW_NWSIZE +{ "neswsize", { 15, 15 } }, //POINTER_WINDOW_NESIZE +{ "neswsize", { 15, 15 } }, //POINTER_WINDOW_SWSIZE +{ "nwsesize", { 15, 15 } }, //POINTER_WINDOW_SESIZE +{ NULL, { 0, 0 } }, //POINTER_HSPLIT +{ NULL, { 0, 0 } }, //POINTER_VSPLIT +{ NULL, { 0, 0 } }, //POINTER_HSIZEBAR +{ NULL, { 0, 0 } }, //POINTER_VSIZEBAR +{ NULL, { 0, 0 } }, //POINTER_HAND +{ NULL, { 0, 0 } }, //POINTER_REFHAND +{ "pen", { 3, 27 } }, //POINTER_PEN +{ "magnify", { 12, 13 } }, //POINTER_MAGNIFY +{ "fill", { 10, 22 } }, //POINTER_FILL +{ "rotate", { 15, 15 } }, //POINTER_ROTATE +{ "hshear", { 15, 15 } }, //POINTER_HSHEAR +{ "vshear", { 15, 15 } }, //POINTER_VSHEAR +{ "mirror", { 14, 12 } }, //POINTER_MIRROR +{ "crook", { 15, 14 } }, //POINTER_CROOK +{ "crop", { 9, 9 } }, //POINTER_CROP +{ "movept", { 0, 0 } }, //POINTER_MOVEPOINT +{ "movebw", { 0, 0 } }, //POINTER_MOVEBEZIERWEIGHT +{ "movedata", { 0, 0 } }, //POINTER_MOVEDATA +{ "copydata", { 0, 0 } }, //POINTER_COPYDATA +{ "linkdata", { 0, 0 } }, //POINTER_LINKDATA +{ "movedlnk", { 0, 0 } }, //POINTER_MOVEDATALINK +{ "copydlnk", { 0, 0 } }, //POINTER_COPYDATALINK +{ "movef", { 8, 8 } }, //POINTER_MOVEFILE +{ "copyf", { 8, 8 } }, //POINTER_COPYFILE +{ "linkf", { 8, 8 } }, //POINTER_LINKFILE +{ "moveflnk", { 8, 8 } }, //POINTER_MOVEFILELINK +{ "copyflnk", { 8, 8 } }, //POINTER_COPYFILELINK +{ "movef2", { 7, 8 } }, //POINTER_MOVEFILES +{ "copyf2", { 7, 8 } }, //POINTER_COPYFILES +{ "notallow", { 15, 15 } }, //POINTER_NOTALLOWED +{ "dline", { 8, 8 } }, //POINTER_DRAW_LINE +{ "drect", { 8, 8 } }, //POINTER_DRAW_RECT +{ "dpolygon", { 8, 8 } }, //POINTER_DRAW_POLYGON +{ "dbezier", { 8, 8 } }, //POINTER_DRAW_BEZIER +{ "darc", { 8, 8 } }, //POINTER_DRAW_ARC +{ "dpie", { 8, 8 } }, //POINTER_DRAW_PIE +{ "dcirccut", { 8, 8 } }, //POINTER_DRAW_CIRCLECUT +{ "dellipse", { 8, 8 } }, //POINTER_DRAW_ELLIPSE +{ "dfree", { 8, 8 } }, //POINTER_DRAW_FREEHAND +{ "dconnect", { 8, 8 } }, //POINTER_DRAW_CONNECT +{ "dtext", { 8, 8 } }, //POINTER_DRAW_TEXT +{ "dcapt", { 8, 8 } }, //POINTER_DRAW_CAPTION +{ "chart", { 15, 16 } }, //POINTER_CHART +{ "detectiv", { 12, 13 } }, //POINTER_DETECTIVE +{ "pivotcol", { 7, 5 } }, //POINTER_PIVOT_COL +{ "pivotrow", { 8, 7 } }, //POINTER_PIVOT_ROW +{ "pivotfld", { 8, 7 } }, //POINTER_PIVOT_FIELD +{ "chain", { 0, 2 } }, //POINTER_CHAIN +{ "chainnot", { 2, 2 } }, //POINTER_CHAIN_NOTALLOWED +{ "timemove", { 16, 16 } }, //POINTER_TIMEEVENT_MOVE +{ "timesize", { 16, 17 } }, //POINTER_TIMEEVENT_SIZE +{ "asn", { 16, 12 } }, //POINTER_AUTOSCROLL_N +{ "ass", { 15, 19 } }, //POINTER_AUTOSCROLL_S +{ "asw", { 12, 15 } }, //POINTER_AUTOSCROLL_W +{ "ase", { 19, 16 } }, //POINTER_AUTOSCROLL_E +{ "asnw", { 10, 10 } }, //POINTER_AUTOSCROLL_NW +{ "asne", { 21, 10 } }, //POINTER_AUTOSCROLL_NE +{ "assw", { 21, 21 } }, //POINTER_AUTOSCROLL_SW +{ "asse", { 21, 21 } }, //POINTER_AUTOSCROLL_SE +{ "asns", { 15, 15 } }, //POINTER_AUTOSCROLL_NS +{ "aswe", { 15, 15 } }, //POINTER_AUTOSCROLL_WE +{ "asnswe", { 15, 15 } }, //POINTER_AUTOSCROLL_NSWE +{ "airbrush", { 5, 22 } }, //POINTER_AIRBRUSH +{ "vtext", { 15, 15 } }, //POINTER_TEXT_VERTICAL +{ "pivotdel", { 18, 15 } }, //POINTER_PIVOT_DELETE +{ "tblsels", { 15, 30 } }, //POINTER_TAB_SELECT_S +{ "tblsele", { 30, 16 } }, //POINTER_TAB_SELECT_E +{ "tblselse", { 30, 30 } }, //POINTER_TAB_SELECT_SE +{ "tblselw", { 1, 16 } }, //POINTER_TAB_SELECT_W +{ "tblselsw", { 1, 30 } }, //POINTER_TAB_SELECT_SW +{ "pntbrsh", { 9, 16 } } //POINTER_PAINTBRUSH +}; + +NSCursor* SalData::getCursor( PointerStyle i_eStyle ) +{ + if( i_eStyle >= POINTER_COUNT ) + return nil; + + NSCursor* pCurs = maCursors[ i_eStyle ]; + if( pCurs == INVALID_CURSOR_PTR ) + { + pCurs = nil; + if( aCursorTab[ i_eStyle ].pBaseName ) + { + NSPoint aHotSpot = aCursorTab[ i_eStyle ].aHotSpot; + CFStringRef pCursorName = + CFStringCreateWithCStringNoCopy( + kCFAllocatorDefault, + aCursorTab[ i_eStyle ].pBaseName, + kCFStringEncodingASCII, + kCFAllocatorNull ); + CFBundleRef hMain = CFBundleGetMainBundle(); + CFURLRef hURL = CFBundleCopyResourceURL( hMain, pCursorName, CFSTR("png"), CFSTR("cursors") ); + if( hURL ) + { + pCurs = [[NSCursor alloc] initWithImage: [[NSImage alloc] initWithContentsOfURL: (NSURL*)hURL] hotSpot: aHotSpot]; + CFRelease( hURL ); + } + CFRelease( pCursorName ); + } + maCursors[ i_eStyle ] = pCurs; + } + return pCurs; +} + +NSStatusItem* SalData::getStatusItem() +{ + SalData* pData = GetSalData(); + if( ! pData->mpStatusItem ) + { + NSStatusBar* pStatBar =[NSStatusBar systemStatusBar]; + if( pStatBar ) + { + pData->mpStatusItem = [pStatBar statusItemWithLength: NSVariableStatusItemLength]; + [pData->mpStatusItem retain]; + OOStatusItemView* pView = [[OOStatusItemView alloc] init]; + [pData->mpStatusItem setView: pView ]; + [pView display]; + } + } + return pData->mpStatusItem; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/salframe.cxx b/vcl/osx/salframe.cxx new file mode 100644 index 000000000000..cf1fe45b97e3 --- /dev/null +++ b/vcl/osx/salframe.cxx @@ -0,0 +1,1769 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include + +#include "rtl/ustrbuf.hxx" + +#include "osl/file.h" + +#include "vcl/svapp.hxx" +#include "vcl/window.hxx" +#include "vcl/syswin.hxx" + +#include "osx/saldata.hxx" +#include "quartz/salgdi.h" +#include "osx/salframe.h" +#include "osx/salmenu.h" +#include "osx/salinst.h" +#include "osx/salframeview.h" +#include "osx/a11yfactory.h" +#include "quartz/utils.h" + +#include "salwtype.hxx" + +#include "premac.h" +#include +// needed for theming +// FIXME: move theming code to salnativewidgets.cxx +#include +#include "postmac.h" + +using namespace std; + +// ======================================================================= + +AquaSalFrame* AquaSalFrame::s_pCaptureFrame = NULL; + +// ======================================================================= + +AquaSalFrame::AquaSalFrame( SalFrame* pParent, sal_uLong salFrameStyle ) : + mpNSWindow(nil), + mpNSView(nil), + mpDockMenuEntry(nil), + mpGraphics(NULL), + mpParent(NULL), + mnMinWidth(0), + mnMinHeight(0), + mnMaxWidth(0), + mnMaxHeight(0), + mbGraphics(false), + mbFullScreen( false ), + mbShown(false), + mbInitShow(true), + mbPositioned(false), + mbSized(false), + mbPresentation( false ), + mnStyle( salFrameStyle ), + mnStyleMask( 0 ), + mnLastEventTime( 0 ), + mnLastModifierFlags( 0 ), + mpMenu( NULL ), + mnExtStyle( 0 ), + mePointerStyle( POINTER_ARROW ), + mnTrackingRectTag( 0 ), + mrClippingPath( 0 ), + mnICOptions( 0 ) +{ + maSysData.nSize = sizeof( SystemEnvData ); + + mpParent = dynamic_cast(pParent); + + initWindowAndView(); + + SalData* pSalData = GetSalData(); + pSalData->maFrames.push_front( this ); + pSalData->maFrameCheck.insert( this ); +} + +// ----------------------------------------------------------------------- + +AquaSalFrame::~AquaSalFrame() +{ + // if the frame is destroyed and has the current menubar + // set the default menubar + if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu ) + AquaSalMenu::setDefaultMenu(); + + // cleanup clipping stuff + ResetClipRegion(); + + [SalFrameView unsetMouseFrame: this]; + + SalData* pSalData = GetSalData(); + pSalData->maFrames.remove( this ); + pSalData->maFrameCheck.erase( this ); + pSalData->maPresentationFrames.remove( this ); + + DBG_ASSERT( this != s_pCaptureFrame, "capture frame destroyed" ); + if( this == s_pCaptureFrame ) + s_pCaptureFrame = NULL; + + delete mpGraphics; + + if( mpDockMenuEntry ) + // life cycle comment: the menu has ownership of the item, so no release + [AquaSalInstance::GetDynamicDockMenu() removeItem: mpDockMenuEntry]; + if ( mpNSView ) { + [AquaA11yFactory revokeView: mpNSView]; + [mpNSView release]; + } + if ( mpNSWindow ) + [mpNSWindow release]; +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::initWindowAndView() +{ + // initialize mirroring parameters + // FIXME: screens changing + NSScreen* pNSScreen = [mpNSWindow screen]; + if( pNSScreen == nil ) + pNSScreen = [NSScreen mainScreen]; + maScreenRect = [pNSScreen frame]; + + // calculate some default geometry + NSRect aVisibleRect = [pNSScreen visibleFrame]; + CocoaToVCL( aVisibleRect ); + + maGeometry.nX = static_cast(aVisibleRect.origin.x + aVisibleRect.size.width / 10); + maGeometry.nY = static_cast(aVisibleRect.origin.y + aVisibleRect.size.height / 10); + maGeometry.nWidth = static_cast(aVisibleRect.size.width * 0.8); + maGeometry.nHeight = static_cast(aVisibleRect.size.height * 0.8); + + // calculate style mask + if( (mnStyle & SAL_FRAME_STYLE_FLOAT) || + (mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) + mnStyleMask = NSBorderlessWindowMask; + else if( mnStyle & SAL_FRAME_STYLE_DEFAULT ) + { + mnStyleMask = NSTitledWindowMask | + NSMiniaturizableWindowMask | + NSResizableWindowMask | + NSClosableWindowMask; + // make default window "maximized" + maGeometry.nX = static_cast(aVisibleRect.origin.x); + maGeometry.nY = static_cast(aVisibleRect.origin.y); + maGeometry.nWidth = static_cast(aVisibleRect.size.width); + maGeometry.nHeight = static_cast(aVisibleRect.size.height); + mbPositioned = mbSized = true; + } + else + { + if( (mnStyle & SAL_FRAME_STYLE_MOVEABLE) ) + { + mnStyleMask |= NSTitledWindowMask; + if( mpParent == NULL ) + mnStyleMask |= NSMiniaturizableWindowMask; + } + if( (mnStyle & SAL_FRAME_STYLE_SIZEABLE) ) + mnStyleMask |= NSResizableWindowMask; + if( (mnStyle & SAL_FRAME_STYLE_CLOSEABLE) ) + mnStyleMask |= NSClosableWindowMask; + // documentation says anything other than NSBorderlessWindowMask (=0) + // should also include NSTitledWindowMask; + if( mnStyleMask != 0 ) + mnStyleMask |= NSTitledWindowMask; + } + + // #i91990# support GUI-less (daemon) execution + @try + { + mpNSWindow = [[SalFrameWindow alloc] initWithSalFrame: this]; + mpNSView = [[SalFrameView alloc] initWithSalFrame: this]; + } + @catch ( id exception ) + { + return; + } + + if( (mnStyle & SAL_FRAME_STYLE_TOOLTIP) ) + [mpNSWindow setIgnoresMouseEvents: YES]; + else + [mpNSWindow setAcceptsMouseMovedEvents: YES]; + [mpNSWindow setHasShadow: YES]; + + // WTF? With the 10.6 SDK and gcc 4.2.1, we get: class 'NSWindow' + // does not implement the 'NSWindowDelegate' protocol. Anyway, + // having the window object be its own delegate object is + // apparently what the code does on purpose, see discussion in + // https://issues.apache.org/ooo/show_bug.cgi?id=91990 + + // So to silence the warning when compiling with -Werror, instead of: + // [mpNSWindow setDelegate: mpNSWindow]; + // do this: + objc_msgSend(mpNSWindow, @selector(setDelegate:), mpNSWindow); + + if( [mpNSWindow respondsToSelector: @selector(setRestorable:)]) + { + objc_msgSend(mpNSWindow, @selector(setRestorable:), NO); + } + NSRect aRect = { { 0,0 }, { static_cast(maGeometry.nWidth), static_cast(maGeometry.nHeight) } }; + mnTrackingRectTag = [mpNSView addTrackingRect: aRect owner: mpNSView userData: nil assumeInside: NO]; + + maSysData.mpNSView = mpNSView; + + UpdateFrameGeometry(); + + [mpNSWindow setContentView: mpNSView]; +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::CocoaToVCL( NSRect& io_rRect, bool bRelativeToScreen ) +{ + if( bRelativeToScreen ) + io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height); + else + io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height); +} + +void AquaSalFrame::VCLToCocoa( NSRect& io_rRect, bool bRelativeToScreen ) +{ + if( bRelativeToScreen ) + io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height); + else + io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height); +} + +void AquaSalFrame::CocoaToVCL( NSPoint& io_rPoint, bool bRelativeToScreen ) +{ + if( bRelativeToScreen ) + io_rPoint.y = maScreenRect.size.height - io_rPoint.y; + else + io_rPoint.y = maGeometry.nHeight - io_rPoint.y; +} + +void AquaSalFrame::VCLToCocoa( NSPoint& io_rPoint, bool bRelativeToScreen ) +{ + if( bRelativeToScreen ) + io_rPoint.y = maScreenRect.size.height - io_rPoint.y; + else + io_rPoint.y = maGeometry.nHeight - io_rPoint.y; +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::screenParametersChanged() +{ + UpdateFrameGeometry(); + + if( mpGraphics ) + mpGraphics->updateResolution(); + CallCallback( SALEVENT_DISPLAYCHANGED, 0 ); +} + +// ----------------------------------------------------------------------- + +SalGraphics* AquaSalFrame::GetGraphics() +{ + if ( mbGraphics ) + return NULL; + + if ( !mpGraphics ) + { + mpGraphics = new AquaSalGraphics; + mpGraphics->SetWindowGraphics( this ); + } + + mbGraphics = TRUE; + return mpGraphics; +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::ReleaseGraphics( SalGraphics *pGraphics ) +{ + (void)pGraphics; + DBG_ASSERT( pGraphics == mpGraphics, "graphics released on wrong frame" ); + mbGraphics = FALSE; +} + +// ----------------------------------------------------------------------- + +sal_Bool AquaSalFrame::PostEvent( void *pData ) +{ + GetSalData()->mpFirstInstance->PostUserEvent( this, SALEVENT_USEREVENT, pData ); + return TRUE; +} + +// ----------------------------------------------------------------------- +void AquaSalFrame::SetTitle(const OUString& rTitle) +{ + if ( !mpNSWindow ) + return; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + NSString* pTitle = CreateNSString( rTitle ); + [mpNSWindow setTitle: pTitle]; + + // create an entry in the dock menu + const sal_uLong nAppWindowStyle = (SAL_FRAME_STYLE_CLOSEABLE | SAL_FRAME_STYLE_MOVEABLE); + if( mpParent == NULL && + (mnStyle & nAppWindowStyle) == nAppWindowStyle ) + { + if( mpDockMenuEntry == NULL ) + { + NSMenu* pDock = AquaSalInstance::GetDynamicDockMenu(); + mpDockMenuEntry = [pDock insertItemWithTitle: pTitle + action: @selector(dockMenuItemTriggered:) + keyEquivalent: @"" + atIndex: 0]; + [mpDockMenuEntry setTarget: mpNSWindow]; + + // TODO: image (either the generic window image or an icon + // check mark (for "main" window ?) + } + else + [mpDockMenuEntry setTitle: pTitle]; + } + + if (pTitle) + [pTitle release]; +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::SetIcon( sal_uInt16 ) +{ +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::SetRepresentedURL( const OUString& i_rDocURL ) +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + if( i_rDocURL.startsWith( "file:" ) ) + { + OUString aSysPath; + osl_getSystemPathFromFileURL( i_rDocURL.pData, &aSysPath.pData ); + NSString* pStr = CreateNSString( aSysPath ); + if( pStr ) + { + [pStr autorelease]; + [mpNSWindow setRepresentedFilename: pStr]; + } + } +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::initShow() +{ + mbInitShow = false; + if( ! mbPositioned && ! mbFullScreen ) + { + Rectangle aScreenRect; + GetWorkArea( aScreenRect ); + if( mpParent ) // center relative to parent + { + // center on parent + long nNewX = mpParent->maGeometry.nX + ((long)mpParent->maGeometry.nWidth - (long)maGeometry.nWidth)/2; + if( nNewX < aScreenRect.Left() ) + nNewX = aScreenRect.Left(); + if( long(nNewX + maGeometry.nWidth) > aScreenRect.Right() ) + nNewX = aScreenRect.Right() - maGeometry.nWidth-1; + long nNewY = mpParent->maGeometry.nY + ((long)mpParent->maGeometry.nHeight - (long)maGeometry.nHeight)/2; + if( nNewY < aScreenRect.Top() ) + nNewY = aScreenRect.Top(); + if( nNewY > aScreenRect.Bottom() ) + nNewY = aScreenRect.Bottom() - maGeometry.nHeight-1; + SetPosSize( nNewX - mpParent->maGeometry.nX, + nNewY - mpParent->maGeometry.nY, + 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ); + } + else if( ! (mnStyle & SAL_FRAME_STYLE_SIZEABLE) ) + { + // center on screen + long nNewX = (aScreenRect.GetWidth() - maGeometry.nWidth)/2; + long nNewY = (aScreenRect.GetHeight() - maGeometry.nHeight)/2; + SetPosSize( nNewX, nNewY, 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ); + } + } + + // make sure the view is present in the wrapper list before any children receive focus + [AquaA11yFactory registerView: mpNSView]; +} + +void AquaSalFrame::SendPaintEvent( const Rectangle* pRect ) +{ + SalPaintEvent aPaintEvt( 0, 0, maGeometry.nWidth, maGeometry.nHeight, true ); + if( pRect ) + { + aPaintEvt.mnBoundX = pRect->Left(); + aPaintEvt.mnBoundY = pRect->Top(); + aPaintEvt.mnBoundWidth = pRect->GetWidth(); + aPaintEvt.mnBoundHeight = pRect->GetHeight(); + } + + CallCallback(SALEVENT_PAINT, &aPaintEvt); +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::Show(sal_Bool bVisible, sal_Bool bNoActivate) +{ + if ( !mpNSWindow ) + return; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + mbShown = bVisible; + if(bVisible) + { + if( mbInitShow ) + initShow(); + + CallCallback(SALEVENT_RESIZE, 0); + // trigger filling our backbuffer + SendPaintEvent(); + + if( bNoActivate || [mpNSWindow canBecomeKeyWindow] == NO ) + [mpNSWindow orderFront: NSApp]; + else + [mpNSWindow makeKeyAndOrderFront: NSApp]; + + if( mpParent ) + { + /* #i92674# #i96433# we do not want an invisible parent to show up (which adding a visible + child implicitly does). However we also do not want a parentless toolbar. + + HACK: try to decide when we should not insert a child to its parent + floaters and ownerdraw windows have not yet shown up in cases where + we don't want the parent to become visible + */ + if( mpParent->mbShown || (mnStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_FLOAT) ) ) + { + [mpParent->mpNSWindow addChildWindow: mpNSWindow ordered: NSWindowAbove]; + } + } + + if( mbPresentation ) + [mpNSWindow makeMainWindow]; + } + else + { + // if the frame holding the current menubar gets hidden + // show the default menubar + if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu ) + AquaSalMenu::setDefaultMenu(); + + // #i90440# #i94443# work around the focus going back to some other window + // if a child gets hidden for a parent window + if( mpParent && mpParent->mbShown && [mpNSWindow isKeyWindow] ) + [mpParent->mpNSWindow makeKeyAndOrderFront: NSApp]; + + [SalFrameView unsetMouseFrame: this]; + if( mpParent && [mpNSWindow parentWindow] == mpParent->mpNSWindow ) + [mpParent->mpNSWindow removeChildWindow: mpNSWindow]; + + [mpNSWindow orderOut: NSApp]; + } +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::Enable( sal_Bool ) +{ +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::SetMinClientSize( long nWidth, long nHeight ) +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + mnMinWidth = nWidth; + mnMinHeight = nHeight; + + if( mpNSWindow ) + { + // Always add the decoration as the dimension concerns only + // the content rectangle + nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration; + nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration; + + NSSize aSize = { static_cast(nWidth), static_cast(nHeight) }; + + // Size of full window (content+structure) although we only + // have the client size in arguments + [mpNSWindow setMinSize: aSize]; + } +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::SetMaxClientSize( long nWidth, long nHeight ) +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + mnMaxWidth = nWidth; + mnMaxHeight = nHeight; + + if( mpNSWindow ) + { + // Always add the decoration as the dimension concerns only + // the content rectangle + nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration; + nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration; + + // Carbon windows can't have a size greater than 32767x32767 + if (nWidth>32767) nWidth=32767; + if (nHeight>32767) nHeight=32767; + + NSSize aSize = { static_cast(nWidth), static_cast(nHeight) }; + + // Size of full window (content+structure) although we only + // have the client size in arguments + [mpNSWindow setMaxSize: aSize]; + } +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::SetClientSize( long nWidth, long nHeight ) +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + if( mpNSWindow ) + { + NSSize aSize = { static_cast(nWidth), static_cast(nHeight) }; + + [mpNSWindow setContentSize: aSize]; + UpdateFrameGeometry(); + if( mbShown ) + // trigger filling our backbuffer + SendPaintEvent(); + } +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::GetClientSize( long& rWidth, long& rHeight ) +{ + if( mbShown || mbInitShow ) + { + rWidth = maGeometry.nWidth; + rHeight = maGeometry.nHeight; + } + else + { + rWidth = 0; + rHeight = 0; + } +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::SetWindowState( const SalFrameState* pState ) +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + if ( mpNSWindow ) + { + // set normal state + NSRect aStateRect = [mpNSWindow frame]; + aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask]; + CocoaToVCL( aStateRect ); + if( pState->mnMask & WINDOWSTATE_MASK_X ) + aStateRect.origin.x = float(pState->mnX); + if( pState->mnMask & WINDOWSTATE_MASK_Y ) + aStateRect.origin.y = float(pState->mnY); + if( pState->mnMask & WINDOWSTATE_MASK_WIDTH ) + aStateRect.size.width = float(pState->mnWidth); + if( pState->mnMask & WINDOWSTATE_MASK_HEIGHT ) + aStateRect.size.height = float(pState->mnHeight); + VCLToCocoa( aStateRect ); + aStateRect = [NSWindow frameRectForContentRect: aStateRect styleMask: mnStyleMask]; + + [mpNSWindow setFrame: aStateRect display: NO]; + if( pState->mnState == WINDOWSTATE_STATE_MINIMIZED ) + [mpNSWindow miniaturize: NSApp]; + else if( [mpNSWindow isMiniaturized] ) + [mpNSWindow deminiaturize: NSApp]; + + + /* ZOOMED is not really maximized (actually it toggles between a user set size and + the program specified one), but comes closest since the default behavior is + "maximized" if the user did not intervene + */ + if( pState->mnState == WINDOWSTATE_STATE_MAXIMIZED ) + { + if(! [mpNSWindow isZoomed]) + [mpNSWindow zoom: NSApp]; + } + else + { + if( [mpNSWindow isZoomed] ) + [mpNSWindow zoom: NSApp]; + } + } + + // get new geometry + UpdateFrameGeometry(); + + sal_uInt16 nEvent = 0; + if( pState->mnMask & (WINDOWSTATE_MASK_X | WINDOWSTATE_MASK_Y) ) + { + mbPositioned = true; + nEvent = SALEVENT_MOVE; + } + + if( pState->mnMask & (WINDOWSTATE_MASK_WIDTH | WINDOWSTATE_MASK_HEIGHT) ) + { + mbSized = true; + nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE; + } + // send event that we were moved/sized + if( nEvent ) + CallCallback( nEvent, NULL ); + + if( mbShown && mpNSWindow ) + { + // trigger filling our backbuffer + SendPaintEvent(); + + // tell the system the views need to be updated + [mpNSWindow display]; + } +} + +// ----------------------------------------------------------------------- + +sal_Bool AquaSalFrame::GetWindowState( SalFrameState* pState ) +{ + if ( !mpNSWindow ) + return FALSE; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + pState->mnMask = WINDOWSTATE_MASK_X | + WINDOWSTATE_MASK_Y | + WINDOWSTATE_MASK_WIDTH | + WINDOWSTATE_MASK_HEIGHT | + WINDOWSTATE_MASK_STATE; + + NSRect aStateRect = [mpNSWindow frame]; + aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask]; + CocoaToVCL( aStateRect ); + pState->mnX = long(aStateRect.origin.x); + pState->mnY = long(aStateRect.origin.y); + pState->mnWidth = long(aStateRect.size.width); + pState->mnHeight = long(aStateRect.size.height); + + if( [mpNSWindow isMiniaturized] ) + pState->mnState = WINDOWSTATE_STATE_MINIMIZED; + else if( ! [mpNSWindow isZoomed] ) + pState->mnState = WINDOWSTATE_STATE_NORMAL; + else + pState->mnState = WINDOWSTATE_STATE_MAXIMIZED; + + return TRUE; +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::SetScreenNumber(unsigned int nScreen) +{ + if ( !mpNSWindow ) + return; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + NSArray* pScreens = [NSScreen screens]; + Rectangle aRet; + NSScreen* pScreen = nil; + if( pScreens && nScreen < [pScreens count] ) + { + // get new screen frame + pScreen = [pScreens objectAtIndex: nScreen]; + NSRect aNewScreen = [pScreen frame]; + + // get current screen frame + pScreen = [mpNSWindow screen]; + if( pScreen ) + { + NSRect aCurScreen = [pScreen frame]; + if( aCurScreen.origin.x != aNewScreen.origin.x || + aCurScreen.origin.y != aNewScreen.origin.y ) + { + NSRect aFrameRect = [mpNSWindow frame]; + aFrameRect.origin.x += aNewScreen.origin.x - aCurScreen.origin.x; + aFrameRect.origin.y += aNewScreen.origin.y - aCurScreen.origin.y; + [mpNSWindow setFrame: aFrameRect display: NO]; + UpdateFrameGeometry(); + } + } + } +} + +void AquaSalFrame::SetApplicationID( const OUString &/*rApplicationID*/ ) +{ +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::ShowFullScreen( sal_Bool bFullScreen, sal_Int32 nDisplay ) +{ + if ( !mpNSWindow ) + return; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + SAL_INFO("vcl.macosx", OSL_THIS_FUNC << ": mbFullScreen=" << mbFullScreen << ", bFullScreen=" << bFullScreen); + + if( mbFullScreen == bFullScreen ) + return; + + mbFullScreen = bFullScreen; + + if( bFullScreen ) + { + // hide the dock and the menubar if we are on the menu screen + // which is always on index 0 according to documentation + bool bHideMenu = (nDisplay == 0); + + NSRect aNewContentRect = { { 0, 0 }, { 0, 0 } }; + // get correct screen + NSScreen* pScreen = nil; + NSArray* pScreens = [NSScreen screens]; + if( pScreens ) + { + if( nDisplay >= 0 && (unsigned int)nDisplay < [pScreens count] ) + pScreen = [pScreens objectAtIndex: nDisplay]; + else + { + // this means span all screens + bHideMenu = true; + NSEnumerator* pEnum = [pScreens objectEnumerator]; + while( (pScreen = [pEnum nextObject]) != nil ) + { + NSRect aScreenRect = [pScreen frame]; + if( aScreenRect.origin.x < aNewContentRect.origin.x ) + { + aNewContentRect.size.width += aNewContentRect.origin.x - aScreenRect.origin.x; + aNewContentRect.origin.x = aScreenRect.origin.x; + } + if( aScreenRect.origin.y < aNewContentRect.origin.y ) + { + aNewContentRect.size.height += aNewContentRect.origin.y - aScreenRect.origin.y; + aNewContentRect.origin.y = aScreenRect.origin.y; + } + if( aScreenRect.origin.x + aScreenRect.size.width > aNewContentRect.origin.x + aNewContentRect.size.width ) + aNewContentRect.size.width = aScreenRect.origin.x + aScreenRect.size.width - aNewContentRect.origin.x; + if( aScreenRect.origin.y + aScreenRect.size.height > aNewContentRect.origin.y + aNewContentRect.size.height ) + aNewContentRect.size.height = aScreenRect.origin.y + aScreenRect.size.height - aNewContentRect.origin.y; + } + } + } + if( aNewContentRect.size.width == 0 && aNewContentRect.size.height == 0 ) + { + if( pScreen == nil ) + pScreen = [mpNSWindow screen]; + if( pScreen == nil ) + pScreen = [NSScreen mainScreen]; + + aNewContentRect = [pScreen frame]; + } + + if( bHideMenu ) + [NSMenu setMenuBarVisible:NO]; + + maFullScreenRect = [mpNSWindow frame]; + { + [mpNSWindow setFrame: [NSWindow frameRectForContentRect: aNewContentRect styleMask: mnStyleMask] display: mbShown ? YES : NO]; + } + + UpdateFrameGeometry(); + + if( mbShown ) + CallCallback( SALEVENT_MOVERESIZE, NULL ); + } + else + { + { + [mpNSWindow setFrame: maFullScreenRect display: mbShown ? YES : NO]; + } + UpdateFrameGeometry(); + + if( mbShown ) + CallCallback( SALEVENT_MOVERESIZE, NULL ); + + // show the dock and the menubar + [NSMenu setMenuBarVisible:YES]; + } + if( mbShown ) + // trigger filling our backbuffer + SendPaintEvent(); +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::StartPresentation( sal_Bool bStart ) +{ + if ( !mpNSWindow ) + return; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + if( bStart ) + { + GetSalData()->maPresentationFrames.push_back( this ); + IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, + kIOPMAssertionLevelOn, + CFSTR("LibreOffice presentation running"), + &mnAssertionID); + [mpNSWindow setLevel: NSPopUpMenuWindowLevel]; + if( mbShown ) + [mpNSWindow makeMainWindow]; + } + else + { + GetSalData()->maPresentationFrames.remove( this ); + IOPMAssertionRelease(mnAssertionID); + [mpNSWindow setLevel: NSNormalWindowLevel]; + } +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::SetAlwaysOnTop( sal_Bool ) +{ +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::ToTop(sal_uInt16 nFlags) +{ + if ( !mpNSWindow ) + return; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + if( ! (nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN) ) + { + if( ! [mpNSWindow isVisible] || [mpNSWindow isMiniaturized] ) + return; + } + if( nFlags & SAL_FRAME_TOTOP_GRABFOCUS ) + [mpNSWindow makeKeyAndOrderFront: NSApp]; + else + [mpNSWindow orderFront: NSApp]; +} + +// ----------------------------------------------------------------------- + +NSCursor* AquaSalFrame::getCurrentCursor() const +{ + NSCursor* pCursor = nil; + switch( mePointerStyle ) + { + case POINTER_TEXT: pCursor = [NSCursor IBeamCursor]; break; + case POINTER_CROSS: pCursor = [NSCursor crosshairCursor]; break; + case POINTER_HAND: + case POINTER_MOVE: pCursor = [NSCursor openHandCursor]; break; + case POINTER_NSIZE: pCursor = [NSCursor resizeUpCursor]; break; + case POINTER_SSIZE: pCursor = [NSCursor resizeDownCursor]; break; + case POINTER_ESIZE: pCursor = [NSCursor resizeRightCursor]; break; + case POINTER_WSIZE: pCursor = [NSCursor resizeLeftCursor]; break; + case POINTER_ARROW: pCursor = [NSCursor arrowCursor]; break; + case POINTER_VSPLIT: + case POINTER_VSIZEBAR: + case POINTER_WINDOW_NSIZE: + case POINTER_WINDOW_SSIZE: + pCursor = [NSCursor resizeUpDownCursor]; break; + case POINTER_HSPLIT: + case POINTER_HSIZEBAR: + case POINTER_WINDOW_ESIZE: + case POINTER_WINDOW_WSIZE: + pCursor = [NSCursor resizeLeftRightCursor]; break; + case POINTER_REFHAND: pCursor = [NSCursor pointingHandCursor]; break; + case POINTER_NULL: [NSCursor hide]; break; + + default: + pCursor = GetSalData()->getCursor( mePointerStyle ); + if( pCursor == nil ) + { + OSL_FAIL( "unmapped cursor" ); + pCursor = [NSCursor arrowCursor]; + } + break; + } + return pCursor; +} + +void AquaSalFrame::SetPointer( PointerStyle ePointerStyle ) +{ + if ( !mpNSWindow ) + return; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + if( ePointerStyle >= POINTER_COUNT || ePointerStyle == mePointerStyle ) + return; + mePointerStyle = ePointerStyle; + + [mpNSWindow invalidateCursorRectsForView: mpNSView]; +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::SetPointerPos( long nX, long nY ) +{ + // FIXME: use Cocoa functions + + // FIXME: multiscreen support + CGPoint aPoint = { static_cast(nX + maGeometry.nX), static_cast(nY + maGeometry.nY) }; + CGDirectDisplayID mainDisplayID = CGMainDisplayID(); + CGDisplayMoveCursorToPoint( mainDisplayID, aPoint ); +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::Flush( void ) +{ + if( !(mbGraphics && mpGraphics && mpNSView && mbShown) ) + return; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + + [mpNSView setNeedsDisplay: YES]; + + // outside of the application's event loop (e.g. IntroWindow) + // nothing would trigger paint event handling + // => fall back to synchronous painting + if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 ) + { + [mpNSView display]; + } +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::Flush( const Rectangle& rRect ) +{ + if( !(mbGraphics && mpGraphics && mpNSView && mbShown) ) + return; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + NSRect aNSRect = { { static_cast(rRect.Left()), static_cast(rRect.Top()) }, { static_cast(rRect.GetWidth()), static_cast(rRect.GetHeight()) } }; + VCLToCocoa( aNSRect, false ); + [mpNSView setNeedsDisplayInRect: aNSRect]; + + // outside of the application's event loop (e.g. IntroWindow) + // nothing would trigger paint event handling + // => fall back to synchronous painting + if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 ) + { + [mpNSView display]; + } +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::Sync() +{ + if( mbGraphics && mpGraphics && mpNSView && mbShown ) + { + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + [mpNSView setNeedsDisplay: YES]; + [mpNSView display]; + } +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::SetInputContext( SalInputContext* pContext ) +{ + if (!pContext) + { + mnICOptions = 0; + return; + } + + mnICOptions = pContext->mnOptions; + + if(!(pContext->mnOptions & SAL_INPUTCONTEXT_TEXT)) + return; +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::EndExtTextInput( sal_uInt16 ) +{ +} + +// ----------------------------------------------------------------------- + +OUString AquaSalFrame::GetKeyName( sal_uInt16 nKeyCode ) +{ + static std::map< sal_uInt16, OUString > aKeyMap; + if( aKeyMap.empty() ) + { + sal_uInt16 i; + for( i = KEY_A; i <= KEY_Z; i++ ) + aKeyMap[ i ] = OUString( sal_Unicode( 'A' + (i - KEY_A) ) ); + for( i = KEY_0; i <= KEY_9; i++ ) + aKeyMap[ i ] = OUString( sal_Unicode( '0' + (i - KEY_0) ) ); + for( i = KEY_F1; i <= KEY_F26; i++ ) + { + OUStringBuffer aKey( 3 ); + aKey.append( 'F' ); + aKey.append( sal_Int32( i - KEY_F1 + 1 ) ); + aKeyMap[ i ] = aKey.makeStringAndClear(); + } + + aKeyMap[ KEY_DOWN ] = OUString( sal_Unicode( 0x21e3 ) ); + aKeyMap[ KEY_UP ] = OUString( sal_Unicode( 0x21e1 ) ); + aKeyMap[ KEY_LEFT ] = OUString( sal_Unicode( 0x21e0 ) ); + aKeyMap[ KEY_RIGHT ] = OUString( sal_Unicode( 0x21e2 ) ); + aKeyMap[ KEY_HOME ] = OUString( sal_Unicode( 0x2196 ) ); + aKeyMap[ KEY_END ] = OUString( sal_Unicode( 0x2198 ) ); + aKeyMap[ KEY_PAGEUP ] = OUString( sal_Unicode( 0x21de ) ); + aKeyMap[ KEY_PAGEDOWN ] = OUString( sal_Unicode( 0x21df ) ); + aKeyMap[ KEY_RETURN ] = OUString( sal_Unicode( 0x21a9 ) ); + aKeyMap[ KEY_ESCAPE ] = OUString( "esc" ); + aKeyMap[ KEY_TAB ] = OUString( sal_Unicode( 0x21e5 ) ); + aKeyMap[ KEY_BACKSPACE ]= OUString( sal_Unicode( 0x232b ) ); + aKeyMap[ KEY_SPACE ] = OUString( sal_Unicode( 0x2423 ) ); + aKeyMap[ KEY_DELETE ] = OUString( sal_Unicode( 0x2326 ) ); + aKeyMap[ KEY_ADD ] = OUString( '+' ); + aKeyMap[ KEY_SUBTRACT ] = OUString( '-' ); + aKeyMap[ KEY_DIVIDE ] = OUString( '/' ); + aKeyMap[ KEY_MULTIPLY ] = OUString( '*' ); + aKeyMap[ KEY_POINT ] = OUString( '.' ); + aKeyMap[ KEY_COMMA ] = OUString( ',' ); + aKeyMap[ KEY_LESS ] = OUString( '<' ); + aKeyMap[ KEY_GREATER ] = OUString( '>' ); + aKeyMap[ KEY_EQUAL ] = OUString( '=' ); + aKeyMap[ KEY_OPEN ] = OUString( sal_Unicode( 0x23cf ) ); + + /* yet unmapped KEYCODES: + aKeyMap[ KEY_INSERT ] = OUString( sal_Unicode( ) ); + aKeyMap[ KEY_CUT ] = OUString( sal_Unicode( ) ); + aKeyMap[ KEY_COPY ] = OUString( sal_Unicode( ) ); + aKeyMap[ KEY_PASTE ] = OUString( sal_Unicode( ) ); + aKeyMap[ KEY_UNDO ] = OUString( sal_Unicode( ) ); + aKeyMap[ KEY_REPEAT ] = OUString( sal_Unicode( ) ); + aKeyMap[ KEY_FIND ] = OUString( sal_Unicode( ) ); + aKeyMap[ KEY_PROPERTIES ] = OUString( sal_Unicode( ) ); + aKeyMap[ KEY_FRONT ] = OUString( sal_Unicode( ) ); + aKeyMap[ KEY_CONTEXTMENU ] = OUString( sal_Unicode( ) ); + aKeyMap[ KEY_MENU ] = OUString( sal_Unicode( ) ); + aKeyMap[ KEY_HELP ] = OUString( sal_Unicode( ) ); + aKeyMap[ KEY_HANGUL_HANJA ] = OUString( sal_Unicode( ) ); + aKeyMap[ KEY_DECIMAL ] = OUString( sal_Unicode( ) ); + aKeyMap[ KEY_TILDE ] = OUString( sal_Unicode( ) ); + aKeyMap[ KEY_QUOTELEFT ]= OUString( sal_Unicode( ) ); + */ + + } + + OUStringBuffer aResult( 16 ); + + sal_uInt16 nUnmodifiedCode = (nKeyCode & KEY_CODE); + std::map< sal_uInt16, OUString >::const_iterator it = aKeyMap.find( nUnmodifiedCode ); + if( it != aKeyMap.end() ) + { + if( (nKeyCode & KEY_SHIFT) != 0 ) + aResult.append( sal_Unicode( 0x21e7 ) ); + if( (nKeyCode & KEY_MOD1) != 0 ) + aResult.append( sal_Unicode( 0x2318 ) ); + // we do not really handle Alt (see below) + // we map it to MOD3, whichis actually Command + if( (nKeyCode & (KEY_MOD2|KEY_MOD3)) != 0 ) + aResult.append( sal_Unicode( 0x2303 ) ); + + aResult.append( it->second ); + } + + return aResult.makeStringAndClear(); +} + +// ----------------------------------------------------------------------- + +static void getAppleScrollBarVariant(StyleSettings &rSettings) +{ + bool bIsScrollbarDoubleMax = true; // default is DoubleMax + + CFStringRef AppleScrollBarType = CFSTR("AppleScrollBarVariant"); + if( AppleScrollBarType ) + { + CFStringRef ScrollBarVariant = ((CFStringRef)CFPreferencesCopyAppValue( AppleScrollBarType, kCFPreferencesCurrentApplication )); + if( ScrollBarVariant ) + { + if( CFGetTypeID( ScrollBarVariant ) == CFStringGetTypeID() ) + { + // TODO: check for the less important variants "DoubleMin" and "DoubleBoth" too + CFStringRef DoubleMax = CFSTR("DoubleMax"); + if (DoubleMax) + { + if ( !CFStringCompare(ScrollBarVariant, DoubleMax, kCFCompareCaseInsensitive) ) + bIsScrollbarDoubleMax = true; + else + bIsScrollbarDoubleMax = false; + CFRelease(DoubleMax); + } + } + CFRelease( ScrollBarVariant ); + } + CFRelease(AppleScrollBarType); + } + + GetSalData()->mbIsScrollbarDoubleMax = bIsScrollbarDoubleMax; + + CFStringRef jumpScroll = CFSTR("AppleScrollerPagingBehavior"); + if( jumpScroll ) + { + CFBooleanRef jumpStr = ((CFBooleanRef)CFPreferencesCopyAppValue( jumpScroll, kCFPreferencesCurrentApplication )); + if( jumpStr ) + { + if( CFGetTypeID( jumpStr ) == CFBooleanGetTypeID() ) + rSettings.SetPrimaryButtonWarpsSlider(jumpStr == kCFBooleanTrue); + CFRelease( jumpStr ); + } + CFRelease( jumpScroll ); + } +} + +static Color getColor( NSColor* pSysColor, const Color& rDefault, NSWindow* pWin ) +{ + Color aRet( rDefault ); + if( pSysColor ) + { + // transform to RGB + NSColor* pRBGColor = [pSysColor colorUsingColorSpaceName: NSDeviceRGBColorSpace device: [pWin deviceDescription]]; + if( pRBGColor ) + { + CGFloat r = 0, g = 0, b = 0, a = 0; + [pRBGColor getRed: &r green: &g blue: &b alpha: &a]; + aRet = Color( int(r*255.999), int(g*255.999), int(b*255.999) ); + /* + do not release here; leads to duplicate free in yield + it seems the converted color comes out autoreleased, although this + is not documented + [pRBGColor release]; + */ + } + } + return aRet; +} + +static Font getFont( NSFont* pFont, long nDPIY, const Font& rDefault ) +{ + Font aResult( rDefault ); + if( pFont ) + { + aResult.SetName( GetOUString( [pFont familyName] ) ); + aResult.SetHeight( static_cast(([pFont pointSize] * 72.0 / (float)nDPIY)+0.5) ); + aResult.SetItalic( ([pFont italicAngle] != 0.0) ? ITALIC_NORMAL : ITALIC_NONE ); + // FIMXE: bold ? + } + + return aResult; +} + +void AquaSalFrame::getResolution( sal_Int32& o_rDPIX, sal_Int32& o_rDPIY ) +{ + if( ! mpGraphics ) + { + GetGraphics(); + ReleaseGraphics( mpGraphics ); + } + mpGraphics->GetResolution( o_rDPIX, o_rDPIY ); +} + +// on OSX-Aqua the style settings are independent of the frame, so it does +// not really belong here. Since the connection to the Appearance_Manager +// is currently done in salnativewidgets.cxx this would be a good place. +// On the other hand VCL's platform independent code currently only asks +// SalFrames for system settings anyway, so moving the code somewhere else +// doesn't make the anything cleaner for now +void AquaSalFrame::UpdateSettings( AllSettings& rSettings ) +{ + if ( !mpNSWindow ) + return; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + [mpNSView lockFocus]; + + StyleSettings aStyleSettings = rSettings.GetStyleSettings(); + + // Background Color + Color aBackgroundColor = Color( 0xEC, 0xEC, 0xEC ); + aStyleSettings.Set3DColors( aBackgroundColor ); + aStyleSettings.SetFaceColor( aBackgroundColor ); + Color aInactiveTabColor( aBackgroundColor ); + aInactiveTabColor.DecreaseLuminance( 32 ); + aStyleSettings.SetInactiveTabColor( aInactiveTabColor ); + + aStyleSettings.SetDialogColor( aBackgroundColor ); + aStyleSettings.SetLightBorderColor( aBackgroundColor ); + Color aShadowColor( aStyleSettings.GetShadowColor() ); + aShadowColor.IncreaseLuminance( 32 ); + aStyleSettings.SetShadowColor( aShadowColor ); + + // get the system font settings + Font aAppFont = aStyleSettings.GetAppFont(); + sal_Int32 nDPIX = 72, nDPIY = 72; + getResolution( nDPIX, nDPIY ); + aAppFont = getFont( [NSFont systemFontOfSize: 0], nDPIY, aAppFont ); + + aStyleSettings.SetToolbarIconSize( STYLE_TOOLBAR_ICONSIZE_LARGE ); + + // TODO: better mapping of OS X<->LibreOffice font settings + aStyleSettings.SetAppFont( aAppFont ); + aStyleSettings.SetHelpFont( aAppFont ); + aStyleSettings.SetPushButtonFont( aAppFont ); + + Font aTitleFont( getFont( [NSFont titleBarFontOfSize: 0], nDPIY, aAppFont ) ); + aStyleSettings.SetTitleFont( aTitleFont ); + aStyleSettings.SetFloatTitleFont( aTitleFont ); + + Font aMenuFont( getFont( [NSFont menuFontOfSize: 0], nDPIY, aAppFont ) ); + aStyleSettings.SetMenuFont( aMenuFont ); + + aStyleSettings.SetToolFont( aAppFont ); + + Font aLabelFont( getFont( [NSFont labelFontOfSize: 0], nDPIY, aAppFont ) ); + aStyleSettings.SetLabelFont( aLabelFont ); + aStyleSettings.SetInfoFont( aLabelFont ); + aStyleSettings.SetRadioCheckFont( aLabelFont ); + aStyleSettings.SetFieldFont( aLabelFont ); + aStyleSettings.SetGroupFont( aLabelFont ); + aStyleSettings.SetIconFont( aLabelFont ); + + Color aHighlightColor( getColor( [NSColor selectedTextBackgroundColor], + aStyleSettings.GetHighlightColor(), mpNSWindow ) ); + aStyleSettings.SetHighlightColor( aHighlightColor ); + Color aHighlightTextColor( getColor( [NSColor selectedTextColor], + aStyleSettings.GetHighlightTextColor(), mpNSWindow ) ); + aStyleSettings.SetHighlightTextColor( aHighlightTextColor ); + + Color aMenuHighlightColor( getColor( [NSColor selectedMenuItemColor], + aStyleSettings.GetMenuHighlightColor(), mpNSWindow ) ); + aStyleSettings.SetMenuHighlightColor( aMenuHighlightColor ); + Color aMenuHighlightTextColor( getColor( [NSColor selectedMenuItemTextColor], + aStyleSettings.GetMenuHighlightTextColor(), mpNSWindow ) ); + aStyleSettings.SetMenuHighlightTextColor( aMenuHighlightTextColor ); + + aStyleSettings.SetMenuColor( aBackgroundColor ); + Color aMenuTextColor( getColor( [NSColor textColor], + aStyleSettings.GetMenuTextColor(), mpNSWindow ) ); + aStyleSettings.SetMenuTextColor( aMenuTextColor ); + aStyleSettings.SetMenuBarTextColor( aMenuTextColor ); + aStyleSettings.SetMenuBarRolloverTextColor( aMenuTextColor ); + + aStyleSettings.SetCursorBlinkTime( 500 ); + + // no mnemonics on OS X + aStyleSettings.SetOptions( aStyleSettings.GetOptions() | STYLE_OPTION_NOMNEMONICS ); + + getAppleScrollBarVariant(aStyleSettings); + + // set scrollbar size + aStyleSettings.SetScrollBarSize( static_cast([NSScroller scrollerWidth]) ); + + // images in menus false for MacOSX + aStyleSettings.SetPreferredUseImagesInMenus( false ); + aStyleSettings.SetHideDisabledMenuItems( sal_True ); + aStyleSettings.SetAcceleratorsInContextMenus( sal_False ); + + rSettings.SetStyleSettings( aStyleSettings ); + + [mpNSView unlockFocus]; +} + +// ----------------------------------------------------------------------- + +const SystemEnvData* AquaSalFrame::GetSystemData() const +{ + return &maSysData; +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::Beep() +{ + NSBeep(); +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::SetPosSize(long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags) +{ + if ( !mpNSWindow ) + return; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + sal_uInt16 nEvent = 0; + + if( [mpNSWindow isMiniaturized] ) + [mpNSWindow deminiaturize: NSApp]; // expand the window + + if (nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y)) + { + mbPositioned = true; + nEvent = SALEVENT_MOVE; + } + + if (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) + { + mbSized = true; + nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE; + } + + NSRect aFrameRect = [mpNSWindow frame]; + NSRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask]; + + // position is always relative to parent frame + NSRect aParentContentRect; + + if( mpParent ) + { + if( Application::GetSettings().GetLayoutRTL() ) + { + if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 ) + nX = mpParent->maGeometry.nWidth - nWidth-1 - nX; + else + nX = mpParent->maGeometry.nWidth - static_cast( aContentRect.size.width-1) - nX; + } + NSRect aParentFrameRect = [mpParent->mpNSWindow frame]; + aParentContentRect = [NSWindow contentRectForFrameRect: aParentFrameRect styleMask: mpParent->mnStyleMask]; + } + else + aParentContentRect = maScreenRect; // use screen if no parent + + CocoaToVCL( aContentRect ); + CocoaToVCL( aParentContentRect ); + + bool bPaint = false; + if( (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) != 0 ) + { + if( nWidth != aContentRect.size.width || nHeight != aContentRect.size.height ) + bPaint = true; + } + + // use old window pos if no new pos requested + if( (nFlags & SAL_FRAME_POSSIZE_X) != 0 ) + aContentRect.origin.x = nX + aParentContentRect.origin.x; + if( (nFlags & SAL_FRAME_POSSIZE_Y) != 0) + aContentRect.origin.y = nY + aParentContentRect.origin.y; + + // use old size if no new size requested + if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 ) + aContentRect.size.width = nWidth; + if( (nFlags & SAL_FRAME_POSSIZE_HEIGHT) != 0) + aContentRect.size.height = nHeight; + + VCLToCocoa( aContentRect ); + + // do not display yet, we need to update our backbuffer + { + [mpNSWindow setFrame: [NSWindow frameRectForContentRect: aContentRect styleMask: mnStyleMask] display: NO]; + } + + UpdateFrameGeometry(); + + if (nEvent) + CallCallback(nEvent, NULL); + + if( mbShown && bPaint ) + { + // trigger filling our backbuffer + SendPaintEvent(); + + // now inform the system that the views need to be drawn + [mpNSWindow display]; + } +} + +void AquaSalFrame::GetWorkArea( Rectangle& rRect ) +{ + if ( !mpNSWindow ) + return; + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + NSScreen* pScreen = [mpNSWindow screen]; + if( pScreen == nil ) + pScreen = [NSScreen mainScreen]; + NSRect aRect = [pScreen visibleFrame]; + CocoaToVCL( aRect ); + rRect.Left() = static_cast(aRect.origin.x); + rRect.Top() = static_cast(aRect.origin.y); + rRect.Right() = static_cast(aRect.origin.x + aRect.size.width - 1); + rRect.Bottom() = static_cast(aRect.origin.y + aRect.size.height - 1); +} + +SalPointerState AquaSalFrame::GetPointerState() +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + SalPointerState state; + state.mnState = 0; + + // get position + NSPoint aPt = [mpNSWindow mouseLocationOutsideOfEventStream]; + CocoaToVCL( aPt, false ); + state.maPos = Point(static_cast(aPt.x), static_cast(aPt.y)); + + NSEvent* pCur = [NSApp currentEvent]; + bool bMouseEvent = false; + if( pCur ) + { + bMouseEvent = true; + switch( [pCur type] ) + { + case NSLeftMouseDown: state.mnState |= MOUSE_LEFT; break; + case NSLeftMouseUp: break; + case NSRightMouseDown: state.mnState |= MOUSE_RIGHT; break; + case NSRightMouseUp: break; + case NSOtherMouseDown: state.mnState |= ([pCur buttonNumber] == 2) ? MOUSE_MIDDLE : 0; break; + case NSOtherMouseUp: break; + case NSMouseMoved: break; + case NSLeftMouseDragged: state.mnState |= MOUSE_LEFT; break; + case NSRightMouseDragged: state.mnState |= MOUSE_RIGHT; break; + case NSOtherMouseDragged: state.mnState |= ([pCur buttonNumber] == 2) ? MOUSE_MIDDLE : 0; break; + break; + default: + bMouseEvent = false; + break; + } + } + if( bMouseEvent ) + { + unsigned int nMask = (unsigned int)[pCur modifierFlags]; + if( (nMask & NSShiftKeyMask) != 0 ) + state.mnState |= KEY_SHIFT; + if( (nMask & NSControlKeyMask) != 0 ) + state.mnState |= KEY_MOD3; + if( (nMask & NSAlternateKeyMask) != 0 ) + state.mnState |= KEY_MOD2; + if( (nMask & NSCommandKeyMask) != 0 ) + state.mnState |= KEY_MOD1; + + } + else + { + // FIXME: replace Carbon by Cocoa + // Cocoa does not have an equivalent for GetCurrentEventButtonState + // and GetCurrentEventKeyModifiers. + // we could try to get away with tracking all events for modifierKeys + // and all mouse events for button state in VCL_NSApllication::sendEvent, + // but it is unclear whether this will get us the same result. + // leave in GetCurrentEventButtonState and GetCurrentEventKeyModifiers for now + + // fill in button state + UInt32 nState = GetCurrentEventButtonState(); + state.mnState = 0; + if( nState & 1 ) + state.mnState |= MOUSE_LEFT; // primary button + if( nState & 2 ) + state.mnState |= MOUSE_RIGHT; // secondary button + if( nState & 4 ) + state.mnState |= MOUSE_MIDDLE; // tertiary button + + // fill in modifier state + nState = GetCurrentEventKeyModifiers(); + if( nState & shiftKey ) + state.mnState |= KEY_SHIFT; + if( nState & controlKey ) + state.mnState |= KEY_MOD3; + if( nState & optionKey ) + state.mnState |= KEY_MOD2; + if( nState & cmdKey ) + state.mnState |= KEY_MOD1; + } + + + return state; +} + +SalFrame::SalIndicatorState AquaSalFrame::GetIndicatorState() +{ + SalIndicatorState aState; + aState.mnState = 0; + return aState; +} + +void AquaSalFrame::SimulateKeyPress( sal_uInt16 /*nKeyCode*/ ) +{ +} + +bool AquaSalFrame::SetPluginParent( SystemParentData* ) +{ + // plugin parent may be killed unexpectedly by + // plugging process; + + //TODO: implement + return sal_False; +} + +sal_Bool AquaSalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , KeyCode& ) +{ + // not supported yet + return FALSE; +} + +LanguageType AquaSalFrame::GetInputLanguage() +{ + //TODO: implement + return LANGUAGE_DONTKNOW; +} + +void AquaSalFrame::DrawMenuBar() +{ +} + +void AquaSalFrame::SetMenu( SalMenu* pSalMenu ) +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + AquaSalMenu* pMenu = static_cast(pSalMenu); + DBG_ASSERT( ! pMenu || pMenu->mbMenuBar, "setting non menubar on frame" ); + mpMenu = pMenu; + if( mpMenu ) + mpMenu->setMainMenu(); +} + +void AquaSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle ) +{ + if ( mpNSWindow ) + { + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + if( (mnExtStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) != (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) ) + [mpNSWindow setDocumentEdited: (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) ? YES : NO]; + } + + mnExtStyle = nStyle; +} + +SalFrame* AquaSalFrame::GetParent() const +{ + return mpParent; +} + +void AquaSalFrame::SetParent( SalFrame* pNewParent ) +{ + bool bShown = mbShown; + // remove from child list + Show( FALSE ); + mpParent = (AquaSalFrame*)pNewParent; + // insert to correct parent and paint + Show( bShown ); +} + +void AquaSalFrame::UpdateFrameGeometry() +{ + if ( !mpNSWindow ) + { + return; + } + + // keep in mind that view and window coordinates are lower left + // whereas vcl's are upper left + + // update screen rect + NSScreen * pScreen = [mpNSWindow screen]; + if( pScreen ) + { + maScreenRect = [pScreen frame]; + NSArray* pScreens = [NSScreen screens]; + if( pScreens ) + maGeometry.nDisplayScreenNumber = [pScreens indexOfObject: pScreen]; + } + + NSRect aFrameRect = [mpNSWindow frame]; + NSRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask]; + + // release old track rect + [mpNSView removeTrackingRect: mnTrackingRectTag]; + // install the new track rect + NSRect aTrackRect = { { 0, 0 }, aContentRect.size }; + mnTrackingRectTag = [mpNSView addTrackingRect: aTrackRect owner: mpNSView userData: nil assumeInside: NO]; + + // convert to vcl convention + CocoaToVCL( aFrameRect ); + CocoaToVCL( aContentRect ); + + maGeometry.nX = static_cast(aContentRect.origin.x); + maGeometry.nY = static_cast(aContentRect.origin.y); + + maGeometry.nLeftDecoration = static_cast(aContentRect.origin.x - aFrameRect.origin.x); + maGeometry.nRightDecoration = static_cast((aFrameRect.origin.x + aFrameRect.size.width) - + (aContentRect.origin.x + aContentRect.size.width)); + + maGeometry.nTopDecoration = static_cast(aContentRect.origin.y - aFrameRect.origin.y); + maGeometry.nBottomDecoration = static_cast((aFrameRect.origin.y + aFrameRect.size.height) - + (aContentRect.origin.y + aContentRect.size.height)); + + maGeometry.nWidth = static_cast(aContentRect.size.width); + maGeometry.nHeight = static_cast(aContentRect.size.height); +} + +// ----------------------------------------------------------------------- + +void AquaSalFrame::CaptureMouse( sal_Bool bCapture ) +{ + /* Remark: + we'll try to use a pidgin version of capture mouse + on MacOSX (neither carbon nor cocoa) there is a + CaptureMouse equivalent (in Carbon there is TrackMouseLocation + but this is useless to use since it is blocking) + + However on cocoa the active frame seems to get mouse events + also outside the window, so we'll try to forward mouse events + to the capture frame in the hope that one of our frames + gets a mouse event. + + This will break as soon as the user activates another app, but + a mouse click will normally lead to a release of the mouse anyway. + + Let's see how far we get this way. Alternatively we could use one + large overlay window like we did for the carbon implementation, + however that is resource intensive. + */ + + if( bCapture ) + s_pCaptureFrame = this; + else if( ! bCapture && s_pCaptureFrame == this ) + s_pCaptureFrame = NULL; +} + +void AquaSalFrame::ResetClipRegion() +{ + if ( !mpNSWindow ) + { + return; + } + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + // release old path and indicate no clipping + CGPathRelease( mrClippingPath ); + mrClippingPath = NULL; + + if( mpNSView && mbShown ) + [mpNSView setNeedsDisplay: YES]; + if( mpNSWindow ) + { + [mpNSWindow setOpaque: YES]; + [mpNSWindow invalidateShadow]; + } +} + +void AquaSalFrame::BeginSetClipRegion( sal_uLong nRects ) +{ + if ( !mpNSWindow ) + { + return; + } + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + // release old path + if( mrClippingPath ) + { + CGPathRelease( mrClippingPath ); + mrClippingPath = NULL; + } + + if( maClippingRects.size() > SAL_CLIPRECT_COUNT && nRects < maClippingRects.size() ) + { + std::vector aEmptyVec; + maClippingRects.swap( aEmptyVec ); + } + maClippingRects.clear(); + maClippingRects.reserve( nRects ); +} + +void AquaSalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + if( nWidth && nHeight ) + { + NSRect aRect = { { static_cast(nX), static_cast(nY) }, { static_cast(nWidth), static_cast(nHeight) } }; + VCLToCocoa( aRect, false ); + maClippingRects.push_back( CGRectMake(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height) ); + } +} + +void AquaSalFrame::EndSetClipRegion() +{ + if ( !mpNSWindow ) + { + return; + } + + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + if( ! maClippingRects.empty() ) + { + mrClippingPath = CGPathCreateMutable(); + CGPathAddRects( mrClippingPath, NULL, &maClippingRects[0], maClippingRects.size() ); + } + if( mpNSView && mbShown ) + [mpNSView setNeedsDisplay: YES]; + if( mpNSWindow ) + { + [mpNSWindow setOpaque: (mrClippingPath != NULL) ? NO : YES]; + [mpNSWindow setBackgroundColor: [NSColor clearColor]]; + // shadow is invalidated when view gets drawn again + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm new file mode 100644 index 000000000000..81ae1cdce8c3 --- /dev/null +++ b/vcl/osx/salframeview.mm @@ -0,0 +1,1805 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include "tools/helpers.hxx" +#include "vcl/window.hxx" +#include "vcl/svapp.hxx" + +#include "osx/salinst.h" +#include "quartz/salgdi.h" +#include "osx/salframe.h" +#include "osx/salframeview.h" +#include "osx/a11yfactory.h" +#include "quartz/utils.h" + +#define WHEEL_EVENT_FACTOR 1.5 + +// for allowing fullscreen support on deployment targets < OSX 10.7 +#if !defined(MAC_OS_X_VERSION_10_7) + #define NSWindowCollectionBehaviorFullScreenPrimary (1 << 7) + #define NSWindowCollectionBehaviorFullScreenAuxiliary (1 << 8) +// #define NSFullScreenWindowMask (1 << 14) +#endif + + +static sal_uInt16 ImplGetModifierMask( unsigned int nMask ) +{ + sal_uInt16 nRet = 0; + if( (nMask & NSShiftKeyMask) != 0 ) + nRet |= KEY_SHIFT; + if( (nMask & NSControlKeyMask) != 0 ) + nRet |= KEY_MOD3; + if( (nMask & NSAlternateKeyMask) != 0 ) + nRet |= KEY_MOD2; + if( (nMask & NSCommandKeyMask) != 0 ) + nRet |= KEY_MOD1; + return nRet; +} + +static sal_uInt16 ImplMapCharCode( sal_Unicode aCode ) +{ + static sal_uInt16 aKeyCodeMap[ 128 ] = + { + 0, 0, 0, 0, 0, 0, 0, 0, + KEY_BACKSPACE, KEY_TAB, KEY_RETURN, 0, 0, KEY_RETURN, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, KEY_TAB, 0, KEY_ESCAPE, 0, 0, 0, 0, + KEY_SPACE, 0, 0, 0, 0, 0, 0, 0, + 0, 0, KEY_MULTIPLY, KEY_ADD, KEY_COMMA, KEY_SUBTRACT, KEY_POINT, KEY_DIVIDE, + KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, + KEY_8, KEY_9, 0, 0, KEY_LESS, KEY_EQUAL, KEY_GREATER, 0, + 0, KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, + KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, + KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, + KEY_X, KEY_Y, KEY_Z, 0, 0, 0, 0, 0, + KEY_QUOTELEFT, KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, + KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, + KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, + KEY_X, KEY_Y, KEY_Z, 0, 0, 0, KEY_TILDE, KEY_BACKSPACE + }; + + // Note: the mapping 0x7f should by rights be KEY_DELETE + // however if you press "backspace" 0x7f is reported + // whereas for "delete" 0xf728 gets reported + + // Note: the mapping of 0x19 to KEY_TAB is because for unknown reasons + // tab alone is reported as 0x09 (as expected) but shift-tab is + // reported as 0x19 (end of medium) + + static sal_uInt16 aFunctionKeyCodeMap[ 128 ] = + { + KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_F1, KEY_F2, KEY_F3, KEY_F4, + KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, + KEY_F13, KEY_F14, KEY_F15, KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20, + KEY_F21, KEY_F22, KEY_F23, KEY_F24, KEY_F25, KEY_F26, 0, 0, + 0, 0, 0, 0, 0, 0, 0, KEY_INSERT, + KEY_DELETE, KEY_HOME, 0, KEY_END, KEY_PAGEUP, KEY_PAGEDOWN, 0, 0, + 0, 0, 0, 0, 0, KEY_MENU, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, KEY_UNDO, KEY_REPEAT, KEY_FIND, KEY_HELP, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + }; + + sal_uInt16 nKeyCode = 0; + if( aCode < SAL_N_ELEMENTS( aKeyCodeMap) ) + nKeyCode = aKeyCodeMap[ aCode ]; + else if( aCode >= 0xf700 && aCode < 0xf780 ) + nKeyCode = aFunctionKeyCodeMap[ aCode - 0xf700 ]; + return nKeyCode; +} + +static sal_uInt16 ImplMapKeyCode(sal_uInt16 nKeyCode) +{ + /* + http://stackoverflow.com/questions/2080312/where-can-i-find-a-list-of-key-codes-for-use-with-cocoas-nsevent-class/2080324#2080324 + /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h + */ + + static sal_uInt16 aKeyCodeMap[ 0x80 ] = + { + KEY_A, KEY_S, KEY_D, KEY_F, KEY_H, KEY_G, KEY_Z, KEY_X, + KEY_C, KEY_V, 0, KEY_B, KEY_Q, KEY_W, KEY_E, KEY_R, + KEY_Y, KEY_T, KEY_1, KEY_2, KEY_3, KEY_4, KEY_6, KEY_5, + KEY_EQUAL, KEY_9, KEY_7, KEY_SUBTRACT, KEY_8, KEY_0, KEY_BRACKETRIGHT, KEY_0, + KEY_U, KEY_BRACKETLEFT, KEY_I, KEY_P, KEY_RETURN, KEY_L, KEY_J, KEY_QUOTELEFT, + KEY_K, KEY_SEMICOLON, 0, KEY_COMMA, KEY_DIVIDE, KEY_N, KEY_M, KEY_POINT, + KEY_TAB, KEY_SPACE, KEY_TILDE, KEY_DELETE, 0, KEY_ESCAPE, 0, 0, + 0, KEY_CAPSLOCK, 0, 0, 0, 0, 0, 0, + KEY_F17, KEY_DECIMAL, 0, KEY_MULTIPLY, 0, KEY_ADD, 0, 0, + 0, 0, 0, KEY_DIVIDE, KEY_RETURN, 0, KEY_SUBTRACT, KEY_F18, + KEY_F19, KEY_EQUAL, 0, 0, 0, 0, 0, 0, + 0, 0, KEY_F20, 0, 0, 0, 0, 0, + KEY_F5, KEY_F6, KEY_F7, KEY_F3, KEY_F8, KEY_F9, 0, KEY_F11, + 0, KEY_F13, KEY_F16, KEY_F14, 0, KEY_F10, 0, KEY_F12, + 0, KEY_F15, KEY_HELP, KEY_HOME, KEY_PAGEUP, KEY_DELETE, KEY_F4, KEY_END, + KEY_F2, KEY_PAGEDOWN, KEY_F1, KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_UP, 0 + }; + + if (nKeyCode < SAL_N_ELEMENTS(aKeyCodeMap)) + return aKeyCodeMap[nKeyCode]; + return 0; +} + +// store the frame the mouse last entered +static AquaSalFrame* s_pMouseFrame = NULL; +// store the last pressed button for enter/exit events +// which lack that information +static sal_uInt16 s_nLastButton = 0; + +// combinations of keys we need to handle ourselves +static const struct ExceptionalKey +{ + const sal_uInt16 nKeyCode; + const unsigned int nModifierMask; +} aExceptionalKeys[] = +{ + { KEY_D, NSControlKeyMask | NSShiftKeyMask | NSAlternateKeyMask }, + { KEY_D, NSCommandKeyMask | NSShiftKeyMask | NSAlternateKeyMask } +}; + +static AquaSalFrame* getMouseContainerFrame() +{ + NSInteger nWindows = 0; + NSCountWindows( &nWindows ); + NSInteger* pWindows = (NSInteger*)alloca( nWindows * sizeof(NSInteger) ); + // note: NSWindowList is supposed to be in z-order front to back + NSWindowList( nWindows, pWindows ); + AquaSalFrame* pDispatchFrame = NULL; + for(int i = 0; i < nWindows && ! pDispatchFrame; i++ ) + { + NSWindow* pWin = [NSApp windowWithWindowNumber: pWindows[i]]; + if( pWin && [pWin isMemberOfClass: [SalFrameWindow class]] && [(SalFrameWindow*)pWin containsMouse] ) + pDispatchFrame = [(SalFrameWindow*)pWin getSalFrame]; + } + return pDispatchFrame; +} + +@implementation SalFrameWindow +-(id)initWithSalFrame: (AquaSalFrame*)pFrame +{ + mDraggingDestinationHandler = nil; + mpFrame = pFrame; + NSRect aRect = { { static_cast(pFrame->maGeometry.nX), static_cast(pFrame->maGeometry.nY) }, + { static_cast(pFrame->maGeometry.nWidth), static_cast(pFrame->maGeometry.nHeight) } }; + pFrame->VCLToCocoa( aRect ); + NSWindow* pNSWindow = [super initWithContentRect: aRect styleMask: mpFrame->getStyleMask() backing: NSBackingStoreBuffered defer: NO ]; + [pNSWindow useOptimizedDrawing: YES]; // OSX recommendation when there are no overlapping subviews within the receiver + + // enable OSX>=10.7 fullscreen options if available and useful + bool bAllowFullScreen = (0 == (mpFrame->mnStyle & (SAL_FRAME_STYLE_DIALOG | SAL_FRAME_STYLE_TOOLTIP | SAL_FRAME_STYLE_SYSTEMCHILD | SAL_FRAME_STYLE_FLOAT | SAL_FRAME_STYLE_TOOLWINDOW | SAL_FRAME_STYLE_INTRO))); + bAllowFullScreen &= (0 == (~mpFrame->mnStyle & (SAL_FRAME_STYLE_SIZEABLE))); + bAllowFullScreen &= (mpFrame->mpParent == NULL); + const SEL setCollectionBehavior = @selector(setCollectionBehavior:); + if( bAllowFullScreen && [pNSWindow respondsToSelector: setCollectionBehavior]) + { + const int bMode= (bAllowFullScreen ? NSWindowCollectionBehaviorFullScreenPrimary : NSWindowCollectionBehaviorFullScreenAuxiliary); + [pNSWindow performSelector:setCollectionBehavior withObject:(id)(intptr_t)bMode]; + } + + // disable OSX>=10.7 window restoration until we support it directly + const SEL setRestorable = @selector(setRestorable:); + if( [pNSWindow respondsToSelector: setRestorable]) { + [pNSWindow performSelector:setRestorable withObject:(id)NO]; + } + + return (SalFrameWindow *) pNSWindow; +} + +-(AquaSalFrame*)getSalFrame +{ + return mpFrame; +} + +-(void)displayIfNeeded +{ + if( GetSalData() && GetSalData()->mpFirstInstance ) + { + comphelper::SolarMutex* pMutex = GetSalData()->mpFirstInstance->GetYieldMutex(); + if( pMutex ) + { + pMutex->acquire(); + [super displayIfNeeded]; + pMutex->release(); + } + } +} + +-(BOOL)containsMouse +{ + // is this event actually inside that NSWindow ? + NSPoint aPt = [NSEvent mouseLocation]; + NSRect aFrameRect = [self frame]; + BOOL bInRect = NSPointInRect( aPt, aFrameRect ); + return bInRect; +} + +-(BOOL)canBecomeKeyWindow +{ + if( (mpFrame->mnStyle & + ( SAL_FRAME_STYLE_FLOAT | + SAL_FRAME_STYLE_TOOLTIP | + SAL_FRAME_STYLE_INTRO + )) == 0 ) + return YES; + if( (mpFrame->mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) != 0 ) + return YES; + if( mpFrame->mbFullScreen ) + return YES; + if( (mpFrame->mnStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) ) + return YES; + return [super canBecomeKeyWindow]; +} + +-(void)windowDidBecomeKey: (NSNotification*)pNotification +{ + (void)pNotification; + YIELD_GUARD; + + if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) + { + static const sal_uLong nGuessDocument = SAL_FRAME_STYLE_MOVEABLE| + SAL_FRAME_STYLE_SIZEABLE| + SAL_FRAME_STYLE_CLOSEABLE; + + if( mpFrame->mpMenu ) + mpFrame->mpMenu->setMainMenu(); + else if( ! mpFrame->mpParent && + ( (mpFrame->mnStyle & nGuessDocument) == nGuessDocument || // set default menu for e.g. help + mpFrame->mbFullScreen ) ) // ser default menu for e.g. presentation + { + AquaSalMenu::setDefaultMenu(); + } + #if 0 + // FIXME: we should disable menus while in modal mode + // however from down here there is currently no reliable way to + // find out when to do this + if( (mpFrame->mpParent && mpFrame->mpParent->GetWindow()->IsInModalMode()) ) + AquaSalMenu::enableMainMenu( false ); + #endif + mpFrame->CallCallback( SALEVENT_GETFOCUS, 0 ); + mpFrame->SendPaintEvent(); // repaint controls as active + } +} + +-(void)windowDidResignKey: (NSNotification*)pNotification +{ + (void)pNotification; + YIELD_GUARD; + + if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) + { + mpFrame->CallCallback(SALEVENT_LOSEFOCUS, 0); + mpFrame->SendPaintEvent(); // repaint controls as inactive + } +} + +-(void)windowDidChangeScreen: (NSNotification*)pNotification +{ + (void)pNotification; + YIELD_GUARD; + + if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) + mpFrame->screenParametersChanged(); +} + +-(void)windowDidMove: (NSNotification*)pNotification +{ + (void)pNotification; + YIELD_GUARD; + + if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) + { + mpFrame->UpdateFrameGeometry(); + mpFrame->CallCallback( SALEVENT_MOVE, 0 ); + } +} + +-(void)windowDidResize: (NSNotification*)pNotification +{ + (void)pNotification; + YIELD_GUARD; + + if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) + { + mpFrame->UpdateFrameGeometry(); + mpFrame->CallCallback( SALEVENT_RESIZE, 0 ); + mpFrame->SendPaintEvent(); + } +} + +-(void)windowDidMiniaturize: (NSNotification*)pNotification +{ + (void)pNotification; + YIELD_GUARD; + + if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) + { + mpFrame->mbShown = false; + mpFrame->UpdateFrameGeometry(); + mpFrame->CallCallback( SALEVENT_RESIZE, 0 ); + } +} + +-(void)windowDidDeminiaturize: (NSNotification*)pNotification +{ + (void)pNotification; + YIELD_GUARD; + + if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) + { + mpFrame->mbShown = true; + mpFrame->UpdateFrameGeometry(); + mpFrame->CallCallback( SALEVENT_RESIZE, 0 ); + } +} + +-(BOOL)windowShouldClose: (NSNotification*)pNotification +{ + (void)pNotification; + YIELD_GUARD; + + BOOL bRet = YES; + if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) + { + // #i84461# end possible input + mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 ); + if( AquaSalFrame::isAlive( mpFrame ) ) + { + mpFrame->CallCallback( SALEVENT_CLOSE, 0 ); + bRet = NO; // application will close the window or not, AppKit shouldn't + } + } + + return bRet; +} + +-(void)windowDidEnterFullScreen: (NSNotification*)pNotification +{ + YIELD_GUARD; + + if( !mpFrame || !AquaSalFrame::isAlive( mpFrame)) + return; + mpFrame->mbFullScreen = true; + (void)pNotification; +} + +-(void)windowDidExitFullScreen: (NSNotification*)pNotification +{ + YIELD_GUARD; + + if( !mpFrame || !AquaSalFrame::isAlive( mpFrame)) + return; + mpFrame->mbFullScreen = false; + (void)pNotification; +} + +-(void)dockMenuItemTriggered: (id)sender +{ + (void)sender; + YIELD_GUARD; + + if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) + mpFrame->ToTop( SAL_FRAME_TOTOP_RESTOREWHENMIN | SAL_FRAME_TOTOP_GRABFOCUS ); +} + +-(::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >)accessibleContext +{ + return mpFrame -> GetWindow() -> GetAccessible() -> getAccessibleContext(); +} + +-(NSDragOperation)draggingEntered:(id )sender +{ + return [mDraggingDestinationHandler draggingEntered: sender]; +} + +-(NSDragOperation)draggingUpdated:(id )sender +{ + return [mDraggingDestinationHandler draggingUpdated: sender]; +} + +-(void)draggingExited:(id )sender +{ + [mDraggingDestinationHandler draggingExited: sender]; +} + +-(BOOL)prepareForDragOperation:(id )sender +{ + return [mDraggingDestinationHandler prepareForDragOperation: sender]; +} + +-(BOOL)performDragOperation:(id )sender +{ + return [mDraggingDestinationHandler performDragOperation: sender]; +} + +-(void)concludeDragOperation:(id )sender +{ + [mDraggingDestinationHandler concludeDragOperation: sender]; +} + +-(void)registerDraggingDestinationHandler:(id)theHandler +{ + mDraggingDestinationHandler = theHandler; +} + +-(void)unregisterDraggingDestinationHandler:(id)theHandler +{ + (void)theHandler; + mDraggingDestinationHandler = nil; +} + +@end + +@implementation SalFrameView ++(void)unsetMouseFrame: (AquaSalFrame*)pFrame +{ + if( pFrame == s_pMouseFrame ) + s_pMouseFrame = NULL; +} + +-(id)initWithSalFrame: (AquaSalFrame*)pFrame +{ + if ((self = [super initWithFrame: [NSWindow contentRectForFrameRect: [pFrame->getNSWindow() frame] styleMask: pFrame->mnStyleMask]]) != nil) + { + mDraggingDestinationHandler = nil; + mpFrame = pFrame; + mMarkedRange = NSMakeRange(NSNotFound, 0); + mSelectedRange = NSMakeRange(NSNotFound, 0); + mpReferenceWrapper = nil; + mpMouseEventListener = nil; + mpLastSuperEvent = nil; + } + + mfLastMagnifyTime = 0.0; + return self; +} + +-(AquaSalFrame*)getSalFrame +{ + return mpFrame; +} + +-(void)resetCursorRects +{ + if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) + { + // FIXME: does this leak the returned NSCursor of getCurrentCursor ? + NSRect aRect = { { 0, 0 }, { static_cast(mpFrame->maGeometry.nWidth), static_cast(mpFrame->maGeometry.nHeight) } }; + [self addCursorRect: aRect cursor: mpFrame->getCurrentCursor()]; + } +} + +-(BOOL)acceptsFirstResponder +{ + return YES; +} + +-(BOOL)acceptsFirstMouse: (NSEvent*)pEvent +{ + (void)pEvent; + return YES; +} + +-(BOOL)isOpaque +{ + if( !mpFrame) + return YES; + if( !AquaSalFrame::isAlive( mpFrame)) + return YES; + if( !mpFrame->getClipPath()) + return YES; + return NO; +} + +// helper class similar to a osl::Guard< comphelper::SolarMutex > for the +// SalYieldMutex; the difference is that it only does tryToAcquire instead of +// acquire so dreaded deadlocks like #i93512# are prevented +class TryGuard +{ +public: + TryGuard() { mbGuarded = ImplSalYieldMutexTryToAcquire(); } + ~TryGuard() { if( mbGuarded ) ImplSalYieldMutexRelease(); } + bool IsGuarded() { return mbGuarded; } +private: + bool mbGuarded; +}; + +-(void)drawRect: (NSRect)aRect +{ + // HOTFIX: #i93512# prevent deadlocks if any other thread already has the SalYieldMutex + TryGuard aTryGuard; + if( !aTryGuard.IsGuarded() ) + { + // NOTE: the mpFrame access below is not guarded yet! + // TODO: mpFrame et al need to be guarded by an independent mutex + AquaSalGraphics* pGraphics = (mpFrame && AquaSalFrame::isAlive(mpFrame)) ? mpFrame->mpGraphics : NULL; + if( pGraphics ) + { + // we did not get the mutex so we cannot draw now => request to redraw later + // convert the NSRect to a CGRect for Refreshrect() + const CGRect aCGRect = {{aRect.origin.x,aRect.origin.y},{aRect.size.width,aRect.size.height}}; + pGraphics->RefreshRect( aCGRect ); + } + return; + } + + if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) + { + if( mpFrame->mpGraphics ) + { + mpFrame->mpGraphics->UpdateWindow( aRect ); + if( mpFrame->getClipPath() ) + [mpFrame->getNSWindow() invalidateShadow]; + } + } +} + +-(void)sendMouseEventToFrame: (NSEvent*)pEvent button:(sal_uInt16)nButton eventtype:(sal_uInt16)nEvent +{ + YIELD_GUARD; + + AquaSalFrame* pDispatchFrame = AquaSalFrame::GetCaptureFrame(); + bool bIsCaptured = false; + if( pDispatchFrame ) + { + bIsCaptured = true; + if( nEvent == SALEVENT_MOUSELEAVE ) // no leave events if mouse is captured + nEvent = SALEVENT_MOUSEMOVE; + } + else if( s_pMouseFrame ) + pDispatchFrame = s_pMouseFrame; + else + pDispatchFrame = mpFrame; + + /* #i81645# Cocoa reports mouse events while a button is pressed + to the window in which it was first pressed. This is reasonable and fine and + gets one around most cases where on other platforms one uses CaptureMouse or XGrabPointer, + however vcl expects mouse events to occur in the window the mouse is over, unless the + mouse is explicitly captured. So we need to find the window the mouse is actually + over for conformance with other platforms. + */ + if( ! bIsCaptured && nButton && pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) ) + { + // is this event actually inside that NSWindow ? + NSPoint aPt = [NSEvent mouseLocation]; + NSRect aFrameRect = [pDispatchFrame->getNSWindow() frame]; + + if ( ! NSPointInRect( aPt, aFrameRect ) ) + { + // no, it is not + // now we need to find the one it may be in + /* #i93756# we ant to get enumerate the application windows in z-order + to check if any contains the mouse. This could be elegantly done with this + code: + + // use NSApp to check windows in ZOrder whether they contain the mouse pointer + NSWindow* pWindow = [NSApp makeWindowsPerform: @selector(containsMouse) inOrder: YES]; + if( pWindow && [pWindow isMemberOfClass: [SalFrameWindow class]] ) + pDispatchFrame = [(SalFrameWindow*)pWindow getSalFrame]; + + However if a non SalFrameWindow is on screen (like e.g. the file dialog) + it can be hit with the containsMouse selector, which it doesn't support. + Sadly NSApplication:makeWindowsPerform does not check (for performance reasons + I assume) whether a window supports a selector before sending it. + */ + AquaSalFrame* pMouseFrame = getMouseContainerFrame(); + if( pMouseFrame ) + pDispatchFrame = pMouseFrame; + } + } + + if( pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) ) + { + pDispatchFrame->mnLastEventTime = static_cast( [pEvent timestamp] * 1000.0 ); + pDispatchFrame->mnLastModifierFlags = [pEvent modifierFlags]; + + NSPoint aPt = [NSEvent mouseLocation]; + pDispatchFrame->CocoaToVCL( aPt ); + + sal_uInt16 nModMask = ImplGetModifierMask( [pEvent modifierFlags] ); + // #i82284# emulate ctrl left + if( nModMask == KEY_MOD3 && nButton == MOUSE_LEFT ) + { + nModMask = 0; + nButton = MOUSE_RIGHT; + } + + SalMouseEvent aEvent; + aEvent.mnTime = pDispatchFrame->mnLastEventTime; + aEvent.mnX = static_cast(aPt.x) - pDispatchFrame->maGeometry.nX; + aEvent.mnY = static_cast(aPt.y) - pDispatchFrame->maGeometry.nY; + aEvent.mnButton = nButton; + aEvent.mnCode = aEvent.mnButton | nModMask; + + // --- RTL --- (mirror mouse pos) + if( Application::GetSettings().GetLayoutRTL() ) + aEvent.mnX = pDispatchFrame->maGeometry.nWidth-1-aEvent.mnX; + + pDispatchFrame->CallCallback( nEvent, &aEvent ); + } +} + +-(void)mouseDown: (NSEvent*)pEvent +{ + if ( mpMouseEventListener != nil && + [mpMouseEventListener respondsToSelector: @selector(mouseDown:)]) + { + [mpMouseEventListener mouseDown: [pEvent copyWithZone: NULL]]; + } + + s_nLastButton = MOUSE_LEFT; + [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEBUTTONDOWN]; +} + +-(void)mouseDragged: (NSEvent*)pEvent +{ + if ( mpMouseEventListener != nil && + [mpMouseEventListener respondsToSelector: @selector(mouseDragged:)]) + { + [mpMouseEventListener mouseDragged: [pEvent copyWithZone: NULL]]; + } + s_nLastButton = MOUSE_LEFT; + [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEMOVE]; +} + +-(void)mouseUp: (NSEvent*)pEvent +{ + s_nLastButton = 0; + [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEBUTTONUP]; +} + +-(void)mouseMoved: (NSEvent*)pEvent +{ + s_nLastButton = 0; + [self sendMouseEventToFrame:pEvent button:0 eventtype:SALEVENT_MOUSEMOVE]; +} + +-(void)mouseEntered: (NSEvent*)pEvent +{ + s_pMouseFrame = mpFrame; + + // #i107215# the only mouse events we get when inactive are enter/exit + // actually we would like to have all of them, but better none than some + if( [NSApp isActive] ) + [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SALEVENT_MOUSEMOVE]; +} + +-(void)mouseExited: (NSEvent*)pEvent +{ + if( s_pMouseFrame == mpFrame ) + s_pMouseFrame = NULL; + + // #i107215# the only mouse events we get when inactive are enter/exit + // actually we would like to have all of them, but better none than some + if( [NSApp isActive] ) + [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SALEVENT_MOUSELEAVE]; +} + +-(void)rightMouseDown: (NSEvent*)pEvent +{ + s_nLastButton = MOUSE_RIGHT; + [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEBUTTONDOWN]; +} + +-(void)rightMouseDragged: (NSEvent*)pEvent +{ + s_nLastButton = MOUSE_RIGHT; + [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEMOVE]; +} + +-(void)rightMouseUp: (NSEvent*)pEvent +{ + s_nLastButton = 0; + [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEBUTTONUP]; +} + +-(void)otherMouseDown: (NSEvent*)pEvent +{ + if( [pEvent buttonNumber] == 2 ) + { + s_nLastButton = MOUSE_MIDDLE; + [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONDOWN]; + } + else + s_nLastButton = 0; +} + +-(void)otherMouseDragged: (NSEvent*)pEvent +{ + if( [pEvent buttonNumber] == 2 ) + { + s_nLastButton = MOUSE_MIDDLE; + [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEMOVE]; + } + else + s_nLastButton = 0; +} + +-(void)otherMouseUp: (NSEvent*)pEvent +{ + s_nLastButton = 0; + if( [pEvent buttonNumber] == 2 ) + [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONUP]; +} + +- (void)magnifyWithEvent: (NSEvent*)pEvent +{ + YIELD_GUARD; + + // TODO: ?? -(float)magnification; + if( AquaSalFrame::isAlive( mpFrame ) ) + { + const NSTimeInterval fMagnifyTime = [pEvent timestamp]; + mpFrame->mnLastEventTime = static_cast( fMagnifyTime * 1000.0 ); + mpFrame->mnLastModifierFlags = [pEvent modifierFlags]; + + // check if this is a new series of magnify events + static const NSTimeInterval fMaxDiffTime = 0.3; + const bool bNewSeries = (fMagnifyTime - mfLastMagnifyTime > fMaxDiffTime); + + if( bNewSeries ) + mfMagnifyDeltaSum = 0.0; + mfMagnifyDeltaSum += [pEvent deltaZ]; + + mfLastMagnifyTime = [pEvent timestamp]; + // TODO: change to 0.1 when COMMAND_WHEEL_ZOOM handlers allow finer zooming control + static const float fMagnifyFactor = 0.25; + static const float fMinMagnifyStep = 15.0 / fMagnifyFactor; + if( fabs(mfMagnifyDeltaSum) <= fMinMagnifyStep ) + return; + + // adapt NSEvent-sensitivity to application expectations + // TODO: rather make COMMAND_WHEEL_ZOOM handlers smarter + const float fDeltaZ = mfMagnifyDeltaSum * fMagnifyFactor; + int nDeltaZ = FRound( fDeltaZ ); + if( !nDeltaZ ) + { + // handle new series immediately + if( !bNewSeries ) + return; + nDeltaZ = (fDeltaZ >= 0.0) ? +1 : -1; + } + // eventually give credit for delta sum + mfMagnifyDeltaSum -= nDeltaZ / fMagnifyFactor; + + NSPoint aPt = [NSEvent mouseLocation]; + mpFrame->CocoaToVCL( aPt ); + + SalWheelMouseEvent aEvent; + aEvent.mnTime = mpFrame->mnLastEventTime; + aEvent.mnX = static_cast(aPt.x) - mpFrame->maGeometry.nX; + aEvent.mnY = static_cast(aPt.y) - mpFrame->maGeometry.nY; + aEvent.mnCode = ImplGetModifierMask( mpFrame->mnLastModifierFlags ); + aEvent.mnCode |= KEY_MOD1; // we want zooming, no scrolling + aEvent.mbDeltaIsPixel = TRUE; + + // --- RTL --- (mirror mouse pos) + if( Application::GetSettings().GetLayoutRTL() ) + aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX; + + aEvent.mnDelta = nDeltaZ; + aEvent.mnNotchDelta = (nDeltaZ >= 0) ? +1 : -1; + if( aEvent.mnDelta == 0 ) + aEvent.mnDelta = aEvent.mnNotchDelta; + aEvent.mbHorz = FALSE; + aEvent.mnScrollLines = nDeltaZ; + if( aEvent.mnScrollLines == 0 ) + aEvent.mnScrollLines = 1; + mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent ); + } +} + +- (void)rotateWithEvent: (NSEvent*)pEvent +{ + //Rotation : -(float)rotation; + // TODO: create new CommandType so rotation is available to the applications + (void)pEvent; +} + +- (void)swipeWithEvent: (NSEvent*)pEvent +{ + YIELD_GUARD; + + if( AquaSalFrame::isAlive( mpFrame ) ) + { + mpFrame->mnLastEventTime = static_cast( [pEvent timestamp] * 1000.0 ); + mpFrame->mnLastModifierFlags = [pEvent modifierFlags]; + + // merge pending scroll wheel events + float dX = 0.0; + float dY = 0.0; + for(;;) + { + dX += [pEvent deltaX]; + dY += [pEvent deltaY]; + NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask + untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ]; + if( !pNextEvent ) + break; + pEvent = pNextEvent; + } + + NSPoint aPt = [NSEvent mouseLocation]; + mpFrame->CocoaToVCL( aPt ); + + SalWheelMouseEvent aEvent; + aEvent.mnTime = mpFrame->mnLastEventTime; + aEvent.mnX = static_cast(aPt.x) - mpFrame->maGeometry.nX; + aEvent.mnY = static_cast(aPt.y) - mpFrame->maGeometry.nY; + aEvent.mnCode = ImplGetModifierMask( mpFrame->mnLastModifierFlags ); + aEvent.mbDeltaIsPixel = TRUE; + + // --- RTL --- (mirror mouse pos) + if( Application::GetSettings().GetLayoutRTL() ) + aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX; + + if( dX != 0.0 ) + { + aEvent.mnDelta = static_cast(floor(dX)); + aEvent.mnNotchDelta = dX < 0 ? -1 : 1; + if( aEvent.mnDelta == 0 ) + aEvent.mnDelta = aEvent.mnNotchDelta; + aEvent.mbHorz = TRUE; + aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL; + mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent ); + } + if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame )) + { + aEvent.mnDelta = static_cast(floor(dY)); + aEvent.mnNotchDelta = dY < 0 ? -1 : 1; + if( aEvent.mnDelta == 0 ) + aEvent.mnDelta = aEvent.mnNotchDelta; + aEvent.mbHorz = FALSE; + aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL; + mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent ); + } + } +} + +-(void)scrollWheel: (NSEvent*)pEvent +{ + YIELD_GUARD; + + if( AquaSalFrame::isAlive( mpFrame ) ) + { + mpFrame->mnLastEventTime = static_cast( [pEvent timestamp] * 1000.0 ); + mpFrame->mnLastModifierFlags = [pEvent modifierFlags]; + + // merge pending scroll wheel events + float dX = 0.0; + float dY = 0.0; + for(;;) + { + dX += [pEvent deltaX]; + dY += [pEvent deltaY]; + NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask + untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ]; + if( !pNextEvent ) + break; + pEvent = pNextEvent; + } + + NSPoint aPt = [NSEvent mouseLocation]; + mpFrame->CocoaToVCL( aPt ); + + SalWheelMouseEvent aEvent; + aEvent.mnTime = mpFrame->mnLastEventTime; + aEvent.mnX = static_cast(aPt.x) - mpFrame->maGeometry.nX; + aEvent.mnY = static_cast(aPt.y) - mpFrame->maGeometry.nY; + aEvent.mnCode = ImplGetModifierMask( mpFrame->mnLastModifierFlags ); + aEvent.mbDeltaIsPixel = FALSE; + + // --- RTL --- (mirror mouse pos) + if( Application::GetSettings().GetLayoutRTL() ) + aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX; + + if( dX != 0.0 ) + { + aEvent.mnDelta = static_cast(floor(dX)); + aEvent.mnNotchDelta = dX < 0 ? -1 : 1; + if( aEvent.mnDelta == 0 ) + aEvent.mnDelta = aEvent.mnNotchDelta; + aEvent.mbHorz = TRUE; + aEvent.mnScrollLines = dX > 0 ? dX/WHEEL_EVENT_FACTOR : -dX/WHEEL_EVENT_FACTOR; + if( aEvent.mnScrollLines == 0 ) + aEvent.mnScrollLines = 1; + + mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent ); + } + if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame ) ) + { + aEvent.mnDelta = static_cast(floor(dY)); + aEvent.mnNotchDelta = dY < 0 ? -1 : 1; + if( aEvent.mnDelta == 0 ) + aEvent.mnDelta = aEvent.mnNotchDelta; + aEvent.mbHorz = FALSE; + aEvent.mnScrollLines = dY > 0 ? dY/WHEEL_EVENT_FACTOR : -dY/WHEEL_EVENT_FACTOR; + if( aEvent.mnScrollLines < 1 ) + aEvent.mnScrollLines = 1; + + mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent ); + } + } +} + + +-(void)keyDown: (NSEvent*)pEvent +{ + YIELD_GUARD; + + if( AquaSalFrame::isAlive( mpFrame ) ) + { + mpLastEvent = pEvent; + mbInKeyInput = true; + mbNeedSpecialKeyHandle = false; + mbKeyHandled = false; + + mpFrame->mnLastEventTime = static_cast( [pEvent timestamp] * 1000.0 ); + mpFrame->mnLastModifierFlags = [pEvent modifierFlags]; + + if( ! [self handleKeyDownException: pEvent] ) + { + NSArray* pArray = [NSArray arrayWithObject: pEvent]; + [self interpretKeyEvents: pArray]; + } + + mbInKeyInput = false; + } +} + +-(BOOL)handleKeyDownException:(NSEvent*)pEvent +{ + // check for a very special set of modified characters + NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers]; + + if( pUnmodifiedString && [pUnmodifiedString length] == 1 ) + { + /* #i103102# key events with command and alternate don't make it through + interpretKeyEvents (why ?). Try to dispatch them here first, + if not successful continue normally + */ + if( (mpFrame->mnLastModifierFlags & (NSAlternateKeyMask | NSCommandKeyMask)) + == (NSAlternateKeyMask | NSCommandKeyMask) ) + { + if( [self sendSingleCharacter: mpLastEvent] ) + return YES; + } + unichar keyChar = [pUnmodifiedString characterAtIndex: 0]; + sal_uInt16 nKeyCode = ImplMapCharCode( keyChar ); + + // Caution: should the table grow to more than 5 or 6 entries, + // we must consider moving it to a kind of hash map + const unsigned int nExceptions = SAL_N_ELEMENTS( aExceptionalKeys ); + for( unsigned int i = 0; i < nExceptions; i++ ) + { + if( nKeyCode == aExceptionalKeys[i].nKeyCode && + (mpFrame->mnLastModifierFlags & aExceptionalKeys[i].nModifierMask) + == aExceptionalKeys[i].nModifierMask ) + { + [self sendKeyInputAndReleaseToFrame: nKeyCode character: 0]; + + return YES; + } + } + } + return NO; +} + +-(void)flagsChanged: (NSEvent*)pEvent +{ + YIELD_GUARD; + + if( AquaSalFrame::isAlive( mpFrame ) ) + { + mpFrame->mnLastEventTime = static_cast( [pEvent timestamp] * 1000.0 ); + mpFrame->mnLastModifierFlags = [pEvent modifierFlags]; + } +} + +-(void)insertText:(id)aString +{ + YIELD_GUARD; + + if( AquaSalFrame::isAlive( mpFrame ) ) + { + NSString* pInsert = nil; + if( [aString isMemberOfClass: [NSAttributedString class]] ) + pInsert = [aString string]; + else + pInsert = aString; + + int nLen = 0; + if( pInsert && ( nLen = [pInsert length] ) > 0 ) + { + OUString aInsertString( GetOUString( pInsert ) ); + // aCharCode initializer is safe since aInsertString will at least contain '\0' + sal_Unicode aCharCode = *aInsertString.getStr(); + + if( nLen == 1 && + aCharCode < 0x80 && + aCharCode > 0x1f && + ! [self hasMarkedText ] + ) + { + sal_uInt16 nKeyCode = ImplMapCharCode( aCharCode ); + unsigned int nLastModifiers = mpFrame->mnLastModifierFlags; + + // #i99567# + // find out the unmodified key code + + // sanity check + if( mpLastEvent && ( [mpLastEvent type] == NSKeyDown || [mpLastEvent type] == NSKeyUp ) ) + { + // get unmodified string + NSString* pUnmodifiedString = [mpLastEvent charactersIgnoringModifiers]; + if( pUnmodifiedString && [pUnmodifiedString length] == 1 ) + { + // map the unmodified key code + unichar keyChar = [pUnmodifiedString characterAtIndex: 0]; + nKeyCode = ImplMapCharCode( keyChar ); + } + nLastModifiers = [mpLastEvent modifierFlags]; + + } + // #i99567# + // applications and vcl's edit fields ignore key events with ALT + // however we're at a place where we know text should be inserted + // so it seems we need to strip the Alt modifier here + if( (nLastModifiers & (NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask)) + == NSAlternateKeyMask ) + { + nLastModifiers = 0; + } + [self sendKeyInputAndReleaseToFrame: nKeyCode character: aCharCode modifiers: nLastModifiers]; + } + else + { + SalExtTextInputEvent aEvent; + aEvent.mnTime = mpFrame->mnLastEventTime; + aEvent.maText = aInsertString; + aEvent.mpTextAttr = NULL; + aEvent.mnCursorPos = aInsertString.getLength(); + aEvent.mnDeltaStart = 0; + aEvent.mnCursorFlags = 0; + aEvent.mbOnlyCursor = FALSE; + mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, &aEvent ); + if( AquaSalFrame::isAlive( mpFrame ) ) + mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 ); + } + } + else + { + SalExtTextInputEvent aEvent; + aEvent.mnTime = mpFrame->mnLastEventTime; + aEvent.maText = OUString(); + aEvent.mpTextAttr = NULL; + aEvent.mnCursorPos = 0; + aEvent.mnDeltaStart = 0; + aEvent.mnCursorFlags = 0; + aEvent.mbOnlyCursor = FALSE; + mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, &aEvent ); + if( AquaSalFrame::isAlive( mpFrame ) ) + mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 ); + + } + mbKeyHandled = true; + [self unmarkText]; + } +} + +-(void)insertTab: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: KEY_TAB character: '\t' modifiers: 0]; +} + +-(void)insertBacktab: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: (KEY_TAB | KEY_SHIFT) character: '\t' modifiers: 0]; +} + +-(void)moveLeft: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: 0]; +} + +-(void)moveLeftAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: NSShiftKeyMask]; +} + +-(void)moveBackwardAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_BACKWARD character: 0 modifiers: 0]; +} + +-(void)moveRight: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: 0]; +} + +-(void)moveRightAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: NSShiftKeyMask]; +} + +-(void)moveForwardAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_FORWARD character: 0 modifiers: 0]; +} + +-(void)moveWordLeft: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_BACKWARD character: 0 modifiers: 0]; +} + +-(void)moveWordBackward: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_BACKWARD character: 0 modifiers: 0]; +} + +-(void)moveWordBackwardAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_BACKWARD character: 0 modifiers: 0]; +} + +-(void)moveWordLeftAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_BACKWARD character: 0 modifiers: 0]; +} + +-(void)moveWordRight: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_FORWARD character: 0 modifiers: 0]; +} + +-(void)moveWordForward: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_FORWARD character: 0 modifiers: 0]; +} + +-(void)moveWordForwardAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_FORWARD character: 0 modifiers: 0]; +} + +-(void)moveWordRightAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_FORWARD character: 0 modifiers: 0]; +} + +-(void)moveToEndOfLine: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_LINE character: 0 modifiers: 0]; +} + +-(void)moveToRightEndOfLine: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_LINE character: 0 modifiers: 0]; +} + +-(void)moveToEndOfLineAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_LINE character: 0 modifiers: 0]; +} + +-(void)moveToRightEndOfLineAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_LINE character: 0 modifiers: 0]; +} + +-(void)moveToBeginningOfLine: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE character: 0 modifiers: 0]; +} + +-(void)moveToLeftEndOfLine: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE character: 0 modifiers: 0]; +} + +-(void)moveToBeginningOfLineAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE character: 0 modifiers: 0]; +} + +-(void)moveToLeftEndOfLineAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE character: 0 modifiers: 0]; +} + +-(void)moveToEndOfParagraph: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0 modifiers: 0]; +} + +-(void)moveToEndOfParagraphAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0 modifiers: 0]; +} + +-(void)moveParagraphForward: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0 modifiers: 0]; +} + +-(void)moveParagraphForwardAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0 modifiers: 0]; +} + +-(void)moveToBeginningOfParagraph: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0 modifiers: 0]; +} + +-(void)moveParagraphBackward: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0 modifiers: 0]; +} + +-(void)moveToBeginningOfParagraphAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0 modifiers: 0]; +} + +-(void)moveParagraphBackwardAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0 modifiers: 0]; +} + +-(void)moveToEndOfDocument: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT character: 0 modifiers: 0]; +} + +-(void)scrollToEndOfDocument: (id)aSender +{ + (void)aSender; + // this is not exactly what we should do, but it makes "End" and "Shift-End" behave consistent + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT character: 0 modifiers: 0]; +} + +-(void)moveToEndOfDocumentAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT character: 0 modifiers: 0]; +} + +-(void)moveToBeginningOfDocument: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT character: 0 modifiers: 0]; +} + +-(void)scrollToBeginningOfDocument: (id)aSender +{ + (void)aSender; + // this is not exactly what we should do, but it makes "Home" and "Shift-Home" behave consistent + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT character: 0 modifiers: 0]; +} + +-(void)moveToBeginningOfDocumentAndModifySelection: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT character: 0 modifiers: 0]; +} + +-(void)moveUp: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: KEY_UP character: 0 modifiers: 0]; +} + +-(void)moveDown: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: KEY_DOWN character: 0 modifiers: 0]; +} + +-(void)insertNewline: (id)aSender +{ + (void)aSender; + // #i91267# make enter and shift-enter work by evaluating the modifiers + [self sendKeyInputAndReleaseToFrame: KEY_RETURN character: '\n' modifiers: mpFrame->mnLastModifierFlags]; +} + +-(void)deleteBackward: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0]; +} + +-(void)deleteForward: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: KEY_DELETE character: 0x7f modifiers: 0]; +} + +-(void)deleteBackwardByDecomposingPreviousCharacter: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0]; +} + +-(void)deleteWordBackward: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_WORD_BACKWARD character: 0 modifiers: 0]; +} + +-(void)deleteWordForward: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_WORD_FORWARD character: 0 modifiers: 0]; +} + +-(void)deleteToBeginningOfLine: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE character: 0 modifiers: 0]; +} + +-(void)deleteToEndOfLine: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_END_OF_LINE character: 0 modifiers: 0]; +} + +-(void)deleteToBeginningOfParagraph: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH character: 0 modifiers: 0]; +} + +-(void)deleteToEndOfParagraph: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_END_OF_PARAGRAPH character: 0 modifiers: 0]; +} + +-(void)insertLineBreak: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::INSERT_LINEBREAK character: 0 modifiers: 0]; +} + +-(void)insertParagraphSeparator: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::INSERT_PARAGRAPH character: 0 modifiers: 0]; +} + +-(void)selectWord: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD character: 0 modifiers: 0]; +} + +-(void)selectLine: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_LINE character: 0 modifiers: 0]; +} + +-(void)selectParagraph: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_PARAGRAPH character: 0 modifiers: 0]; +} + +-(void)selectAll: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_ALL character: 0 modifiers: 0]; +} + +-(void)cancelOperation: (id)aSender +{ + (void)aSender; + [self sendKeyInputAndReleaseToFrame: KEY_ESCAPE character: 0x1b modifiers: 0]; +} + +-(void)noop: (id)aSender +{ + (void)aSender; + if( ! mbKeyHandled ) + { + if( ! [self sendSingleCharacter:mpLastEvent] ) + { + /* prevent recursion */ + if( mpLastEvent != mpLastSuperEvent && [NSApp respondsToSelector: @selector(sendSuperEvent:)] ) + { + id pLastSuperEvent = mpLastSuperEvent; + mpLastSuperEvent = mpLastEvent; + [NSApp performSelector:@selector(sendSuperEvent:) withObject: mpLastEvent]; + mpLastSuperEvent = pLastSuperEvent; + + std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent ); + if( it != GetSalData()->maKeyEventAnswer.end() ) + it->second = true; + } + } + } +} + +-(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar +{ + return [self sendKeyInputAndReleaseToFrame: nKeyCode character: aChar modifiers: mpFrame->mnLastModifierFlags]; +} + +-(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar modifiers: (unsigned int)nMod +{ + return [self sendKeyToFrameDirect: nKeyCode character: aChar modifiers: nMod] || + [self sendSingleCharacter: mpLastEvent]; +} + +-(BOOL)sendKeyToFrameDirect: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar modifiers: (unsigned int)nMod +{ + YIELD_GUARD; + + long nRet = 0; + if( AquaSalFrame::isAlive( mpFrame ) ) + { + SalKeyEvent aEvent; + aEvent.mnTime = mpFrame->mnLastEventTime; + aEvent.mnCode = nKeyCode | ImplGetModifierMask( nMod ); + aEvent.mnCharCode = aChar; + aEvent.mnRepeat = FALSE; + nRet = mpFrame->CallCallback( SALEVENT_KEYINPUT, &aEvent ); + std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent ); + if( it != GetSalData()->maKeyEventAnswer.end() ) + it->second = nRet ? true : false; + if( AquaSalFrame::isAlive( mpFrame ) ) + mpFrame->CallCallback( SALEVENT_KEYUP, &aEvent ); + } + return nRet ? YES : NO; +} + + +-(BOOL)sendSingleCharacter: (NSEvent *)pEvent +{ + NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers]; + + if( pUnmodifiedString && [pUnmodifiedString length] == 1 ) + { + unichar keyChar = [pUnmodifiedString characterAtIndex: 0]; + sal_uInt16 nKeyCode = ImplMapCharCode( keyChar ); + if (nKeyCode == 0) + { + sal_uInt16 nOtherKeyCode = [pEvent keyCode]; + nKeyCode = ImplMapKeyCode(nOtherKeyCode); + } + if( nKeyCode != 0 ) + { + // don't send unicodes in the private use area + if( keyChar >= 0xf700 && keyChar < 0xf780 ) + keyChar = 0; + BOOL bRet = [self sendKeyToFrameDirect: nKeyCode character: keyChar modifiers: mpFrame->mnLastModifierFlags]; + mbInKeyInput = false; + + return bRet; + } + } + return NO; +} + + +// NSTextInput protocol +- (NSArray *)validAttributesForMarkedText +{ + return [NSArray arrayWithObjects:NSUnderlineStyleAttributeName, nil]; +} + +- (BOOL)hasMarkedText +{ + BOOL bHasMarkedText; + + bHasMarkedText = ( mMarkedRange.location != NSNotFound ) && + ( mMarkedRange.length != 0 ); + // hack to check keys like "Control-j" + if( mbInKeyInput ) + { + mbNeedSpecialKeyHandle = true; + } + + // FIXME: + // #i106901# + // if we come here outside of mbInKeyInput, this is likely to be because + // of the keyboard viewer. For unknown reasons having no marked range + // in this case causes a crash. So we say we have a marked range anyway + // This is a hack, since it is not understood what a) causes that crash + // and b) why we should have a marked range at this point. + if( ! mbInKeyInput ) + bHasMarkedText = YES; + + return bHasMarkedText; +} + +- (NSRange)markedRange +{ + // FIXME: + // #i106901# + // if we come here outside of mbInKeyInput, this is likely to be because + // of the keyboard viewer. For unknown reasons having no marked range + // in this case causes a crash. So we say we have a marked range anyway + // This is a hack, since it is not understood what a) causes that crash + // and b) why we should have a marked range at this point. + if( ! mbInKeyInput ) + return NSMakeRange( 0, 0 ); + + return [self hasMarkedText] ? mMarkedRange : NSMakeRange( NSNotFound, 0 ); +} + +- (NSRange)selectedRange +{ + return mSelectedRange; +} + +- (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange +{ + if( ![aString isKindOfClass:[NSAttributedString class]] ) + aString = [[[NSAttributedString alloc] initWithString:aString] autorelease]; + NSRange rangeToReplace = [self hasMarkedText] ? [self markedRange] : [self selectedRange]; + if( rangeToReplace.location == NSNotFound ) + { + mMarkedRange = NSMakeRange( selRange.location, [aString length] ); + mSelectedRange = NSMakeRange( selRange.location, selRange.length ); + } + else + { + mMarkedRange = NSMakeRange( rangeToReplace.location, [aString length] ); + mSelectedRange = NSMakeRange( rangeToReplace.location + selRange.location, selRange.length ); + } + + int len = [aString length]; + SalExtTextInputEvent aInputEvent; + aInputEvent.mnTime = mpFrame->mnLastEventTime; + aInputEvent.mnDeltaStart = 0; + aInputEvent.mbOnlyCursor = FALSE; + if( len > 0 ) { + NSString *pString = [aString string]; + OUString aInsertString( GetOUString( pString ) ); + std::vector aInputFlags = std::vector( std::max( 1, len ), 0 ); + for ( int i = 0; i < len; i++ ) + { + unsigned int nUnderlineValue; + NSRange effectiveRange; + + effectiveRange = NSMakeRange(i, 1); + nUnderlineValue = [[aString attribute:NSUnderlineStyleAttributeName atIndex:i effectiveRange:&effectiveRange] unsignedIntValue]; + + switch (nUnderlineValue & 0xff) { + case NSUnderlineStyleSingle: + aInputFlags[i] = EXTTEXTINPUT_ATTR_UNDERLINE; + break; + case NSUnderlineStyleThick: + aInputFlags[i] = EXTTEXTINPUT_ATTR_UNDERLINE | EXTTEXTINPUT_ATTR_HIGHLIGHT; + break; + case NSUnderlineStyleDouble: + aInputFlags[i] = EXTTEXTINPUT_ATTR_BOLDUNDERLINE; + break; + default: + aInputFlags[i] = EXTTEXTINPUT_ATTR_HIGHLIGHT; + break; + } + } + + aInputEvent.maText = aInsertString; + aInputEvent.mnCursorPos = selRange.location; + aInputEvent.mpTextAttr = &aInputFlags[0]; + mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void *)&aInputEvent ); + } else { + aInputEvent.maText = OUString(); + aInputEvent.mnCursorPos = 0; + aInputEvent.mnCursorFlags = 0; + aInputEvent.mpTextAttr = 0; + mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void *)&aInputEvent ); + mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 ); + } + mbKeyHandled= true; +} + +- (void)unmarkText +{ + mSelectedRange = mMarkedRange = NSMakeRange(NSNotFound, 0); +} + +- (NSAttributedString *)attributedSubstringFromRange:(NSRange)theRange +{ + (void)theRange; + // FIXME + return nil; +} + +- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint +{ + (void)thePoint; + // FIXME + return 0; +} + +- (NSInteger)conversationIdentifier +{ + return (long)self; +} + +- (void)doCommandBySelector:(SEL)aSelector +{ + if( AquaSalFrame::isAlive( mpFrame ) ) + { + #if OSL_DEBUG_LEVEL > 1 + // fprintf( stderr, "SalFrameView: doCommandBySelector %s\n", (char*)aSelector ); + #endif + if( (mpFrame->mnICOptions & SAL_INPUTCONTEXT_TEXT) != 0 && + aSelector != NULL && [self respondsToSelector: aSelector] ) + { + [self performSelector: aSelector]; + } + else + { + [self sendSingleCharacter:mpLastEvent]; + } + } + + mbKeyHandled = true; +} + +-(void)clearLastEvent +{ + mpLastEvent = nil; +} + +- (NSRect)firstRectForCharacterRange:(NSRange)theRange +{ + (void)theRange; + SalExtTextInputPosEvent aPosEvent; + mpFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void *)&aPosEvent ); + + NSRect rect; + + rect.origin.x = aPosEvent.mnX + mpFrame->maGeometry.nX; + rect.origin.y = aPosEvent.mnY + mpFrame->maGeometry.nY + 4; // add some space for underlines + rect.size.width = aPosEvent.mnWidth; + rect.size.height = aPosEvent.mnHeight; + + mpFrame->VCLToCocoa( rect ); + return rect; +} + +-(id)parentAttribute { + return mpFrame->getNSWindow(); +} + +-(::com::sun::star::accessibility::XAccessibleContext *)accessibleContext +{ + if ( mpReferenceWrapper == nil ) { + // some frames never become visible .. + Window *pWindow = mpFrame -> GetWindow(); + if ( ! pWindow ) + return nil; + + mpReferenceWrapper = new ReferenceWrapper; + mpReferenceWrapper -> rAccessibleContext = pWindow -> /*GetAccessibleChildWindow( 0 ) ->*/ GetAccessible() -> getAccessibleContext(); + [ AquaA11yFactory insertIntoWrapperRepository: self forAccessibleContext: mpReferenceWrapper -> rAccessibleContext ]; + } + return [ super accessibleContext ]; +} + +-(NSView*)viewElementForParent +{ + return mpFrame->getNSView(); +} + +-(void)registerMouseEventListener: (id)theListener +{ + mpMouseEventListener = theListener; +} + +-(void)unregisterMouseEventListener: (id)theListener +{ + (void)theListener; + mpMouseEventListener = nil; +} + +-(NSDragOperation)draggingEntered:(id )sender +{ + return [mDraggingDestinationHandler draggingEntered: sender]; +} + +-(NSDragOperation)draggingUpdated:(id )sender +{ + return [mDraggingDestinationHandler draggingUpdated: sender]; +} + +-(void)draggingExited:(id )sender +{ + [mDraggingDestinationHandler draggingExited: sender]; +} + +-(BOOL)prepareForDragOperation:(id )sender +{ + return [mDraggingDestinationHandler prepareForDragOperation: sender]; +} + +-(BOOL)performDragOperation:(id )sender +{ + return [mDraggingDestinationHandler performDragOperation: sender]; +} + +-(void)concludeDragOperation:(id )sender +{ + [mDraggingDestinationHandler concludeDragOperation: sender]; +} + +-(void)registerDraggingDestinationHandler:(id)theHandler +{ + mDraggingDestinationHandler = theHandler; +} + +-(void)unregisterDraggingDestinationHandler:(id)theHandler +{ + (void)theHandler; + mDraggingDestinationHandler = nil; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx new file mode 100644 index 000000000000..9aab3a066c24 --- /dev/null +++ b/vcl/osx/salinst.cxx @@ -0,0 +1,1207 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include + +#include + +#include "osl/process.h" + +#include "rtl/ustrbuf.hxx" + +#include "vcl/svapp.hxx" +#include "vcl/window.hxx" +#include "vcl/timer.hxx" +#include "vcl/solarmutex.hxx" + +#include "osx/saldata.hxx" +#include "osx/salinst.h" +#include "osx/salframe.h" +#include "osx/salobj.h" +#include "osx/salsys.h" +#include "osx/salvd.h" +#include "quartz/salbmp.h" +#include "quartz/utils.h" +#include "osx/salprn.h" +#include "osx/saltimer.h" +#include "osx/vclnsapp.h" + +#include "print.h" +#include "impbmp.hxx" +#include "salimestatus.hxx" + +#include + +#include +#include +#include + +#include "premac.h" +#include +#include +#import "apple_remote/RemoteMainController.h" +#include "apple_remote/RemoteControl.h" +#include "postmac.h" + +using namespace std; +using namespace ::com::sun::star; + +extern sal_Bool ImplSVMain(); + +static int* gpnInit = 0; +static NSMenu* pDockMenu = nil; +static bool bNoSVMain = true; +static bool bLeftMain = false; +// ----------------------------------------------------------------------- + +class AquaDelayedSettingsChanged : public Timer +{ + bool mbInvalidate; + public: + AquaDelayedSettingsChanged( bool bInvalidate ) : + mbInvalidate( bInvalidate ) + { + } + + virtual void Timeout() + { + SalData* pSalData = GetSalData(); + if( ! pSalData->maFrames.empty() ) + pSalData->maFrames.front()->CallCallback( SALEVENT_SETTINGSCHANGED, NULL ); + + if( mbInvalidate ) + { + for( std::list< AquaSalFrame* >::iterator it = pSalData->maFrames.begin(); + it != pSalData->maFrames.end(); ++it ) + { + if( (*it)->mbShown ) + (*it)->SendPaintEvent( NULL ); + } + } + Stop(); + delete this; + } +}; + +void AquaSalInstance::delayedSettingsChanged( bool bInvalidate ) +{ + osl::Guard< comphelper::SolarMutex > aGuard( *mpSalYieldMutex ); + AquaDelayedSettingsChanged* pTimer = new AquaDelayedSettingsChanged( bInvalidate ); + pTimer->SetTimeout( 50 ); + pTimer->Start(); +} + + +// the AppEventList must be available before any SalData/SalInst/etc. objects are ready +AquaSalInstance::AppEventList AquaSalInstance::aAppEventList; + +NSMenu* AquaSalInstance::GetDynamicDockMenu() +{ + if( ! pDockMenu && ! bLeftMain ) + pDockMenu = [[NSMenu alloc] initWithTitle: @""]; + return pDockMenu; +} + +bool AquaSalInstance::isOnCommandLine( const OUString& rArg ) +{ + sal_uInt32 nArgs = osl_getCommandArgCount(); + for( sal_uInt32 i = 0; i < nArgs; i++ ) + { + OUString aArg; + osl_getCommandArg( i, &aArg.pData ); + if( aArg.equals( rArg ) ) + return true; + } + return false; +} + + +// initialize the cocoa VCL_NSApplication object +// returns an NSAutoreleasePool that must be released when the event loop begins +static void initNSApp() +{ + // create our cocoa NSApplication + [VCL_NSApplication sharedApplication]; + + SalData::ensureThreadAutoreleasePool(); + + // put cocoa into multithreaded mode + [NSThread detachNewThreadSelector:@selector(enableCocoaThreads:) toTarget:[[CocoaThreadEnabler alloc] init] withObject:nil]; + + // activate our delegate methods + [NSApp setDelegate: NSApp]; + + [[NSNotificationCenter defaultCenter] addObserver: NSApp + selector: @selector(systemColorsChanged:) + name: NSSystemColorsDidChangeNotification + object: nil ]; + [[NSNotificationCenter defaultCenter] addObserver: NSApp + selector: @selector(screenParametersChanged:) + name: NSApplicationDidChangeScreenParametersNotification + object: nil ]; + // add observers for some settings changes that affect vcl's settings + // scrollbar variant + [[NSDistributedNotificationCenter defaultCenter] addObserver: NSApp + selector: @selector(scrollbarVariantChanged:) + name: @"AppleAquaScrollBarVariantChanged" + object: nil ]; + // scrollbar page behavior ("jump to here" or not) + [[NSDistributedNotificationCenter defaultCenter] addObserver: NSApp + selector: @selector(scrollbarSettingsChanged:) + name: @"AppleNoRedisplayAppearancePreferenceChanged" + object: nil ]; +#if !HAVE_FEATURE_MACOSX_SANDBOX + // Initialize Apple Remote + GetSalData()->mpMainController = [[MainController alloc] init]; + + [[NSDistributedNotificationCenter defaultCenter] addObserver: NSApp + selector: @selector(applicationWillBecomeActive:) + name: @"AppleRemoteWillBecomeActive" + object: nil ]; + + [[NSDistributedNotificationCenter defaultCenter] addObserver: NSApp + selector: @selector(applicationWillResignActive:) + name: @"AppleRemoteWillResignActive" + object: nil ]; +#endif +} + +sal_Bool ImplSVMainHook( int * pnInit ) +{ + unlink([[NSString stringWithFormat:@"%@/Library/Saved Application State/%s.savedState/restorecount.plist", NSHomeDirectory(), MACOSX_BUNDLE_IDENTIFIER] UTF8String]); + + gpnInit = pnInit; + + bNoSVMain = false; + initNSApp(); + + NSPoint aPt = { 0, 0 }; + NSEvent* pEvent = [NSEvent otherEventWithType: NSApplicationDefined + location: aPt + modifierFlags: 0 + timestamp: 0 + windowNumber: 0 + context: nil + subtype: AquaSalInstance::AppExecuteSVMain + data1: 0 + data2: 0 ]; + if( pEvent ) + { + [NSApp postEvent: pEvent atStart: NO]; + + OUString aExeURL, aExe; + osl_getExecutableFile( &aExeURL.pData ); + osl_getSystemPathFromFileURL( aExeURL.pData, &aExe.pData ); + OString aByteExe( OUStringToOString( aExe, osl_getThreadTextEncoding() ) ); + +#ifdef DEBUG + aByteExe += OString ( " NSAccessibilityDebugLogLevel 1" ); + const char* pArgv[] = { aByteExe.getStr(), NULL }; + NSApplicationMain( 3, pArgv ); +#else + const char* pArgv[] = { aByteExe.getStr(), NULL }; + NSApplicationMain( 1, pArgv ); +#endif + } + else + { + OSL_FAIL( "NSApplication initialization could not be done" ); + } + + return TRUE; // indicate that ImplSVMainHook is implemented +} + +// ======================================================================= + +void SalAbort( const OUString& rErrorText, bool bDumpCore ) +{ + if( rErrorText.isEmpty() ) + fprintf( stderr, "Application Error " ); + else + fprintf( stderr, "%s ", + OUStringToOString( rErrorText, osl_getThreadTextEncoding() ).getStr() ); + if( bDumpCore ) + abort(); + else + _exit(1); +} + +// ----------------------------------------------------------------------- + +void InitSalData() +{ + SalData *pSalData = new SalData; + SetSalData( pSalData ); +} + +// ----------------------------------------------------------------------- + +const OUString& SalGetDesktopEnvironment() +{ + static OUString aDesktopEnvironment( "MacOSX" ); + return aDesktopEnvironment; +} + +// ----------------------------------------------------------------------- + +void DeInitSalData() +{ + SalData *pSalData = GetSalData(); + if( pSalData->mpStatusItem ) + { + [pSalData->mpStatusItem release]; + pSalData->mpStatusItem = nil; + } + delete pSalData; + SetSalData( NULL ); +} + +// ----------------------------------------------------------------------- + +extern "C" { +#include +} + +// ----------------------------------------------------------------------- + +void InitSalMain() +{ +} + +// ======================================================================= + +SalYieldMutex::SalYieldMutex() +{ + mnCount = 0; + mnThreadId = 0; +} + +void SalYieldMutex::acquire() +{ + SolarMutexObject::acquire(); + mnThreadId = osl::Thread::getCurrentIdentifier(); + mnCount++; +} + +void SalYieldMutex::release() +{ + if ( mnThreadId == osl::Thread::getCurrentIdentifier() ) + { + if ( mnCount == 1 ) + mnThreadId = 0; + mnCount--; + } + SolarMutexObject::release(); +} + +bool SalYieldMutex::tryToAcquire() +{ + if ( SolarMutexObject::tryToAcquire() ) + { + mnThreadId = osl::Thread::getCurrentIdentifier(); + mnCount++; + return true; + } + else + return false; +} + +// ----------------------------------------------------------------------- + +// some convenience functions regarding the yield mutex, aka solar mutex + +sal_Bool ImplSalYieldMutexTryToAcquire() +{ + AquaSalInstance* pInst = (AquaSalInstance*) GetSalData()->mpFirstInstance; + if ( pInst ) + return pInst->mpSalYieldMutex->tryToAcquire(); + else + return FALSE; +} + +void ImplSalYieldMutexAcquire() +{ + AquaSalInstance* pInst = (AquaSalInstance*) GetSalData()->mpFirstInstance; + if ( pInst ) + pInst->mpSalYieldMutex->acquire(); +} + +void ImplSalYieldMutexRelease() +{ + AquaSalInstance* pInst = (AquaSalInstance*) GetSalData()->mpFirstInstance; + if ( pInst ) + pInst->mpSalYieldMutex->release(); +} + +// ======================================================================= + +SalInstance* CreateSalInstance() +{ + // this is the case for not using SVMain + // not so good + if( bNoSVMain ) + initNSApp(); + + SalData* pSalData = GetSalData(); + DBG_ASSERT( pSalData->mpFirstInstance == NULL, "more than one instance created" ); + AquaSalInstance* pInst = new AquaSalInstance; + + // init instance (only one instance in this version !!!) + pSalData->mpFirstInstance = pInst; + // this one is for outside AquaSalInstance::Yield + SalData::ensureThreadAutoreleasePool(); + // no focus rects on NWF + ImplGetSVData()->maNWFData.mbNoFocusRects = true; + ImplGetSVData()->maNWFData.mbNoActiveTabTextRaise = true; + ImplGetSVData()->maNWFData.mbCenteredTabs = true; + ImplGetSVData()->maNWFData.mbProgressNeedsErase = true; + ImplGetSVData()->maNWFData.mbCheckBoxNeedsErase = true; + ImplGetSVData()->maNWFData.mnStatusBarLowerRightOffset = 10; + ImplGetSVData()->maGDIData.mbNoXORClipping = true; + ImplGetSVData()->maWinData.mbNoSaveBackground = true; + + return pInst; +} + +// ----------------------------------------------------------------------- + +void DestroySalInstance( SalInstance* pInst ) +{ + delete pInst; +} + +// ----------------------------------------------------------------------- + +AquaSalInstance::AquaSalInstance() +{ + mpSalYieldMutex = new SalYieldMutex; + mpSalYieldMutex->acquire(); + ::tools::SolarMutex::SetSolarMutex( mpSalYieldMutex ); + maMainThread = osl::Thread::getCurrentIdentifier(); + mbWaitingYield = false; + maUserEventListMutex = osl_createMutex(); + mnActivePrintJobs = 0; + maWaitingYieldCond = osl_createCondition(); +} + +// ----------------------------------------------------------------------- + +AquaSalInstance::~AquaSalInstance() +{ + ::tools::SolarMutex::SetSolarMutex( 0 ); + mpSalYieldMutex->release(); + delete mpSalYieldMutex; + osl_destroyMutex( maUserEventListMutex ); + osl_destroyCondition( maWaitingYieldCond ); +} + +// ----------------------------------------------------------------------- + +void AquaSalInstance::wakeupYield() +{ + // wakeup :Yield + if( mbWaitingYield ) + { + SalData::ensureThreadAutoreleasePool(); + NSPoint aPt = { 0, 0 }; + NSEvent* pEvent = [NSEvent otherEventWithType: NSApplicationDefined + location: aPt + modifierFlags: 0 + timestamp: 0 + windowNumber: 0 + context: nil + subtype: AquaSalInstance::YieldWakeupEvent + data1: 0 + data2: 0 ]; + if( pEvent ) + [NSApp postEvent: pEvent atStart: NO]; + } +} + +// ----------------------------------------------------------------------- + +void AquaSalInstance::PostUserEvent( AquaSalFrame* pFrame, sal_uInt16 nType, void* pData ) +{ + osl_acquireMutex( maUserEventListMutex ); + maUserEvents.push_back( SalUserEvent( pFrame, pData, nType ) ); + osl_releaseMutex( maUserEventListMutex ); + + // notify main loop that an event has arrived + wakeupYield(); +} + +// ----------------------------------------------------------------------- + +comphelper::SolarMutex* AquaSalInstance::GetYieldMutex() +{ + return mpSalYieldMutex; +} + +// ----------------------------------------------------------------------- + +sal_uLong AquaSalInstance::ReleaseYieldMutex() +{ + SalYieldMutex* pYieldMutex = mpSalYieldMutex; + if ( pYieldMutex->GetThreadId() == + osl::Thread::getCurrentIdentifier() ) + { + sal_uLong nCount = pYieldMutex->GetAcquireCount(); + sal_uLong n = nCount; + while ( n ) + { + pYieldMutex->release(); + n--; + } + + return nCount; + } + else + return 0; +} + +// ----------------------------------------------------------------------- + +void AquaSalInstance::AcquireYieldMutex( sal_uLong nCount ) +{ + SalYieldMutex* pYieldMutex = mpSalYieldMutex; + while ( nCount ) + { + pYieldMutex->acquire(); + nCount--; + } +} + +// ----------------------------------------------------------------------- + +bool AquaSalInstance::CheckYieldMutex() +{ + bool bRet = true; + + SalYieldMutex* pYieldMutex = mpSalYieldMutex; + if ( pYieldMutex->GetThreadId() != osl::Thread::getCurrentIdentifier()) + { + bRet = false; + } + + return bRet; +} + +// ----------------------------------------------------------------------- + +bool AquaSalInstance::isNSAppThread() const +{ + return osl::Thread::getCurrentIdentifier() == maMainThread; +} + +// ----------------------------------------------------------------------- + +void AquaSalInstance::handleAppDefinedEvent( NSEvent* pEvent ) +{ + switch( [pEvent subtype] ) + { + case AppStartTimerEvent: + AquaSalTimer::handleStartTimerEvent( pEvent ); + break; + case AppEndLoopEvent: + [NSApp stop: NSApp]; + break; + case AppExecuteSVMain: + { + int nResult = ImplSVMain(); + if( gpnInit ) + *gpnInit = nResult; + [NSApp stop: NSApp]; + bLeftMain = true; + if( pDockMenu ) + { + [pDockMenu release]; + pDockMenu = nil; + } + } + break; + case AppleRemoteEvent: + { + sal_Int16 nCommand = 0; + SalData* pSalData = GetSalData(); + bool bIsFullScreenMode = false; + + std::list::iterator it = pSalData->maFrames.begin(); + while( it != pSalData->maFrames.end() ) + { + if ( (*it) && ((*it)->mbFullScreen == true) ) + bIsFullScreenMode = true; + ++it; + } + + switch ([pEvent data1]) + { + case kRemoteButtonPlay: + nCommand = ( bIsFullScreenMode == true ) ? MEDIA_COMMAND_PLAY_PAUSE : MEDIA_COMMAND_PLAY; + break; + + // kept for experimentation purpose (scheduled for future implementation) + // case kRemoteButtonMenu: nCommand = MEDIA_COMMAND_MENU; break; + + case kRemoteButtonPlus: nCommand = MEDIA_COMMAND_VOLUME_UP; break; + + case kRemoteButtonMinus: nCommand = MEDIA_COMMAND_VOLUME_DOWN; break; + + case kRemoteButtonRight: nCommand = MEDIA_COMMAND_NEXTTRACK; break; + + case kRemoteButtonRight_Hold: nCommand = MEDIA_COMMAND_NEXTTRACK_HOLD; break; + + case kRemoteButtonLeft: nCommand = MEDIA_COMMAND_PREVIOUSTRACK; break; + + case kRemoteButtonLeft_Hold: nCommand = MEDIA_COMMAND_REWIND; break; + + case kRemoteButtonPlay_Hold: nCommand = MEDIA_COMMAND_PLAY_HOLD; break; + + case kRemoteButtonMenu_Hold: nCommand = MEDIA_COMMAND_STOP; break; + + // FIXME : not detected + case kRemoteButtonPlus_Hold: + case kRemoteButtonMinus_Hold: + break; + + default: + break; + } + AquaSalFrame* pFrame = pSalData->maFrames.front(); + Window * pWindow = pFrame->GetWindow() ? pSalData->maFrames.front()->GetWindow() : NULL; + + if( pWindow ) + { + const Point aPoint; + CommandEvent aCEvt( aPoint, COMMAND_MEDIA, FALSE, &nCommand ); + NotifyEvent aNCmdEvt( EVENT_COMMAND, pWindow, &aCEvt ); + + if ( !ImplCallPreNotify( aNCmdEvt ) ) + pWindow->Command( aCEvt ); + } + + } + break; + + case YieldWakeupEvent: + // do nothing, fall out of Yield + break; + + default: + OSL_FAIL( "unhandled NSApplicationDefined event" ); + break; + }; +} + +// ----------------------------------------------------------------------- + +class ReleasePoolHolder +{ + NSAutoreleasePool* mpPool; + public: + ReleasePoolHolder() : mpPool( [[NSAutoreleasePool alloc] init] ) {} + ~ReleasePoolHolder() { [mpPool release]; } +}; + +void AquaSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents ) +{ + // ensure that the per thread autorelease pool is top level and + // will therefore not be destroyed by cocoa implicitly + SalData::ensureThreadAutoreleasePool(); + + // NSAutoreleasePool documentation suggests we should have + // an own pool for each yield level + ReleasePoolHolder aReleasePool; + + // Release all locks so that we don't deadlock when we pull pending + // events from the event queue + bool bDispatchUser = true; + while( bDispatchUser ) + { + sal_uLong nCount = ReleaseYieldMutex(); + + // get one user event + osl_acquireMutex( maUserEventListMutex ); + SalUserEvent aEvent( NULL, NULL, 0 ); + if( ! maUserEvents.empty() ) + { + aEvent = maUserEvents.front(); + maUserEvents.pop_front(); + } + else + bDispatchUser = false; + osl_releaseMutex( maUserEventListMutex ); + + AcquireYieldMutex( nCount ); + + // dispatch it + if( aEvent.mpFrame && AquaSalFrame::isAlive( aEvent.mpFrame ) ) + { + aEvent.mpFrame->CallCallback( aEvent.mnType, aEvent.mpData ); + osl_setCondition( maWaitingYieldCond ); + // return if only one event is asked for + if( ! bHandleAllCurrentEvents ) + return; + } + } + + // handle cocoa event queue + // cocoa events mye be only handled in the thread the NSApp was created + if( isNSAppThread() && mnActivePrintJobs == 0 ) + { + // we need to be woken up by a cocoa-event + // if a user event should be posted by the event handling below + bool bOldWaitingYield = mbWaitingYield; + mbWaitingYield = bWait; + + // handle available events + NSEvent* pEvent = nil; + bool bHadEvent = false; + do + { + sal_uLong nCount = ReleaseYieldMutex(); + + pEvent = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: nil + inMode: NSDefaultRunLoopMode dequeue: YES]; + if( pEvent ) + { + [NSApp sendEvent: pEvent]; + bHadEvent = true; + } + [NSApp updateWindows]; + + AcquireYieldMutex( nCount ); + } while( bHandleAllCurrentEvents && pEvent ); + + // if we had no event yet, wait for one if requested + if( bWait && ! bHadEvent ) + { + sal_uLong nCount = ReleaseYieldMutex(); + + NSDate* pDt = AquaSalTimer::pRunningTimer ? [AquaSalTimer::pRunningTimer fireDate] : [NSDate distantFuture]; + pEvent = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: pDt + inMode: NSDefaultRunLoopMode dequeue: YES]; + if( pEvent ) + [NSApp sendEvent: pEvent]; + [NSApp updateWindows]; + + AcquireYieldMutex( nCount ); + + // #i86581# + // FIXME: sometimes the NSTimer will never fire. Firing it by hand then + // fixes the problem even seems to set the correct next firing date + // Why oh why ? + if( ! pEvent && AquaSalTimer::pRunningTimer ) + { + // this cause crashes on MacOSX 10.4 + // [AquaSalTimer::pRunningTimer fire]; + ImplGetSVData()->mpSalTimer->CallCallback(); + } + } + + mbWaitingYield = bOldWaitingYield; + + // collect update rectangles + const std::list< AquaSalFrame* > rFrames( GetSalData()->maFrames ); + for( std::list< AquaSalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it ) + { + if( (*it)->mbShown && ! (*it)->maInvalidRect.IsEmpty() ) + { + (*it)->Flush( (*it)->maInvalidRect ); + (*it)->maInvalidRect.SetEmpty(); + } + } + osl_setCondition( maWaitingYieldCond ); + } + else if( bWait ) + { + // #i103162# + // wait until any thread (most likely the main thread) + // has dispatched an event, cop out at 200 ms + osl_resetCondition( maWaitingYieldCond ); + TimeValue aVal = { 0, 200000000 }; + sal_uLong nCount = ReleaseYieldMutex(); + osl_waitCondition( maWaitingYieldCond, &aVal ); + AcquireYieldMutex( nCount ); + } + + // we get some apple events way too early + // before the application is ready to handle them, + // so their corresponding application events need to be delayed + // now is a good time to handle at least one of them + if( bWait && !aAppEventList.empty() && ImplGetSVData()->maAppData.mbInAppExecute ) + { + // make sure that only one application event is active at a time + static bool bInAppEvent = false; + if( !bInAppEvent ) + { + bInAppEvent = true; + // get the next delayed application event + const ApplicationEvent* pAppEvent = aAppEventList.front(); + aAppEventList.pop_front(); + // handle one application event (no recursion) + const ImplSVData* pSVData = ImplGetSVData(); + pSVData->mpApp->AppEvent( *pAppEvent ); + delete pAppEvent; + // allow the next delayed application event + bInAppEvent = false; + } + } +} + +// ----------------------------------------------------------------------- + +bool AquaSalInstance::AnyInput( sal_uInt16 nType ) +{ + if( nType & VCL_INPUT_APPEVENT ) + { + if( ! aAppEventList.empty() ) + return true; + if( nType == VCL_INPUT_APPEVENT ) + return false; + } + + if( nType & VCL_INPUT_TIMER ) + { + if( AquaSalTimer::pRunningTimer ) + { + NSDate* pDt = [AquaSalTimer::pRunningTimer fireDate]; + if( pDt && [pDt timeIntervalSinceNow] < 0 ) + { + return true; + } + } + } + + unsigned/*NSUInteger*/ nEventMask = 0; + if( nType & VCL_INPUT_MOUSE) + nEventMask |= + NSLeftMouseDownMask | NSRightMouseDownMask | NSOtherMouseDownMask | + NSLeftMouseUpMask | NSRightMouseUpMask | NSOtherMouseUpMask | + NSLeftMouseDraggedMask | NSRightMouseDraggedMask | NSOtherMouseDraggedMask | + NSScrollWheelMask | + // NSMouseMovedMask | + NSMouseEnteredMask | NSMouseExitedMask; + if( nType & VCL_INPUT_KEYBOARD) + nEventMask |= NSKeyDownMask | NSKeyUpMask | NSFlagsChangedMask; + if( nType & VCL_INPUT_OTHER) + nEventMask |= NSTabletPoint; + // TODO: VCL_INPUT_PAINT / more VCL_INPUT_OTHER + if( !nType) + return false; + + NSEvent* pEvent = [NSApp nextEventMatchingMask: nEventMask untilDate: nil + inMode: NSDefaultRunLoopMode dequeue: NO]; + return (pEvent != NULL); +} + +// ----------------------------------------------------------------------- + +SalFrame* AquaSalInstance::CreateChildFrame( SystemParentData*, sal_uLong /*nSalFrameStyle*/ ) +{ + return NULL; +} + +// ----------------------------------------------------------------------- + +SalFrame* AquaSalInstance::CreateFrame( SalFrame* pParent, sal_uLong nSalFrameStyle ) +{ + SalData::ensureThreadAutoreleasePool(); + + SalFrame* pFrame = new AquaSalFrame( pParent, nSalFrameStyle ); + return pFrame; +} + +// ----------------------------------------------------------------------- + +void AquaSalInstance::DestroyFrame( SalFrame* pFrame ) +{ + delete pFrame; +} + +// ----------------------------------------------------------------------- + +SalObject* AquaSalInstance::CreateObject( SalFrame* pParent, SystemWindowData* /* pWindowData */, sal_Bool /* bShow */ ) +{ + // SystemWindowData is meaningless on Mac OS X + AquaSalObject *pObject = NULL; + + if ( pParent ) + pObject = new AquaSalObject( static_cast(pParent) ); + + return pObject; +} + +// ----------------------------------------------------------------------- + +void AquaSalInstance::DestroyObject( SalObject* pObject ) +{ + delete ( pObject ); +} + +// ----------------------------------------------------------------------- + +SalPrinter* AquaSalInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter ) +{ + return new AquaSalPrinter( dynamic_cast(pInfoPrinter) ); +} + +// ----------------------------------------------------------------------- + +void AquaSalInstance::DestroyPrinter( SalPrinter* pPrinter ) +{ + delete pPrinter; +} + +// ----------------------------------------------------------------------- + +void AquaSalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList ) +{ + NSArray* pNames = [NSPrinter printerNames]; + NSArray* pTypes = [NSPrinter printerTypes]; + unsigned int nNameCount = pNames ? [pNames count] : 0; + unsigned int nTypeCount = pTypes ? [pTypes count] : 0; + DBG_ASSERT( nTypeCount == nNameCount, "type count not equal to printer count" ); + for( unsigned int i = 0; i < nNameCount; i++ ) + { + NSString* pName = [pNames objectAtIndex: i]; + NSString* pType = i < nTypeCount ? [pTypes objectAtIndex: i] : nil; + if( pName ) + { + SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo; + pInfo->maPrinterName = GetOUString( pName ); + if( pType ) + pInfo->maDriver = GetOUString( pType ); + pInfo->mnStatus = 0; + pInfo->mnJobs = 0; + pInfo->mpSysData = NULL; + + pList->Add( pInfo ); + } + } +} + +// ----------------------------------------------------------------------- + +void AquaSalInstance::GetPrinterQueueState( SalPrinterQueueInfo* ) +{ +} + +// ----------------------------------------------------------------------- + +void AquaSalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo ) +{ + delete pInfo; +} + +// ----------------------------------------------------------------------- + +OUString AquaSalInstance::GetDefaultPrinter() +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + if( maDefaultPrinter.isEmpty() ) + { + NSPrintInfo* pPI = [NSPrintInfo sharedPrintInfo]; + DBG_ASSERT( pPI, "no print info" ); + if( pPI ) + { + NSPrinter* pPr = [pPI printer]; + DBG_ASSERT( pPr, "no printer in default info" ); + if( pPr ) + { + NSString* pDefName = [pPr name]; + DBG_ASSERT( pDefName, "printer has no name" ); + maDefaultPrinter = GetOUString( pDefName ); + } + } + } + return maDefaultPrinter; +} + +// ----------------------------------------------------------------------- + +SalInfoPrinter* AquaSalInstance::CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo, + ImplJobSetup* pSetupData ) +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + SalInfoPrinter* pNewInfoPrinter = NULL; + if( pQueueInfo ) + { + pNewInfoPrinter = new AquaSalInfoPrinter( *pQueueInfo ); + if( pSetupData ) + pNewInfoPrinter->SetPrinterData( pSetupData ); + } + + return pNewInfoPrinter; +} + +// ----------------------------------------------------------------------- + +void AquaSalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter ) +{ + // #i113170# may not be the main thread if called from UNO API + SalData::ensureThreadAutoreleasePool(); + + delete pPrinter; +} + +// ----------------------------------------------------------------------- + +SalSystem* AquaSalInstance::CreateSystem() +{ + return new AquaSalSystem(); +} + +// ----------------------------------------------------------------------- + +void AquaSalInstance::DestroySystem( SalSystem* pSystem ) +{ + delete pSystem; +} + +// ----------------------------------------------------------------------- + +void AquaSalInstance::SetEventCallback( void*, bool(*)(void*,void*,int) ) +{ +} + +// ----------------------------------------------------------------------- + +void AquaSalInstance::SetErrorEventCallback( void*, bool(*)(void*,void*,int) ) +{ +} + +// ----------------------------------------------------------------------- + +void* AquaSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes ) +{ + rReturnedBytes = 1; + rReturnedType = AsciiCString; + return (void*)""; +} + +// We need to re-encode file urls because osl_getFileURLFromSystemPath converts +// to UTF-8 before encoding non ascii characters, which is not what other apps expect. +static OUString translateToExternalUrl(const OUString& internalUrl) +{ + uno::Reference< uno::XComponentContext > context( + comphelper::getProcessComponentContext()); + return uri::ExternalUriReferenceTranslator::create(context)->translateToExternal(internalUrl); +} + +// #i104525# many versions of OSX have problems with some URLs: +// when an app requests OSX to add one of these URLs to the "Recent Items" list +// then this app gets killed (TextEdit, Preview, etc. and also OOo) +static bool isDangerousUrl( const OUString& rUrl ) +{ + // use a heuristic that detects all known cases since there is no official comment + // on the exact impact and root cause of the OSX bug + const int nLen = rUrl.getLength(); + const sal_Unicode* p = rUrl.getStr(); + for( int i = 0; i < nLen-3; ++i, ++p ) { + if( p[0] != '%' ) + continue; + // escaped percent? + if( (p[1] == '2') && (p[2] == '5') ) + return true; + // escapes are considered to be UTF-8 encoded + // => check for invalid UTF-8 leading byte + if( (p[1] != 'f') && (p[1] != 'F') ) + continue; + int cLowNibble = p[2]; + if( (cLowNibble >= '0' ) && (cLowNibble <= '9')) + return false; + if( cLowNibble >= 'a' ) + cLowNibble -= 'a' - 'A'; + if( (cLowNibble < 'A') || (cLowNibble >= 'C')) + return true; + } + + return false; +} + +void AquaSalInstance::AddToRecentDocumentList(const OUString& rFileUrl, const OUString& /*rMimeType*/, const OUString& /*rDocumentService*/) +{ + // Convert file URL for external use (see above) + OUString externalUrl = translateToExternalUrl(rFileUrl); + if( externalUrl.isEmpty() ) + externalUrl = rFileUrl; + + if( !externalUrl.isEmpty() && !isDangerousUrl( externalUrl ) ) + { + NSString* pString = CreateNSString( externalUrl ); + NSURL* pURL = [NSURL URLWithString: pString]; + + if( pURL ) + { + NSDocumentController* pCtrl = [NSDocumentController sharedDocumentController]; + [pCtrl noteNewRecentDocumentURL: pURL]; + } + if( pString ) + [pString release]; + } +} + + +// ----------------------------------------------------------------------- + +SalTimer* AquaSalInstance::CreateSalTimer() +{ + return new AquaSalTimer(); +} + +// ----------------------------------------------------------------------- + +SalSystem* AquaSalInstance::CreateSalSystem() +{ + return new AquaSalSystem(); +} + +// ----------------------------------------------------------------------- + +SalBitmap* AquaSalInstance::CreateSalBitmap() +{ + return new QuartzSalBitmap(); +} + +// ----------------------------------------------------------------------- + +SalSession* AquaSalInstance::CreateSalSession() +{ + return NULL; +} + +// ----------------------------------------------------------------------- + +class MacImeStatus : public SalI18NImeStatus +{ +public: + MacImeStatus() {} + virtual ~MacImeStatus() {} + + // asks whether there is a status window available + // to toggle into menubar + virtual bool canToggle() { return false; } + virtual void toggle() {} +}; + +// ----------------------------------------------------------------------- + +SalI18NImeStatus* AquaSalInstance::CreateI18NImeStatus() +{ + return new MacImeStatus(); +} + +// YieldMutexReleaser +YieldMutexReleaser::YieldMutexReleaser() : mnCount( 0 ) +{ + SalData* pSalData = GetSalData(); + if( ! pSalData->mpFirstInstance->isNSAppThread() ) + { + SalData::ensureThreadAutoreleasePool(); + mnCount = pSalData->mpFirstInstance->ReleaseYieldMutex(); + } +} + +YieldMutexReleaser::~YieldMutexReleaser() +{ + if( mnCount != 0 ) + GetSalData()->mpFirstInstance->AcquireYieldMutex( mnCount ); +} + +CGImageRef CreateCGImage( const Image& rImage ) +{ + BitmapEx aBmpEx( rImage.GetBitmapEx() ); + Bitmap aBmp( aBmpEx.GetBitmap() ); + + if( ! aBmp || ! aBmp.ImplGetImpBitmap() ) + return NULL; + + // simple case, no transparency + QuartzSalBitmap* pSalBmp = static_cast(aBmp.ImplGetImpBitmap()->ImplGetSalBitmap()); + + if( ! pSalBmp ) + return NULL; + + CGImageRef xImage = NULL; + if( ! (aBmpEx.IsAlpha() || aBmpEx.IsTransparent() ) ) + xImage = pSalBmp->CreateCroppedImage( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight ); + else if( aBmpEx.IsAlpha() ) + { + AlphaMask aAlphaMask( aBmpEx.GetAlpha() ); + Bitmap aMask( aAlphaMask.GetBitmap() ); + QuartzSalBitmap* pMaskBmp = static_cast(aMask.ImplGetImpBitmap()->ImplGetSalBitmap()); + if( pMaskBmp ) + xImage = pSalBmp->CreateWithMask( *pMaskBmp, 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight ); + else + xImage = pSalBmp->CreateCroppedImage( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight ); + } + else if( aBmpEx.GetTransparentType() == TRANSPARENT_BITMAP ) + { + Bitmap aMask( aBmpEx.GetMask() ); + QuartzSalBitmap* pMaskBmp = static_cast(aMask.ImplGetImpBitmap()->ImplGetSalBitmap()); + if( pMaskBmp ) + xImage = pSalBmp->CreateWithMask( *pMaskBmp, 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight ); + else + xImage = pSalBmp->CreateCroppedImage( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight ); + } + else if( aBmpEx.GetTransparentType() == TRANSPARENT_COLOR ) + { + Color aTransColor( aBmpEx.GetTransparentColor() ); + SalColor nTransColor = MAKE_SALCOLOR( aTransColor.GetRed(), aTransColor.GetGreen(), aTransColor.GetBlue() ); + xImage = pSalBmp->CreateColorMask( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight, nTransColor ); + } + + return xImage; +} + +NSImage* CreateNSImage( const Image& rImage ) +{ + CGImageRef xImage = CreateCGImage( rImage ); + + if( ! xImage ) + return nil; + + Size aSize( rImage.GetSizePixel() ); + NSImage* pImage = [[NSImage alloc] initWithSize: NSMakeSize( aSize.Width(), aSize.Height() )]; + if( pImage ) + { + [pImage setFlipped: YES]; + [pImage lockFocus]; + + NSGraphicsContext* pContext = [NSGraphicsContext currentContext]; + CGContextRef rCGContext = reinterpret_cast([pContext graphicsPort]); + + const CGRect aDstRect = { {0, 0}, { static_cast(aSize.Width()), static_cast(aSize.Height()) } }; + CGContextDrawImage( rCGContext, aDstRect, xImage ); + + [pImage unlockFocus]; + } + + CGImageRelease( xImage ); + + return pImage; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/salmenu.cxx b/vcl/osx/salmenu.cxx new file mode 100644 index 000000000000..db3dd2ef845c --- /dev/null +++ b/vcl/osx/salmenu.cxx @@ -0,0 +1,963 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include "rtl/ustrbuf.hxx" + +#include "vcl/cmdevt.hxx" +#include "vcl/floatwin.hxx" +#include "vcl/window.hxx" +#include "vcl/svapp.hxx" + +#include "osx/saldata.hxx" +#include "osx/salinst.h" +#include "osx/salmenu.h" +#include "osx/salnsmenu.h" +#include "osx/salframe.h" +#include "osx/a11ywrapper.h" +#include "quartz/utils.h" + +#include "svids.hrc" +#include "window.h" + +#include + +const AquaSalMenu* AquaSalMenu::pCurrentMenuBar = NULL; + +@interface MainMenuSelector : NSObject +{ +} +-(void)showDialog: (int)nDialog; +-(void)showPreferences: (id)sender; +-(void)showAbout: (id)sender; +@end + +@implementation MainMenuSelector +-(void)showDialog: (int)nDialog +{ + if( AquaSalMenu::pCurrentMenuBar ) + { + const AquaSalFrame* pFrame = AquaSalMenu::pCurrentMenuBar->mpFrame; + if( pFrame && AquaSalFrame::isAlive( pFrame ) ) + { + pFrame->CallCallback( SALEVENT_SHOWDIALOG, reinterpret_cast(nDialog) ); + } + } + else + { + OUString aDialog; + if( nDialog == SHOWDIALOG_ID_ABOUT ) + aDialog = "ABOUT"; + else if( nDialog == SHOWDIALOG_ID_PREFERENCES ) + aDialog = "PREFERENCES"; + const ApplicationEvent* pAppEvent = new ApplicationEvent( + ApplicationEvent::TYPE_SHOWDIALOG, aDialog); + AquaSalInstance::aAppEventList.push_back( pAppEvent ); + } +} + +-(void)showPreferences: (id) sender +{ + (void)sender; + YIELD_GUARD; + + [self showDialog: SHOWDIALOG_ID_PREFERENCES]; +} +-(void)showAbout: (id) sender +{ + (void)sender; + YIELD_GUARD; + + [self showDialog: SHOWDIALOG_ID_ABOUT]; +} +@end + + +// FIXME: currently this is leaked +static MainMenuSelector* pMainMenuSelector = nil; + +static void initAppMenu() +{ + static bool bOnce = true; + if( bOnce ) + { + bOnce = false; + + ResMgr* pMgr = ImplGetResMgr(); + if( pMgr ) + { + // get the main menu + NSMenu* pMainMenu = [NSApp mainMenu]; + if( pMainMenu != nil ) + { + // create the action selector + pMainMenuSelector = [[MainMenuSelector alloc] init]; + + // get the proper submenu + NSMenu* pAppMenu = [[pMainMenu itemAtIndex: 0] submenu]; + if( pAppMenu ) + { + // insert about entry + OUString aAbout( ResId( SV_STDTEXT_ABOUT, *pMgr ) ); + NSString* pString = CreateNSString( aAbout ); + NSMenuItem* pNewItem = [pAppMenu insertItemWithTitle: pString + action: @selector(showAbout:) + keyEquivalent: @"" + atIndex: 0]; + if (pString) + [pString release]; + if( pNewItem ) + { + [pNewItem setTarget: pMainMenuSelector]; + [pAppMenu insertItem: [NSMenuItem separatorItem] atIndex: 1]; + } + + // insert preferences entry + OUString aPref( ResId( SV_STDTEXT_PREFERENCES, *pMgr ) ); + pString = CreateNSString( aPref ); + pNewItem = [pAppMenu insertItemWithTitle: pString + action: @selector(showPreferences:) + keyEquivalent: @"," + atIndex: 2]; + if (pString) + [pString release]; + if( pNewItem ) + { + [pNewItem setKeyEquivalentModifierMask: NSCommandKeyMask]; + [pNewItem setTarget: pMainMenuSelector]; + [pAppMenu insertItem: [NSMenuItem separatorItem] atIndex: 3]; + } + + // WARNING: ultra ugly code ahead + + // rename standard entries + // rename "Services" + pNewItem = [pAppMenu itemAtIndex: 4]; + if( pNewItem ) + { + pString = CreateNSString( OUString( ResId( SV_MENU_MAC_SERVICES, *pMgr ) ) ); + [pNewItem setTitle: pString]; + if( pString ) + [pString release]; + } + + // rename "Hide NewApplication" + pNewItem = [pAppMenu itemAtIndex: 6]; + if( pNewItem ) + { + pString = CreateNSString( OUString( ResId( SV_MENU_MAC_HIDEAPP, *pMgr ) ) ); + [pNewItem setTitle: pString]; + if( pString ) + [pString release]; + } + + // rename "Hide Others" + pNewItem = [pAppMenu itemAtIndex: 7]; + if( pNewItem ) + { + pString = CreateNSString( OUString( ResId( SV_MENU_MAC_HIDEALL, *pMgr ) ) ); + [pNewItem setTitle: pString]; + if( pString ) + [pString release]; + } + + // rename "Show all" + pNewItem = [pAppMenu itemAtIndex: 8]; + if( pNewItem ) + { + pString = CreateNSString( OUString( ResId( SV_MENU_MAC_SHOWALL, *pMgr ) ) ); + [pNewItem setTitle: pString]; + if( pString ) + [pString release]; + } + + // rename "Quit NewApplication" + pNewItem = [pAppMenu itemAtIndex: 10]; + if( pNewItem ) + { + pString = CreateNSString( OUString( ResId( SV_MENU_MAC_QUITAPP, *pMgr ) ) ); + [pNewItem setTitle: pString]; + if( pString ) + [pString release]; + } + } + } + } + } +} + +// ======================================================================= + +SalMenu* AquaSalInstance::CreateMenu( sal_Bool bMenuBar, Menu* pVCLMenu ) +{ + initAppMenu(); + + AquaSalMenu *pAquaSalMenu = new AquaSalMenu( bMenuBar ); + pAquaSalMenu->mpVCLMenu = pVCLMenu; + + return pAquaSalMenu; +} + +void AquaSalInstance::DestroyMenu( SalMenu* pSalMenu ) +{ + delete pSalMenu; +} + +SalMenuItem* AquaSalInstance::CreateMenuItem( const SalItemParams* pItemData ) +{ + if( !pItemData ) + return NULL; + + AquaSalMenuItem *pSalMenuItem = new AquaSalMenuItem( pItemData ); + + return pSalMenuItem; +} + +void AquaSalInstance::DestroyMenuItem( SalMenuItem* pSalMenuItem ) +{ + delete pSalMenuItem; +} + + +// ======================================================================= + + +/* + * AquaSalMenu + */ + +AquaSalMenu::AquaSalMenu( bool bMenuBar ) : + mbMenuBar( bMenuBar ), + mpMenu( nil ), + mpVCLMenu( NULL ), + mpFrame( NULL ), + mpParentSalMenu( NULL ) +{ + if( ! mbMenuBar ) + { + mpMenu = [[SalNSMenu alloc] initWithMenu: this]; + // With the 10.6 SDK and gcc 4.2.1, we get: class 'NSMenu' + // does not implement the 'NSMenuDelegate' protocol. Anyway, + // having the menu object be its own delegate object is + // apparently what the code does on purpose. + + // So to silcense the warning, instead of: + // [mpMenu setDelegate: mpMenu]; + // do this: + objc_msgSend(mpMenu, @selector(setDelegate:), mpMenu); + } + else + { + mpMenu = [NSApp mainMenu]; + } + [mpMenu setAutoenablesItems: NO]; +} + +AquaSalMenu::~AquaSalMenu() +{ + // actually someone should have done AquaSalFrame::SetMenu( NULL ) + // on our frame, alas it is not so + if( mpFrame && AquaSalFrame::isAlive( mpFrame ) && mpFrame->mpMenu == this ) + const_cast(mpFrame)->mpMenu = NULL; + + // this should normally be empty already, but be careful... + for( size_t i = 0; i < maButtons.size(); i++ ) + releaseButtonEntry( maButtons[i] ); + maButtons.clear(); + + // is this leaking in some cases ? the release often leads to a duplicate release + // it seems the parent item gets ownership of the menu + if( mpMenu ) + { + if( mbMenuBar ) + { + if( pCurrentMenuBar == this ) + { + // if the current menubar gets destroyed, set the default menubar + setDefaultMenu(); + } + } + else + // the system may still hold a reference on mpMenu + { + // so set the pointer to this AquaSalMenu to NULL + // to protect from calling a dead object + + // in ! mbMenuBar case our mpMenu is actually a SalNSMenu* + // so we can safely cast here + [static_cast(mpMenu) setSalMenu: NULL]; + /* #i89860# FIXME: + using [autorelease] here (and in AquaSalMenuItem::~AquaSalMenuItem) + instead of [release] fixes an occasional crash. That should + indicate that we release menus / menu items in the wrong order + somewhere, but I could not find that case. + */ + [mpMenu autorelease]; + } + } +} + +sal_Int32 removeUnusedItemsRunner(NSMenu * pMenu) +{ + NSArray * elements = [pMenu itemArray]; + NSEnumerator * it = [elements objectEnumerator]; + id elem; + NSMenuItem * lastDisplayedMenuItem = nil; + sal_Int32 drawnItems = 0; + bool firstEnabledItemIsNoSeparator = false; + while((elem=[it nextObject]) != nil) { + NSMenuItem * item = static_cast(elem); + if( (![item isEnabled] && ![item isSeparatorItem]) || ([item isSeparatorItem] && (lastDisplayedMenuItem != nil && [lastDisplayedMenuItem isSeparatorItem])) ) { + [[item menu]removeItem:item]; + } else { + if( ! firstEnabledItemIsNoSeparator && [item isSeparatorItem] ) { + [[item menu]removeItem:item]; + } else { + firstEnabledItemIsNoSeparator = true; + lastDisplayedMenuItem = item; + drawnItems++; + if( [item hasSubmenu] ) { + removeUnusedItemsRunner( [item submenu] ); + } + } + } + } + if( lastDisplayedMenuItem != nil && [lastDisplayedMenuItem isSeparatorItem]) { + [[lastDisplayedMenuItem menu]removeItem:lastDisplayedMenuItem]; + } + return drawnItems; +} + +bool AquaSalMenu::ShowNativePopupMenu(FloatingWindow * pWin, const Rectangle& rRect, sal_uLong nFlags) +{ + // do not use native popup menu when AQUA_NATIVE_MENUS is set to sal_False + if( ! VisibleMenuBar() ) { + return false; + } + + // set offsets for positioning + const float offset = 9.0; + + // get the pointers + AquaSalFrame * pParentAquaSalFrame = (AquaSalFrame *) pWin->ImplGetWindowImpl()->mpRealParent->ImplGetFrame(); + NSWindow* pParentNSWindow = pParentAquaSalFrame->mpNSWindow; + NSView* pParentNSView = [pParentNSWindow contentView]; + NSView* pPopupNSView = ((AquaSalFrame *) pWin->ImplGetWindow()->ImplGetFrame())->mpNSView; + NSRect popupFrame = [pPopupNSView frame]; + + // since we manipulate the menu below (removing entries) + // let's rather make a copy here and work with that + NSMenu* pCopyMenu = [mpMenu copy]; + + // filter disabled elements + removeUnusedItemsRunner( pCopyMenu ); + + // create frame rect + NSRect displayPopupFrame = NSMakeRect( rRect.Left()+(offset-1), rRect.Top()+(offset+1), popupFrame.size.width, 0 ); + pParentAquaSalFrame->VCLToCocoa(displayPopupFrame, false); + + // do the same strange semantics as vcl popup windows to arrive at a frame geometry + // in mirrored UI case; best done by actually executing the same code + sal_uInt16 nArrangeIndex; + pWin->SetPosPixel( pWin->ImplCalcPos( pWin, rRect, nFlags, nArrangeIndex ) ); + displayPopupFrame.origin.x = pWin->ImplGetFrame()->maGeometry.nX - pParentAquaSalFrame->maGeometry.nX + offset; + displayPopupFrame.origin.y = pWin->ImplGetFrame()->maGeometry.nY - pParentAquaSalFrame->maGeometry.nY + offset; + pParentAquaSalFrame->VCLToCocoa(displayPopupFrame, false); + + // #i111992# if this menu was opened due to a key event, prevent dispatching that yet again + if( [pParentNSView respondsToSelector: @selector(clearLastEvent)] ) + [pParentNSView performSelector:@selector(clearLastEvent)]; + + // open popup menu + NSPopUpButtonCell * pPopUpButtonCell = [[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]; + [pPopUpButtonCell setMenu: pCopyMenu]; + [pPopUpButtonCell selectItem:nil]; + [AquaA11yWrapper setPopupMenuOpen: YES]; + [pPopUpButtonCell performClickWithFrame:displayPopupFrame inView:pParentNSView]; + [pPopUpButtonCell release]; + [AquaA11yWrapper setPopupMenuOpen: NO]; + + // clean up the copy + [pCopyMenu release]; + return true; +} + +int AquaSalMenu::getItemIndexByPos( sal_uInt16 nPos ) const +{ + int nIndex = 0; + if( nPos == MENU_APPEND ) + nIndex = [mpMenu numberOfItems]; + else + nIndex = sal::static_int_cast( mbMenuBar ? nPos+1 : nPos ); + return nIndex; +} + +const AquaSalFrame* AquaSalMenu::getFrame() const +{ + const AquaSalMenu* pMenu = this; + while( pMenu && ! pMenu->mpFrame ) + pMenu = pMenu->mpParentSalMenu; + return pMenu ? pMenu->mpFrame : NULL; +} + +void AquaSalMenu::unsetMainMenu() +{ + pCurrentMenuBar = NULL; + + // remove items from main menu + NSMenu* pMenu = [NSApp mainMenu]; + for( int nItems = [pMenu numberOfItems]; nItems > 1; nItems-- ) + [pMenu removeItemAtIndex: 1]; +} + +void AquaSalMenu::setMainMenu() +{ + DBG_ASSERT( mbMenuBar, "setMainMenu on non menubar" ); + if( mbMenuBar ) + { + if( pCurrentMenuBar != this ) + { + unsetMainMenu(); + // insert our items + for( unsigned int i = 0; i < maItems.size(); i++ ) + { + NSMenuItem* pItem = maItems[i]->mpMenuItem; + [mpMenu insertItem: pItem atIndex: i+1]; + } + pCurrentMenuBar = this; + + // change status item + statusLayout(); + } + enableMainMenu( true ); + } +} + +void AquaSalMenu::setDefaultMenu() +{ + NSMenu* pMenu = [NSApp mainMenu]; + + unsetMainMenu(); + + // insert default items + std::vector< NSMenuItem* >& rFallbackMenu( GetSalData()->maFallbackMenu ); + for( unsigned int i = 0, nAddItems = rFallbackMenu.size(); i < nAddItems; i++ ) + { + NSMenuItem* pItem = rFallbackMenu[i]; + if( [pItem menu] == nil ) + [pMenu insertItem: pItem atIndex: i+1]; + } +} + +void AquaSalMenu::enableMainMenu( bool bEnable ) +{ + NSMenu* pMainMenu = [NSApp mainMenu]; + if( pMainMenu ) + { + // enable/disable items from main menu + int nItems = [pMainMenu numberOfItems]; + for( int n = 1; n < nItems; n++ ) + { + NSMenuItem* pItem = [pMainMenu itemAtIndex: n]; + [pItem setEnabled: bEnable ? YES : NO]; + } + } +} + +void AquaSalMenu::addFallbackMenuItem( NSMenuItem* pNewItem ) +{ + initAppMenu(); + + std::vector< NSMenuItem* >& rFallbackMenu( GetSalData()->maFallbackMenu ); + + // prevent duplicate insertion + int nItems = rFallbackMenu.size(); + for( int i = 0; i < nItems; i++ ) + { + if( rFallbackMenu[i] == pNewItem ) + return; + } + + // push the item to the back and retain it + [pNewItem retain]; + rFallbackMenu.push_back( pNewItem ); + + if( pCurrentMenuBar == NULL ) + setDefaultMenu(); +} + +void AquaSalMenu::removeFallbackMenuItem( NSMenuItem* pOldItem ) +{ + std::vector< NSMenuItem* >& rFallbackMenu( GetSalData()->maFallbackMenu ); + + // find item + unsigned int nItems = rFallbackMenu.size(); + for( unsigned int i = 0; i < nItems; i++ ) + { + if( rFallbackMenu[i] == pOldItem ) + { + // remove item and release + rFallbackMenu.erase( rFallbackMenu.begin() + i ); + [pOldItem release]; + + if( pCurrentMenuBar == NULL ) + setDefaultMenu(); + + return; + } + } +} + +sal_Bool AquaSalMenu::VisibleMenuBar() +{ + // Enable/disable experimental native menus code? + // + // To disable native menus, set the environment variable AQUA_NATIVE_MENUS to FALSE + + static const char *pExperimental = getenv ("AQUA_NATIVE_MENUS"); + + if ( pExperimental && !strcasecmp(pExperimental, "FALSE") ) + return sal_False; + + // End of experimental code enable/disable part + + return sal_True; +} + +void AquaSalMenu::SetFrame( const SalFrame *pFrame ) +{ + mpFrame = static_cast(pFrame); +} + +void AquaSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos ) +{ + AquaSalMenuItem *pAquaSalMenuItem = static_cast(pSalMenuItem); + + pAquaSalMenuItem->mpParentMenu = this; + DBG_ASSERT( pAquaSalMenuItem->mpVCLMenu == NULL || + pAquaSalMenuItem->mpVCLMenu == mpVCLMenu || + mpVCLMenu == NULL, + "resetting menu ?" ); + if( pAquaSalMenuItem->mpVCLMenu ) + mpVCLMenu = pAquaSalMenuItem->mpVCLMenu; + + if( nPos == MENU_APPEND || nPos == maItems.size() ) + maItems.push_back( pAquaSalMenuItem ); + else if( nPos < maItems.size() ) + maItems.insert( maItems.begin() + nPos, pAquaSalMenuItem ); + else + { + OSL_FAIL( "invalid item index in insert" ); + return; + } + + if( ! mbMenuBar || pCurrentMenuBar == this ) + [mpMenu insertItem: pAquaSalMenuItem->mpMenuItem atIndex: getItemIndexByPos(nPos)]; +} + +void AquaSalMenu::RemoveItem( unsigned nPos ) +{ + AquaSalMenuItem* pRemoveItem = NULL; + if( nPos == MENU_APPEND || nPos == (maItems.size()-1) ) + { + pRemoveItem = maItems.back(); + maItems.pop_back(); + } + else if( nPos < maItems.size() ) + { + pRemoveItem = maItems[ nPos ]; + maItems.erase( maItems.begin()+nPos ); + } + else + { + OSL_FAIL( "invalid item index in remove" ); + return; + } + + pRemoveItem->mpParentMenu = NULL; + + if( ! mbMenuBar || pCurrentMenuBar == this ) + [mpMenu removeItemAtIndex: getItemIndexByPos(nPos)]; +} + +void AquaSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned /*nPos*/ ) +{ + AquaSalMenuItem *pAquaSalMenuItem = static_cast(pSalMenuItem); + AquaSalMenu *subAquaSalMenu = static_cast(pSubMenu); + + if (subAquaSalMenu) + { + pAquaSalMenuItem->mpSubMenu = subAquaSalMenu; + if( subAquaSalMenu->mpParentSalMenu == NULL ) + { + subAquaSalMenu->mpParentSalMenu = this; + [pAquaSalMenuItem->mpMenuItem setSubmenu: subAquaSalMenu->mpMenu]; + + // set title of submenu + [subAquaSalMenu->mpMenu setTitle: [pAquaSalMenuItem->mpMenuItem title]]; + } + else if( subAquaSalMenu->mpParentSalMenu != this ) + { + // cocoa doesn't allow menus to be submenus of multiple + // menu items, so place a copy in the menu item instead ? + // let's hope that NSMenu copy does the right thing + NSMenu* pCopy = [subAquaSalMenu->mpMenu copy]; + [pAquaSalMenuItem->mpMenuItem setSubmenu: pCopy]; + + // set title of submenu + [pCopy setTitle: [pAquaSalMenuItem->mpMenuItem title]]; + } + } + else + { + if( pAquaSalMenuItem->mpSubMenu ) + { + if( pAquaSalMenuItem->mpSubMenu->mpParentSalMenu == this ) + pAquaSalMenuItem->mpSubMenu->mpParentSalMenu = NULL; + } + pAquaSalMenuItem->mpSubMenu = NULL; + [pAquaSalMenuItem->mpMenuItem setSubmenu: nil]; + } +} + +void AquaSalMenu::CheckItem( unsigned nPos, sal_Bool bCheck ) +{ + if( nPos < maItems.size() ) + { + NSMenuItem* pItem = maItems[nPos]->mpMenuItem; + [pItem setState: bCheck ? NSOnState : NSOffState]; + } +} + +void AquaSalMenu::EnableItem( unsigned nPos, sal_Bool bEnable ) +{ + if( nPos < maItems.size() ) + { + NSMenuItem* pItem = maItems[nPos]->mpMenuItem; + [pItem setEnabled: bEnable ? YES : NO]; + } +} + +void AquaSalMenu::SetItemImage( unsigned /*nPos*/, SalMenuItem* pSMI, const Image& rImage ) +{ + AquaSalMenuItem* pSalMenuItem = static_cast( pSMI ); + if( ! pSalMenuItem || ! pSalMenuItem->mpMenuItem ) + return; + + NSImage* pImage = CreateNSImage( rImage ); + + [pSalMenuItem->mpMenuItem setImage: pImage]; + if( pImage ) + [pImage release]; +} + +void AquaSalMenu::SetItemText( unsigned /*i_nPos*/, SalMenuItem* i_pSalMenuItem, const OUString& i_rText ) +{ + if (!i_pSalMenuItem) + return; + + AquaSalMenuItem *pAquaSalMenuItem = (AquaSalMenuItem *) i_pSalMenuItem; + + // Delete mnemonics + OUString aText( comphelper::string::remove(i_rText, '~') ); + + /* #i90015# until there is a correct solution + strip out any appended (.*) in menubar entries + */ + if( mbMenuBar ) + { + sal_Int32 nPos = aText.lastIndexOf( '(' ); + if( nPos != -1 ) + { + sal_Int32 nPos2 = aText.indexOf( ')' ); + if( nPos2 != -1 ) + aText = aText.replaceAt( nPos, nPos2-nPos+1, "" ); + } + } + + NSString* pString = CreateNSString( aText ); + if (pString) + { + [pAquaSalMenuItem->mpMenuItem setTitle: pString]; + // if the menu item has a submenu, change its title as well + if (pAquaSalMenuItem->mpSubMenu) + [pAquaSalMenuItem->mpSubMenu->mpMenu setTitle: pString]; + [pString release]; + } +} + +void AquaSalMenu::SetAccelerator( unsigned /*nPos*/, SalMenuItem* pSalMenuItem, const KeyCode& rKeyCode, const OUString& /*rKeyName*/ ) +{ + sal_uInt16 nModifier; + sal_Unicode nCommandKey = 0; + + sal_uInt16 nKeyCode=rKeyCode.GetCode(); + if( nKeyCode ) + { + if ((nKeyCode>=KEY_A) && (nKeyCode<=KEY_Z)) // letter A..Z + nCommandKey = nKeyCode-KEY_A + 'a'; + else if ((nKeyCode>=KEY_0) && (nKeyCode<=KEY_9)) // numbers 0..9 + nCommandKey = nKeyCode-KEY_0 + '0'; + else if ((nKeyCode>=KEY_F1) && (nKeyCode<=KEY_F26)) // function keys F1..F26 + nCommandKey = nKeyCode-KEY_F1 + NSF1FunctionKey; + else if( nKeyCode == KEY_REPEAT ) + nCommandKey = NSRedoFunctionKey; + else if( nKeyCode == KEY_SPACE ) + nCommandKey = ' '; + else + { + switch (nKeyCode) + { + case KEY_ADD: + nCommandKey='+'; + break; + case KEY_SUBTRACT: + nCommandKey='-'; + break; + case KEY_MULTIPLY: + nCommandKey='*'; + break; + case KEY_DIVIDE: + nCommandKey='/'; + break; + case KEY_POINT: + nCommandKey='.'; + break; + case KEY_LESS: + nCommandKey='<'; + break; + case KEY_GREATER: + nCommandKey='>'; + break; + case KEY_EQUAL: + nCommandKey='='; + break; + } + } + } + else // not even a code ? nonsense -> ignore + return; + + DBG_ASSERT( nCommandKey, "unmapped accelerator key" ); + + nModifier=rKeyCode.GetAllModifier(); + + // should always use the command key + int nItemModifier = 0; + + if (nModifier & KEY_SHIFT) + { + nItemModifier |= NSShiftKeyMask; // actually useful only for function keys + if( nKeyCode >= KEY_A && nKeyCode <= KEY_Z ) + nCommandKey = nKeyCode - KEY_A + 'A'; + } + + if (nModifier & KEY_MOD1) + nItemModifier |= NSCommandKeyMask; + + if(nModifier & KEY_MOD2) + nItemModifier |= NSAlternateKeyMask; + + if(nModifier & KEY_MOD3) + nItemModifier |= NSControlKeyMask; + + AquaSalMenuItem *pAquaSalMenuItem = (AquaSalMenuItem *) pSalMenuItem; + NSString* pString = CreateNSString( OUString( &nCommandKey, 1 ) ); + [pAquaSalMenuItem->mpMenuItem setKeyEquivalent: pString]; + [pAquaSalMenuItem->mpMenuItem setKeyEquivalentModifierMask: nItemModifier]; + if (pString) + [pString release]; +} + +void AquaSalMenu::GetSystemMenuData( SystemMenuData* ) +{ +} + +AquaSalMenu::MenuBarButtonEntry* AquaSalMenu::findButtonItem( sal_uInt16 i_nItemId ) +{ + for( size_t i = 0; i < maButtons.size(); ++i ) + { + if( maButtons[i].maButton.mnId == i_nItemId ) + return &maButtons[i]; + } + return NULL; +} + +void AquaSalMenu::statusLayout() +{ + if( GetSalData()->mpStatusItem ) + { + NSView* pNSView = [GetSalData()->mpStatusItem view]; + if( [pNSView isMemberOfClass: [OOStatusItemView class]] ) // well of course it is + [(OOStatusItemView*)pNSView layout]; + else + OSL_FAIL( "someone stole our status view" ); + } +} + +void AquaSalMenu::releaseButtonEntry( MenuBarButtonEntry& i_rEntry ) +{ + if( i_rEntry.mpNSImage ) + { + [i_rEntry.mpNSImage release]; + i_rEntry.mpNSImage = nil; + } + if( i_rEntry.mpToolTipString ) + { + [i_rEntry.mpToolTipString release]; + i_rEntry.mpToolTipString = nil; + } +} + +bool AquaSalMenu::AddMenuBarButton( const SalMenuButtonItem& i_rNewItem ) +{ + if( ! mbMenuBar || ! VisibleMenuBar() ) + return false; + + MenuBarButtonEntry* pEntry = findButtonItem( i_rNewItem.mnId ); + if( pEntry ) + { + releaseButtonEntry( *pEntry ); + pEntry->maButton = i_rNewItem; + pEntry->mpNSImage = CreateNSImage( i_rNewItem.maImage ); + if( i_rNewItem.maToolTipText.getLength() ) + pEntry->mpToolTipString = CreateNSString( i_rNewItem.maToolTipText ); + } + else + { + maButtons.push_back( MenuBarButtonEntry( i_rNewItem ) ); + maButtons.back().mpNSImage = CreateNSImage( i_rNewItem.maImage ); + maButtons.back().mpToolTipString = CreateNSString( i_rNewItem.maToolTipText ); + } + + // lazy create status item + SalData::getStatusItem(); + + if( pCurrentMenuBar == this ) + statusLayout(); + + return true; +} + +void AquaSalMenu::RemoveMenuBarButton( sal_uInt16 i_nId ) +{ + MenuBarButtonEntry* pEntry = findButtonItem( i_nId ); + if( pEntry ) + { + releaseButtonEntry( *pEntry ); + // note: vector guarantees that its contents are in a plain array + maButtons.erase( maButtons.begin() + (pEntry - &maButtons[0]) ); + } + + if( pCurrentMenuBar == this ) + statusLayout(); +} + +Rectangle AquaSalMenu::GetMenuBarButtonRectPixel( sal_uInt16 i_nItemId, SalFrame* i_pReferenceFrame ) +{ + if( ! i_pReferenceFrame || ! AquaSalFrame::isAlive( static_cast(i_pReferenceFrame) ) ) + return Rectangle(); + + MenuBarButtonEntry* pEntry = findButtonItem( i_nItemId ); + + if( ! pEntry ) + return Rectangle(); + + NSStatusItem* pItem = SalData::getStatusItem(); + if( ! pItem ) + return Rectangle(); + + NSView* pNSView = [pItem view]; + if( ! pNSView ) + return Rectangle(); + NSWindow* pNSWin = [pNSView window]; + if( ! pNSWin ) + return Rectangle(); + + NSRect aRect = [pNSWin frame]; + aRect.origin = [pNSWin convertBaseToScreen: NSMakePoint( 0, 0 )]; + + // make coordinates relative to reference frame + static_cast(i_pReferenceFrame)->CocoaToVCL( aRect.origin ); + aRect.origin.x -= i_pReferenceFrame->maGeometry.nX; + aRect.origin.y -= i_pReferenceFrame->maGeometry.nY + aRect.size.height; + + return Rectangle( Point(static_cast(aRect.origin.x), + static_cast(aRect.origin.y) + ), + Size( static_cast(aRect.size.width), + static_cast(aRect.size.height) + ) + ); +} + +// ======================================================================= + +/* + * SalMenuItem + */ + +AquaSalMenuItem::AquaSalMenuItem( const SalItemParams* pItemData ) : + mnId( pItemData->nId ), + mpVCLMenu( pItemData->pMenu ), + mpParentMenu( NULL ), + mpSubMenu( NULL ), + mpMenuItem( nil ) +{ + // Delete mnemonics + OUString aText( comphelper::string::remove(pItemData->aText, '~') ); + + if (pItemData->eType == MENUITEM_SEPARATOR) + { + mpMenuItem = [NSMenuItem separatorItem]; + // these can go occasionally go in and out of a menu, ensure their lifecycle + // also for the release in AquaSalMenuItem destructor + [mpMenuItem retain]; + } + else + { + mpMenuItem = [[SalNSMenuItem alloc] initWithMenuItem: this]; + [mpMenuItem setEnabled: YES]; + NSString* pString = CreateNSString( aText ); + if (pString) + { + [mpMenuItem setTitle: pString]; + [pString release]; + } + // anything but a separator should set a menu to dispatch to + DBG_ASSERT( mpVCLMenu, "no menu" ); + } +} + +AquaSalMenuItem::~AquaSalMenuItem() +{ + /* #i89860# FIXME: + using [autorelease] here (and in AquaSalMenu:::~AquaSalMenu) instead of + [release] fixes an occasional crash. That should indicate that we release + menus / menu items in the wrong order somewhere, but I + could not find that case. + */ + if( mpMenuItem ) + [mpMenuItem autorelease]; +} + +// ------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/salnativewidgets.cxx b/vcl/osx/salnativewidgets.cxx new file mode 100644 index 000000000000..ec6ca1d9c72f --- /dev/null +++ b/vcl/osx/salnativewidgets.cxx @@ -0,0 +1,1462 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "vcl/salnativewidgets.hxx" +#include "vcl/decoview.hxx" +#include "vcl/svapp.hxx" +#include "vcl/timer.hxx" + +#include "quartz/salgdi.h" +#include "osx/salnativewidgets.h" +#include "osx/saldata.hxx" +#include "osx/salframe.h" + +#include "premac.h" +#include +#include "postmac.h" + +#ifndef NSAppKitVersionNumber10_7 +#define NSAppKitVersionNumber10_7 1138 +#endif + +class AquaBlinker : public Timer +{ + AquaSalFrame* mpFrame; + Rectangle maInvalidateRect; + + AquaBlinker( AquaSalFrame* pFrame, const Rectangle& rRect ) + : mpFrame( pFrame ), maInvalidateRect( rRect ) + { + mpFrame->maBlinkers.push_back( this ); + } + + public: + + static void Blink( AquaSalFrame*, const Rectangle&, int nTimeout = 80 ); + + virtual void Timeout() + { + Stop(); + if( AquaSalFrame::isAlive( mpFrame ) && mpFrame->mbShown ) + { + mpFrame->maBlinkers.remove( this ); + mpFrame->SendPaintEvent( &maInvalidateRect ); + } + delete this; + } +}; + +void AquaBlinker::Blink( AquaSalFrame* pFrame, const Rectangle& rRect, int nTimeout ) +{ + // prevent repeated paints from triggering themselves all the time + for( std::list< AquaBlinker* >::const_iterator it = pFrame->maBlinkers.begin(); + it != pFrame->maBlinkers.end(); ++it ) + { + if( (*it)->maInvalidateRect == rRect ) + return; + } + AquaBlinker* pNew = new AquaBlinker( pFrame, rRect ); + pNew->SetTimeout( nTimeout ); + pNew->Start(); +} + +// Helper returns an HIRect + +static HIRect ImplGetHIRectFromRectangle(Rectangle aRect) +{ + HIRect aHIRect; + aHIRect.origin.x = static_cast(aRect.Left()); + aHIRect.origin.y = static_cast(aRect.Top()); + aHIRect.size.width = static_cast(aRect.GetWidth()); + aHIRect.size.height = static_cast(aRect.GetHeight()); + return aHIRect; +} + +static ThemeButtonValue ImplGetButtonValue( ButtonValue aButtonValue ) +{ + switch( aButtonValue ) + { + case BUTTONVALUE_ON: + return kThemeButtonOn; + break; + + case BUTTONVALUE_OFF: + return kThemeButtonOff; + break; + + case BUTTONVALUE_MIXED: + case BUTTONVALUE_DONTKNOW: + default: + return kThemeButtonMixed; + break; + } +} + +static bool AquaGetScrollRect( /* TODO: int nScreen, */ ControlPart nPart, + const Rectangle& rControlRect, Rectangle& rResultRect ) +{ + bool bRetVal = true; + rResultRect = rControlRect; + + switch( nPart ) + { + case PART_BUTTON_UP: + if (NSAppKitVersionNumber < NSAppKitVersionNumber10_7) + { + if( GetSalData()->mbIsScrollbarDoubleMax ) + rResultRect.Top() = rControlRect.Bottom() - 2*BUTTON_HEIGHT; + rResultRect.Bottom() = rResultRect.Top() + BUTTON_HEIGHT; + } + else + { + rResultRect.Bottom() = rResultRect.Top(); + } + break; + + case PART_BUTTON_DOWN: + if (NSAppKitVersionNumber < NSAppKitVersionNumber10_7) + { + rResultRect.Top() = rControlRect.Bottom() - BUTTON_HEIGHT; + } + else + { + rResultRect.Top() = rResultRect.Bottom(); + } + break; + + case PART_BUTTON_LEFT: + if (NSAppKitVersionNumber < NSAppKitVersionNumber10_7) + { + if( GetSalData()->mbIsScrollbarDoubleMax ) + rResultRect.Left() = rControlRect.Right() - 2*BUTTON_WIDTH; + rResultRect.Right() = rResultRect.Left() + BUTTON_WIDTH; + } + else + { + rResultRect.Right() = rResultRect.Left(); + } + break; + + case PART_BUTTON_RIGHT: + if (NSAppKitVersionNumber < NSAppKitVersionNumber10_7) + { + rResultRect.Left() = rControlRect.Right() - BUTTON_WIDTH; + } + else + { + rResultRect.Left() = rResultRect.Right(); + } + break; + + case PART_TRACK_HORZ_AREA: + if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) + break; + rResultRect.Right() -= BUTTON_WIDTH + 1; + if( GetSalData()->mbIsScrollbarDoubleMax ) + rResultRect.Right() -= BUTTON_WIDTH; + else + rResultRect.Left() += BUTTON_WIDTH + 1; + break; + + case PART_TRACK_VERT_AREA: + if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) + break; + rResultRect.Bottom() -= BUTTON_HEIGHT + 1; + if( GetSalData()->mbIsScrollbarDoubleMax ) + rResultRect.Bottom() -= BUTTON_HEIGHT; + else + rResultRect.Top() += BUTTON_HEIGHT + 1; + break; + case PART_THUMB_HORZ: + if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) + break; + if( GetSalData()->mbIsScrollbarDoubleMax ) + { + rResultRect.Left() += 8; + rResultRect.Right() += 6; + } + else + { + rResultRect.Left() += 4; + rResultRect.Right() += 4; + } + break; + case PART_THUMB_VERT: + if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) + break; + if( GetSalData()->mbIsScrollbarDoubleMax ) + { + rResultRect.Top() += 8; + rResultRect.Bottom() += 8; + } + else + { + rResultRect.Top() += 4; + rResultRect.Bottom() += 4; + } + break; + case PART_TRACK_HORZ_LEFT: + if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) + break; + if( GetSalData()->mbIsScrollbarDoubleMax ) + rResultRect.Right() += 8; + else + rResultRect.Right() += 4; + break; + case PART_TRACK_HORZ_RIGHT: + if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) + break; + if( GetSalData()->mbIsScrollbarDoubleMax ) + rResultRect.Left() += 6; + else + rResultRect.Left() += 4; + break; + case PART_TRACK_VERT_UPPER: + if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) + break; + if( GetSalData()->mbIsScrollbarDoubleMax ) + rResultRect.Bottom() += 8; + else + rResultRect.Bottom() += 4; + break; + case PART_TRACK_VERT_LOWER: + if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) + break; + if( GetSalData()->mbIsScrollbarDoubleMax ) + rResultRect.Top() += 8; + else + rResultRect.Top() += 4; + break; + default: + bRetVal = false; + } + + return bRetVal; +} + +/* + * IsNativeControlSupported() + * -------------------------- + * Returns sal_True if the platform supports native + * drawing of the control defined by nPart. + * + */ +sal_Bool AquaSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart ) +{ + bool bOk = sal_False; + + // Native controls are now defaults + // If you want to disable experimental native controls code, + // just set the environment variable SAL_NO_NWF to something + // and vcl controls will be used as default again. + + switch( nType ) + { + case CTRL_PUSHBUTTON: + case CTRL_RADIOBUTTON: + case CTRL_CHECKBOX: + case CTRL_LISTNODE: + if( nPart == PART_ENTIRE_CONTROL ) + return true; + break; + + case CTRL_SCROLLBAR: + if( nPart == PART_DRAW_BACKGROUND_HORZ || + nPart == PART_DRAW_BACKGROUND_VERT || + nPart == PART_ENTIRE_CONTROL || + nPart == HAS_THREE_BUTTONS ) + return true; + break; + + case CTRL_SLIDER: + if( nPart == PART_TRACK_HORZ_AREA || nPart == PART_TRACK_VERT_AREA ) + return true; + break; + + case CTRL_EDITBOX: + if( nPart == PART_ENTIRE_CONTROL || + nPart == HAS_BACKGROUND_TEXTURE ) + return true; + break; + + case CTRL_MULTILINE_EDITBOX: + if( nPart == PART_ENTIRE_CONTROL || + nPart == HAS_BACKGROUND_TEXTURE ) + return true; + break; + + case CTRL_SPINBOX: + if( nPart == PART_ENTIRE_CONTROL || + nPart == PART_ALL_BUTTONS || + nPart == HAS_BACKGROUND_TEXTURE ) + return true; + break; + + case CTRL_SPINBUTTONS: + return false; + break; + + case CTRL_COMBOBOX: + if( nPart == PART_ENTIRE_CONTROL || + nPart == HAS_BACKGROUND_TEXTURE ) + return true; + break; + + case CTRL_LISTBOX: + if( nPart == PART_ENTIRE_CONTROL || + nPart == PART_WINDOW || + nPart == HAS_BACKGROUND_TEXTURE || + nPart == PART_SUB_EDIT + ) + return true; + break; + + case CTRL_TAB_ITEM: + case CTRL_TAB_PANE: + case CTRL_TAB_BODY: // see vcl/source/window/tabpage.cxx + if( nPart == PART_ENTIRE_CONTROL || + nPart == PART_TABS_DRAW_RTL || + nPart == HAS_BACKGROUND_TEXTURE ) + return true; + break; + + // when PART_BUTTON is used, toolbar icons are not highlighted when mouse rolls over. + // More Aqua compliant + case CTRL_TOOLBAR: + if( nPart == PART_ENTIRE_CONTROL || + nPart == PART_DRAW_BACKGROUND_HORZ || + nPart == PART_DRAW_BACKGROUND_VERT) + return true; + break; + + case CTRL_WINDOW_BACKGROUND: + if ( nPart == PART_BACKGROUND_WINDOW || + nPart == PART_BACKGROUND_DIALOG ) + return true; + break; + + case CTRL_MENUBAR: + if( nPart == PART_ENTIRE_CONTROL ) + return true; + break; + + case CTRL_TOOLTIP: // ** TO DO + break; + + case CTRL_MENU_POPUP: + if( nPart == PART_ENTIRE_CONTROL || + nPart == PART_MENU_ITEM || + nPart == PART_MENU_ITEM_CHECK_MARK || + nPart == PART_MENU_ITEM_RADIO_MARK) + return true; + break; + case CTRL_PROGRESS: + case CTRL_INTROPROGRESS: + if( nPart == PART_ENTIRE_CONTROL ) + return true; + break; + case CTRL_FRAME: + if( nPart == PART_BORDER ) + return true; + break; + case CTRL_LISTNET: + if( nPart == PART_ENTIRE_CONTROL ) + return true; + break; + } + + return bOk; +} + +/* + * HitTestNativeControl() + * + * If the return value is sal_True, bIsInside contains information whether + * aPos was or was not inside the native widget specified by the + * nType/nPart combination. + */ +sal_Bool AquaSalGraphics::hitTestNativeControl( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, + const Point& rPos, sal_Bool& rIsInside ) +{ + if ( nType == CTRL_SCROLLBAR ) + { + Rectangle aRect; + bool bValid = AquaGetScrollRect( /* TODO: m_nScreen */ nPart, rControlRegion, aRect ); + rIsInside = bValid ? aRect.IsInside( rPos ) : sal_False; + if( NSAppKitVersionNumber < NSAppKitVersionNumber10_7 && + GetSalData()->mbIsScrollbarDoubleMax ) + { + // in double max mode the actual trough is a little smaller than the track + // there is some visual filler that is not sensitive + if( bValid && rIsInside ) + { + if( nPart == PART_TRACK_HORZ_AREA ) + { + // the left 4 pixels are not hit sensitive + if( rPos.X() - aRect.Left() < 4 ) + rIsInside = sal_False; + } + else if( nPart == PART_TRACK_VERT_AREA ) + { + // the top 4 pixels are not hit sensitive + if( rPos.Y() - aRect.Top() < 4 ) + rIsInside = sal_False; + } + } + } + return bValid; + } // CTRL_SCROLLBAR + + return sal_False; +} + +/* + kThemeStateInactive = 0, + kThemeStateActive = 1, + kThemeStatePressed = 2, + kThemeStateRollover = 6, + kThemeStateUnavailable = 7, + kThemeStateUnavailableInactive = 8 + kThemeStatePressedUp = 2, + kThemeStatePressedDown = 3 + +#define CTRL_STATE_ENABLED 0x0001 +#define CTRL_STATE_FOCUSED 0x0002 +#define CTRL_STATE_PRESSED 0x0004 +#define CTRL_STATE_ROLLOVER 0x0008 +#define CTRL_STATE_HIDDEN 0x0010 +#define CTRL_STATE_DEFAULT 0x0020 +#define CTRL_STATE_SELECTED 0x0040 +#define CTRL_CACHING_ALLOWED 0x8000 // set when the control is completely visible (i.e. not clipped) +*/ +UInt32 AquaSalGraphics::getState( ControlState nState ) +{ + const bool bDrawActive = mpFrame ? ([mpFrame->getNSWindow() isKeyWindow] ? true : false) : true; + if( (nState & CTRL_STATE_ENABLED) == 0 || ! bDrawActive ) + { + if( (nState & CTRL_STATE_HIDDEN) == 0 ) + return kThemeStateInactive; + else + return kThemeStateUnavailableInactive; + } + + if( (nState & CTRL_STATE_HIDDEN) != 0 ) + return kThemeStateUnavailable; + + if( (nState & CTRL_STATE_PRESSED) != 0 ) + return kThemeStatePressed; + + return kThemeStateActive; +} + +UInt32 AquaSalGraphics::getTrackState( ControlState nState ) +{ + const bool bDrawActive = mpFrame ? ([mpFrame->getNSWindow() isKeyWindow] ? true : false) : true; + if( (nState & CTRL_STATE_ENABLED) == 0 || ! bDrawActive ) + return kThemeTrackInactive; + + return kThemeTrackActive; +} + +/* + * DrawNativeControl() + * + * Draws the requested control described by nPart/nState. + * + * rControlRegion: The bounding region of the complete control in VCL frame coordinates. + * aValue: An optional value (tristate/numerical/string) + * aCaption: A caption or title string (like button text etc) + */ +sal_Bool AquaSalGraphics::drawNativeControl(ControlType nType, + ControlPart nPart, + const Rectangle& rControlRegion, + ControlState nState, + const ImplControlValue& aValue, + const OUString& ) +{ + sal_Bool bOK = sal_False; + + if( ! CheckContext() ) + return false; + + CGContextSaveGState( mrContext ); + + Rectangle buttonRect = rControlRegion; + HIRect rc = ImplGetHIRectFromRectangle(buttonRect); + + switch( nType ) + { + + case CTRL_COMBOBOX: + if ( nPart == HAS_BACKGROUND_TEXTURE || + nPart == PART_ENTIRE_CONTROL ) + { + HIThemeButtonDrawInfo aComboInfo; + aComboInfo.version = 0; + aComboInfo.kind = kThemeComboBox; + aComboInfo.state = getState( nState ); + aComboInfo.value = kThemeButtonOn; + aComboInfo.adornment = kThemeAdornmentNone; + + if( (nState & CTRL_STATE_FOCUSED) != 0 ) + aComboInfo.adornment |= kThemeAdornmentFocus; + + HIThemeDrawButton(&rc, &aComboInfo, mrContext, kHIThemeOrientationNormal,&rc); + bOK = true; + } + break; + + case CTRL_TOOLBAR: + { + HIThemeMenuItemDrawInfo aMenuItemDrawInfo; + aMenuItemDrawInfo.version = 0; + aMenuItemDrawInfo.state = kThemeMenuActive; + aMenuItemDrawInfo.itemType = kThemeMenuItemHierBackground; + HIThemeDrawMenuItem(&rc,&rc,&aMenuItemDrawInfo,mrContext,kHIThemeOrientationNormal,NULL); + bOK = true; + } + break; + + case CTRL_WINDOW_BACKGROUND: + { + HIThemeBackgroundDrawInfo aThemeBackgroundInfo; + aThemeBackgroundInfo.version = 0; + aThemeBackgroundInfo.state = getState( nState ); + aThemeBackgroundInfo.kind = kThemeBrushDialogBackgroundActive; + // FIXME: without this magical offset there is a 2 pixel black border on the right and bottom + rc.size.width += 2; + rc.size.height += 2; + + HIThemeApplyBackground( &rc, &aThemeBackgroundInfo, mrContext, kHIThemeOrientationNormal); + CGContextFillRect( mrContext, rc ); + bOK = true; + } + break; + + case CTRL_MENUBAR: + case CTRL_MENU_POPUP: + { + if ((nPart == PART_ENTIRE_CONTROL) || (nPart == PART_MENU_ITEM )|| (nPart == HAS_BACKGROUND_TEXTURE )) + { + // FIXME: without this magical offset there is a 2 pixel black border on the right + rc.size.width += 2; + + HIThemeMenuDrawInfo aMenuInfo; + aMenuInfo.version = 0; + aMenuInfo.menuType = kThemeMenuTypePullDown; + + HIThemeMenuItemDrawInfo aMenuItemDrawInfo; + // the Aqua grey theme when the item is selected is drawn here. + aMenuItemDrawInfo.itemType = kThemeMenuItemPlain; + + if ((nPart == PART_MENU_ITEM ) && (nState & CTRL_STATE_SELECTED)) + { + // the blue theme when the item is selected is drawn here. + aMenuItemDrawInfo.state = kThemeMenuSelected; + } + else + { + // normal color for non selected item + aMenuItemDrawInfo.state = kThemeMenuActive; + } + + // repaints the background of the pull down menu + HIThemeDrawMenuBackground(&rc,&aMenuInfo,mrContext,kHIThemeOrientationNormal); + + // repaints the item either blue (selected) and/or Aqua grey (active only) + HIThemeDrawMenuItem(&rc,&rc,&aMenuItemDrawInfo,mrContext,kHIThemeOrientationNormal,&rc); + + bOK = true; + } + else if(( nPart == PART_MENU_ITEM_CHECK_MARK )||( nPart == PART_MENU_ITEM_RADIO_MARK )) { + if( nState & CTRL_STATE_PRESSED ) {//checked, else it is not displayed (see vcl/source/window/menu.cxx) + HIThemeTextInfo aTextInfo; + aTextInfo.version = 0; + aTextInfo.state = ((nState & CTRL_STATE_ENABLED)==0) ? kThemeStateInactive: kThemeStateActive; + aTextInfo.fontID = kThemeMenuItemMarkFont; + aTextInfo.horizontalFlushness=kHIThemeTextHorizontalFlushCenter; + aTextInfo.verticalFlushness=kHIThemeTextVerticalFlushTop; + aTextInfo.options=kHIThemeTextBoxOptionNone; + aTextInfo.truncationPosition=kHIThemeTextTruncationNone; + //aTextInfo.truncationMaxLines unused because of kHIThemeTextTruncationNone + + if( nState & CTRL_STATE_SELECTED) aTextInfo.state = kThemeStatePressed; //item highlighted + + UniChar mark=( nPart == PART_MENU_ITEM_CHECK_MARK ) ? kCheckUnicode: kBulletUnicode;//0x2713; + CFStringRef cfString = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, &mark, 1, kCFAllocatorNull); + HIThemeDrawTextBox(cfString, &rc, &aTextInfo, mrContext, kHIThemeOrientationNormal); + if (cfString) + CFRelease(cfString); + + bOK = true; + } + } + } + break; + + case CTRL_PUSHBUTTON: + { + // [ FIXME] : instead of use a value, vcl can retrieve corect values on the fly (to be implemented) + const int PB_Mini_Height = 15; + const int PB_Norm_Height = 21; + + HIThemeButtonDrawInfo aPushInfo; + aPushInfo.version = 0; + + // no animation + aPushInfo.animation.time.start = 0; + aPushInfo.animation.time.current = 0; + PushButtonValue* pPBVal = aValue.getType() == CTRL_PUSHBUTTON ? (PushButtonValue*)&aValue : NULL; + int nPaintHeight = static_cast(rc.size.height); + + if( pPBVal && pPBVal->mbBevelButton ) + { + aPushInfo.kind = kThemeRoundedBevelButton; + } + else if( rc.size.height <= PB_Norm_Height ) + { + aPushInfo.kind = kThemePushButtonMini; + nPaintHeight = PB_Mini_Height; + } + else if( pPBVal->mbSingleLine || rc.size.height < (PB_Norm_Height + PB_Norm_Height/2) ) + { + aPushInfo.kind = kThemePushButtonNormal; + nPaintHeight = PB_Norm_Height; + + // avoid clipping when focused + rc.origin.x += FOCUS_RING_WIDTH/2; + rc.size.width -= FOCUS_RING_WIDTH; + + if( (nState & CTRL_STATE_DEFAULT) != 0 ) + { + AquaBlinker::Blink( mpFrame, buttonRect ); + // show correct animation phase + aPushInfo.animation.time.current = CFAbsoluteTimeGetCurrent(); + } + } + else + aPushInfo.kind = kThemeBevelButton; + + // translate the origin for controls with fixed paint height + // so content ends up somewhere sensible + int delta_y = static_cast(rc.size.height) - nPaintHeight; + rc.origin.y += delta_y/2; + + aPushInfo.state = getState( nState ); + aPushInfo.value = ImplGetButtonValue( aValue.getTristateVal() ); + + aPushInfo.adornment = (( nState & CTRL_STATE_DEFAULT ) != 0) ? + kThemeAdornmentDefault : + kThemeAdornmentNone; + if( (nState & CTRL_STATE_FOCUSED) != 0 ) + aPushInfo.adornment |= kThemeAdornmentFocus; + + HIThemeDrawButton( &rc, &aPushInfo, mrContext, kHIThemeOrientationNormal, NULL ); + bOK = true; + } + break; + + case CTRL_RADIOBUTTON: + case CTRL_CHECKBOX: + { + HIThemeButtonDrawInfo aInfo; + aInfo.version = 0; + switch( nType ) + { + case CTRL_RADIOBUTTON: if(rc.size.width >= BUTTON_HEIGHT) aInfo.kind = kThemeRadioButton; + else aInfo.kind = kThemeSmallRadioButton; + break; + case CTRL_CHECKBOX: if(rc.size.width >= BUTTON_HEIGHT) aInfo.kind = kThemeCheckBox; + else aInfo.kind = kThemeSmallCheckBox; + break; + } + + aInfo.state = getState( nState ); + + ButtonValue aButtonValue = aValue.getTristateVal(); + aInfo.value = ImplGetButtonValue( aButtonValue ); + + aInfo.adornment = (( nState & CTRL_STATE_DEFAULT ) != 0) ? + kThemeAdornmentDefault : + kThemeAdornmentNone; + if( (nState & CTRL_STATE_FOCUSED) != 0 ) + aInfo.adornment |= kThemeAdornmentFocus; + HIThemeDrawButton( &rc, &aInfo, mrContext, kHIThemeOrientationNormal, NULL ); + bOK = true; + } + break; + + case CTRL_LISTNODE: + { + ButtonValue aButtonValue = aValue.getTristateVal(); + + if( Application::GetSettings().GetLayoutRTL() && aButtonValue == BUTTONVALUE_OFF ) + { + // FIXME: a value of kThemeDisclosureLeft + // should draw a theme compliant left disclosure triangle + // sadly this does not seem to work, so we'll draw a left + // grey equilateral triangle here ourselves. + // Perhaps some other HIThemeButtonDrawInfo setting would do the trick ? + + CGContextSetShouldAntialias( mrContext, true ); + CGFloat aGrey[] = { 0.45, 0.45, 0.45, 1.0 }; + CGContextSetFillColor( mrContext, aGrey ); + CGContextBeginPath( mrContext ); + float x = rc.origin.x + rc.size.width; + float y = rc.origin.y; + CGContextMoveToPoint( mrContext, x, y ); + y += rc.size.height; + CGContextAddLineToPoint( mrContext, x, y ); + x -= rc.size.height * 0.866; // cos( 30 degree ) is approx. 0.866 + y -= rc.size.height/2; + CGContextAddLineToPoint( mrContext, x, y ); + CGContextDrawPath( mrContext, kCGPathEOFill ); + } + else + { + HIThemeButtonDrawInfo aInfo; + aInfo.version = 0; + aInfo.kind = kThemeDisclosureTriangle; + aInfo.value = kThemeDisclosureRight; + aInfo.state = getState( nState ); + + aInfo.adornment = kThemeAdornmentNone; + + switch( aButtonValue ) { + case BUTTONVALUE_ON: aInfo.value = kThemeDisclosureDown;//expanded + break; + case BUTTONVALUE_OFF: + // FIXME: this should have drawn a theme compliant disclosure triangle + // (see above) + if( Application::GetSettings().GetLayoutRTL() ) + { + aInfo.value = kThemeDisclosureLeft;//collapsed, RTL + } + break; + case BUTTONVALUE_DONTKNOW: //what to do? + default: + break; + } + + HIThemeDrawButton( &rc, &aInfo, mrContext, kHIThemeOrientationNormal, NULL ); + } + bOK = true; + } + break; + + case CTRL_PROGRESS: + case CTRL_INTROPROGRESS: + { + long nProgressWidth = aValue.getNumericVal(); + HIThemeTrackDrawInfo aTrackInfo; + aTrackInfo.version = 0; + aTrackInfo.kind = (rc.size.height > 10) ? kThemeProgressBarLarge : kThemeProgressBarMedium; + aTrackInfo.bounds = rc; + aTrackInfo.min = 0; + aTrackInfo.max = static_cast(rc.size.width); + aTrackInfo.value = nProgressWidth; + aTrackInfo.reserved = 0; + aTrackInfo.bounds.origin.y -= 2; // FIXME: magic for shadow + aTrackInfo.bounds.size.width -= 2; // FIXME: magic for shadow + aTrackInfo.attributes = kThemeTrackHorizontal; + if( Application::GetSettings().GetLayoutRTL() ) + aTrackInfo.attributes |= kThemeTrackRightToLeft; + aTrackInfo.enableState = getTrackState( nState ); + // the intro bitmap never gets key anyway; we want to draw that enabled + if( nType == CTRL_INTROPROGRESS ) + aTrackInfo.enableState = kThemeTrackActive; + aTrackInfo.filler1 = 0; + aTrackInfo.trackInfo.progress.phase = static_cast(CFAbsoluteTimeGetCurrent()*10.0); + + HIThemeDrawTrack( &aTrackInfo, NULL, mrContext, kHIThemeOrientationNormal ); + bOK = true; + } + break; + + case CTRL_SLIDER: + { + SliderValue* pSLVal = (SliderValue*)&aValue; + + HIThemeTrackDrawInfo aTrackDraw; + aTrackDraw.kind = kThemeSliderMedium; + if( nPart == PART_TRACK_HORZ_AREA || nPart == PART_TRACK_VERT_AREA ) + { + aTrackDraw.bounds = rc; + aTrackDraw.min = pSLVal->mnMin; + aTrackDraw.max = pSLVal->mnMax; + aTrackDraw.value = pSLVal->mnCur; + aTrackDraw.reserved = 0; + aTrackDraw.attributes = kThemeTrackShowThumb; + if( nPart == PART_TRACK_HORZ_AREA ) + aTrackDraw.attributes |= kThemeTrackHorizontal; + aTrackDraw.enableState = (nState & CTRL_STATE_ENABLED) + ? kThemeTrackActive : kThemeTrackInactive; + + SliderTrackInfo aSlideInfo; + aSlideInfo.thumbDir = kThemeThumbUpward; + aSlideInfo.pressState = 0; + aTrackDraw.trackInfo.slider = aSlideInfo; + + HIThemeDrawTrack( &aTrackDraw, NULL, mrContext, kHIThemeOrientationNormal ); + bOK = true; + } + } + break; + + case CTRL_SCROLLBAR: + { + const ScrollbarValue* pScrollbarVal = (aValue.getType() == CTRL_SCROLLBAR) ? static_cast(&aValue) : NULL; + + if( nPart == PART_DRAW_BACKGROUND_VERT || + nPart == PART_DRAW_BACKGROUND_HORZ ) + { + HIThemeTrackDrawInfo aTrackDraw; + aTrackDraw.kind = kThemeMediumScrollBar; + // FIXME: the scrollbar length must be adjusted + if (nPart == PART_DRAW_BACKGROUND_VERT) + rc.size.height += 2; + else + rc.size.width += 2; + + aTrackDraw.bounds = rc; + aTrackDraw.min = pScrollbarVal->mnMin; + aTrackDraw.max = pScrollbarVal->mnMax - pScrollbarVal->mnVisibleSize; + aTrackDraw.value = pScrollbarVal->mnCur; + aTrackDraw.reserved = 0; + aTrackDraw.attributes = kThemeTrackShowThumb; + if( nPart == PART_DRAW_BACKGROUND_HORZ ) + aTrackDraw.attributes |= kThemeTrackHorizontal; + aTrackDraw.enableState = getTrackState( nState ); + + ScrollBarTrackInfo aScrollInfo; + aScrollInfo.viewsize = pScrollbarVal->mnVisibleSize; + aScrollInfo.pressState = 0; + + if ( pScrollbarVal->mnButton1State & CTRL_STATE_ENABLED ) + { + if ( pScrollbarVal->mnButton1State & CTRL_STATE_PRESSED ) + aScrollInfo.pressState = kThemeTopOutsideArrowPressed; + } + + if ( pScrollbarVal->mnButton2State & CTRL_STATE_ENABLED ) + { + if ( pScrollbarVal->mnButton2State & CTRL_STATE_PRESSED ) + aScrollInfo.pressState = kThemeBottomOutsideArrowPressed; + } + + if ( pScrollbarVal->mnThumbState & CTRL_STATE_ENABLED ) + { + if ( pScrollbarVal->mnThumbState & CTRL_STATE_PRESSED ) + aScrollInfo.pressState = kThemeThumbPressed; + } + + aTrackDraw.trackInfo.scrollbar = aScrollInfo; + + HIThemeDrawTrack( &aTrackDraw, NULL, mrContext, kHIThemeOrientationNormal ); + bOK = true; + } + } + break; + + case CTRL_TAB_PANE: + { + HIThemeTabPaneDrawInfo aTabPaneDrawInfo; + aTabPaneDrawInfo.version = 1; + aTabPaneDrawInfo.state = kThemeStateActive; + aTabPaneDrawInfo.direction=kThemeTabNorth; + aTabPaneDrawInfo.size=kHIThemeTabSizeNormal; + aTabPaneDrawInfo.kind=kHIThemeTabKindNormal; + + //the border is outside the rect rc for Carbon + //but for VCL it should be inside + rc.origin.x+=1; + rc.origin.y-=TAB_HEIGHT_NORMAL/2; + rc.size.height+=TAB_HEIGHT_NORMAL/2; + rc.size.width-=2; + + HIThemeDrawTabPane(&rc, &aTabPaneDrawInfo, mrContext, kHIThemeOrientationNormal); + + bOK = true; + } + break; + + case CTRL_TAB_ITEM: + { + HIThemeTabDrawInfo aTabItemDrawInfo; + aTabItemDrawInfo.version=1; + aTabItemDrawInfo.style=kThemeTabNonFront; + aTabItemDrawInfo.direction=kThemeTabNorth; + aTabItemDrawInfo.size=kHIThemeTabSizeNormal; + aTabItemDrawInfo.adornment=kHIThemeTabAdornmentTrailingSeparator; + //State + if(nState & CTRL_STATE_SELECTED) { + aTabItemDrawInfo.style=kThemeTabFront; + } + if(nState & CTRL_STATE_FOCUSED) { + aTabItemDrawInfo.adornment|=kHIThemeTabAdornmentFocus; + } + + //first, last or middle tab + aTabItemDrawInfo.position=kHIThemeTabPositionMiddle; + + TabitemValue* pTabValue = (TabitemValue *) &aValue; + unsigned int nAlignment = pTabValue->mnAlignment; + //TABITEM_LEFTALIGNED (and TABITEM_RIGHTALIGNED) for the leftmost (or rightmost) tab + //when there are several lines of tabs because there is only one first tab and one + //last tab and TABITEM_FIRST_IN_GROUP (and TABITEM_LAST_IN_GROUP) because when the + //line width is different from window width, there may not be TABITEM_RIGHTALIGNED + if( ( (nAlignment & TABITEM_LEFTALIGNED)&&(nAlignment & TABITEM_RIGHTALIGNED) ) || + ( (nAlignment & TABITEM_FIRST_IN_GROUP)&&(nAlignment & TABITEM_LAST_IN_GROUP) ) + ) //tab alone + aTabItemDrawInfo.position=kHIThemeTabPositionOnly; + else if((nAlignment & TABITEM_LEFTALIGNED)||(nAlignment & TABITEM_FIRST_IN_GROUP)) + aTabItemDrawInfo.position=kHIThemeTabPositionFirst; + else if((nAlignment & TABITEM_RIGHTALIGNED)||(nAlignment & TABITEM_LAST_IN_GROUP)) + aTabItemDrawInfo.position=kHIThemeTabPositionLast; + + //support for RTL + //see issue 79748 + if( Application::GetSettings().GetLayoutRTL() ) { + if( aTabItemDrawInfo.position == kHIThemeTabPositionFirst ) + aTabItemDrawInfo.position = kHIThemeTabPositionLast; + else if( aTabItemDrawInfo.position == kHIThemeTabPositionLast ) + aTabItemDrawInfo.position = kHIThemeTabPositionFirst; + } + + rc.size.width+=2;//because VCL has 2 empty pixels between 2 tabs + rc.origin.x-=1; + + HIThemeDrawTab(&rc, &aTabItemDrawInfo, mrContext, kHIThemeOrientationNormal, &rc ); + + bOK=true; + } + break; + + case CTRL_LISTBOX: + switch( nPart) + { + case PART_ENTIRE_CONTROL: + case PART_BUTTON_DOWN: + { + HIThemeButtonDrawInfo aListInfo; + aListInfo.version = 0; + aListInfo.kind = kThemePopupButton; + aListInfo.state = getState( nState );//kThemeStateInactive -> greyed + aListInfo.value = kThemeButtonOn; + + aListInfo.adornment = kThemeAdornmentDefault; + if( (nState & CTRL_STATE_FOCUSED) != 0 ) + aListInfo.adornment |= kThemeAdornmentFocus; + + HIThemeDrawButton(&rc, &aListInfo, mrContext, kHIThemeOrientationNormal,&rc); + bOK = true; + break; + } + case PART_WINDOW: + { + HIThemeFrameDrawInfo aTextDrawInfo; + aTextDrawInfo.version=0; + aTextDrawInfo.kind=kHIThemeFrameTextFieldSquare; + aTextDrawInfo.state=getState( nState ); + aTextDrawInfo.isFocused=false; + + rc.size.width+=1;//else there's a white space because an OS X theme has no 3D border + rc.size.height+=1; + HIThemeDrawFrame(&rc, &aTextDrawInfo, mrContext, kHIThemeOrientationNormal); + + if(nState & CTRL_STATE_FOCUSED) HIThemeDrawFocusRect(&rc, true, mrContext, kHIThemeOrientationNormal); + + bOK=true; + break; + } + } + break; + + case CTRL_EDITBOX: + case CTRL_MULTILINE_EDITBOX: + { + HIThemeFrameDrawInfo aTextDrawInfo; + aTextDrawInfo.version=0; + aTextDrawInfo.kind=kHIThemeFrameTextFieldSquare; + aTextDrawInfo.state=getState( nState ); + aTextDrawInfo.isFocused=false; + + rc.size.width += 1; // else there may be a white space because an OS X theme has no 3D border + // change rc so that the frame will encompass only the content region + // see counterpart in GetNativeControlRegion + rc.size.width += 2; + rc.size.height += 2; + + //CGContextSetFillColorWithColor + CGContextFillRect (mrContext, CGRectMake(rc.origin.x, rc.origin.y, rc.size.width, rc.size.height)); + //fill a white background, because drawFrame only draws the border + + HIThemeDrawFrame(&rc, &aTextDrawInfo, mrContext, kHIThemeOrientationNormal); + + if(nState & CTRL_STATE_FOCUSED) HIThemeDrawFocusRect(&rc, true, mrContext, kHIThemeOrientationNormal); + + bOK=true; + } + break; + + case CTRL_SPINBOX: + { + if(nPart == PART_ENTIRE_CONTROL) + { + //text field: + HIThemeFrameDrawInfo aTextDrawInfo; + aTextDrawInfo.version=0; + aTextDrawInfo.kind=kHIThemeFrameTextFieldSquare; + aTextDrawInfo.state=getState( nState ); + aTextDrawInfo.isFocused=false; + + //rc.size.width contains the full size of the spinbox ie textfield + button + //so we remove the button width and the space between the button and the textfield + rc.size.width -= SPIN_BUTTON_SPACE + SPIN_BUTTON_WIDTH + 2*FOCUS_RING_WIDTH; + rc.origin.x += FOCUS_RING_WIDTH; + rc.origin.y += FOCUS_RING_WIDTH; + + //CGContextSetFillColorWithColor + CGContextFillRect (mrContext, CGRectMake(rc.origin.x, rc.origin.y, rc.size.width, rc.size.height)); + //fill a white background, because drawFrame only draws the border + + HIThemeDrawFrame(&rc, &aTextDrawInfo, mrContext, kHIThemeOrientationNormal); + + if(nState & CTRL_STATE_FOCUSED) HIThemeDrawFocusRect(&rc, true, mrContext, kHIThemeOrientationNormal); + + //buttons: + const SpinbuttonValue* pSpinButtonVal = (aValue.getType() == CTRL_SPINBUTTONS) ? static_cast(&aValue) : NULL; + ControlState nUpperState = CTRL_STATE_ENABLED;//state of the upper button + ControlState nLowerState = CTRL_STATE_ENABLED;//and of the lower button + if(pSpinButtonVal) {//pSpinButtonVal is sometimes null + nUpperState = (ControlState) pSpinButtonVal->mnUpperState; + nLowerState = (ControlState) pSpinButtonVal->mnLowerState; + + HIThemeButtonDrawInfo aSpinInfo; + aSpinInfo.kind = kThemeIncDecButton; + aSpinInfo.state = kThemeStateActive; + if(nUpperState & CTRL_STATE_PRESSED) + aSpinInfo.state = kThemeStatePressedUp; + else if(nLowerState & CTRL_STATE_PRESSED) + aSpinInfo.state = kThemeStatePressedDown; + else if((nUpperState & ~CTRL_STATE_ENABLED)||(nLowerState & ~CTRL_STATE_ENABLED)) + aSpinInfo.state = kThemeStateInactive; + else if((nUpperState & CTRL_STATE_ROLLOVER)||(nLowerState & CTRL_STATE_ROLLOVER)) + aSpinInfo.state = kThemeStateRollover; + + Rectangle aSpinRect( pSpinButtonVal->maUpperRect ); + aSpinRect.Union( pSpinButtonVal->maLowerRect ); + HIRect buttonRc = ImplGetHIRectFromRectangle(aSpinRect); + + // FIXME: without this fuzz factor there is some unwanted clipping + if( Application::GetSettings().GetLayoutRTL() ) + buttonRc.origin.x -= FOCUS_RING_WIDTH - CLIP_FUZZ; + else + buttonRc.origin.x += FOCUS_RING_WIDTH + CLIP_FUZZ; + + switch( aValue.getTristateVal() ) + { + case BUTTONVALUE_ON: aSpinInfo.value = kThemeButtonOn; + break; + case BUTTONVALUE_OFF: aSpinInfo.value = kThemeButtonOff; + break; + case BUTTONVALUE_MIXED: + case BUTTONVALUE_DONTKNOW: + default: aSpinInfo.value = kThemeButtonMixed; + break; + } + + aSpinInfo.adornment = ( ((nUpperState & CTRL_STATE_DEFAULT) != 0 ) || + ((nLowerState & CTRL_STATE_DEFAULT) != 0 )) ? + kThemeAdornmentDefault : + kThemeAdornmentNone; + if( ((nUpperState & CTRL_STATE_FOCUSED) != 0 ) || ((nLowerState & CTRL_STATE_FOCUSED) != 0 )) + aSpinInfo.adornment |= kThemeAdornmentFocus; + + HIThemeDrawButton( &buttonRc, &aSpinInfo, mrContext, kHIThemeOrientationNormal, NULL ); + } + + bOK=true; + } + + } + break; + + case CTRL_FRAME: + { + sal_uInt16 nStyle = aValue.getNumericVal(); + if( nPart == PART_BORDER ) { + if(!( nStyle & FRAME_DRAW_MENU ) && !(nStyle & FRAME_DRAW_WINDOWBORDER) ) + { + // #i84756# strange effects start to happen when HIThemeDrawFrame + // meets the border of the window. These can be avoided by clipping + // to the boundary of the frame + if( rc.origin.y + rc.size.height >= mpFrame->maGeometry.nHeight-3 ) + { + CGMutablePathRef rPath = CGPathCreateMutable(); + CGPathAddRect( rPath, NULL, CGRectMake( 0, 0, mpFrame->maGeometry.nWidth-1, mpFrame->maGeometry.nHeight-1 ) ); + + CGContextBeginPath( mrContext ); + CGContextAddPath( mrContext, rPath ); + CGContextClip( mrContext ); + CGPathRelease( rPath ); + } + + HIThemeFrameDrawInfo aTextDrawInfo; + aTextDrawInfo.version=0; + aTextDrawInfo.kind=kHIThemeFrameListBox; + aTextDrawInfo.state=kThemeStateActive; + aTextDrawInfo.isFocused=false; + + HIThemeDrawFrame(&rc, &aTextDrawInfo, mrContext, kHIThemeOrientationNormal); + + bOK=true; + } + } + } + break; + + case CTRL_LISTNET: + { + //do nothing as there isn't net for listviews on macos + bOK=true; + } + break; + + } + + CGContextRestoreGState( mrContext ); + + /* #i90291# in most cases invalidating the whole control region instead + of just the unclipped part of it is sufficient (and probably faster). + However for the window background we should not unnecessarily enlarge + the really changed rectangle since the difference is usually quite high + (the background is always drawn as a whole since we don't know anything + about its possible contents) + */ + if( nType == CTRL_WINDOW_BACKGROUND ) + { + CGRect aRect = { { 0, 0 }, { 0, 0 } }; + if( mxClipPath ) + aRect = CGPathGetBoundingBox( mxClipPath ); + if( aRect.size.width != 0 && aRect.size.height != 0 ) + buttonRect.Intersection( Rectangle( Point( static_cast(aRect.origin.x), + static_cast(aRect.origin.y) ), + Size( static_cast(aRect.size.width), + static_cast(aRect.size.height) ) ) ); + } + + RefreshRect( buttonRect.Left(), buttonRect.Top(), buttonRect.GetWidth(), buttonRect.GetHeight() ); + + return bOK; +} + +/* + * GetNativeControlRegion() + * + * If the return value is sal_True, rNativeBoundingRegion + * contains the true bounding region covered by the control + * including any adornment, while rNativeContentRegion contains the area + * within the control that can be safely drawn into without drawing over + * the borders of the control. + * + * rControlRegion: The bounding region of the control in VCL frame coordinates. + * aValue: An optional value (tristate/numerical/string) + * aCaption: A caption or title string (like button text etc) + */ +sal_Bool AquaSalGraphics::getNativeControlRegion( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, ControlState /*nState*/, + const ImplControlValue& aValue, const OUString&, + Rectangle &rNativeBoundingRegion, Rectangle &rNativeContentRegion ) + +{ + sal_Bool toReturn = sal_False; + + Rectangle aCtrlBoundRect( rControlRegion ); + short x = aCtrlBoundRect.Left(); + short y = aCtrlBoundRect.Top(); + short w, h; + + sal_uInt8 nBorderCleanup = 0; + + switch (nType) + { + case CTRL_SLIDER: + { + if( nPart == PART_THUMB_HORZ ) + { + w = 19; // taken from HIG + h = aCtrlBoundRect.GetHeight(); + rNativeBoundingRegion = rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h ) ); + toReturn = true; + } + else if( nPart == PART_THUMB_VERT ) + { + w = aCtrlBoundRect.GetWidth(); + h = 18; // taken from HIG + rNativeBoundingRegion = rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h ) ); + toReturn = true; + } + } + break; + + case CTRL_SCROLLBAR: + { + Rectangle aRect; + if( AquaGetScrollRect( /* m_nScreen */ nPart, aCtrlBoundRect, aRect ) ) + { + toReturn = sal_True; + rNativeBoundingRegion = aRect; + rNativeContentRegion = aRect; + } + } + break; + + case CTRL_PUSHBUTTON: + case CTRL_RADIOBUTTON: + case CTRL_CHECKBOX: + { + if ( nType == CTRL_PUSHBUTTON ) + { + w = aCtrlBoundRect.GetWidth(); + h = aCtrlBoundRect.GetHeight(); + } + else + { + // checkbox and radio borders need cleanup after unchecking them + nBorderCleanup = 4; + + // TEXT_SEPARATOR to respect Aqua HIG + w = BUTTON_WIDTH + TEXT_SEPARATOR; + h = BUTTON_HEIGHT; + + } + + rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h + nBorderCleanup) ); + rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h ) ); + + toReturn = sal_True; + } + break; + case CTRL_PROGRESS: + { + Rectangle aRect( aCtrlBoundRect ); + if( aRect.GetHeight() < 16 ) + aRect.Bottom() = aRect.Top() + 9; // values taken from HIG for medium progress + else + aRect.Bottom() = aRect.Top() + 15; // values taken from HIG for large progress + rNativeBoundingRegion = aRect; + rNativeContentRegion = aRect; + toReturn = sal_True; + } + break; + + case CTRL_INTROPROGRESS: + { + Rectangle aRect( aCtrlBoundRect ); + aRect.Bottom() = aRect.Top() + INTRO_PROGRESS_HEIGHT; // values taken from HIG for medium progress + rNativeBoundingRegion = aRect; + rNativeContentRegion = aRect; + toReturn = sal_True; + } + break; + + case CTRL_TAB_ITEM: + + w = aCtrlBoundRect.GetWidth() + 2*TAB_TEXT_OFFSET - 2*VCL_TAB_TEXT_OFFSET; + +#ifdef OLD_TAB_STYLE + h = TAB_HEIGHT_NORMAL; +#else + h = TAB_HEIGHT_NORMAL+2; +#endif + rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h ) ); + rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h ) ); + + toReturn = sal_True; + + break; + + case CTRL_EDITBOX: + { + w = aCtrlBoundRect.GetWidth(); + if( w < 3+2*FOCUS_RING_WIDTH ) + w = 3+2*FOCUS_RING_WIDTH; + h = TEXT_EDIT_HEIGHT_NORMAL+2*FOCUS_RING_WIDTH; + if( h < aCtrlBoundRect.GetHeight() ) + h = aCtrlBoundRect.GetHeight(); + + rNativeContentRegion = Rectangle( Point( x+FOCUS_RING_WIDTH, y+FOCUS_RING_WIDTH ), Size( w-2*(FOCUS_RING_WIDTH+1), h-2*(FOCUS_RING_WIDTH+1) ) ); + rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h ) ); + + toReturn = sal_True; + } + break; + case CTRL_LISTBOX: + case CTRL_COMBOBOX: + { + if( nPart == PART_ENTIRE_CONTROL ) + { + w = aCtrlBoundRect.GetWidth(); + h = COMBOBOX_HEIGHT_NORMAL;//listboxes and comboxes have the same height + + rNativeContentRegion = Rectangle( Point( x+FOCUS_RING_WIDTH, y+FOCUS_RING_WIDTH ), Size( w-2*FOCUS_RING_WIDTH, h ) ); + rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h+2*FOCUS_RING_WIDTH ) ); + + toReturn = sal_True; + } + else if( nPart == PART_BUTTON_DOWN ) + { + w = aCtrlBoundRect.GetWidth(); + if( w < 3+2*FOCUS_RING_WIDTH ) + w = 3+2*FOCUS_RING_WIDTH; + h = COMBOBOX_HEIGHT_NORMAL;//listboxes and comboxes have the same height + + x += w-DROPDOWN_BUTTON_WIDTH - FOCUS_RING_WIDTH; + y += FOCUS_RING_WIDTH; + w = DROPDOWN_BUTTON_WIDTH; + + rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h ) ); + rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w+FOCUS_RING_WIDTH, h+2*FOCUS_RING_WIDTH ) ); + + toReturn = true; + } + else if( nPart == PART_SUB_EDIT ) + { + w = aCtrlBoundRect.GetWidth(); + h = COMBOBOX_HEIGHT_NORMAL;//listboxes and comboxes have the same height + + x += FOCUS_RING_WIDTH; + x += 3; // add an offset for rounded borders + y += 2; // don't draw into upper border + y += FOCUS_RING_WIDTH; + w -= 3 + DROPDOWN_BUTTON_WIDTH + 2*FOCUS_RING_WIDTH; + if( nType == CTRL_LISTBOX ) + w -= 9; // HIG specifies 9 units distance between dropdown button area and content + h -= 4; // don't draw into lower border + + rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h ) ); + rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w+FOCUS_RING_WIDTH, h+2*FOCUS_RING_WIDTH ) ); + + toReturn = true; + } + } + break; + case CTRL_SPINBOX: + if( nPart == PART_ENTIRE_CONTROL ) { + w = aCtrlBoundRect.GetWidth(); + if( w < 3+2*FOCUS_RING_WIDTH+SPIN_BUTTON_SPACE+SPIN_BUTTON_WIDTH ) + w = 3+2*FOCUS_RING_WIDTH+SPIN_BUTTON_SPACE+SPIN_BUTTON_WIDTH; + h = TEXT_EDIT_HEIGHT_NORMAL; + + rNativeContentRegion = Rectangle( Point( x+FOCUS_RING_WIDTH, y ), Size( w-2*FOCUS_RING_WIDTH, h ) ); + rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h+2*FOCUS_RING_WIDTH ) ); + + toReturn = sal_True; + } + else if( nPart == PART_SUB_EDIT ) { + w = aCtrlBoundRect.GetWidth() - SPIN_BUTTON_SPACE - SPIN_BUTTON_WIDTH; + h = TEXT_EDIT_HEIGHT_NORMAL; + x += 4; // add an offset for rounded borders + y += 2; // don't draw into upper border + w -= 8; // offset for left and right rounded border + h -= 4; // don't draw into upper or ower border + + rNativeContentRegion = Rectangle( Point( x + FOCUS_RING_WIDTH, y + FOCUS_RING_WIDTH ), Size( w - 2* FOCUS_RING_WIDTH, h ) ); + rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h+2*FOCUS_RING_WIDTH ) ); + + toReturn = sal_True; + } + else if( nPart == PART_BUTTON_UP ) { + //aCtrlBoundRect.GetWidth() contains the width of the full control + //ie the width of the textfield + button + //x is the position of the left corner of the full control + x += aCtrlBoundRect.GetWidth() - SPIN_BUTTON_WIDTH - SPIN_BUTTON_SPACE - CLIP_FUZZ; + y += FOCUS_RING_WIDTH - CLIP_FUZZ; + w = SPIN_BUTTON_WIDTH + 2*CLIP_FUZZ; + h = SPIN_UPPER_BUTTON_HEIGHT + 2*CLIP_FUZZ; + + rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h ) ); + rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h ) ); + + toReturn = sal_True; + } + else if( nPart == PART_BUTTON_DOWN ) { + x += aCtrlBoundRect.GetWidth() - SPIN_BUTTON_WIDTH - SPIN_BUTTON_SPACE - CLIP_FUZZ; + y += SPIN_UPPER_BUTTON_HEIGHT + FOCUS_RING_WIDTH - CLIP_FUZZ; + w = SPIN_BUTTON_WIDTH + 2*CLIP_FUZZ; + h = SPIN_LOWER_BUTTON_HEIGHT + 2*CLIP_FUZZ; + + rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h ) ); + rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h ) ); + + toReturn = sal_True; + } + break; + case CTRL_FRAME: + { + sal_uInt16 nStyle = aValue.getNumericVal(); + if( ( nPart == PART_BORDER ) && + !( nStyle & (FRAME_DRAW_MENU | FRAME_DRAW_WINDOWBORDER | FRAME_DRAW_BORDERWINDOWBORDER) ) ) + { + Rectangle aRect(aCtrlBoundRect); + if( nStyle & FRAME_DRAW_DOUBLEIN ) + { + aRect.Left() += 1; + aRect.Top() += 1; + //rRect.Right() -= 1; + //rRect.Bottom() -= 1; + } + else + { + aRect.Left() += 1; + aRect.Top() += 1; + aRect.Right() -= 1; + aRect.Bottom() -= 1; + } + + rNativeContentRegion = aRect; + rNativeBoundingRegion = aRect; + + toReturn = sal_True; + } + } + break; + + case CTRL_MENUBAR: + case CTRL_MENU_POPUP: + { + if(( nPart == PART_MENU_ITEM_CHECK_MARK )||( nPart == PART_MENU_ITEM_RADIO_MARK )) { + + w=10; + h=10;//dimensions of the mark (10px font) + + rNativeContentRegion = Rectangle( Point( x, y ), Size( w, h ) ); + rNativeBoundingRegion = Rectangle( Point( x, y ), Size( w, h ) ); + + toReturn = sal_True; + } + } + break; + + } + + return toReturn; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/salnsmenu.mm b/vcl/osx/salnsmenu.mm new file mode 100644 index 000000000000..796b05ca7ae4 --- /dev/null +++ b/vcl/osx/salnsmenu.mm @@ -0,0 +1,207 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/salinst.h" +#include "osx/saldata.hxx" +#include "osx/salframe.h" +#include "osx/salmenu.h" +#include "osx/salnsmenu.h" + +#include "vcl/window.hxx" + +@implementation SalNSMenu +-(id)initWithMenu: (AquaSalMenu*)pMenu +{ + mpMenu = pMenu; + return [super initWithTitle: [NSString string]]; +} + +-(void)menuNeedsUpdate: (NSMenu*)pMenu +{ + (void)pMenu; + YIELD_GUARD; + + if( mpMenu ) + { + const AquaSalFrame* pFrame = mpMenu->getFrame(); + if( pFrame && AquaSalFrame::isAlive( pFrame ) ) + { + SalMenuEvent aMenuEvt; + aMenuEvt.mnId = 0; + aMenuEvt.mpMenu = mpMenu->mpVCLMenu; + if( aMenuEvt.mpMenu ) + { + pFrame->CallCallback(SALEVENT_MENUACTIVATE, &aMenuEvt); + pFrame->CallCallback(SALEVENT_MENUDEACTIVATE, &aMenuEvt); + } + else + OSL_FAIL( "unconnected menu" ); + } + } +} + +-(void)setSalMenu: (AquaSalMenu*)pMenu +{ + mpMenu = pMenu; +} +@end + +@implementation SalNSMenuItem +-(id)initWithMenuItem: (AquaSalMenuItem*)pMenuItem +{ + mpMenuItem = pMenuItem; + id ret = [super initWithTitle: [NSString string] + action: @selector(menuItemTriggered:) + keyEquivalent: [NSString string]]; + [ret setTarget: self]; + return ret; +} +-(void)menuItemTriggered: (id)aSender +{ + (void)aSender; + YIELD_GUARD; + + const AquaSalFrame* pFrame = mpMenuItem->mpParentMenu ? mpMenuItem->mpParentMenu->getFrame() : NULL; + if( pFrame && AquaSalFrame::isAlive( pFrame ) && ! pFrame->GetWindow()->IsInModalMode() ) + { + SalMenuEvent aMenuEvt( mpMenuItem->mnId, mpMenuItem->mpVCLMenu ); + pFrame->CallCallback(SALEVENT_MENUCOMMAND, &aMenuEvt); + } + else if( mpMenuItem->mpVCLMenu ) + { + // if an item from submenu was selected. the corresponding Window does not exist because + // we use native popup menus, so we have to set the selected menuitem directly + // incidentally this of course works for top level popup menus, too + PopupMenu * pPopupMenu = dynamic_cast(mpMenuItem->mpVCLMenu); + if( pPopupMenu ) + { + // FIXME: revise this ugly code + + // select handlers in vcl are dispatch on the original menu + // if not consumed by the select handler of the current menu + // however since only the starting menu ever came into Execute + // the hierarchy is not build up. Workaround this by getting + // the menu it should have been + + // get started from hierarchy in vcl menus + AquaSalMenu* pParentMenu = mpMenuItem->mpParentMenu; + Menu* pCurMenu = mpMenuItem->mpVCLMenu; + while( pParentMenu && pParentMenu->mpVCLMenu ) + { + pCurMenu = pParentMenu->mpVCLMenu; + pParentMenu = pParentMenu->mpParentSalMenu; + } + + pPopupMenu->SetSelectedEntry( mpMenuItem->mnId ); + pPopupMenu->ImplSelectWithStart( pCurMenu ); + } + else + OSL_FAIL( "menubar item without frame !" ); + } +} +@end + +@implementation OOStatusItemView +-(void)drawRect: (NSRect)aRect +{ + NSGraphicsContext* pContext = [NSGraphicsContext currentContext]; + [pContext saveGraphicsState]; + [SalData::getStatusItem() drawStatusBarBackgroundInRect: aRect withHighlight: NO]; + if( AquaSalMenu::pCurrentMenuBar ) + { + const std::vector< AquaSalMenu::MenuBarButtonEntry >& rButtons( AquaSalMenu::pCurrentMenuBar->getButtons() ); + NSRect aFrame = [self frame]; + NSRect aImgRect = { { 2, 0 }, { 0, 0 } }; + for( size_t i = 0; i < rButtons.size(); ++i ) + { + NSRect aFromRect = { { 0, 0 }, + { static_cast(rButtons[i].maButton.maImage.GetSizePixel().Width()), + static_cast(rButtons[i].maButton.maImage.GetSizePixel().Height()) } }; + aImgRect.origin.y = floor((aFrame.size.height - aFromRect.size.height)/2); + aImgRect.size = aFromRect.size; + if( rButtons[i].mpNSImage ) + [rButtons[i].mpNSImage drawInRect: aImgRect fromRect: aFromRect operation: NSCompositeSourceOver fraction: 1.0]; + aImgRect.origin.x += aFromRect.size.width + 2; + } + } + [pContext restoreGraphicsState]; +} + +-(void)mouseUp: (NSEvent *)pEvent +{ + /* check if button goes up inside one of our status buttons */ + if( AquaSalMenu::pCurrentMenuBar ) + { + const std::vector< AquaSalMenu::MenuBarButtonEntry >& rButtons( AquaSalMenu::pCurrentMenuBar->getButtons() ); + NSRect aFrame = [self frame]; + NSRect aImgRect = { { 2, 0 }, { 0, 0 } }; + NSPoint aMousePt = [pEvent locationInWindow]; + for( size_t i = 0; i < rButtons.size(); ++i ) + { + NSRect aFromRect = { { 0, 0 }, + { static_cast(rButtons[i].maButton.maImage.GetSizePixel().Width()), + static_cast(rButtons[i].maButton.maImage.GetSizePixel().Height()) } }; + aImgRect.origin.y = (aFrame.size.height - aFromRect.size.height)/2; + aImgRect.size = aFromRect.size; + if( aMousePt.x >= aImgRect.origin.x && aMousePt.x <= (aImgRect.origin.x+aImgRect.size.width) && + aMousePt.y >= aImgRect.origin.y && aMousePt.y <= (aImgRect.origin.y+aImgRect.size.height) ) + { + if( AquaSalMenu::pCurrentMenuBar->mpFrame && AquaSalFrame::isAlive( AquaSalMenu::pCurrentMenuBar->mpFrame ) ) + { + SalMenuEvent aMenuEvt( rButtons[i].maButton.mnId, AquaSalMenu::pCurrentMenuBar->mpVCLMenu ); + AquaSalMenu::pCurrentMenuBar->mpFrame->CallCallback(SALEVENT_MENUBUTTONCOMMAND, &aMenuEvt); + } + return; + } + + aImgRect.origin.x += aFromRect.size.width + 2; + } + } +} + +-(void)layout +{ + NSStatusBar* pStatBar = [NSStatusBar systemStatusBar]; + NSSize aSize = { 0, [pStatBar thickness] }; + [self removeAllToolTips]; + if( AquaSalMenu::pCurrentMenuBar ) + { + const std::vector< AquaSalMenu::MenuBarButtonEntry >& rButtons( AquaSalMenu::pCurrentMenuBar->getButtons() ); + if( ! rButtons.empty() ) + { + aSize.width = 2; + for( size_t i = 0; i < rButtons.size(); ++i ) + { + NSRect aImgRect = { { static_cast(aSize.width), + static_cast(floor((aSize.height-rButtons[i].maButton.maImage.GetSizePixel().Height())/2)) }, + { static_cast(rButtons[i].maButton.maImage.GetSizePixel().Width()), + static_cast(rButtons[i].maButton.maImage.GetSizePixel().Height()) } }; + if( rButtons[i].mpToolTipString ) + [self addToolTipRect: aImgRect owner: rButtons[i].mpToolTipString userData: NULL]; + aSize.width += 2 + aImgRect.size.width; + } + } + } + [self setFrameSize: aSize]; +} +@end + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/salnstimer.mm b/vcl/osx/salnstimer.mm new file mode 100644 index 000000000000..bad2f4e51ff7 --- /dev/null +++ b/vcl/osx/salnstimer.mm @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/saltimer.h" +#include "osx/salnstimer.h" +#include "osx/salinst.h" +#include "osx/saldata.hxx" + +#include "svdata.hxx" + +@implementation TimerCallbackCaller +-(void)timerElapsed:(NSTimer*)pTimer +{ + (void)pTimer; + ImplSVData* pSVData = ImplGetSVData(); + if( AquaSalTimer::bDispatchTimer ) + { + if( pSVData->mpSalTimer ) + { + YIELD_GUARD; + pSVData->mpSalTimer->CallCallback(); + + // NSTimer does not end nextEventMatchingMask of NSApplication + // so we need to wakeup a waiting Yield to inform it something happened + GetSalData()->mpFirstInstance->wakeupYield(); + } + } +} +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/salobj.cxx b/vcl/osx/salobj.cxx new file mode 100644 index 000000000000..16a56b5261ca --- /dev/null +++ b/vcl/osx/salobj.cxx @@ -0,0 +1,206 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include + +#include "osx/saldata.hxx" +#include "osx/salobj.h" +#include "osx/salframe.h" + +// ======================================================================= + +AquaSalObject::AquaSalObject( AquaSalFrame* pFrame ) : + mpFrame( pFrame ), + mnClipX( -1 ), + mnClipY( -1 ), + mnClipWidth( -1 ), + mnClipHeight( -1 ), + mbClip( false ), + mnX( 0 ), + mnY( 0 ), + mnWidth( 20 ), + mnHeight( 20 ) +{ + maSysData.nSize = sizeof( maSysData ); + maSysData.mpNSView = NULL; + + NSRect aInitFrame = { { 0, 0 }, { 20, 20 } }; + mpClipView = [[NSClipView alloc] initWithFrame: aInitFrame ]; + if( mpClipView ) + { + [mpFrame->getNSView() addSubview: mpClipView]; + [mpClipView setHidden: YES]; + } + maSysData.mpNSView = [[NSView alloc] initWithFrame: aInitFrame]; + if( maSysData.mpNSView ) + { + if( mpClipView ) + [mpClipView setDocumentView: maSysData.mpNSView]; + } +} + +// ----------------------------------------------------------------------- + +AquaSalObject::~AquaSalObject() +{ + if( maSysData.mpNSView ) + { + NSView *pView = maSysData.mpNSView; + [pView removeFromSuperview]; + [pView release]; + } + if( mpClipView ) + { + [mpClipView removeFromSuperview]; + [mpClipView release]; + } +} + +/* + sadly there seems to be no way to impose clipping on a child view, + especially a QTMovieView which seems to ignore the current context + completely. Also there is no real way to shape a window; on Aqua a + similar effect to non-rectangular windows is achieved by using a + non-opaque window and not painting where one wants the background + to shine through. + + With respect to SalObject this leaves us to having an NSClipView + containing the child view. Even a QTMovieView respects the boundaries of + that, which gives us a clip "region" consisting of one rectangle. + This is gives us an 80% solution only, though. +*/ + +// ----------------------------------------------------------------------- + +void AquaSalObject::ResetClipRegion() +{ + mbClip = false; + setClippedPosSize(); +} + +// ----------------------------------------------------------------------- + +sal_uInt16 AquaSalObject::GetClipRegionType() +{ + return SAL_OBJECT_CLIP_INCLUDERECTS; +} + +// ----------------------------------------------------------------------- + +void AquaSalObject::BeginSetClipRegion( sal_uLong ) +{ + mbClip = false; +} + +// ----------------------------------------------------------------------- + +void AquaSalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) +{ + if( mbClip ) + { + if( nX < mnClipX ) + { + mnClipWidth += mnClipX - nX; + mnClipX = nX; + } + if( nX + nWidth > mnClipX + mnClipWidth ) + mnClipWidth = nX + nWidth - mnClipX; + if( nY < mnClipY ) + { + mnClipHeight += mnClipY - nY; + mnClipY = nY; + } + if( nY + nHeight > mnClipY + mnClipHeight ) + mnClipHeight = nY + nHeight - mnClipY; + } + else + { + mnClipX = nX; + mnClipY = nY; + mnClipWidth = nWidth; + mnClipHeight = nHeight; + mbClip = true; + } +} + +// ----------------------------------------------------------------------- + +void AquaSalObject::EndSetClipRegion() +{ + setClippedPosSize(); +} + +// ----------------------------------------------------------------------- + +void AquaSalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight ) +{ + mnX = nX; + mnY = nY; + mnWidth = nWidth; + mnHeight = nHeight; + setClippedPosSize(); +} + +// ----------------------------------------------------------------------- + +void AquaSalObject::setClippedPosSize() +{ + NSRect aViewRect = { { 0, 0 }, { static_cast(mnWidth), static_cast(mnHeight) } }; + if( maSysData.mpNSView ) + { + NSView* pNSView = maSysData.mpNSView; + [pNSView setFrame: aViewRect]; + } + + NSRect aClipViewRect = { { static_cast(mnX), static_cast(mnY) }, { static_cast(mnWidth), static_cast(mnHeight) } }; + NSPoint aClipPt = { 0, 0 }; + if( mbClip ) + { + aClipViewRect.origin.x += mnClipX; + aClipViewRect.origin.y += mnClipY; + aClipViewRect.size.width = mnClipWidth; + aClipViewRect.size.height = mnClipHeight; + aClipPt.x = mnClipX; + if( mnClipY == 0 ) + aClipPt.y = mnHeight - mnClipHeight; + } + + mpFrame->VCLToCocoa( aClipViewRect, false ); + [mpClipView setFrame: aClipViewRect]; + + [mpClipView scrollToPoint: aClipPt]; +} + +// ----------------------------------------------------------------------- + +void AquaSalObject::Show( sal_Bool bVisible ) +{ + if( mpClipView ) + [mpClipView setHidden: (bVisible ? NO : YES)]; +} + +// ----------------------------------------------------------------------- + +const SystemEnvData* AquaSalObject::GetSystemData() const +{ + return &maSysData; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/salprn.cxx b/vcl/osx/salprn.cxx new file mode 100644 index 000000000000..082fa1cdc199 --- /dev/null +++ b/vcl/osx/salprn.cxx @@ -0,0 +1,755 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include "officecfg/Office/Common.hxx" + +#include "vcl/print.hxx" +#include + +#include "osx/salinst.h" +#include "osx/salprn.h" +#include "osx/printview.h" +#include "quartz/salgdi.h" +#include "osx/saldata.hxx" +#include "quartz/utils.h" + +#include "jobset.h" +#include "salptype.hxx" + +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/awt/Size.hpp" +#include "com/sun/star/uno/Sequence.hxx" + +#include + +using namespace vcl; +using namespace com::sun::star; +using namespace com::sun::star::beans; + + +// ======================================================================= + +AquaSalInfoPrinter::AquaSalInfoPrinter( const SalPrinterQueueInfo& i_rQueue ) : + mpGraphics( 0 ), + mbGraphics( false ), + mbJob( false ), + mpPrinter( nil ), + mpPrintInfo( nil ), + mePageOrientation( ORIENTATION_PORTRAIT ), + mnStartPageOffsetX( 0 ), + mnStartPageOffsetY( 0 ), + mnCurPageRangeStart( 0 ), + mnCurPageRangeCount( 0 ) +{ + NSString* pStr = CreateNSString( i_rQueue.maPrinterName ); + mpPrinter = [NSPrinter printerWithName: pStr]; + [pStr release]; + + NSPrintInfo* pShared = [NSPrintInfo sharedPrintInfo]; + if( pShared ) + { + mpPrintInfo = [pShared copy]; + [mpPrintInfo setPrinter: mpPrinter]; + mePageOrientation = ([mpPrintInfo orientation] == NSLandscapeOrientation) ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT; +#if MACOSX_SDK_VERSION >= 1090 + [mpPrintInfo setOrientation: NSPaperOrientationPortrait]; +#else + [mpPrintInfo setOrientation: NSPortraitOrientation]; +#endif + } + + mpGraphics = new AquaSalGraphics(); + + const int nWidth = 100, nHeight = 100; + maContextMemory.reset( reinterpret_cast( rtl_allocateMemory( nWidth * 4 * nHeight ) ), + boost::bind( rtl_freeMemory, _1 ) ); + + if( maContextMemory ) + { + mrContext = CGBitmapContextCreate( maContextMemory.get(), nWidth, nHeight, 8, nWidth * 4, GetSalData()->mxRGBSpace, kCGImageAlphaNoneSkipFirst ); + if( mrContext ) + SetupPrinterGraphics( mrContext ); + } +} + +// ----------------------------------------------------------------------- + +AquaSalInfoPrinter::~AquaSalInfoPrinter() +{ + delete mpGraphics; + if( mpPrintInfo ) + [mpPrintInfo release]; + if( mrContext ) + CFRelease( mrContext ); +} + +// ----------------------------------------------------------------------- + +void AquaSalInfoPrinter::SetupPrinterGraphics( CGContextRef i_rContext ) const +{ + if( mpGraphics ) + { + if( mpPrintInfo ) + { + // FIXME: get printer resolution + long nDPIX = 720, nDPIY = 720; + NSSize aPaperSize = [mpPrintInfo paperSize]; + + NSRect aImageRect = [mpPrintInfo imageablePageBounds]; + if( mePageOrientation == ORIENTATION_PORTRAIT ) + { + // move mirrored CTM back into paper + double dX = 0, dY = aPaperSize.height; + // move CTM to reflect imageable area + dX += aImageRect.origin.x; + dY -= aPaperSize.height - aImageRect.size.height - aImageRect.origin.y; + CGContextTranslateCTM( i_rContext, dX + mnStartPageOffsetX, dY - mnStartPageOffsetY ); + // scale to be top/down and reflect our "virtual" DPI + CGContextScaleCTM( i_rContext, 72.0/double(nDPIX), -(72.0/double(nDPIY)) ); + } + else + { + // move CTM to reflect imageable area + double dX = aImageRect.origin.x, dY = aPaperSize.height - aImageRect.size.height - aImageRect.origin.y; + CGContextTranslateCTM( i_rContext, -dX, -dY ); + // turn by 90 degree + CGContextRotateCTM( i_rContext, M_PI/2 ); + // move turned CTM back into paper + dX = aPaperSize.height; + dY = -aPaperSize.width; + CGContextTranslateCTM( i_rContext, dX + mnStartPageOffsetY, dY - mnStartPageOffsetX ); + // scale to be top/down and reflect our "virtual" DPI + CGContextScaleCTM( i_rContext, -(72.0/double(nDPIY)), (72.0/double(nDPIX)) ); + } + mpGraphics->SetPrinterGraphics( i_rContext, nDPIX, nDPIY, 1.0 ); + } + else + OSL_FAIL( "no print info in SetupPrinterGraphics" ); + } +} + +// ----------------------------------------------------------------------- + +SalGraphics* AquaSalInfoPrinter::GetGraphics() +{ + SalGraphics* pGraphics = mbGraphics ? NULL : mpGraphics; + mbGraphics = true; + return pGraphics; +} + +// ----------------------------------------------------------------------- + +void AquaSalInfoPrinter::ReleaseGraphics( SalGraphics* ) +{ + mbGraphics = false; +} + +// ----------------------------------------------------------------------- + +sal_Bool AquaSalInfoPrinter::Setup( SalFrame*, ImplJobSetup* ) +{ + return sal_False; +} + +// ----------------------------------------------------------------------- + +sal_Bool AquaSalInfoPrinter::SetPrinterData( ImplJobSetup* io_pSetupData ) +{ + // FIXME: implement driver data + if( io_pSetupData && io_pSetupData->mpDriverData ) + return SetData( ~0, io_pSetupData ); + + + sal_Bool bSuccess = sal_True; + + // set system type + io_pSetupData->mnSystem = JOBSETUP_SYSTEM_MAC; + + // get paper format + if( mpPrintInfo ) + { + NSSize aPaperSize = [mpPrintInfo paperSize]; + double width = aPaperSize.width, height = aPaperSize.height; + // set paper + PaperInfo aInfo( PtTo10Mu( width ), PtTo10Mu( height ) ); + aInfo.doSloppyFit(); + io_pSetupData->mePaperFormat = aInfo.getPaper(); + if( io_pSetupData->mePaperFormat == PAPER_USER ) + { + io_pSetupData->mnPaperWidth = PtTo10Mu( width ); + io_pSetupData->mnPaperHeight = PtTo10Mu( height ); + } + else + { + io_pSetupData->mnPaperWidth = 0; + io_pSetupData->mnPaperHeight = 0; + } + + // set orientation + io_pSetupData->meOrientation = mePageOrientation; + + io_pSetupData->mnPaperBin = 0; + io_pSetupData->mpDriverData = reinterpret_cast(rtl_allocateMemory( 4 )); + io_pSetupData->mnDriverDataLen = 4; + } + else + bSuccess = sal_False; + + + return bSuccess; +} + +// ----------------------------------------------------------------------- + +void AquaSalInfoPrinter::setPaperSize( long i_nWidth, long i_nHeight, Orientation i_eSetOrientation ) +{ + + Orientation ePaperOrientation = ORIENTATION_PORTRAIT; + const PaperInfo* pPaper = matchPaper( i_nWidth, i_nHeight, ePaperOrientation ); + + if( pPaper ) + { + NSString* pPaperName = [CreateNSString( OStringToOUString(PaperInfo::toPSName(pPaper->getPaper()), RTL_TEXTENCODING_ASCII_US) ) autorelease]; + [mpPrintInfo setPaperName: pPaperName]; + } + else if( i_nWidth > 0 && i_nHeight > 0 ) + { + NSSize aPaperSize = { static_cast(TenMuToPt(i_nWidth)), static_cast(TenMuToPt(i_nHeight)) }; + [mpPrintInfo setPaperSize: aPaperSize]; + } + // this seems counterintuitive + mePageOrientation = i_eSetOrientation; +} + +// ----------------------------------------------------------------------- + +sal_Bool AquaSalInfoPrinter::SetData( sal_uLong i_nFlags, ImplJobSetup* io_pSetupData ) +{ + if( ! io_pSetupData || io_pSetupData->mnSystem != JOBSETUP_SYSTEM_MAC ) + return sal_False; + + + if( mpPrintInfo ) + { + if( (i_nFlags & SAL_JOBSET_ORIENTATION) != 0 ) + mePageOrientation = io_pSetupData->meOrientation; + + if( (i_nFlags & SAL_JOBSET_PAPERSIZE) != 0) + { + // set paper format + long width = 21000, height = 29700; + if( io_pSetupData->mePaperFormat == PAPER_USER ) + { + // #i101108# sanity check + if( io_pSetupData->mnPaperWidth && io_pSetupData->mnPaperHeight ) + { + width = io_pSetupData->mnPaperWidth; + height = io_pSetupData->mnPaperHeight; + } + } + else + { + PaperInfo aInfo( io_pSetupData->mePaperFormat ); + width = aInfo.getWidth(); + height = aInfo.getHeight(); + } + + setPaperSize( width, height, mePageOrientation ); + } + } + + return mpPrintInfo != nil; +} + +// ----------------------------------------------------------------------- + +sal_uLong AquaSalInfoPrinter::GetPaperBinCount( const ImplJobSetup* ) +{ + return 0; +} + +// ----------------------------------------------------------------------- + +OUString AquaSalInfoPrinter::GetPaperBinName( const ImplJobSetup*, sal_uLong ) +{ + return OUString(); +} + +// ----------------------------------------------------------------------- + +sal_uLong AquaSalInfoPrinter::GetCapabilities( const ImplJobSetup*, sal_uInt16 i_nType ) +{ + switch( i_nType ) + { + case PRINTER_CAPABILITIES_SUPPORTDIALOG: + return 0; + case PRINTER_CAPABILITIES_COPIES: + return 0xffff; + case PRINTER_CAPABILITIES_COLLATECOPIES: + return 0xffff; + case PRINTER_CAPABILITIES_SETORIENTATION: + return 1; + case PRINTER_CAPABILITIES_SETDUPLEX: + return 0; + case PRINTER_CAPABILITIES_SETPAPERBIN: + return 0; + case PRINTER_CAPABILITIES_SETPAPERSIZE: + return 1; + case PRINTER_CAPABILITIES_SETPAPER: + return 1; + case PRINTER_CAPABILITIES_EXTERNALDIALOG: + return officecfg::Office::Common::Misc::UseSystemPrintDialog::get() + ? 1 : 0; + case PRINTER_CAPABILITIES_PDF: + return 1; + case PRINTER_CAPABILITIES_USEPULLMODEL: + return 1; + default: break; + }; + return 0; +} + +// ----------------------------------------------------------------------- + +void AquaSalInfoPrinter::GetPageInfo( const ImplJobSetup*, + long& o_rOutWidth, long& o_rOutHeight, + long& o_rPageOffX, long& o_rPageOffY, + long& o_rPageWidth, long& o_rPageHeight ) +{ + if( mpPrintInfo ) + { + sal_Int32 nDPIX = 72, nDPIY = 72; + mpGraphics->GetResolution( nDPIX, nDPIY ); + const double fXScaling = static_cast(nDPIX)/72.0, + fYScaling = static_cast(nDPIY)/72.0; + + NSSize aPaperSize = [mpPrintInfo paperSize]; + o_rPageWidth = static_cast( double(aPaperSize.width) * fXScaling ); + o_rPageHeight = static_cast( double(aPaperSize.height) * fYScaling ); + + NSRect aImageRect = [mpPrintInfo imageablePageBounds]; + o_rPageOffX = static_cast( aImageRect.origin.x * fXScaling ); + o_rPageOffY = static_cast( (aPaperSize.height - aImageRect.size.height - aImageRect.origin.y) * fYScaling ); + o_rOutWidth = static_cast( aImageRect.size.width * fXScaling ); + o_rOutHeight = static_cast( aImageRect.size.height * fYScaling ); + + if( mePageOrientation == ORIENTATION_LANDSCAPE ) + { + std::swap( o_rOutWidth, o_rOutHeight ); + std::swap( o_rPageWidth, o_rPageHeight ); + std::swap( o_rPageOffX, o_rPageOffY ); + } + } +} + +static Size getPageSize( vcl::PrinterController& i_rController, sal_Int32 i_nPage ) +{ + Size aPageSize; + uno::Sequence< PropertyValue > aPageParms( i_rController.getPageParameters( i_nPage ) ); + for( sal_Int32 nProperty = 0, nPropertyCount = aPageParms.getLength(); nProperty < nPropertyCount; ++nProperty ) + { + if ( aPageParms[ nProperty ].Name == "PageSize" ) + { + awt::Size aSize; + aPageParms[ nProperty].Value >>= aSize; + aPageSize.Width() = aSize.Width; + aPageSize.Height() = aSize.Height; + break; + } + } + return aPageSize; +} + +sal_Bool AquaSalInfoPrinter::StartJob( const OUString* i_pFileName, + const OUString& i_rJobName, + const OUString& /*i_rAppName*/, + ImplJobSetup* i_pSetupData, + vcl::PrinterController& i_rController + ) +{ + if( mbJob ) + return sal_False; + + sal_Bool bSuccess = sal_False; + bool bWasAborted = false; + AquaSalInstance* pInst = GetSalData()->mpFirstInstance; + PrintAccessoryViewState aAccViewState; + sal_Int32 nAllPages = 0; + + // reset IsLastPage + i_rController.setLastPage( sal_False ); + + // update job data + if( i_pSetupData ) + SetData( ~0, i_pSetupData ); + + // do we want a progress panel ? + sal_Bool bShowProgressPanel = sal_True; + beans::PropertyValue* pMonitor = i_rController.getValue( OUString( "MonitorVisible" ) ); + if( pMonitor ) + pMonitor->Value >>= bShowProgressPanel; + if( ! i_rController.isShowDialogs() ) + bShowProgressPanel = sal_False; + + // possibly create one job for collated output + sal_Bool bSinglePrintJobs = sal_False; + beans::PropertyValue* pSingleValue = i_rController.getValue( OUString( "PrintCollateAsSingleJobs" ) ); + if( pSingleValue ) + { + pSingleValue->Value >>= bSinglePrintJobs; + } + + // FIXME: jobStarted() should be done after the print dialog has ended (if there is one) + // how do I know when that might be ? + i_rController.jobStarted(); + + + int nCopies = i_rController.getPrinter()->GetCopyCount(); + int nJobs = 1; + if( bSinglePrintJobs ) + { + nJobs = nCopies; + nCopies = 1; + } + + for( int nCurJob = 0; nCurJob < nJobs; nCurJob++ ) + { + aAccViewState.bNeedRestart = true; + do + { + if( aAccViewState.bNeedRestart ) + { + mnCurPageRangeStart = 0; + mnCurPageRangeCount = 0; + nAllPages = i_rController.getFilteredPageCount(); + } + + aAccViewState.bNeedRestart = false; + + Size aCurSize( 21000, 29700 ); + if( nAllPages > 0 ) + { + mnCurPageRangeCount = 1; + aCurSize = getPageSize( i_rController, mnCurPageRangeStart ); + Size aNextSize( aCurSize ); + + // print pages up to a different size + while( mnCurPageRangeCount + mnCurPageRangeStart < nAllPages ) + { + aNextSize = getPageSize( i_rController, mnCurPageRangeStart + mnCurPageRangeCount ); + if( aCurSize == aNextSize // same page size + || + (aCurSize.Width() == aNextSize.Height() && aCurSize.Height() == aNextSize.Width()) // same size, but different orientation + ) + { + mnCurPageRangeCount++; + } + else + break; + } + } + else + mnCurPageRangeCount = 0; + + // now for the current run + mnStartPageOffsetX = mnStartPageOffsetY = 0; + // setup the paper size and orientation + // do this on our associated Printer object, since that is + // out interface to the applications which occasionally rely on the paper + // information (e.g. brochure printing scales to the found paper size) + // also SetPaperSizeUser has the advantage that we can share a + // platform independent paper matching algorithm + boost::shared_ptr pPrinter( i_rController.getPrinter() ); + pPrinter->SetMapMode( MapMode( MAP_100TH_MM ) ); + pPrinter->SetPaperSizeUser( aCurSize, true ); + + // create view + NSView* pPrintView = [[AquaPrintView alloc] initWithController: &i_rController withInfoPrinter: this]; + + NSMutableDictionary* pPrintDict = [mpPrintInfo dictionary]; + + // set filename + if( i_pFileName ) + { + [mpPrintInfo setJobDisposition: NSPrintSaveJob]; + NSString* pPath = CreateNSString( *i_pFileName ); + [pPrintDict setObject: pPath forKey: NSPrintSavePath]; + [pPath release]; + } + + [pPrintDict setObject: [[NSNumber numberWithInt: nCopies] autorelease] forKey: NSPrintCopies]; + if( nCopies > 1 ) + [pPrintDict setObject: [[NSNumber numberWithBool: pPrinter->IsCollateCopy()] autorelease] forKey: NSPrintMustCollate]; + [pPrintDict setObject: [[NSNumber numberWithBool: YES] autorelease] forKey: NSPrintDetailedErrorReporting]; + [pPrintDict setObject: [[NSNumber numberWithInt: 1] autorelease] forKey: NSPrintFirstPage]; + // #i103253# weird: for some reason, autoreleasing the value below like the others above + // leads do a double free malloc error. Why this value should behave differently from all the others + // is a mystery. + [pPrintDict setObject: [NSNumber numberWithInt: mnCurPageRangeCount] forKey: NSPrintLastPage]; + + + // create print operation + NSPrintOperation* pPrintOperation = [NSPrintOperation printOperationWithView: pPrintView printInfo: mpPrintInfo]; + + if( pPrintOperation ) + { + NSObject* pReleaseAfterUse = nil; + bool bShowPanel = !i_rController.isDirectPrint() + && (officecfg::Office::Common::Misc::UseSystemPrintDialog:: + get()) + && i_rController.isShowDialogs(); + [pPrintOperation setShowsPrintPanel: bShowPanel ? YES : NO ]; + [pPrintOperation setShowsProgressPanel: bShowProgressPanel ? YES : NO]; + + // set job title (since MacOSX 10.5) + if( [pPrintOperation respondsToSelector: @selector(setJobTitle:)] ) + [pPrintOperation performSelector: @selector(setJobTitle:) withObject: [CreateNSString( i_rJobName ) autorelease]]; + + if( bShowPanel && mnCurPageRangeStart == 0 && nCurJob == 0) // only the first range of pages (in the first job) gets the accesory view + pReleaseAfterUse = [AquaPrintAccessoryView setupPrinterPanel: pPrintOperation withController: &i_rController withState: &aAccViewState]; + + bSuccess = sal_True; + mbJob = true; + pInst->startedPrintJob(); + [pPrintOperation runOperation]; + pInst->endedPrintJob(); + bWasAborted = [[[pPrintOperation printInfo] jobDisposition] compare: NSPrintCancelJob] == NSOrderedSame; + mbJob = false; + if( pReleaseAfterUse ) + [pReleaseAfterUse release]; + } + + mnCurPageRangeStart += mnCurPageRangeCount; + mnCurPageRangeCount = 1; + } while( aAccViewState.bNeedRestart || mnCurPageRangeStart + mnCurPageRangeCount < nAllPages ); + } + + // inform application that it can release its data + // this is awkward, but the XRenderable interface has no method for this, + // so we need to call XRenderadble::render one last time with IsLastPage = sal_True + i_rController.setLastPage( sal_True ); + GDIMetaFile aPageFile; + if( mrContext ) + SetupPrinterGraphics( mrContext ); + i_rController.getFilteredPageFile( 0, aPageFile ); + + i_rController.setJobState( bWasAborted + ? view::PrintableState_JOB_ABORTED + : view::PrintableState_JOB_SPOOLED ); + + mnCurPageRangeStart = mnCurPageRangeCount = 0; + + return bSuccess; +} + +// ----------------------------------------------------------------------- + +sal_Bool AquaSalInfoPrinter::EndJob() +{ + mnStartPageOffsetX = mnStartPageOffsetY = 0; + mbJob = false; + return sal_True; +} + +// ----------------------------------------------------------------------- + +sal_Bool AquaSalInfoPrinter::AbortJob() +{ + mbJob = false; + + // FIXME: implementation + return sal_False; +} + +// ----------------------------------------------------------------------- + +SalGraphics* AquaSalInfoPrinter::StartPage( ImplJobSetup* i_pSetupData, sal_Bool i_bNewJobData ) +{ + if( i_bNewJobData && i_pSetupData ) + SetPrinterData( i_pSetupData ); + + CGContextRef rContext = reinterpret_cast([[NSGraphicsContext currentContext] graphicsPort]); + + SetupPrinterGraphics( rContext ); + + return mpGraphics; +} + +// ----------------------------------------------------------------------- + +sal_Bool AquaSalInfoPrinter::EndPage() +{ + mpGraphics->InvalidateContext(); + return sal_True; +} + +// ----------------------------------------------------------------------- + +sal_uLong AquaSalInfoPrinter::GetErrorCode() const +{ + return 0; +} + +// ======================================================================= + +AquaSalPrinter::AquaSalPrinter( AquaSalInfoPrinter* i_pInfoPrinter ) : + mpInfoPrinter( i_pInfoPrinter ) +{ +} + +// ----------------------------------------------------------------------- + +AquaSalPrinter::~AquaSalPrinter() +{ +} + +// ----------------------------------------------------------------------- + +sal_Bool AquaSalPrinter::StartJob( const OUString* i_pFileName, + const OUString& i_rJobName, + const OUString& i_rAppName, + ImplJobSetup* i_pSetupData, + vcl::PrinterController& i_rController ) +{ + return mpInfoPrinter->StartJob( i_pFileName, i_rJobName, i_rAppName, i_pSetupData, i_rController ); +} + +// ----------------------------------------------------------------------- + +sal_Bool AquaSalPrinter::StartJob( const OUString* /*i_pFileName*/, + const OUString& /*i_rJobName*/, + const OUString& /*i_rAppName*/, + sal_uLong /*i_nCopies*/, + bool /*i_bCollate*/, + bool /*i_bDirect*/, + ImplJobSetup* ) +{ + OSL_FAIL( "should never be called" ); + return sal_False; +} + +// ----------------------------------------------------------------------- + +sal_Bool AquaSalPrinter::EndJob() +{ + return mpInfoPrinter->EndJob(); +} + +// ----------------------------------------------------------------------- + +sal_Bool AquaSalPrinter::AbortJob() +{ + return mpInfoPrinter->AbortJob(); +} + +// ----------------------------------------------------------------------- + +SalGraphics* AquaSalPrinter::StartPage( ImplJobSetup* i_pSetupData, sal_Bool i_bNewJobData ) +{ + return mpInfoPrinter->StartPage( i_pSetupData, i_bNewJobData ); +} + +// ----------------------------------------------------------------------- + +sal_Bool AquaSalPrinter::EndPage() +{ + return mpInfoPrinter->EndPage(); +} + +// ----------------------------------------------------------------------- + +sal_uLong AquaSalPrinter::GetErrorCode() +{ + return mpInfoPrinter->GetErrorCode(); +} + +void AquaSalInfoPrinter::InitPaperFormats( const ImplJobSetup* ) +{ + m_aPaperFormats.clear(); + m_bPapersInit = true; + + if( mpPrinter ) + { + if( [mpPrinter statusForTable: @"PPD"] == NSPrinterTableOK ) + { + NSArray* pPaperNames = [mpPrinter stringListForKey: @"PageSize" inTable: @"PPD"]; + if( pPaperNames ) + { + unsigned int nPapers = [pPaperNames count]; + for( unsigned int i = 0; i < nPapers; i++ ) + { + NSString* pPaper = [pPaperNames objectAtIndex: i]; + // first try to match the name + OString aPaperName( [pPaper UTF8String] ); + Paper ePaper = PaperInfo::fromPSName( aPaperName ); + if( ePaper != PAPER_USER ) + { + m_aPaperFormats.push_back( PaperInfo( ePaper ) ); + } + else + { + NSSize aPaperSize = [mpPrinter pageSizeForPaper: pPaper]; + if( aPaperSize.width > 0 && aPaperSize.height > 0 ) + { + PaperInfo aInfo( PtTo10Mu( aPaperSize.width ), + PtTo10Mu( aPaperSize.height ) ); + if( aInfo.getPaper() == PAPER_USER ) + aInfo.doSloppyFit(); + m_aPaperFormats.push_back( aInfo ); + } + } + } + } + } + } +} + +const PaperInfo* AquaSalInfoPrinter::matchPaper( long i_nWidth, long i_nHeight, Orientation& o_rOrientation ) const +{ + if( ! m_bPapersInit ) + const_cast(this)->InitPaperFormats( NULL ); + + const PaperInfo* pMatch = NULL; + o_rOrientation = ORIENTATION_PORTRAIT; + for( int n = 0; n < 2 ; n++ ) + { + for( size_t i = 0; i < m_aPaperFormats.size(); i++ ) + { + if( abs( m_aPaperFormats[i].getWidth() - i_nWidth ) < 50 && + abs( m_aPaperFormats[i].getHeight() - i_nHeight ) < 50 ) + { + pMatch = &m_aPaperFormats[i]; + return pMatch; + } + } + o_rOrientation = ORIENTATION_LANDSCAPE; + std::swap( i_nWidth, i_nHeight ); + } + return pMatch; +} + +int AquaSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* ) +{ + return 900; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/salsys.cxx b/vcl/osx/salsys.cxx new file mode 100644 index 000000000000..9ac4b5aeb61f --- /dev/null +++ b/vcl/osx/salsys.cxx @@ -0,0 +1,190 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "rtl/ustrbuf.hxx" + +#include "vcl/button.hxx" + +#include "osx/salsys.h" +#include "osx/saldata.hxx" +#include "osx/salinst.h" +#include "quartz/utils.h" + +#include "svids.hrc" + + +// ======================================================================= + +AquaSalSystem::~AquaSalSystem() +{ +} + +unsigned int AquaSalSystem::GetDisplayScreenCount() +{ + NSArray* pScreens = [NSScreen screens]; + return pScreens ? [pScreens count] : 1; +} + +Rectangle AquaSalSystem::GetDisplayScreenPosSizePixel( unsigned int nScreen ) +{ + NSArray* pScreens = [NSScreen screens]; + Rectangle aRet; + NSScreen* pScreen = nil; + if( pScreens && nScreen < [pScreens count] ) + pScreen = [pScreens objectAtIndex: nScreen]; + else + pScreen = [NSScreen mainScreen]; + + if( pScreen ) + { + NSRect aFrame = [pScreen frame]; + aRet = Rectangle( Point( static_cast(aFrame.origin.x), static_cast(aFrame.origin.y) ), + Size( static_cast(aFrame.size.width), static_cast(aFrame.size.height) ) ); + } + return aRet; +} + +OUString AquaSalSystem::GetDisplayScreenName( unsigned int nScreen ) +{ + NSArray* pScreens = [NSScreen screens]; + OUString aRet; + if( nScreen < [pScreens count] ) + { + ResMgr* pMgr = ImplGetResMgr(); + if( pMgr ) + { + OUString aScreenName(ResId(SV_MAC_SCREENNNAME, *pMgr).toString()); + aRet = aScreenName.replaceAll("%d", OUString::number(nScreen)); + } + } + return aRet; +} + +static NSString* getStandardString( int nButtonId, bool bUseResources ) +{ + OUString aText; + if( bUseResources ) + { + aText = Button::GetStandardText( nButtonId ); + } + if( aText.isEmpty() ) // this is for bad cases, we might be missing the vcl resource + { + switch( nButtonId ) + { + case BUTTON_OK: aText = "OK";break; + case BUTTON_ABORT: aText = "Abort";break; + case BUTTON_CANCEL: aText = "Cancel";break; + case BUTTON_RETRY: aText = "Retry";break; + case BUTTON_YES: aText = "Yes";break; + case BUTTON_NO : aText = "No";break; + } + } + return aText.isEmpty() ? nil : CreateNSString( aText); +} + +int AquaSalSystem::ShowNativeMessageBox( const OUString& rTitle, + const OUString& rMessage, + int nButtonCombination, + int nDefaultButton, bool bUseResources) +{ + NSString* pTitle = CreateNSString( rTitle ); + NSString* pMessage = CreateNSString( rMessage ); + + struct id_entry + { + int nCombination; + int nDefaultButton; + int nTextIds[3]; + } aButtonIds[] = + { + { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK, { BUTTON_OK, -1, -1 } }, + { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK, { BUTTON_OK, BUTTON_CANCEL, -1 } }, + { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL, { BUTTON_CANCEL, BUTTON_OK, -1 } }, + { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_ABORT_RETRY_IGNORE, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_ABORT, { BUTTON_ABORT, BUTTON_IGNORE, BUTTON_RETRY } }, + { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_ABORT_RETRY_IGNORE, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_RETRY, { BUTTON_RETRY, BUTTON_IGNORE, BUTTON_ABORT } }, + { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_ABORT_RETRY_IGNORE, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_IGNORE, { BUTTON_IGNORE, BUTTON_IGNORE, BUTTON_ABORT } }, + { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_YES_NO_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_YES, { BUTTON_YES, BUTTON_NO, BUTTON_CANCEL } }, + { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_YES_NO_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO, { BUTTON_NO, BUTTON_YES, BUTTON_CANCEL } }, + { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_YES_NO_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL, { BUTTON_CANCEL, BUTTON_YES, BUTTON_NO } }, + { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_YES_NO, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_YES, { BUTTON_YES, BUTTON_NO, -1 } }, + { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_YES_NO, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO, { BUTTON_NO, BUTTON_YES, -1 } }, + { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_RETRY, { BUTTON_RETRY, BUTTON_CANCEL, -1 } }, + { SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL, SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL, { BUTTON_CANCEL, BUTTON_RETRY, -1 } } + }; + + NSString* pDefText = nil; + NSString* pAltText = nil; + NSString* pOthText = nil; + + unsigned int nC; + for( nC = 0; nC < sizeof(aButtonIds)/sizeof(aButtonIds[0]); nC++ ) + { + if( aButtonIds[nC].nCombination == nButtonCombination ) + { + if( aButtonIds[nC].nDefaultButton == nDefaultButton ) + { + if( aButtonIds[nC].nTextIds[0] != -1 ) + pDefText = getStandardString( + aButtonIds[nC].nTextIds[0], bUseResources ); + if( aButtonIds[nC].nTextIds[1] != -1 ) + pAltText = getStandardString( + aButtonIds[nC].nTextIds[1], bUseResources ); + if( aButtonIds[nC].nTextIds[2] != -1 ) + pOthText = getStandardString( + aButtonIds[nC].nTextIds[2], bUseResources ); + break; + } + } + } + + + int nResult = NSRunAlertPanel( pTitle, pMessage, pDefText, pAltText, pOthText ); + + if( pTitle ) + [pTitle release]; + if( pMessage ) + [pMessage release]; + if( pDefText ) + [pDefText release]; + if( pAltText ) + [pAltText release]; + if( pOthText ) + [pOthText release]; + + int nRet = 0; + if( nC < sizeof(aButtonIds)/sizeof(aButtonIds[0]) && nResult >= 1 && nResult <= 3 ) + { + int nPressed = aButtonIds[nC].nTextIds[nResult-1]; + switch( nPressed ) + { + case BUTTON_NO: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO; break; + case BUTTON_YES: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_YES; break; + case BUTTON_OK: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK; break; + case BUTTON_CANCEL: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL; break; + case BUTTON_ABORT: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_ABORT; break; + case BUTTON_RETRY: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_RETRY; break; + case BUTTON_IGNORE: nRet = SALSYSTEM_SHOWNATIVEMSGBOX_BTN_IGNORE; break; + } + } + + return nRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/saltimer.cxx b/vcl/osx/saltimer.cxx new file mode 100644 index 000000000000..ad0959048964 --- /dev/null +++ b/vcl/osx/saltimer.cxx @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osx/saltimer.h" +#include "osx/salnstimer.h" +#include "osx/saldata.hxx" +#include "osx/salframe.h" +#include "osx/salinst.h" + +// ======================================================================= + +NSTimer* AquaSalTimer::pRunningTimer = nil; +bool AquaSalTimer::bDispatchTimer = false; + + +void ImplSalStartTimer( sal_uLong nMS ) +{ + SalData* pSalData = GetSalData(); + if( pSalData->mpFirstInstance->isNSAppThread() ) + { + AquaSalTimer::bDispatchTimer = true; + NSTimeInterval aTI = double(nMS)/1000.0; + if( AquaSalTimer::pRunningTimer != nil ) + { + if( [AquaSalTimer::pRunningTimer timeInterval] == aTI ) + // set new fire date + [AquaSalTimer::pRunningTimer setFireDate: [NSDate dateWithTimeIntervalSinceNow: aTI]]; + else + { + [AquaSalTimer::pRunningTimer invalidate]; + AquaSalTimer::pRunningTimer = nil; + } + } + if( AquaSalTimer::pRunningTimer == nil ) + { + AquaSalTimer::pRunningTimer = [NSTimer scheduledTimerWithTimeInterval: aTI + target: [[[TimerCallbackCaller alloc] init] autorelease] + selector: @selector(timerElapsed:) + userInfo: nil + repeats: YES]; + /* #i84055# add timer to tracking run loop mode, + so they also elapse while e.g. life resize + */ + [[NSRunLoop currentRunLoop] addTimer: AquaSalTimer::pRunningTimer forMode: NSEventTrackingRunLoopMode]; + } + } + else + { + SalData::ensureThreadAutoreleasePool(); + // post an event so we can get into the main thread + NSPoint aPt = { 0, 0 }; + NSEvent* pEvent = [NSEvent otherEventWithType: NSApplicationDefined + location: aPt + modifierFlags: 0 + timestamp: [NSDate timeIntervalSinceReferenceDate] + windowNumber: 0 + context: nil + subtype: AquaSalInstance::AppStartTimerEvent + data1: (int)nMS + data2: 0 ]; + if( pEvent ) + [NSApp postEvent: pEvent atStart: YES]; + } +} + +void ImplSalStopTimer() +{ + AquaSalTimer::bDispatchTimer = false; +} + +void AquaSalTimer::handleStartTimerEvent( NSEvent* pEvent ) +{ + ImplSVData* pSVData = ImplGetSVData(); + if( pSVData->mpSalTimer ) + { + NSTimeInterval posted = [pEvent timestamp] + NSTimeInterval([pEvent data1])/1000.0; + NSTimeInterval current = [NSDate timeIntervalSinceReferenceDate]; + if( (posted - current) <= 0.0 ) + { + YIELD_GUARD; + // timer already elapsed since event posted + pSVData->mpSalTimer->CallCallback(); + } + ImplSalStartTimer( sal_uLong( [pEvent data1] ) ); + } + +} + +AquaSalTimer::AquaSalTimer( ) +{ +} + +AquaSalTimer::~AquaSalTimer() +{ + ImplSalStopTimer(); +} + +void AquaSalTimer::Start( sal_uLong nMS ) +{ + ImplSalStartTimer( nMS ); +} + +void AquaSalTimer::Stop() +{ + ImplSalStopTimer(); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/salvd.cxx b/vcl/osx/salvd.cxx new file mode 100644 index 000000000000..3f69ab9f5f7c --- /dev/null +++ b/vcl/osx/salvd.cxx @@ -0,0 +1,261 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "vcl/svapp.hxx" +#include "vcl/sysdata.hxx" + +#include "osx/salvd.h" +#include "osx/salinst.h" +#include "quartz/salgdi.h" +#include "osx/saldata.hxx" +#include "osx/salframe.h" + +// ----------------------------------------------------------------------- + +SalVirtualDevice* AquaSalInstance::CreateVirtualDevice( SalGraphics* pGraphics, + long nDX, long nDY, sal_uInt16 nBitCount, const SystemGraphicsData *pData ) +{ + // #i92075# can be called first in a thread + SalData::ensureThreadAutoreleasePool(); + + return new AquaSalVirtualDevice( static_cast< AquaSalGraphics* >( pGraphics ), nDX, nDY, nBitCount, pData ); +} + +// ----------------------------------------------------------------------- + +void AquaSalInstance::DestroyVirtualDevice( SalVirtualDevice* pDevice ) +{ + delete pDevice; +} + +// ======================================================================= + +AquaSalVirtualDevice::AquaSalVirtualDevice( AquaSalGraphics* pGraphic, long nDX, long nDY, sal_uInt16 nBitCount, const SystemGraphicsData *pData ) +: mbGraphicsUsed( false ) +, mxBitmapContext( NULL ) +, mnBitmapDepth( 0 ) +, mxLayer( NULL ) +{ + if( pGraphic && pData && pData->rCGContext ) + { + // Create virtual device based on existing SystemGraphicsData + // We ignore nDx and nDY, as the desired size comes from the SystemGraphicsData + mbForeignContext = true; // the mxContext is from pData + mpGraphics = new AquaSalGraphics( /*pGraphic*/ ); + mpGraphics->SetVirDevGraphics( mxLayer, pData->rCGContext ); + } + else + { + // create empty new virtual device + mbForeignContext = false; // the mxContext is created within VCL + mpGraphics = new AquaSalGraphics(); // never fails + mnBitmapDepth = nBitCount; + + // inherit resolution from reference device + if( pGraphic ) + { + AquaSalFrame* pFrame = pGraphic->getGraphicsFrame(); + if( pFrame && AquaSalFrame::isAlive( pFrame ) ) + { + mpGraphics->setGraphicsFrame( pFrame ); + mpGraphics->copyResolution( *pGraphic ); + } + } + + if( nDX && nDY ) + SetSize( nDX, nDY ); + + // NOTE: if SetSize does not succeed, we just ignore the nDX and nDY + } +} + +// ----------------------------------------------------------------------- + +AquaSalVirtualDevice::~AquaSalVirtualDevice() +{ + if( mpGraphics ) + { + mpGraphics->SetVirDevGraphics( NULL, NULL ); + delete mpGraphics; + mpGraphics = 0; + } + Destroy(); +} + +// ----------------------------------------------------------------------- + +void AquaSalVirtualDevice::Destroy() +{ + if( mbForeignContext ) { + // Do not delete mxContext that we have received from outside VCL + mxLayer = NULL; + return; + } + + if( mxLayer ) + { + if( mpGraphics ) + mpGraphics->SetVirDevGraphics( NULL, NULL ); + CGLayerRelease( mxLayer ); + mxLayer = NULL; + } + + if( mxBitmapContext ) + { + void* pRawData = CGBitmapContextGetData( mxBitmapContext ); + rtl_freeMemory( pRawData ); + CGContextRelease( mxBitmapContext ); + mxBitmapContext = NULL; + } +} + +// ----------------------------------------------------------------------- + +SalGraphics* AquaSalVirtualDevice::GetGraphics() +{ + if( mbGraphicsUsed || !mpGraphics ) + return 0; + + mbGraphicsUsed = true; + return mpGraphics; +} + +// ----------------------------------------------------------------------- + +void AquaSalVirtualDevice::ReleaseGraphics( SalGraphics* ) +{ + mbGraphicsUsed = false; +} + +// ----------------------------------------------------------------------- + +sal_Bool AquaSalVirtualDevice::SetSize( long nDX, long nDY ) +{ + if( mbForeignContext ) + { + // Do not delete/resize mxContext that we have received from outside VCL + return true; + } + + if( mxLayer ) + { + const CGSize aSize = CGLayerGetSize( mxLayer ); + if( (nDX == aSize.width) && (nDY == aSize.height) ) + { + // Yay, we do not have to do anything :) + return true; + } + } + + Destroy(); + + // create a Quartz layer matching to the intended virdev usage + CGContextRef xCGContext = NULL; + if( mnBitmapDepth && (mnBitmapDepth < 16) ) + { + mnBitmapDepth = 8; // TODO: are 1bit vdevs worth it? + const CGColorSpaceRef aCGColorSpace = GetSalData()->mxGraySpace; + const CGBitmapInfo aCGBmpInfo = kCGImageAlphaNone; + const int nBytesPerRow = (mnBitmapDepth * nDX + 7) / 8; + + void* pRawData = rtl_allocateMemory( nBytesPerRow * nDY ); + mxBitmapContext = ::CGBitmapContextCreate( pRawData, nDX, nDY, + mnBitmapDepth, nBytesPerRow, aCGColorSpace, aCGBmpInfo ); + xCGContext = mxBitmapContext; + } + else + { + // default to a NSView target context + AquaSalFrame* pSalFrame = mpGraphics->getGraphicsFrame(); + if( !pSalFrame || !AquaSalFrame::isAlive( pSalFrame )) + { + if( !GetSalData()->maFrames.empty() ) + { + // get the first matching frame + pSalFrame = *GetSalData()->maFrames.begin(); + } + else + { + // ensure we don't reuse a dead AquaSalFrame on the very + // unlikely case of no other frame to use + pSalFrame = NULL; + } + // update the frame reference + mpGraphics->setGraphicsFrame( pSalFrame ); + } + if( pSalFrame ) + { + // #i91990# + NSWindow* pNSWindow = pSalFrame->getNSWindow(); + if ( pNSWindow ) + { + NSGraphicsContext* pNSContext = [NSGraphicsContext graphicsContextWithWindow: pNSWindow]; + if( pNSContext ) + xCGContext = reinterpret_cast([pNSContext graphicsPort]); + } + else + { + // fall back to a bitmap context + mnBitmapDepth = 32; + const CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace; + const CGBitmapInfo aCGBmpInfo = kCGImageAlphaNoneSkipFirst; + const int nBytesPerRow = (mnBitmapDepth * nDX) / 8; + + void* pRawData = rtl_allocateMemory( nBytesPerRow * nDY ); + mxBitmapContext = ::CGBitmapContextCreate( pRawData, nDX, nDY, + 8, nBytesPerRow, aCGColorSpace, aCGBmpInfo ); + xCGContext = mxBitmapContext; + } + } + } + + DBG_ASSERT( xCGContext, "no context" ); + + const CGSize aNewSize = { static_cast(nDX), static_cast(nDY) }; + mxLayer = CGLayerCreateWithContext( xCGContext, aNewSize, NULL ); + + if( mxLayer && mpGraphics ) + { + // get the matching Quartz context + CGContextRef xDrawContext = CGLayerGetContext( mxLayer ); + mpGraphics->SetVirDevGraphics( mxLayer, xDrawContext, mnBitmapDepth ); + } + + return (mxLayer != NULL); +} + +// ----------------------------------------------------------------------- + +void AquaSalVirtualDevice::GetSize( long& rWidth, long& rHeight ) +{ + if( mxLayer ) + { + const CGSize aSize = CGLayerGetSize( mxLayer ); + rWidth = static_cast(aSize.width); + rHeight = static_cast(aSize.height); + } + else + { + rWidth = 0; + rHeight = 0; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/service_entry.cxx b/vcl/osx/service_entry.cxx new file mode 100644 index 000000000000..d4fa284c2ddb --- /dev/null +++ b/vcl/osx/service_entry.cxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "osl/diagnose.h" + +#include "vcl/svapp.hxx" + +#include "osx/saldata.hxx" +#include "osx/salinst.h" + +#include "DragSource.hxx" +#include "DropTarget.hxx" +#include "clipboard.hxx" + +using namespace ::osl; +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::cppu; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::datatransfer::clipboard; + + +uno::Reference< XInterface > AquaSalInstance::CreateClipboard( const Sequence< Any >& i_rArguments ) +{ + if ( Application::IsHeadlessModeEnabled() ) + return SalInstance::CreateClipboard( i_rArguments ); + + SalData* pSalData = GetSalData(); + if( ! pSalData->mxClipboard.is() ) + pSalData->mxClipboard = uno::Reference(static_cast< XClipboard* >(new AquaClipboard()), UNO_QUERY); + return pSalData->mxClipboard; +} + +uno::Reference AquaSalInstance::CreateDragSource() +{ + if ( Application::IsHeadlessModeEnabled() ) + return SalInstance::CreateDragSource(); + + return uno::Reference(static_cast< XInitialization* >(new DragSource()), UNO_QUERY); +} + +uno::Reference AquaSalInstance::CreateDropTarget() +{ + if ( Application::IsHeadlessModeEnabled() ) + return SalInstance::CreateDropTarget(); + + return uno::Reference(static_cast< XInitialization* >(new DropTarget()), UNO_QUERY); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/vclnsapp.mm b/vcl/osx/vclnsapp.mm new file mode 100644 index 000000000000..18079fb1ca9b --- /dev/null +++ b/vcl/osx/vclnsapp.mm @@ -0,0 +1,517 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include "sal/config.h" + +#include + +#include "vcl/window.hxx" +#include "vcl/svapp.hxx" +#include "vcl/cmdevt.hxx" + +#include "osx/vclnsapp.h" +#include "osx/salinst.h" +#include "osx/saldata.hxx" +#include "osx/salframe.h" +#include "osx/salframeview.h" +#include "quartz/utils.h" + +#include "impimagetree.hxx" + +#include "premac.h" +#include +#import "Carbon/Carbon.h" +#import "apple_remote/RemoteControl.h" +#include "postmac.h" + + +@implementation CocoaThreadEnabler +-(void)enableCocoaThreads:(id)param +{ + // do nothing, this is just to start an NSThread and therefore put + // Cocoa into multithread mode + (void)param; +} +@end + +// If you wonder how this VCL_NSApplication stuff works, one thing you +// might have missed is that the NSPrincipalClass property in +// desktop/macosx/Info.plist has the value VCL_NSApplication. + +@implementation VCL_NSApplication +-(void)sendEvent:(NSEvent*)pEvent +{ + NSEventType eType = [pEvent type]; + if( eType == NSApplicationDefined ) + GetSalData()->mpFirstInstance->handleAppDefinedEvent( pEvent ); + else if( eType == NSKeyDown && ([pEvent modifierFlags] & NSCommandKeyMask) != 0 ) + { + NSWindow* pKeyWin = [NSApp keyWindow]; + if( pKeyWin && [pKeyWin isKindOfClass: [SalFrameWindow class]] ) + { + AquaSalFrame* pFrame = [(SalFrameWindow*)pKeyWin getSalFrame]; + // handle Cmd-W + // FIXME: the correct solution would be to handle this in framework + // in the menu code + // however that is currently being revised, so let's use a preliminary solution here + // this hack is based on assumption + // a) Cmd-W is the same in all languages in OOo's menu conig + // b) Cmd-W is the same in all languages in on MacOS + // for now this seems to be true + unsigned int nModMask = ([pEvent modifierFlags] & (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask)); + if( (pFrame->mnStyleMask & NSClosableWindowMask) != 0 ) + { + if( nModMask == NSCommandKeyMask + && [[pEvent charactersIgnoringModifiers] isEqualToString: @"w"] ) + { + // Note: gcc 4.2.1 (in the 10.6 SDK) tells us + // 'NSWindow' may not respond to + // '-windowShouldClose:' . Is that a bogus + // warning, or is this code bogus? No idea. + // Anyway, so that we can compile also against + // this SDK with -Werror, use objc_msgSend + // instead. + + // Instead of: + // [pFrame->getNSWindow() windowShouldClose: nil]; + // do: + objc_msgSend(pFrame->getNSWindow(), @selector(windowShouldClose:), nil); + + return; + } + } + + /* + * #i98949# - Cmd-M miniaturize window, Cmd-Option-M miniaturize all windows + */ + if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"m"] ) + { + if ( nModMask == NSCommandKeyMask && ([pFrame->getNSWindow() styleMask] & NSMiniaturizableWindowMask) ) + { + [pFrame->getNSWindow() performMiniaturize: nil]; + return; + } + + if ( nModMask == ( NSCommandKeyMask | NSAlternateKeyMask ) ) + { + [NSApp miniaturizeAll: nil]; + return; + } + } + + // #i90083# handle frame switching + // FIXME: lousy workaround + if( (nModMask & (NSControlKeyMask|NSAlternateKeyMask)) == 0 ) + { + if( [[pEvent characters] isEqualToString: @"<"] || + [[pEvent characters] isEqualToString: @"~"] ) + { + [self cycleFrameForward: pFrame]; + return; + } + else if( [[pEvent characters] isEqualToString: @">"] || + [[pEvent characters] isEqualToString: @"`"] ) + { + [self cycleFrameBackward: pFrame]; + return; + } + } + + // get information whether the event was handled; keyDown returns nothing + GetSalData()->maKeyEventAnswer[ pEvent ] = false; + bool bHandled = false; + + // dispatch to view directly to avoid the key event being consumed by the menubar + // popup windows do not get the focus, so they don't get these either + // simplest would be dispatch this to the key window always if it is without parent + // however e.g. in document we want the menu shortcut if e.g. the stylist has focus + if( pFrame->mpParent && (pFrame->mnStyle & SAL_FRAME_STYLE_FLOAT) == 0 ) + { + [[pKeyWin contentView] keyDown: pEvent]; + bHandled = GetSalData()->maKeyEventAnswer[ pEvent ]; + } + + // see whether the main menu consumes this event + // if not, we want to dispatch it ourselves. Unless we do this "trick" + // the main menu just beeps for an unknown or disabled key equivalent + // and swallows the event wholesale + NSMenu* pMainMenu = [NSApp mainMenu]; + if( ! bHandled && (pMainMenu == 0 || ! [pMainMenu performKeyEquivalent: pEvent]) ) + { + [[pKeyWin contentView] keyDown: pEvent]; + bHandled = GetSalData()->maKeyEventAnswer[ pEvent ]; + } + else + bHandled = true; // event handled already or main menu just handled it + + GetSalData()->maKeyEventAnswer.erase( pEvent ); + if( bHandled ) + return; + } + else if( pKeyWin ) + { + // #i94601# a window not of vcl's making has the focus. + // Since our menus do not invoke the usual commands + // try to play nice with native windows like the file dialog + // and emulate them + // precondition: this ONLY works because CMD-V (paste), CMD-C (copy) and CMD-X (cut) are + // NOT localized, that is the same in all locales. Should this be + // different in any locale, this hack will fail. + unsigned int nModMask = ([pEvent modifierFlags] & (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask)); + if( nModMask == NSCommandKeyMask ) + { + + if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"v"] ) + { + if( [NSApp sendAction: @selector(paste:) to: nil from: nil] ) + return; + } + else if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"c"] ) + { + if( [NSApp sendAction: @selector(copy:) to: nil from: nil] ) + return; + } + else if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"x"] ) + { + if( [NSApp sendAction: @selector(cut:) to: nil from: nil] ) + return; + } + } + } + } + [super sendEvent: pEvent]; +} + +-(void)sendSuperEvent:(NSEvent*)pEvent +{ + [super sendEvent: pEvent]; +} + +-(void)cycleFrameForward: (AquaSalFrame*)pCurFrame +{ + // find current frame in list + std::list< AquaSalFrame* >& rFrames( GetSalData()->maFrames ); + std::list< AquaSalFrame* >::iterator it = rFrames.begin(); + for( ; it != rFrames.end() && *it != pCurFrame; ++it ) + ; + if( it != rFrames.end() ) + { + // now find the next frame (or end) + do + { + ++it; + if( it != rFrames.end() ) + { + if( (*it)->mpDockMenuEntry != NULL && + (*it)->mbShown ) + { + [(*it)->getNSWindow() makeKeyAndOrderFront: NSApp]; + return; + } + } + } while( it != rFrames.end() ); + // cycle around, find the next up to pCurFrame + it = rFrames.begin(); + while( *it != pCurFrame ) + { + if( (*it)->mpDockMenuEntry != NULL && + (*it)->mbShown ) + { + [(*it)->getNSWindow() makeKeyAndOrderFront: NSApp]; + return; + } + ++it; + } + } +} + +-(void)cycleFrameBackward: (AquaSalFrame*)pCurFrame +{ + // do the same as cycleFrameForward only with a reverse iterator + + // find current frame in list + std::list< AquaSalFrame* >& rFrames( GetSalData()->maFrames ); + std::list< AquaSalFrame* >::reverse_iterator it = rFrames.rbegin(); + for( ; it != rFrames.rend() && *it != pCurFrame; ++it ) + ; + if( it != rFrames.rend() ) + { + // now find the next frame (or end) + do + { + ++it; + if( it != rFrames.rend() ) + { + if( (*it)->mpDockMenuEntry != NULL && + (*it)->mbShown ) + { + [(*it)->getNSWindow() makeKeyAndOrderFront: NSApp]; + return; + } + } + } while( it != rFrames.rend() ); + // cycle around, find the next up to pCurFrame + it = rFrames.rbegin(); + while( *it != pCurFrame ) + { + if( (*it)->mpDockMenuEntry != NULL && + (*it)->mbShown ) + { + [(*it)->getNSWindow() makeKeyAndOrderFront: NSApp]; + return; + } + ++it; + } + } +} + +-(NSMenu*)applicationDockMenu:(NSApplication *)sender +{ + (void)sender; + return AquaSalInstance::GetDynamicDockMenu(); +} + +-(BOOL)application: (NSApplication*)app openFile: (NSString*)pFile +{ + (void)app; + std::vector aFile; + aFile.push_back( GetOUString( pFile ) ); + if( ! AquaSalInstance::isOnCommandLine( aFile[0] ) ) + { + const ApplicationEvent* pAppEvent = new ApplicationEvent(ApplicationEvent::TYPE_OPEN, aFile); + AquaSalInstance::aAppEventList.push_back( pAppEvent ); + } + return YES; +} + +-(void)application: (NSApplication*) app openFiles: (NSArray*)files +{ + (void)app; + std::vector aFileList; + + NSEnumerator* it = [files objectEnumerator]; + NSString* pFile = nil; + + while( (pFile = [it nextObject]) != nil ) + { + const rtl::OUString aFile( GetOUString( pFile ) ); + if( ! AquaSalInstance::isOnCommandLine( aFile ) ) + { + aFileList.push_back( aFile ); + } + } + + if( !aFileList.empty() ) + { + // we have no back channel here, we have to assume success, in which case + // replyToOpenOrPrint does not need to be called according to documentation + // [app replyToOpenOrPrint: NSApplicationDelegateReplySuccess]; + const ApplicationEvent* pAppEvent = new ApplicationEvent(ApplicationEvent::TYPE_OPEN, aFileList); + AquaSalInstance::aAppEventList.push_back( pAppEvent ); + } +} + +-(BOOL)application: (NSApplication*)app printFile: (NSString*)pFile +{ + (void)app; + std::vector aFile; + aFile.push_back( GetOUString( pFile ) ); + const ApplicationEvent* pAppEvent = new ApplicationEvent(ApplicationEvent::TYPE_PRINT, aFile); + AquaSalInstance::aAppEventList.push_back( pAppEvent ); + return YES; +} +-(NSApplicationPrintReply)application: (NSApplication *) app printFiles:(NSArray *)files withSettings: (NSDictionary *)printSettings showPrintPanels:(BOOL)bShowPrintPanels +{ + (void)app; + (void)printSettings; + (void)bShowPrintPanels; + // currently ignores print settings an bShowPrintPanels + std::vector aFileList; + + NSEnumerator* it = [files objectEnumerator]; + NSString* pFile = nil; + + while( (pFile = [it nextObject]) != nil ) + { + aFileList.push_back( GetOUString( pFile ) ); + } + const ApplicationEvent* pAppEvent = new ApplicationEvent(ApplicationEvent::TYPE_PRINT, aFileList); + AquaSalInstance::aAppEventList.push_back( pAppEvent ); + // we have no back channel here, we have to assume success + // correct handling would be NSPrintingReplyLater and then send [app replyToOpenOrPrint] + return NSPrintingSuccess; +} + +-(NSApplicationTerminateReply)applicationShouldTerminate: (NSApplication *) app +{ + (void)app; + NSApplicationTerminateReply aReply = NSTerminateNow; + { + YIELD_GUARD; + + SalData* pSalData = GetSalData(); + if( ! pSalData->maFrames.empty() ) + { + // the following QueryExit will likely present a message box, activate application + [NSApp activateIgnoringOtherApps: YES]; + aReply = pSalData->maFrames.front()->CallCallback( SALEVENT_SHUTDOWN, NULL ) ? NSTerminateCancel : NSTerminateNow; + } + + if( aReply == NSTerminateNow ) + { + ApplicationEvent aEv(ApplicationEvent::TYPE_PRIVATE_DOSHUTDOWN); + GetpApp()->AppEvent( aEv ); + ImplImageTreeSingletonRef()->shutDown(); + // DeInitVCL should be called in ImplSVMain - unless someon _exits first which + // can occur in Desktop::doShutdown for example + } + } + + return aReply; +} + +-(void)systemColorsChanged: (NSNotification*) pNotification +{ + (void)pNotification; + YIELD_GUARD; + + const SalData* pSalData = GetSalData(); + if( !pSalData->maFrames.empty() ) + pSalData->maFrames.front()->CallCallback( SALEVENT_SETTINGSCHANGED, NULL ); +} + +-(void)screenParametersChanged: (NSNotification*) pNotification +{ + (void)pNotification; + YIELD_GUARD; + + SalData* pSalData = GetSalData(); + std::list< AquaSalFrame* >::iterator it; + for( it = pSalData->maFrames.begin(); it != pSalData->maFrames.end(); ++it ) + { + (*it)->screenParametersChanged(); + } +} + +-(void)scrollbarVariantChanged: (NSNotification*) pNotification +{ + (void)pNotification; + GetSalData()->mpFirstInstance->delayedSettingsChanged( true ); +} + +-(void)scrollbarSettingsChanged: (NSNotification*) pNotification +{ + (void)pNotification; + GetSalData()->mpFirstInstance->delayedSettingsChanged( false ); +} + +-(void)addFallbackMenuItem: (NSMenuItem*)pNewItem +{ + AquaSalMenu::addFallbackMenuItem( pNewItem ); +} + +-(void)removeFallbackMenuItem: (NSMenuItem*)pItem +{ + AquaSalMenu::removeFallbackMenuItem( pItem ); +} + +-(void)addDockMenuItem: (NSMenuItem*)pNewItem +{ + NSMenu* pDock = AquaSalInstance::GetDynamicDockMenu(); + [pDock insertItem: pNewItem atIndex: [pDock numberOfItems]]; +} + +// for Apple Remote implementation + +#if !HAVE_FEATURE_MACOSX_SANDBOX +- (void)applicationWillBecomeActive:(NSNotification *)pNotification +{ + (void)pNotification; + SalData* pSalData = GetSalData(); + if( pSalData->mpMainController && pSalData->mpMainController->remoteControl) + { + // [remoteControl startListening: self]; + // does crash because the right thing to do is + // [GetSalData()->mpMainController->remoteControl startListening: self]; + // but the instance variable 'remoteControl' is declared protected + // workaround : declare remoteControl instance variable as public in RemoteMainController.m + + [pSalData->mpMainController->remoteControl startListening: self]; +#ifdef DEBUG + NSLog(@"Apple Remote will become active - Using remote controls"); +#endif + } + for( std::list< AquaSalFrame* >::const_iterator it = pSalData->maPresentationFrames.begin(); + it != pSalData->maPresentationFrames.end(); ++it ) + { + NSWindow* pNSWindow = (*it)->getNSWindow(); + [pNSWindow setLevel: NSPopUpMenuWindowLevel]; + if( [pNSWindow isVisible] ) + [pNSWindow orderFront: NSApp]; + } +} + +- (void)applicationWillResignActive:(NSNotification *)pNotification +{ + (void)pNotification; + SalData* pSalData = GetSalData(); + if( pSalData->mpMainController && pSalData->mpMainController->remoteControl) + { + // [remoteControl stopListening: self]; + // does crash because the right thing to do is + // [GetSalData()->mpMainController->remoteControl stopListening: self]; + // but the instance variable 'remoteControl' is declared protected + // workaround : declare remoteControl instance variable as public in RemoteMainController.m + + [pSalData->mpMainController->remoteControl stopListening: self]; +#ifdef DEBUG + NSLog(@"Apple Remote will resign active - Releasing remote controls"); +#endif + } + for( std::list< AquaSalFrame* >::const_iterator it = pSalData->maPresentationFrames.begin(); + it != pSalData->maPresentationFrames.end(); ++it ) + { + [(*it)->getNSWindow() setLevel: NSNormalWindowLevel]; + } +} +#endif + +- (BOOL)applicationShouldHandleReopen: (NSApplication*)pApp hasVisibleWindows: (BOOL) bWinVisible +{ + (void)pApp; + (void)bWinVisible; + NSObject* pHdl = GetSalData()->mpDockIconClickHandler; + if( pHdl && [pHdl respondsToSelector: @selector(dockIconClicked:)] ) + { + [pHdl performSelector:@selector(dockIconClicked:) withObject: self]; + } + return YES; +} + +-(void)setDockIconClickHandler: (NSObject*)pHandler +{ + GetSalData()->mpDockIconClickHandler = pHandler; +} + + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/quartz/ctfonts.cxx b/vcl/quartz/ctfonts.cxx new file mode 100644 index 000000000000..d93d4b59b7d3 --- /dev/null +++ b/vcl/quartz/ctfonts.cxx @@ -0,0 +1,478 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include "impfont.hxx" +#include "outfont.hxx" +#include "sallayout.hxx" + +#ifdef MACOSX +#include "osx/salinst.h" +#include "osx/saldata.hxx" +#endif +#include "quartz/salgdi.h" +#include "quartz/utils.h" +#include "ctfonts.hxx" + +#include "basegfx/polygon/b2dpolygon.hxx" +#include "basegfx/matrix/b2dhommatrix.hxx" + +// ======================================================================= + +inline double toRadian(int nDegree) +{ + return nDegree * (M_PI / 1800.0); +} + +CoreTextStyle::CoreTextStyle( const FontSelectPattern& rFSD ) +: mpFontData( (CoreTextFontData*)rFSD.mpFontData ) +, mfFontStretch( 1.0 ) +, mfFontRotation( 0.0 ) +, mpStyleDict( NULL ) +{ + mpFontData = (CoreTextFontData*)rFSD.mpFontData; + const FontSelectPattern* const pReqFont = &rFSD; + + double fScaledFontHeight = pReqFont->mfExactHeight; + + // convert font rotation to radian + mfFontRotation = toRadian(pReqFont->mnOrientation); + + // dummy matrix so we can use CGAffineTransformConcat() below + CGAffineTransform aMatrix = CGAffineTransformMakeTranslation(0, 0); + + // handle font stretching if any + if( (pReqFont->mnWidth != 0) && (pReqFont->mnWidth != pReqFont->mnHeight) ) + { + mfFontStretch = (float)pReqFont->mnWidth / pReqFont->mnHeight; + aMatrix = CGAffineTransformConcat(aMatrix, CGAffineTransformMakeScale(mfFontStretch, 1.0F)); + } + + // create the style object for CoreText font attributes + static const CFIndex nMaxDictSize = 16; // TODO: does this really suffice? + mpStyleDict = CFDictionaryCreateMutable( NULL, nMaxDictSize, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); + + CFBooleanRef pCFVertBool = pReqFont->mbVertical ? kCFBooleanTrue : kCFBooleanFalse; + CFDictionarySetValue( mpStyleDict, kCTVerticalFormsAttributeName, pCFVertBool ); + + // fake bold + if ((pReqFont->GetWeight() >= WEIGHT_BOLD) && (mpFontData->GetWeight() < WEIGHT_SEMIBOLD)) + { + int nStroke = -10.0; + CFNumberRef rStroke = CFNumberCreate(NULL, kCFNumberSInt32Type, &nStroke); + CFDictionarySetValue(mpStyleDict, kCTStrokeWidthAttributeName, rStroke); + } + + // fake italic + if (((pReqFont->GetSlant() == ITALIC_NORMAL) || (pReqFont->GetSlant() == ITALIC_OBLIQUE)) + && !((mpFontData->GetSlant() == ITALIC_NORMAL) || (mpFontData->GetSlant() == ITALIC_OBLIQUE))) + { + aMatrix = CGAffineTransformConcat(aMatrix, CGAffineTransformMake(1, 0, toRadian(120), 1, 0, 0)); + } + + CTFontDescriptorRef pFontDesc = (CTFontDescriptorRef)mpFontData->GetFontId(); + CTFontRef pNewCTFont = CTFontCreateWithFontDescriptor( pFontDesc, fScaledFontHeight, &aMatrix ); + CFDictionarySetValue( mpStyleDict, kCTFontAttributeName, pNewCTFont ); + CFRelease( pNewCTFont); + +#if 0 // LastResort is implicit in CoreText's font cascading + const void* aGFBDescriptors[] = { CTFontDescriptorCreateWithNameAndSize( CFSTR("LastResort"), 0) }; // TODO: use the full GFB list + const int nGfbCount = sizeof(aGFBDescriptors) / sizeof(*aGFBDescriptors); + CFArrayRef pGfbList = CFArrayCreate( NULL, aGFBDescriptors, nGfbCount, &kCFTypeArrayCallBacks); + CFDictionaryAddValue( mpStyleDict, kCTFontCascadeListAttribute, pGfbList); + CFRelease( pGfbList); +#endif +} + +// ----------------------------------------------------------------------- + +CoreTextStyle::~CoreTextStyle( void ) +{ + if( mpStyleDict ) + CFRelease( mpStyleDict ); +} + +// ----------------------------------------------------------------------- + +void CoreTextStyle::GetFontMetric( float fPixelSize, ImplFontMetricData& rMetric ) const +{ + // get the matching CoreText font handle + // TODO: is it worth it to cache the CTFontRef in SetFont() and reuse it here? + CTFontRef aCTFontRef = (CTFontRef)CFDictionaryGetValue( mpStyleDict, kCTFontAttributeName ); + + rMetric.mnAscent = lrint( CTFontGetAscent( aCTFontRef ) * fPixelSize); + rMetric.mnDescent = lrint( CTFontGetDescent( aCTFontRef ) * fPixelSize); + rMetric.mnExtLeading = lrint( CTFontGetLeading( aCTFontRef ) * fPixelSize); + rMetric.mnIntLeading = 0; + // since ImplFontMetricData::mnWidth is only used for stretching/squeezing fonts + // setting this width to the pixel height of the fontsize is good enough + // it also makes the calculation of the stretch factor simple + rMetric.mnWidth = lrint( CTFontGetSize( aCTFontRef ) * fPixelSize * mfFontStretch); + + // all CoreText fonts are scalable + rMetric.mbScalableFont = true; + rMetric.mbKernableFont = true; +} + +// ----------------------------------------------------------------------- + +bool CoreTextStyle::GetGlyphBoundRect( sal_GlyphId nGlyphId, Rectangle& rRect ) const +{ + CGGlyph nCGGlyph = nGlyphId & GF_IDXMASK; + // XXX: this is broken if the glyph came from fallback font + CTFontRef aCTFontRef = (CTFontRef)CFDictionaryGetValue( mpStyleDict, kCTFontAttributeName ); + + const CTFontOrientation aFontOrientation = kCTFontDefaultOrientation; // TODO: horz/vert + const CGRect aCGRect = CTFontGetBoundingRectsForGlyphs( aCTFontRef, aFontOrientation, &nCGGlyph, NULL, 1 ); + + rRect.Left() = lrint( aCGRect.origin.x ); + rRect.Top() = lrint( aCGRect.origin.y ); + rRect.Right() = lrint( aCGRect.origin.x + aCGRect.size.width ); + rRect.Bottom() = lrint( aCGRect.origin.y + aCGRect.size.height ); + return true; +} + +// ----------------------------------------------------------------------- + +// callbacks from CTFontCreatePathForGlyph+CGPathApply for GetGlyphOutline() +struct GgoData { basegfx::B2DPolygon maPolygon; basegfx::B2DPolyPolygon* mpPolyPoly; }; + +static void MyCGPathApplierFunc( void* pData, const CGPathElement* pElement ) +{ + basegfx::B2DPolygon& rPolygon = static_cast(pData)->maPolygon; + const int nPointCount = rPolygon.count(); + + switch( pElement->type ) + { + case kCGPathElementCloseSubpath: + case kCGPathElementMoveToPoint: + if( nPointCount > 0 ) { + static_cast(pData)->mpPolyPoly->append( rPolygon ); + rPolygon.clear(); + } + // fall through for kCGPathElementMoveToPoint: + if( pElement->type != kCGPathElementMoveToPoint ) + break; + case kCGPathElementAddLineToPoint: + rPolygon.append( basegfx::B2DPoint( +pElement->points[0].x, -pElement->points[0].y ) ); + break; + case kCGPathElementAddCurveToPoint: + rPolygon.append( basegfx::B2DPoint( +pElement->points[2].x, -pElement->points[2].y ) ); + rPolygon.setNextControlPoint( nPointCount-1, basegfx::B2DPoint( pElement->points[0].x, -pElement->points[0].y ) ); + rPolygon.setPrevControlPoint( nPointCount+0, basegfx::B2DPoint( pElement->points[1].x, -pElement->points[1].y ) ); + break; + case kCGPathElementAddQuadCurveToPoint: { + const basegfx::B2DPoint aStartPt = rPolygon.getB2DPoint( nPointCount-1 ); + const basegfx::B2DPoint aCtrPt1( (aStartPt.getX() + 2* pElement->points[0].x) / 3.0, + (aStartPt.getY() - 2 * pElement->points[0].y) / 3.0 ); + const basegfx::B2DPoint aCtrPt2( (+2 * +pElement->points[0].x + pElement->points[1].x) / 3.0, + (-2 * pElement->points[0].y - pElement->points[1].y) / 3.0 ); + rPolygon.append( basegfx::B2DPoint( +pElement->points[1].x, -pElement->points[1].y ) ); + rPolygon.setNextControlPoint( nPointCount-1, aCtrPt1 ); + rPolygon.setPrevControlPoint( nPointCount+0, aCtrPt2 ); + } break; + } +} + +bool CoreTextStyle::GetGlyphOutline( sal_GlyphId nGlyphId, basegfx::B2DPolyPolygon& rResult ) const +{ + rResult.clear(); + + CGGlyph nCGGlyph = nGlyphId & GF_IDXMASK; + // XXX: this is broken if the glyph came from fallback font + CTFontRef pCTFont = (CTFontRef)CFDictionaryGetValue( mpStyleDict, kCTFontAttributeName ); + CGPathRef xPath = CTFontCreatePathForGlyph( pCTFont, nCGGlyph, NULL ); + + GgoData aGgoData; + aGgoData.mpPolyPoly = &rResult; + CGPathApply( xPath, (void*)&aGgoData, MyCGPathApplierFunc ); +#if 0 // TODO: does OSX ensure that the last polygon is always closed? + const CGPathElement aClosingElement = { kCGPathElementCloseSubpath, NULL }; + MyCGPathApplierFunc( (void*)&aGgoData, &aClosingElement ); +#endif + + return true; +} + +// ----------------------------------------------------------------------- + +void CoreTextStyle::SetTextColor( const RGBAColor& rColor ) +{ + CGFloat aColor[] = { rColor.GetRed(), rColor.GetGreen(), rColor.GetBlue(), rColor.GetAlpha() }; + CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); + CGColorRef pCGColor = CGColorCreate( cs, aColor ); + CGColorSpaceRelease( cs ); + CFDictionarySetValue( mpStyleDict, kCTForegroundColorAttributeName, pCGColor ); + CFRelease( pCGColor); +} + +// ======================================================================= + +PhysicalFontFace* CoreTextFontData::Clone( void ) const +{ + return new CoreTextFontData( *this); +} + +// ----------------------------------------------------------------------- + +CoreTextStyle* CoreTextFontData::CreateTextStyle( const FontSelectPattern& rFSD ) const +{ + return new CoreTextStyle( rFSD); +} + +// ----------------------------------------------------------------------- + +ImplFontEntry* CoreTextFontData::CreateFontInstance( /*const*/ FontSelectPattern& rFSD ) const +{ + return new ImplFontEntry( rFSD); +} + +// ----------------------------------------------------------------------- + +int CoreTextFontData::GetFontTable( const char pTagName[5], unsigned char* pResultBuf ) const +{ + DBG_ASSERT( pTagName[4]=='\0', "CoreTextFontData::GetFontTable with invalid tagname!\n" ); + + const CTFontTableTag nTagCode = (pTagName[0]<<24) + (pTagName[1]<<16) + (pTagName[2]<<8) + (pTagName[3]<<0); + + // get the raw table length + CTFontDescriptorRef pFontDesc = reinterpret_cast( GetFontId()); + CTFontRef rCTFont = CTFontCreateWithFontDescriptor( pFontDesc, 0.0, NULL); +#if defined(MACOSX) && MACOSX_SDK_VERSION < 1080 + const uint32_t opts( kCTFontTableOptionExcludeSynthetic ); +#else + const uint32_t opts( kCTFontTableOptionNoOptions ); +#endif + CFDataRef pDataRef = CTFontCopyTable( rCTFont, nTagCode, opts); + CFRelease( rCTFont); + if( !pDataRef) + return 0; + + const CFIndex nByteLength = CFDataGetLength( pDataRef); + + // get the raw table data if requested + if( pResultBuf && (nByteLength > 0)) + { + const CFRange aFullRange = CFRangeMake( 0, nByteLength); + CFDataGetBytes( pDataRef, aFullRange, (UInt8*)pResultBuf); + } + + CFRelease( pDataRef); + + return (int)nByteLength; +} + +// ======================================================================= + +ImplDevFontAttributes DevFontFromCTFontDescriptor( CTFontDescriptorRef pFD, bool* bFontEnabled ) +{ + // all CoreText fonts are device fonts that can rotate just fine + ImplDevFontAttributes rDFA; + rDFA.mbOrientation = true; + rDFA.mbDevice = true; + rDFA.mnQuality = 0; + + // reset the font attributes + rDFA.SetFamilyType( FAMILY_DONTKNOW ); + rDFA.SetPitch( PITCH_VARIABLE ); + rDFA.SetWidthType( WIDTH_NORMAL ); + rDFA.SetWeight( WEIGHT_NORMAL ); + rDFA.SetItalic( ITALIC_NONE ); + rDFA.SetSymbolFlag( false ); + + // all scalable fonts on this platform are subsettable + rDFA.mbEmbeddable = false; + rDFA.mbSubsettable = true; + + // get font name + CFStringRef pFamilyName = (CFStringRef)CTFontDescriptorCopyAttribute( pFD, kCTFontFamilyNameAttribute ); + rDFA.SetFamilyName( GetOUString( pFamilyName ) ); + // get font style + CFStringRef pStyleName = (CFStringRef)CTFontDescriptorCopyAttribute( pFD, kCTFontStyleNameAttribute ); + rDFA.SetStyleName( GetOUString( pStyleName ) ); + + // get font-enabled status + if( bFontEnabled ) { + int bEnabled = FALSE; + CFNumberRef pEnabled = (CFNumberRef)CTFontDescriptorCopyAttribute( pFD, kCTFontEnabledAttribute ); + CFNumberGetValue( pEnabled, kCFNumberIntType, &bEnabled ); + *bFontEnabled = bEnabled; + } + + // get font attributes + CFDictionaryRef pAttrDict = (CFDictionaryRef)CTFontDescriptorCopyAttribute( pFD, kCTFontTraitsAttribute ); + + // get symbolic trait + // TODO: use other traits such as MonoSpace/Condensed/Expanded or Vertical too + SInt64 nSymbolTrait = 0; + CFNumberRef pSymbolNum = NULL; + if( CFDictionaryGetValueIfPresent( pAttrDict, kCTFontSymbolicTrait, (const void**)&pSymbolNum ) ) { + CFNumberGetValue( pSymbolNum, kCFNumberSInt64Type, &nSymbolTrait ); + rDFA.SetSymbolFlag( ((nSymbolTrait & kCTFontClassMaskTrait) == kCTFontSymbolicClass) ); + } + + // get the font weight + double fWeight = 0; + CFNumberRef pWeightNum = (CFNumberRef)CFDictionaryGetValue( pAttrDict, kCTFontWeightTrait ); + CFNumberGetValue( pWeightNum, kCFNumberDoubleType, &fWeight ); + int nInt = WEIGHT_NORMAL; + if( fWeight > 0 ) { + nInt = rint(WEIGHT_NORMAL + fWeight * ((WEIGHT_BLACK - WEIGHT_NORMAL)/0.68)); + if( nInt > WEIGHT_BLACK ) + nInt = WEIGHT_BLACK; + } else if( fWeight < 0 ) { + nInt = rint(WEIGHT_NORMAL + fWeight * ((WEIGHT_NORMAL - WEIGHT_THIN)/0.9)); + if( nInt < WEIGHT_THIN ) + nInt = WEIGHT_THIN; + } + rDFA.SetWeight( (FontWeight)nInt ); + + // get the font slant + double fSlant = 0; + CFNumberRef pSlantNum = (CFNumberRef)CFDictionaryGetValue( pAttrDict, kCTFontSlantTrait ); + CFNumberGetValue( pSlantNum, kCFNumberDoubleType, &fSlant ); + if( fSlant >= 0.035 ) + rDFA.SetItalic( ITALIC_NORMAL ); + + // get width trait + double fWidth = 0; + CFNumberRef pWidthNum = (CFNumberRef)CFDictionaryGetValue( pAttrDict, kCTFontWidthTrait ); + CFNumberGetValue( pWidthNum, kCFNumberDoubleType, &fWidth ); + nInt = WIDTH_NORMAL; + if( fWidth > 0 ) { + nInt = rint( WIDTH_NORMAL + fWidth * ((WIDTH_ULTRA_EXPANDED - WIDTH_NORMAL)/0.4)); + if( nInt > WIDTH_ULTRA_EXPANDED ) + nInt = WIDTH_ULTRA_EXPANDED; + } else if( fWidth < 0 ) { + nInt = rint( WIDTH_NORMAL + fWidth * ((WIDTH_NORMAL - WIDTH_ULTRA_CONDENSED)/0.5)); + if( nInt < WIDTH_ULTRA_CONDENSED ) + nInt = WIDTH_ULTRA_CONDENSED; + } + rDFA.SetWidthType( (FontWidth)nInt ); + + // release the attribute dict that we had copied + CFRelease( pAttrDict ); + + // TODO? also use the HEAD table if available to get more attributes +// CFDataRef CTFontCopyTable( CTFontRef, kCTFontTableHead, /*kCTFontTableOptionNoOptions*/kCTFontTableOptionExcludeSynthetic ); + + return rDFA; +} + +static void CTFontEnumCallBack( const void* pValue, void* pContext ) +{ + CTFontDescriptorRef pFD = static_cast(pValue); + + bool bFontEnabled; + ImplDevFontAttributes rDFA = DevFontFromCTFontDescriptor( pFD, &bFontEnabled ); + + if( bFontEnabled) + { + const sal_IntPtr nFontId = (sal_IntPtr)pValue; + CoreTextFontData* pFontData = new CoreTextFontData( rDFA, nFontId ); + SystemFontList* pFontList = (SystemFontList*)pContext; + pFontList->AddFont( pFontData ); + } +} + +// ======================================================================= + +SystemFontList::SystemFontList() +: mpCTFontCollection( NULL ) +, mpCTFontArray( NULL ) +{} + +// ----------------------------------------------------------------------- + +SystemFontList::~SystemFontList() +{ + CTFontContainer::const_iterator it = maFontContainer.begin(); + for(; it != maFontContainer.end(); ++it ) + delete (*it).second; + maFontContainer.clear(); + + if( mpCTFontArray ) + CFRelease( mpCTFontArray ); + if( mpCTFontCollection ) + CFRelease( mpCTFontCollection ); +} + +// ----------------------------------------------------------------------- + +void SystemFontList::AddFont( CoreTextFontData* pFontData ) +{ + sal_IntPtr nFontId = pFontData->GetFontId(); + maFontContainer[ nFontId ] = pFontData; +} + +// ----------------------------------------------------------------------- + +void SystemFontList::AnnounceFonts( ImplDevFontList& rFontList ) const +{ + CTFontContainer::const_iterator it = maFontContainer.begin(); + for(; it != maFontContainer.end(); ++it ) + rFontList.Add( (*it).second->Clone() ); +} + +// ----------------------------------------------------------------------- + +CoreTextFontData* SystemFontList::GetFontDataFromId( sal_IntPtr nFontId ) const +{ + CTFontContainer::const_iterator it = maFontContainer.find( nFontId ); + if( it == maFontContainer.end() ) + return NULL; + return (*it).second; +} + +// ----------------------------------------------------------------------- + +bool SystemFontList::Init( void ) +{ + // enumerate available system fonts + static const int nMaxDictEntries = 8; + CFMutableDictionaryRef pCFDict = CFDictionaryCreateMutable( NULL, + nMaxDictEntries, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); + CFDictionaryAddValue( pCFDict, kCTFontCollectionRemoveDuplicatesOption, kCFBooleanTrue ); + mpCTFontCollection = CTFontCollectionCreateFromAvailableFonts( pCFDict ); + CFRelease( pCFDict ); + + mpCTFontArray = CTFontCollectionCreateMatchingFontDescriptors( mpCTFontCollection ); + const int nFontCount = CFArrayGetCount( mpCTFontArray ); + const CFRange aFullRange = CFRangeMake( 0, nFontCount ); + CFArrayApplyFunction( mpCTFontArray, aFullRange, CTFontEnumCallBack, this ); + + return true; +} + +// ======================================================================= + +SystemFontList* GetCoretextFontList( void ) +{ + SystemFontList* pList = new SystemFontList(); + if( !pList->Init() ) { + delete pList; + return NULL; + } + + return pList; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/quartz/ctfonts.hxx b/vcl/quartz/ctfonts.hxx new file mode 100644 index 000000000000..00dc6a9783f3 --- /dev/null +++ b/vcl/quartz/ctfonts.hxx @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "quartz/salgdi.h" +#ifdef IOS +#include "headless/svpgdi.hxx" +#endif +#include "sallayout.hxx" + +SystemFontList* GetCoretextFontList(void); +ImplDevFontAttributes DevFontFromCTFontDescriptor( CTFontDescriptorRef, bool* ); +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/quartz/ctlayout.cxx b/vcl/quartz/ctlayout.cxx new file mode 100644 index 000000000000..56d86967aa53 --- /dev/null +++ b/vcl/quartz/ctlayout.cxx @@ -0,0 +1,501 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tools/debug.hxx" + +#include "ctfonts.hxx" + +class CTLayout +: public SalLayout +{ +public: + explicit CTLayout( const CoreTextStyle* ); + virtual ~CTLayout( void ); + + virtual bool LayoutText( ImplLayoutArgs& ); + virtual void AdjustLayout( ImplLayoutArgs& ); + virtual void DrawText( SalGraphics& ) const; + + virtual int GetNextGlyphs( int nLen, sal_GlyphId* pGlyphs, Point& rPos, int&, + sal_Int32* pGlyphAdvances, int* pCharIndexes, + const PhysicalFontFace** pFallbackFonts ) const; + + virtual long GetTextWidth() const; + virtual long FillDXArray( sal_Int32* pDXArray ) const; + virtual sal_Int32 GetTextBreak(long nMaxWidth, long nCharExtra, int nFactor) const SAL_OVERRIDE; + virtual void GetCaretPositions( int nArraySize, sal_Int32* pCaretXArray ) const; + virtual bool GetGlyphOutlines( SalGraphics&, PolyPolyVector& ) const; + virtual bool GetBoundRect( SalGraphics&, Rectangle& ) const; + + virtual void InitFont( void) const; + virtual void MoveGlyph( int nStart, long nNewXPos ); + virtual void DropGlyph( int nStart ); + virtual void Simplify( bool bIsBase ); + +private: + CGPoint GetTextDrawPosition(void) const; + double GetWidth(void) const; + + const CoreTextStyle* const mpTextStyle; + + // CoreText specific objects + CFAttributedStringRef mpAttrString; + CTLineRef mpCTLine; + + int mnCharCount; // ==mnEndCharPos-mnMinCharPos + + // cached details about the resulting layout + // mutable members since these details are all lazy initialized + mutable double mfCachedWidth; // cached value of resulting typographical width + + // x-offset relative to layout origin + // currently only used in RTL-layouts + mutable double mfBaseAdv; +}; + +CTLayout::CTLayout( const CoreTextStyle* pTextStyle ) +: mpTextStyle( pTextStyle ) +, mpAttrString( NULL ) +, mpCTLine( NULL ) +, mnCharCount( 0 ) +, mfCachedWidth( -1 ) +, mfBaseAdv( 0 ) +{ +} + +CTLayout::~CTLayout() +{ + if( mpCTLine ) + CFRelease( mpCTLine ); + if( mpAttrString ) + CFRelease( mpAttrString ); +} + +bool CTLayout::LayoutText( ImplLayoutArgs& rArgs ) +{ + if( mpAttrString ) + CFRelease( mpAttrString ); + mpAttrString = NULL; + if( mpCTLine ) + CFRelease( mpCTLine ); + mpCTLine = NULL; + + SalLayout::AdjustLayout( rArgs ); + mnCharCount = mnEndCharPos - mnMinCharPos; + + // short circuit if there is nothing to do + if( mnCharCount <= 0 ) + return false; + + // create the CoreText line layout + CFStringRef aCFText = CFStringCreateWithCharactersNoCopy( NULL, rArgs.mpStr + mnMinCharPos, mnCharCount, kCFAllocatorNull ); + // CFAttributedStringCreate copies the attribues parameter + mpAttrString = CFAttributedStringCreate( NULL, aCFText, mpTextStyle->GetStyleDict() ); + mpCTLine = CTLineCreateWithAttributedString( mpAttrString ); + CFRelease( aCFText); + + return true; +} + +void CTLayout::AdjustLayout( ImplLayoutArgs& rArgs ) +{ + if( !mpCTLine) + return; + + int nOrigWidth = GetTextWidth(); + int nPixelWidth = rArgs.mnLayoutWidth; + if( nPixelWidth ) + { + if( nPixelWidth <= 0) + return; + } + else if( rArgs.mpDXArray ) + { + // for now we are only interested in the layout width + // TODO: use all mpDXArray elements for layouting + nPixelWidth = rArgs.mpDXArray[ mnCharCount - 1 ]; + } + + float fTrailingSpace = CTLineGetTrailingWhitespaceWidth( mpCTLine ); + // in RTL-layouts trailing spaces are leftmost + // TODO: use BiDi-algorithm to thoroughly check this assumption + if( rArgs.mnFlags & SAL_LAYOUT_BIDI_RTL) + mfBaseAdv = fTrailingSpace; + + // return early if there is nothing to do + if( nPixelWidth <= 0 ) + return; + + // HACK: justification requests which change the width by just one pixel are probably + // #i86038# introduced by lossy conversions between integer based coordinate system + if( (nOrigWidth >= nPixelWidth-1) && (nOrigWidth <= nPixelWidth+1) ) + return; + + CTLineRef pNewCTLine = CTLineCreateJustifiedLine( mpCTLine, 1.0, nPixelWidth - fTrailingSpace ); + if( !pNewCTLine ) { // CTLineCreateJustifiedLine can and does fail + // handle failure by keeping the unjustified layout + // TODO: a better solution such as + // - forcing glyph overlap + // - changing the font size + // - changing the CTM matrix + return; + } + CFRelease( mpCTLine ); + mpCTLine = pNewCTLine; + mfCachedWidth = nPixelWidth; +} + +// When drawing right aligned text, rounding errors in the position returned by +// GetDrawPosition() cause the right margin of the text to change whenever text +// width changes causing "jumping letters" effect. So here we calculate the +// drawing position relative to the right margin on our own to avoid the +// rounding errors. That is basically a hack, and it should go away if one day +// we managed to get rid of those rounding errors. +// +// We continue using GetDrawPosition() for non-right aligned text, to minimize +// any unforeseen side effects. +CGPoint CTLayout::GetTextDrawPosition(void) const +{ + float fPosX, fPosY; + + if (mnLayoutFlags & SAL_LAYOUT_RIGHT_ALIGN) + { + // text is always drawn at its leftmost point + const Point aPos = DrawBase(); + fPosX = aPos.X() + mfBaseAdv - GetWidth(); + fPosY = aPos.Y(); + } + else + { + const Point aPos = GetDrawPosition(Point(mfBaseAdv, 0)); + fPosX = aPos.X(); + fPosY = aPos.Y(); + } + + CGPoint aTextPos = { +fPosX, -fPosY }; + return aTextPos; +} + +void CTLayout::DrawText( SalGraphics& rGraphics ) const +{ + AquaSalGraphics& rAquaGraphics = static_cast(rGraphics); + + // short circuit if there is nothing to do + if( (mnCharCount <= 0) + || !rAquaGraphics.CheckContext() ) + return; + + // the view is vertically flipped => flipped glyphs + // so apply a temporary transformation that it flips back + // also compensate if the font was size limited + CGContextSaveGState( rAquaGraphics.mrContext ); + CGContextScaleCTM( rAquaGraphics.mrContext, 1.0, -1.0 ); + CGContextSetShouldAntialias( rAquaGraphics.mrContext, !rAquaGraphics.mbNonAntialiasedText ); + + // Draw the text + CGPoint aTextPos = GetTextDrawPosition(); + + if( mpTextStyle->mfFontRotation != 0.0 ) + { + const CGFloat fRadians = mpTextStyle->mfFontRotation; + CGContextRotateCTM( rAquaGraphics.mrContext, +fRadians ); + + const CGAffineTransform aInvMatrix = CGAffineTransformMakeRotation( -fRadians ); + aTextPos = CGPointApplyAffineTransform( aTextPos, aInvMatrix ); + } + + CGContextSetTextPosition( rAquaGraphics.mrContext, aTextPos.x, aTextPos.y ); + CTLineDraw( mpCTLine, rAquaGraphics.mrContext ); +#ifndef IOS + // request an update of the changed window area + if( rAquaGraphics.IsWindowGraphics() ) + { + const CGRect aInkRect = CTLineGetImageBounds( mpCTLine, rAquaGraphics.mrContext ); + const CGRect aRefreshRect = CGContextConvertRectToDeviceSpace( rAquaGraphics.mrContext, aInkRect ); + rAquaGraphics.RefreshRect( aRefreshRect ); + } +#endif + // restore the original graphic context transformations + CGContextRestoreGState( rAquaGraphics.mrContext ); +} + +int CTLayout::GetNextGlyphs( int nLen, sal_GlyphId* pGlyphIDs, Point& rPos, int& nStart, + sal_Int32* pGlyphAdvances, int* pCharIndexes, + const PhysicalFontFace** pFallbackFonts ) const +{ + if( !mpCTLine ) + return 0; + + if( nStart < 0 ) // first glyph requested? + nStart = 0; + nLen = 1; // TODO: handle nLen>1 below + + // prepare to iterate over the glyph runs + int nCount = 0; + int nSubIndex = nStart; + + typedef std::vector CGGlyphVector; + typedef std::vector CGPointVector; + typedef std::vector CGSizeVector; + typedef std::vector CFIndexVector; + CGGlyphVector aCGGlyphVec; + CGPointVector aCGPointVec; + CGSizeVector aCGSizeVec; + CFIndexVector aCFIndexVec; + + // TODO: iterate over cached layout + CFArrayRef aGlyphRuns = CTLineGetGlyphRuns( mpCTLine ); + const int nRunCount = CFArrayGetCount( aGlyphRuns ); + for( int nRunIndex = 0; nRunIndex < nRunCount; ++nRunIndex ) { + CTRunRef pGlyphRun = (CTRunRef)CFArrayGetValueAtIndex( aGlyphRuns, nRunIndex ); + const CFIndex nGlyphsInRun = CTRunGetGlyphCount( pGlyphRun ); + // skip to the first glyph run of interest + if( nSubIndex >= nGlyphsInRun ) { + nSubIndex -= nGlyphsInRun; + continue; + } + const CFRange aFullRange = CFRangeMake( 0, nGlyphsInRun ); + + // get glyph run details + const CGGlyph* pCGGlyphIdx = CTRunGetGlyphsPtr( pGlyphRun ); + if( !pCGGlyphIdx ) { + aCGGlyphVec.reserve( nGlyphsInRun ); + CTRunGetGlyphs( pGlyphRun, aFullRange, &aCGGlyphVec[0] ); + pCGGlyphIdx = &aCGGlyphVec[0]; + } + const CGPoint* pCGGlyphPos = CTRunGetPositionsPtr( pGlyphRun ); + if( !pCGGlyphPos ) { + aCGPointVec.reserve( nGlyphsInRun ); + CTRunGetPositions( pGlyphRun, aFullRange, &aCGPointVec[0] ); + pCGGlyphPos = &aCGPointVec[0]; + } + + const CGSize* pCGGlyphAdvs = NULL; + if( pGlyphAdvances) { + pCGGlyphAdvs = CTRunGetAdvancesPtr( pGlyphRun ); + if( !pCGGlyphAdvs) { + aCGSizeVec.reserve( nGlyphsInRun ); + CTRunGetAdvances( pGlyphRun, aFullRange, &aCGSizeVec[0] ); + pCGGlyphAdvs = &aCGSizeVec[0]; + } + } + + const CFIndex* pCGGlyphStrIdx = NULL; + if( pCharIndexes) { + pCGGlyphStrIdx = CTRunGetStringIndicesPtr( pGlyphRun ); + if( !pCGGlyphStrIdx) { + aCFIndexVec.reserve( nGlyphsInRun ); + CTRunGetStringIndices( pGlyphRun, aFullRange, &aCFIndexVec[0] ); + pCGGlyphStrIdx = &aCFIndexVec[0]; + } + } + + const PhysicalFontFace* pFallbackFont = NULL; + if( pFallbackFonts ) { + CFDictionaryRef pRunAttributes = CTRunGetAttributes( pGlyphRun ); + CTFontRef pRunFont = (CTFontRef)CFDictionaryGetValue( pRunAttributes, kCTFontAttributeName ); + + CFDictionaryRef pAttributes = mpTextStyle->GetStyleDict(); + CTFontRef pFont = (CTFontRef)CFDictionaryGetValue( pAttributes, kCTFontAttributeName ); + if ( !CFEqual( pRunFont, pFont ) ) { + CTFontDescriptorRef pFontDesc = CTFontCopyFontDescriptor( pRunFont ); + ImplDevFontAttributes rDevFontAttr = DevFontFromCTFontDescriptor( pFontDesc, NULL ); + pFallbackFont = new CoreTextFontData( rDevFontAttr, (sal_IntPtr)pFontDesc ); + } + } + + // get the details for each interesting glyph + // TODO: handle nLen>1 + for(; (--nLen >= 0) && (nSubIndex < nGlyphsInRun); ++nSubIndex, ++nStart ) + { + // convert glyph details for VCL + *(pGlyphIDs++) = pCGGlyphIdx[ nSubIndex ]; + if( pGlyphAdvances ) + *(pGlyphAdvances++) = lrint(pCGGlyphAdvs[ nSubIndex ].width); + if( pCharIndexes ) + *(pCharIndexes++) = pCGGlyphStrIdx[ nSubIndex] + mnMinCharPos; + if( pFallbackFonts ) + *(pFallbackFonts++) = pFallbackFont; + if( !nCount++ ) { + const CGPoint& rCurPos = pCGGlyphPos[ nSubIndex ]; + rPos = GetDrawPosition( Point( rCurPos.x, rCurPos.y) ); + } + } + nSubIndex = 0; // prepare for the next glyph run + break; // TODO: handle nLen>1 + } + + return nCount; +} + +double CTLayout::GetWidth() const +{ + if( (mnCharCount <= 0) || !mpCTLine ) + return 0; + + if( mfCachedWidth < 0.0 ) { + mfCachedWidth = CTLineGetTypographicBounds( mpCTLine, NULL, NULL, NULL); + } + + return mfCachedWidth; +} + +long CTLayout::GetTextWidth() const +{ + return lrint(GetWidth()); +} + +long CTLayout::FillDXArray( sal_Int32* pDXArray ) const +{ + // short circuit requests which don't need full details + if( !pDXArray ) + return GetTextWidth(); + + long nPixWidth = GetTextWidth(); + if( pDXArray ) { + // initialize the result array + for( int i = 0; i < mnCharCount; ++i) + pDXArray[i] = 0; + // handle each glyph run + CFArrayRef aGlyphRuns = CTLineGetGlyphRuns( mpCTLine ); + const int nRunCount = CFArrayGetCount( aGlyphRuns ); + typedef std::vector CGSizeVector; + CGSizeVector aSizeVec; + typedef std::vector CFIndexVector; + CFIndexVector aIndexVec; + for( int nRunIndex = 0; nRunIndex < nRunCount; ++nRunIndex ) { + CTRunRef pGlyphRun = (CTRunRef)CFArrayGetValueAtIndex( aGlyphRuns, nRunIndex ); + const CFIndex nGlyphCount = CTRunGetGlyphCount( pGlyphRun ); + const CFRange aFullRange = CFRangeMake( 0, nGlyphCount ); + aSizeVec.reserve( nGlyphCount ); + aIndexVec.reserve( nGlyphCount ); + CTRunGetAdvances( pGlyphRun, aFullRange, &aSizeVec[0] ); + CTRunGetStringIndices( pGlyphRun, aFullRange, &aIndexVec[0] ); + for( int i = 0; i != nGlyphCount; ++i ) { + const int nRelIdx = aIndexVec[i]; + pDXArray[ nRelIdx ] += lrint(aSizeVec[i].width); + } + } + } + + return nPixWidth; +} + +sal_Int32 CTLayout::GetTextBreak( long nMaxWidth, long /*nCharExtra*/, int nFactor ) const +{ + if( !mpCTLine ) + return -1; + + CTTypesetterRef aCTTypeSetter = CTTypesetterCreateWithAttributedString( mpAttrString ); + const double fCTMaxWidth = (double)nMaxWidth / nFactor; + CFIndex nIndex = CTTypesetterSuggestClusterBreak( aCTTypeSetter, 0, fCTMaxWidth ); + if( nIndex >= mnCharCount ) + return -1; + + nIndex += mnMinCharPos; + return nIndex; +} + +void CTLayout::GetCaretPositions( int nMaxIndex, sal_Int32* pCaretXArray ) const +{ + DBG_ASSERT( ((nMaxIndex>0)&&!(nMaxIndex&1)), + "CTLayout::GetCaretPositions() : invalid number of caret pairs requested"); + + // initialize the caret positions + for( int i = 0; i < nMaxIndex; ++i ) + pCaretXArray[ i ] = -1; + + for( int n = 0; n <= mnCharCount; ++n ) + { + // measure the characters cursor position + CGFloat fPos2 = -1; + const CGFloat fPos1 = CTLineGetOffsetForStringIndex( mpCTLine, n, &fPos2 ); + (void)fPos2; // TODO: split cursor at line direction change + // update previous trailing position + if( n > 0 ) + pCaretXArray[ 2*n-1 ] = lrint( fPos1 ); + // update current leading position + if( 2*n >= nMaxIndex ) + break; + pCaretXArray[ 2*n+0 ] = lrint( fPos1 ); + } +} + +bool CTLayout::GetBoundRect( SalGraphics& rGraphics, Rectangle& rVCLRect ) const +{ + // Closely mimic DrawText(), except that instead of calling + // CTLineDraw() to draw the line, we call CTLineGetImageBounds() + // to get its bounds. But all the coordinate system manipulation + // before that is the same => should be factored out? + + AquaSalGraphics& rAquaGraphics = static_cast(rGraphics); + + if( !rAquaGraphics.CheckContext() ) + return false; + + CGContextSaveGState( rAquaGraphics.mrContext ); + CGContextScaleCTM( rAquaGraphics.mrContext, 1.0, -1.0 ); + CGContextSetShouldAntialias( rAquaGraphics.mrContext, !rAquaGraphics.mbNonAntialiasedText ); + + const CGPoint aVclPos = GetTextDrawPosition(); + CGPoint aTextPos = GetTextDrawPosition(); + + if( mpTextStyle->mfFontRotation != 0.0 ) + { + const CGFloat fRadians = mpTextStyle->mfFontRotation; + CGContextRotateCTM( rAquaGraphics.mrContext, +fRadians ); + + const CGAffineTransform aInvMatrix = CGAffineTransformMakeRotation( -fRadians ); + aTextPos = CGPointApplyAffineTransform( aTextPos, aInvMatrix ); + } + + CGContextSetTextPosition( rAquaGraphics.mrContext, aTextPos.x, aTextPos.y ); + CGRect aMacRect = CTLineGetImageBounds( mpCTLine, rAquaGraphics.mrContext ); + + if( mpTextStyle->mfFontRotation != 0.0 ) + { + const CGFloat fRadians = mpTextStyle->mfFontRotation; + const CGAffineTransform aMatrix = CGAffineTransformMakeRotation( +fRadians ); + aMacRect = CGRectApplyAffineTransform( aMacRect, aMatrix ); + } + + CGContextRestoreGState( rAquaGraphics.mrContext ); + + rVCLRect.Left() = aVclPos.x + lrint(aMacRect.origin.x); + rVCLRect.Right() = aVclPos.x + lrint(aMacRect.origin.x + aMacRect.size.width); + rVCLRect.Bottom() = aVclPos.x - lrint(aMacRect.origin.y); + rVCLRect.Top() = aVclPos.x - lrint(aMacRect.origin.y + aMacRect.size.height); + + return true; +} + +// glyph fallback is supported directly by Aqua +// so methods used only by MultiSalLayout can be dummy implementated +bool CTLayout::GetGlyphOutlines( SalGraphics&, PolyPolyVector& ) const { return false; } +void CTLayout::InitFont() const {} +void CTLayout::MoveGlyph( int /*nStart*/, long /*nNewXPos*/ ) {} +void CTLayout::DropGlyph( int /*nStart*/ ) {} +void CTLayout::Simplify( bool /*bIsBase*/ ) {} + +SalLayout* CoreTextStyle::GetTextLayout( void ) const +{ + return new CTLayout( this); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/quartz/salbmp.cxx b/vcl/quartz/salbmp.cxx index 73ead103c6fa..1a509bd68e46 100644 --- a/vcl/quartz/salbmp.cxx +++ b/vcl/quartz/salbmp.cxx @@ -31,7 +31,7 @@ #include "quartz/salbmp.h" #ifdef MACOSX -#include "aqua/saldata.hxx" +#include "osx/saldata.hxx" #else #include "saldatabasic.hxx" #endif diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx new file mode 100644 index 000000000000..0a48e2d6b2f6 --- /dev/null +++ b/vcl/quartz/salgdi.cxx @@ -0,0 +1,889 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include "sal/config.h" + +#include "osl/file.hxx" +#include "osl/process.h" + +#include "osl/mutex.hxx" + +#include "rtl/bootstrap.h" +#include "rtl/strbuf.hxx" + +#include "basegfx/range/b2drectangle.hxx" +#include "basegfx/polygon/b2dpolygon.hxx" +#include "basegfx/polygon/b2dpolygontools.hxx" +#include "basegfx/matrix/b2dhommatrix.hxx" +#include "basegfx/matrix/b2dhommatrixtools.hxx" + +#include "vcl/sysdata.hxx" +#include "vcl/svapp.hxx" + +#include "quartz/salgdi.h" + +#ifdef MACOSX +#include "osx/salframe.h" +#endif + +#ifdef IOS +#include "saldatabasic.hxx" +#include +#endif + +#include "ctfonts.hxx" + +#include "fontsubset.hxx" +#include "impfont.hxx" +#include "sallayout.hxx" +#include "sft.hxx" + + +using namespace vcl; + +// ======================================================================= + +CoreTextFontData::CoreTextFontData( const CoreTextFontData& rSrc ) +: PhysicalFontFace( rSrc ) +, mnFontId( rSrc.mnFontId ) +, mpCharMap( rSrc.mpCharMap ) +, mbOs2Read( rSrc.mbOs2Read ) +, mbHasOs2Table( rSrc.mbHasOs2Table ) +, mbCmapEncodingRead( rSrc.mbCmapEncodingRead ) +{ + if( mpCharMap ) + mpCharMap->AddReference(); +} + +// ----------------------------------------------------------------------- + +CoreTextFontData::CoreTextFontData( const ImplDevFontAttributes& rDFA, sal_IntPtr nFontId ) +: PhysicalFontFace( rDFA, 0 ) +, mnFontId( nFontId ) +, mpCharMap( NULL ) +, mbOs2Read( false ) +, mbHasOs2Table( false ) +, mbCmapEncodingRead( false ) +, mbFontCapabilitiesRead( false ) +{ +} + +// ----------------------------------------------------------------------- + +CoreTextFontData::~CoreTextFontData() +{ + if( mpCharMap ) + mpCharMap->DeReference(); +} + +// ----------------------------------------------------------------------- + +sal_IntPtr CoreTextFontData::GetFontId() const +{ + return (sal_IntPtr)mnFontId; +} + +// ----------------------------------------------------------------------- + +static unsigned GetUShort( const unsigned char* p ){return((p[0]<<8)+p[1]);} + +const ImplFontCharMap* CoreTextFontData::GetImplFontCharMap() const +{ + // return the cached charmap + if( mpCharMap ) + return mpCharMap; + + // set the default charmap + mpCharMap = ImplFontCharMap::GetDefaultMap(); + mpCharMap->AddReference(); + + // get the CMAP byte size + // allocate a buffer for the CMAP raw data + const int nBufSize = GetFontTable( "cmap", NULL ); + DBG_ASSERT( (nBufSize > 0), "CoreTextFontData::GetImplFontCharMap : GetFontTable1 failed!\n"); + if( nBufSize <= 0 ) + return mpCharMap; + + // get the CMAP raw data + ByteVector aBuffer( nBufSize ); + const int nRawLength = GetFontTable( "cmap", &aBuffer[0] ); + DBG_ASSERT( (nRawLength > 0), "CoreTextFontData::GetImplFontCharMap : GetFontTable2 failed!\n"); + if( nRawLength <= 0 ) + return mpCharMap; + DBG_ASSERT( (nBufSize==nRawLength), "CoreTextFontData::GetImplFontCharMap : ByteCount mismatch!\n"); + + // parse the CMAP + CmapResult aCmapResult; + if( ParseCMAP( &aBuffer[0], nRawLength, aCmapResult ) ) + { + // create the matching charmap + mpCharMap->DeReference(); + mpCharMap = new ImplFontCharMap( aCmapResult ); + mpCharMap->AddReference(); + } + + return mpCharMap; +} + +bool CoreTextFontData::GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const +{ + // read this only once per font + if( mbFontCapabilitiesRead ) + { + rFontCapabilities = maFontCapabilities; + return !rFontCapabilities.maUnicodeRange.empty() || !rFontCapabilities.maCodePageRange.empty(); + } + mbFontCapabilitiesRead = true; + + int nBufSize = 0; + // prepare to get the GSUB table raw data + nBufSize = GetFontTable( "GSUB", NULL ); + if( nBufSize > 0 ) + { + // allocate a buffer for the GSUB raw data + ByteVector aBuffer( nBufSize ); + // get the GSUB raw data + const int nRawLength = GetFontTable( "GSUB", &aBuffer[0] ); + if( nRawLength > 0 ) + { + const unsigned char* pGSUBTable = &aBuffer[0]; + vcl::getTTScripts(maFontCapabilities.maGSUBScriptTags, pGSUBTable, nRawLength); + } + } + nBufSize = GetFontTable( "OS/2", NULL ); + if( nBufSize > 0 ) + { + // allocate a buffer for the OS/2 raw data + ByteVector aBuffer( nBufSize ); + // get the OS/2 raw data + const int nRawLength = GetFontTable( "OS/2", &aBuffer[0] ); + if( nRawLength > 0 ) + { + const unsigned char* pOS2Table = &aBuffer[0]; + vcl::getTTCoverage( + maFontCapabilities.maUnicodeRange, + maFontCapabilities.maCodePageRange, + pOS2Table, nRawLength); + } + } + rFontCapabilities = maFontCapabilities; + return !rFontCapabilities.maUnicodeRange.empty() || !rFontCapabilities.maCodePageRange.empty(); +} + +// ----------------------------------------------------------------------- + +void CoreTextFontData::ReadOs2Table( void ) const +{ + // read this only once per font + if( mbOs2Read ) + return; + mbOs2Read = true; + mbHasOs2Table = false; + + // prepare to get the OS/2 table raw data + const int nBufSize = GetFontTable( "OS/2", NULL ); + DBG_ASSERT( (nBufSize > 0), "CoreTextFontData::ReadOs2Table : GetFontTable1 failed!\n"); + if( nBufSize <= 0 ) + return; + + // get the OS/2 raw data + ByteVector aBuffer( nBufSize ); + const int nRawLength = GetFontTable( "cmap", &aBuffer[0] ); + DBG_ASSERT( (nRawLength > 0), "CoreTextFontData::ReadOs2Table : GetFontTable2 failed!\n"); + if( nRawLength <= 0 ) + return; + DBG_ASSERT( (nBufSize==nRawLength), "CoreTextFontData::ReadOs2Table : ByteCount mismatch!\n"); + mbHasOs2Table = true; + + // parse the OS/2 raw data + // TODO: also analyze panose info, etc. +} + +void CoreTextFontData::ReadMacCmapEncoding( void ) const +{ + // read this only once per font + if( mbCmapEncodingRead ) + return; + mbCmapEncodingRead = true; + + const int nBufSize = GetFontTable( "cmap", NULL ); + if( nBufSize <= 0 ) + return; + + // get the CMAP raw data + ByteVector aBuffer( nBufSize ); + const int nRawLength = GetFontTable( "cmap", &aBuffer[0] ); + if( nRawLength < 24 ) + return; + DBG_ASSERT( (nBufSize==nRawLength), "CoreTextFontData::ReadMacCmapEncoding : ByteCount mismatch!\n"); + + const unsigned char* pCmap = &aBuffer[0]; + if( GetUShort( pCmap ) != 0x0000 ) + return; +} + +// ----------------------------------------------------------------------- + +AquaSalGraphics::AquaSalGraphics() +#ifdef MACOSX + : mpFrame( NULL ) + , mxLayer( NULL ) + , mrContext( NULL ) + , mpXorEmulation( NULL ) + , mnXorMode( 0 ) + , mnWidth( 0 ) + , mnHeight( 0 ) + , mnBitmapDepth( 0 ) + , mnRealDPIX( 0 ) + , mnRealDPIY( 0 ) + , mfFakeDPIScale( 1.0 ) + , mxClipPath( NULL ) + , maLineColor( COL_WHITE ) + , maFillColor( COL_BLACK ) + , mpFontData( NULL ) + , mpTextStyle( NULL ) + , maTextColor( COL_BLACK ) + , mbNonAntialiasedText( false ) + , mbPrinter( false ) + , mbVirDev( false ) + , mbWindow( false ) +#else + : mrContext( NULL ) + , mfFakeDPIScale( 1.0 ) + , mpFontData( NULL ) + , mpTextStyle( NULL ) + , maTextColor( COL_BLACK ) + , mbNonAntialiasedText( false ) +#endif +{} + +// ----------------------------------------------------------------------- + +AquaSalGraphics::~AquaSalGraphics() +{ +#ifdef MACOSX + CGPathRelease( mxClipPath ); + delete mpTextStyle; + + if( mpXorEmulation ) + delete mpXorEmulation; + + if( mxLayer ) + CGLayerRelease( mxLayer ); + else if( mrContext && mbWindow ) + { + // destroy backbuffer bitmap context that we created ourself + CGContextRelease( mrContext ); + mrContext = NULL; + } +#endif +} + +// ======================================================================= + +void AquaSalGraphics::SetTextColor( SalColor nSalColor ) +{ + maTextColor = RGBAColor( nSalColor ); + if( mpTextStyle) + mpTextStyle->SetTextColor( maTextColor ); +} + +// ----------------------------------------------------------------------- + +void AquaSalGraphics::GetFontMetric( ImplFontMetricData* pMetric, int /*nFallbackLevel*/ ) +{ + mpTextStyle->GetFontMetric( mfFakeDPIScale, *pMetric ); +} + +// ----------------------------------------------------------------------- + +static bool AddTempDevFont(const OUString& rFontFileURL) +{ + OUString aUSytemPath; + OSL_VERIFY( !osl::FileBase::getSystemPathFromFileURL( rFontFileURL, aUSytemPath ) ); + OString aCFileName = OUStringToOString( aUSytemPath, RTL_TEXTENCODING_UTF8 ); + + CFStringRef rFontPath = CFStringCreateWithCString(NULL, aCFileName.getStr(), kCFStringEncodingUTF8); + CFURLRef rFontURL = CFURLCreateWithFileSystemPath(NULL, rFontPath, kCFURLPOSIXPathStyle, true); + + CFErrorRef error; + bool success = CTFontManagerRegisterFontsForURL(rFontURL, kCTFontManagerScopeProcess, &error); + + if (!success) + { + CFRelease(error); + return false; + } + + return true; +} + +static void AddTempFontDir( const OUString &rFontDirUrl ) +{ + osl::Directory aFontDir( rFontDirUrl ); + osl::FileBase::RC rcOSL = aFontDir.open(); + if( rcOSL == osl::FileBase::E_None ) + { + osl::DirectoryItem aDirItem; + + while( aFontDir.getNextItem( aDirItem, 10 ) == osl::FileBase::E_None ) + { + osl::FileStatus aFileStatus( osl_FileStatus_Mask_FileURL ); + rcOSL = aDirItem.getFileStatus( aFileStatus ); + if ( rcOSL == osl::FileBase::E_None ) + AddTempDevFont(aFileStatus.getFileURL()); + } + } +} + +static void AddLocalTempFontDirs() +{ + static bool bFirst = true; + if( !bFirst ) + return; + bFirst = false; + + // add private font files + + OUString aBrandStr( "$BRAND_BASE_DIR" ); + rtl_bootstrap_expandMacros( &aBrandStr.pData ); + AddTempFontDir( aBrandStr + "/" LIBO_SHARE_FOLDER "/fonts/truetype/" ); +} + +void AquaSalGraphics::GetDevFontList( ImplDevFontList* pFontList ) +{ + DBG_ASSERT( pFontList, "AquaSalGraphics::GetDevFontList(NULL) !"); + + AddLocalTempFontDirs(); + + // The idea is to cache the list of system fonts once it has been generated. + // SalData seems to be a good place for this caching. However we have to + // carefully make the access to the font list thread-safe. If we register + // a font-change event handler to update the font list in case fonts have + // changed on the system we have to lock access to the list. The right + // way to do that is the solar mutex since GetDevFontList is protected + // through it as should be all event handlers + + SalData* pSalData = GetSalData(); + if( !pSalData->mpFontList ) + pSalData->mpFontList = GetCoretextFontList(); + + // Copy all PhysicalFontFace objects contained in the SystemFontList + pSalData->mpFontList->AnnounceFonts( *pFontList ); +} + +void AquaSalGraphics::ClearDevFontCache() +{ + SalData* pSalData = GetSalData(); + delete pSalData->mpFontList; + pSalData->mpFontList = NULL; +} + +// ----------------------------------------------------------------------- + +bool AquaSalGraphics::AddTempDevFont( ImplDevFontList*, + const OUString& rFontFileURL, const OUString& /*rFontName*/ ) +{ + return ::AddTempDevFont(rFontFileURL); +} + +// ----------------------------------------------------------------------- + +sal_Bool AquaSalGraphics::GetGlyphOutline( sal_GlyphId nGlyphId, basegfx::B2DPolyPolygon& rPolyPoly ) +{ + const bool bRC = mpTextStyle->GetGlyphOutline( nGlyphId, rPolyPoly ); + return bRC; +} + +// ----------------------------------------------------------------------- + +sal_Bool AquaSalGraphics::GetGlyphBoundRect( sal_GlyphId nGlyphId, Rectangle& rRect ) +{ + const bool bRC = mpTextStyle->GetGlyphBoundRect( nGlyphId, rRect ); + return bRC; +} + +// ----------------------------------------------------------------------- + +void AquaSalGraphics::DrawServerFontLayout( const ServerFontLayout& ) +{ +} + +// ----------------------------------------------------------------------- + +sal_uInt16 AquaSalGraphics::SetFont( FontSelectPattern* pReqFont, int /*nFallbackLevel*/ ) +{ + // release the text style + delete mpTextStyle; + mpTextStyle = NULL; + + // handle NULL request meaning: release-font-resources request + if( !pReqFont ) + { + mpFontData = NULL; + return 0; + } + + // update the text style + mpFontData = static_cast( pReqFont->mpFontData ); + mpTextStyle = mpFontData->CreateTextStyle( *pReqFont ); + mpTextStyle->SetTextColor( maTextColor ); + + SAL_INFO("vcl.coretext", + "SetFont" + << " to " << mpFontData->GetFamilyName() + << ", " << mpFontData->GetStyleName() + << " fontid=" << mpFontData->GetFontId() + << " for " << pReqFont->GetFamilyName() + << ", " << pReqFont->GetStyleName() + << " weight=" << pReqFont->GetWeight() + << " slant=" << pReqFont->GetSlant() + << " size=" << pReqFont->mnHeight << "x" << pReqFont->mnWidth + << " orientation=" << pReqFont->mnOrientation + ); + + return 0; +} + +// ----------------------------------------------------------------------- + +SalLayout* AquaSalGraphics::GetTextLayout( ImplLayoutArgs& /*rArgs*/, int /*nFallbackLevel*/ ) +{ + SalLayout* pSalLayout = mpTextStyle->GetTextLayout(); + return pSalLayout; +} + +// ----------------------------------------------------------------------- + +const ImplFontCharMap* AquaSalGraphics::GetImplFontCharMap() const +{ + if( !mpFontData ) + return ImplFontCharMap::GetDefaultMap(); + + return mpFontData->GetImplFontCharMap(); +} + +bool AquaSalGraphics::GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const +{ + if( !mpFontData ) + return false; + + return mpFontData->GetImplFontCapabilities(rFontCapabilities); +} + +// ----------------------------------------------------------------------- + +// fake a SFNT font directory entry for a font table +// see http://developer.apple.com/fonts/TTRefMan/RM06/Chap6.html#Directory +static void FakeDirEntry( const char aTag[5], ByteCount nOfs, ByteCount nLen, + const unsigned char* /*pData*/, unsigned char*& rpDest ) +{ + // write entry tag + rpDest[ 0] = aTag[0]; + rpDest[ 1] = aTag[1]; + rpDest[ 2] = aTag[2]; + rpDest[ 3] = aTag[3]; + // TODO: get entry checksum and write it + // not too important since the subsetter doesn't care currently + // for( pData+nOfs ... pData+nOfs+nLen ) + // write entry offset + rpDest[ 8] = (char)(nOfs >> 24); + rpDest[ 9] = (char)(nOfs >> 16); + rpDest[10] = (char)(nOfs >> 8); + rpDest[11] = (char)(nOfs >> 0); + // write entry length + rpDest[12] = (char)(nLen >> 24); + rpDest[13] = (char)(nLen >> 16); + rpDest[14] = (char)(nLen >> 8); + rpDest[15] = (char)(nLen >> 0); + // advance to next entry + rpDest += 16; +} + +// fake a TTF or CFF font as directly accessing font file is not possible +// when only the fontid is known. This approach also handles *.dfont fonts. +bool AquaSalGraphics::GetRawFontData( const PhysicalFontFace* pFontData, + ByteVector& rBuffer, bool* pJustCFF ) +{ + const CoreTextFontData* pMacFont = static_cast(pFontData); + + // short circuit for CFF-only fonts + const int nCffSize = pMacFont->GetFontTable( "CFF ", NULL); + if( pJustCFF != NULL ) + { + *pJustCFF = (nCffSize > 0); + if( *pJustCFF) + { + rBuffer.resize( nCffSize); + const int nCffRead = pMacFont->GetFontTable( "CFF ", &rBuffer[0]); + if( nCffRead != nCffSize) + return false; + return true; + } + } + + // get font table availability and size in bytes + const int nHeadSize = pMacFont->GetFontTable( "head", NULL); + if( nHeadSize <= 0) + return false; + const int nMaxpSize = pMacFont->GetFontTable( "maxp", NULL); + if( nMaxpSize <= 0) + return false; + const int nCmapSize = pMacFont->GetFontTable( "cmap", NULL); + if( nCmapSize <= 0) + return false; + const int nNameSize = pMacFont->GetFontTable( "name", NULL); + if( nNameSize <= 0) + return false; + const int nHheaSize = pMacFont->GetFontTable( "hhea", NULL); + if( nHheaSize <= 0) + return false; + const int nHmtxSize = pMacFont->GetFontTable( "hmtx", NULL); + if( nHmtxSize <= 0) + return false; + + // get the ttf-glyf outline tables + int nLocaSize = 0; + int nGlyfSize = 0; + if( nCffSize <= 0) + { + nLocaSize = pMacFont->GetFontTable( "loca", NULL); + if( nLocaSize <= 0) + return false; + nGlyfSize = pMacFont->GetFontTable( "glyf", NULL); + if( nGlyfSize <= 0) + return false; + } + + int nPrepSize = 0, nCvtSize = 0, nFpgmSize = 0; + if( nGlyfSize) // TODO: reduce PDF size by making hint subsetting optional + { + nPrepSize = pMacFont->GetFontTable( "prep", NULL); + nCvtSize = pMacFont->GetFontTable( "cvt ", NULL); + nFpgmSize = pMacFont->GetFontTable( "fpgm", NULL); + } + + // prepare a byte buffer for a fake font + int nTableCount = 7; + nTableCount += (nPrepSize>0) + (nCvtSize>0) + (nFpgmSize>0) + (nGlyfSize>0); + const ByteCount nFdirSize = 12 + 16*nTableCount; + ByteCount nTotalSize = nFdirSize; + nTotalSize += nHeadSize + nMaxpSize + nNameSize + nCmapSize; + if( nGlyfSize ) + nTotalSize += nLocaSize + nGlyfSize; + else + nTotalSize += nCffSize; + nTotalSize += nHheaSize + nHmtxSize; + nTotalSize += nPrepSize + nCvtSize + nFpgmSize; + rBuffer.resize( nTotalSize ); + + // fake a SFNT font directory header + if( nTableCount < 16 ) + { + int nLog2 = 0; + while( (nTableCount >> nLog2) > 1 ) ++nLog2; + rBuffer[ 1] = 1; // Win-TTF style scaler + rBuffer[ 5] = nTableCount; // table count + rBuffer[ 7] = nLog2*16; // searchRange + rBuffer[ 9] = nLog2; // entrySelector + rBuffer[11] = (nTableCount-nLog2)*16; // rangeShift + } + + // get font table raw data and update the fake directory entries + ByteCount nOfs = nFdirSize; + unsigned char* pFakeEntry = &rBuffer[12]; + if( nCmapSize != pMacFont->GetFontTable( "cmap", &rBuffer[nOfs])) + return false; + FakeDirEntry( "cmap", nOfs, nCmapSize, &rBuffer[0], pFakeEntry ); + nOfs += nCmapSize; + if( nCvtSize ) { + if( nCvtSize != pMacFont->GetFontTable( "cvt ", &rBuffer[nOfs])) + return false; + FakeDirEntry( "cvt ", nOfs, nCvtSize, &rBuffer[0], pFakeEntry ); + nOfs += nCvtSize; + } + if( nFpgmSize ) { + if( nFpgmSize != pMacFont->GetFontTable( "fpgm", &rBuffer[nOfs])) + return false; + FakeDirEntry( "fpgm", nOfs, nFpgmSize, &rBuffer[0], pFakeEntry ); + nOfs += nFpgmSize; + } + if( nCffSize ) { + if( nCffSize != pMacFont->GetFontTable( "CFF ", &rBuffer[nOfs])) + return false; + FakeDirEntry( "CFF ", nOfs, nCffSize, &rBuffer[0], pFakeEntry ); + nOfs += nGlyfSize; + } else { + if( nGlyfSize != pMacFont->GetFontTable( "glyf", &rBuffer[nOfs])) + return false; + FakeDirEntry( "glyf", nOfs, nGlyfSize, &rBuffer[0], pFakeEntry ); + nOfs += nGlyfSize; + if( nLocaSize != pMacFont->GetFontTable( "loca", &rBuffer[nOfs])) + return false; + FakeDirEntry( "loca", nOfs, nLocaSize, &rBuffer[0], pFakeEntry ); + nOfs += nLocaSize; + } + if( nHeadSize != pMacFont->GetFontTable( "head", &rBuffer[nOfs])) + return false; + FakeDirEntry( "head", nOfs, nHeadSize, &rBuffer[0], pFakeEntry ); + nOfs += nHeadSize; + if( nHheaSize != pMacFont->GetFontTable( "hhea", &rBuffer[nOfs])) + return false; + FakeDirEntry( "hhea", nOfs, nHheaSize, &rBuffer[0], pFakeEntry ); + nOfs += nHheaSize; + if( nHmtxSize != pMacFont->GetFontTable( "hmtx", &rBuffer[nOfs])) + return false; + FakeDirEntry( "hmtx", nOfs, nHmtxSize, &rBuffer[0], pFakeEntry ); + nOfs += nHmtxSize; + if( nMaxpSize != pMacFont->GetFontTable( "maxp", &rBuffer[nOfs])) + return false; + FakeDirEntry( "maxp", nOfs, nMaxpSize, &rBuffer[0], pFakeEntry ); + nOfs += nMaxpSize; + if( nNameSize != pMacFont->GetFontTable( "name", &rBuffer[nOfs])) + return false; + FakeDirEntry( "name", nOfs, nNameSize, &rBuffer[0], pFakeEntry ); + nOfs += nNameSize; + if( nPrepSize ) { + if( nPrepSize != pMacFont->GetFontTable( "prep", &rBuffer[nOfs])) + return false; + FakeDirEntry( "prep", nOfs, nPrepSize, &rBuffer[0], pFakeEntry ); + nOfs += nPrepSize; + } + + DBG_ASSERT( (nOfs==nTotalSize), "AquaSalGraphics::CreateFontSubset (nOfs!=nTotalSize)"); + + return true; +} + +// ----------------------------------------------------------------------- + +void AquaSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFontData, bool bVertical, + Int32Vector& rGlyphWidths, Ucs2UIntMap& rUnicodeEnc ) +{ + rGlyphWidths.clear(); + rUnicodeEnc.clear(); + + if( pFontData->IsSubsettable() ) + { + ByteVector aBuffer; + if( !GetRawFontData( pFontData, aBuffer, NULL ) ) + return; + + // TODO: modernize psprint's horrible fontsubset C-API + // this probably only makes sense after the switch to another SCM + // that can preserve change history after file renames + + // use the font subsetter to get the widths + TrueTypeFont* pSftFont = NULL; + int nRC = ::OpenTTFontBuffer( (void*)&aBuffer[0], aBuffer.size(), 0, &pSftFont); + if( nRC != SF_OK ) + return; + + const int nGlyphCount = ::GetTTGlyphCount( pSftFont ); + if( nGlyphCount > 0 ) + { + // get glyph metrics + rGlyphWidths.resize(nGlyphCount); + std::vector aGlyphIds(nGlyphCount); + for( int i = 0; i < nGlyphCount; i++ ) + aGlyphIds[i] = static_cast(i); + const TTSimpleGlyphMetrics* pGlyphMetrics = ::GetTTSimpleGlyphMetrics( + pSftFont, &aGlyphIds[0], nGlyphCount, bVertical ); + if( pGlyphMetrics ) + { + for( int i = 0; i < nGlyphCount; ++i ) + rGlyphWidths[i] = pGlyphMetrics[i].adv; + free( (void*)pGlyphMetrics ); + } + + const ImplFontCharMap* pMap = mpFontData->GetImplFontCharMap(); + DBG_ASSERT( pMap && pMap->GetCharCount(), "no charmap" ); + pMap->AddReference(); // TODO: add and use RAII object instead + + // get unicode<->glyph encoding + // TODO? avoid sft mapping by using the pMap itself + int nCharCount = pMap->GetCharCount(); + sal_uInt32 nChar = pMap->GetFirstChar(); + for(; --nCharCount >= 0; nChar = pMap->GetNextChar( nChar ) ) + { + if( nChar > 0xFFFF ) // TODO: allow UTF-32 chars + break; + sal_Ucs nUcsChar = static_cast(nChar); + sal_uInt32 nGlyph = ::MapChar( pSftFont, nUcsChar, bVertical ); + if( nGlyph > 0 ) + rUnicodeEnc[ nUcsChar ] = nGlyph; + } + + pMap->DeReference(); // TODO: add and use RAII object instead + } + + ::CloseTTFont( pSftFont ); + } + else if( pFontData->IsEmbeddable() ) + { + // get individual character widths + OSL_FAIL("not implemented for non-subsettable fonts!\n"); + } +} + +// ----------------------------------------------------------------------- + +const Ucs2SIntMap* AquaSalGraphics::GetFontEncodingVector( + const PhysicalFontFace*, const Ucs2OStrMap** /*ppNonEncoded*/ ) +{ + return NULL; +} + +// ----------------------------------------------------------------------- + +const void* AquaSalGraphics::GetEmbedFontData( const PhysicalFontFace*, + const sal_Ucs* /*pUnicodes*/, + sal_Int32* /*pWidths*/, + FontSubsetInfo&, + long* /*pDataLen*/ ) +{ + return NULL; +} + +// ----------------------------------------------------------------------- + +void AquaSalGraphics::FreeEmbedFontData( const void* pData, long /*nDataLen*/ ) +{ + // TODO: implementing this only makes sense when the implementation of + // AquaSalGraphics::GetEmbedFontData() returns non-NULL + (void)pData; + DBG_ASSERT( (pData!=NULL), "AquaSalGraphics::FreeEmbedFontData() is not implemented\n"); +} + +// ----------------------------------------------------------------------- + +SystemFontData AquaSalGraphics::GetSysFontData( int /* nFallbacklevel */ ) const +{ + SystemFontData aSysFontData; + aSysFontData.nSize = sizeof( SystemFontData ); + + aSysFontData.bAntialias = !mbNonAntialiasedText; + + return aSysFontData; +} + +#ifdef IOS + +// Note that "SvpSalGraphics" is actually called AquaSalGraphics for iOS + +bool SvpSalGraphics::CheckContext() +{ + const basegfx::B2IVector size = m_aDevice->getSize(); + const basegfx::B2IVector bufferSize = m_aDevice->getBufferSize(); + const sal_Int32 scanlineStride = m_aDevice->getScanlineStride(); + basebmp::RawMemorySharedArray pixelBuffer = m_aDevice->getBuffer(); + bool warned = false; + + SAL_INFO( "vcl.ios", + "CheckContext: device=" << m_aDevice.get() << + " size=" << size.getX() << "x" << size.getY() << + (m_aDevice->isTopDown() ? " top-down" : " bottom-up") << + " stride=" << scanlineStride << + " bufferSize=(" << bufferSize.getX() << "," << bufferSize.getY() << ")" ); + + switch( m_aDevice->getScanlineFormat() ) { + case basebmp::FORMAT_EIGHT_BIT_PAL: + mrContext = CGBitmapContextCreate(pixelBuffer.get(), + bufferSize.getX(), bufferSize.getY(), + 8, scanlineStride, + CGColorSpaceCreateDeviceGray(), + kCGImageAlphaNone); + break; + case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_RGBA: + mrContext = CGBitmapContextCreate(pixelBuffer.get(), + bufferSize.getX(), bufferSize.getY(), + 8, scanlineStride, + CGColorSpaceCreateDeviceRGB(), + kCGImageAlphaNoneSkipLast); + break; + case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_BGRA: + mrContext = CGBitmapContextCreate(pixelBuffer.get(), + bufferSize.getX(), bufferSize.getY(), + 8, scanlineStride, + CGColorSpaceCreateDeviceRGB(), + kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little); + break; + default: + SAL_WARN( "vcl.ios", "CheckContext: unsupported color format " << basebmp::formatName( m_aDevice->getScanlineFormat() ) ); + warned = true; + } + + SAL_WARN_IF( mrContext == NULL && !warned, "vcl.ios", "CheckContext: CGBitmapContextCreate() failed" ); + + // Should we also clip the context? (Then we need to add a + // getBounds() function to BitmapDevice.) + + if( mrContext != NULL && m_aDevice->isTopDown() ) + { + CGContextTranslateCTM( mrContext, 0, bufferSize.getY() ); + CGContextScaleCTM( mrContext, 1, -1 ); + } + + + if (mrContext) + { + RectangleVector aRectangles; + m_aClipRegion.GetRegionRectangles(aRectangles); + + CGContextBeginPath( mrContext ); + + for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter) + { + const long nW(aRectIter->Right() - aRectIter->Left() + 1); // uses +1 logic in original + + if(nW) + { + const long nH(aRectIter->Bottom() - aRectIter->Top() + 1); // uses +1 logic in original + + if(nH) + { + CGRect aRect = {{ (CGFloat) aRectIter->Left(), (CGFloat) aRectIter->Top() }, { (CGFloat) nW, (CGFloat) nH }}; + CGContextAddRect( mrContext, aRect ); + } + } + } + + if (!CGContextIsPathEmpty(mrContext)) + CGContextClip(mrContext); + } + + + SAL_INFO( "vcl.ios", "CheckContext: context=" << mrContext ); + + return ( mrContext != NULL ); +} + +CGContextRef SvpSalGraphics::GetContext() +{ + if ( !mrContext ) + CheckContext(); + + return mrContext; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/quartz/salgdicommon.cxx b/vcl/quartz/salgdicommon.cxx new file mode 100644 index 000000000000..8c5aef267976 --- /dev/null +++ b/vcl/quartz/salgdicommon.cxx @@ -0,0 +1,1755 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "sal/config.h" + +#include + +#include +#include +#include + +#include "basegfx/polygon/b2dpolygon.hxx" + +#include "quartz/salbmp.h" +#include "quartz/salgdi.h" + +#include "fontsubset.hxx" +#include "sft.hxx" + +using namespace vcl; + + +//typedef unsigned char Boolean; // copied from MacTypes.h, should be properly included +typedef std::vector ByteVector; + +static const basegfx::B2DPoint aHalfPointOfs ( 0.5, 0.5 ); + +static void AddPolygonToPath( CGMutablePathRef xPath, + const ::basegfx::B2DPolygon& rPolygon, + bool bClosePath, bool bPixelSnap, bool bLineDraw ) +{ + // short circuit if there is nothing to do + const int nPointCount = rPolygon.count(); + if( nPointCount <= 0 ) + { + return; + } + (void)bPixelSnap; // TODO + const CGAffineTransform* pTransform = NULL; + + const bool bHasCurves = rPolygon.areControlPointsUsed(); + for( int nPointIdx = 0, nPrevIdx = 0;; nPrevIdx = nPointIdx++ ) + { + int nClosedIdx = nPointIdx; + if( nPointIdx >= nPointCount ) + { + // prepare to close last curve segment if needed + if( bClosePath && (nPointIdx == nPointCount) ) + { + nClosedIdx = 0; + } + else + { + break; + } + } + + ::basegfx::B2DPoint aPoint = rPolygon.getB2DPoint( nClosedIdx ); + + if( bPixelSnap) + { + // snap device coordinates to full pixels + aPoint.setX( basegfx::fround( aPoint.getX() ) ); + aPoint.setY( basegfx::fround( aPoint.getY() ) ); + } + + if( bLineDraw ) + { + aPoint += aHalfPointOfs; + } + if( !nPointIdx ) + { + // first point => just move there + CGPathMoveToPoint( xPath, pTransform, aPoint.getX(), aPoint.getY() ); + continue; + } + + bool bPendingCurve = false; + if( bHasCurves ) + { + bPendingCurve = rPolygon.isNextControlPointUsed( nPrevIdx ); + bPendingCurve |= rPolygon.isPrevControlPointUsed( nClosedIdx ); + } + + if( !bPendingCurve ) // line segment + { + CGPathAddLineToPoint( xPath, pTransform, aPoint.getX(), aPoint.getY() ); + } + else // cubic bezier segment + { + basegfx::B2DPoint aCP1 = rPolygon.getNextControlPoint( nPrevIdx ); + basegfx::B2DPoint aCP2 = rPolygon.getPrevControlPoint( nClosedIdx ); + if( bLineDraw ) + { + aCP1 += aHalfPointOfs; + aCP2 += aHalfPointOfs; + } + CGPathAddCurveToPoint( xPath, pTransform, aCP1.getX(), aCP1.getY(), + aCP2.getX(), aCP2.getY(), aPoint.getX(), aPoint.getY() ); + } + } + + if( bClosePath ) + { + CGPathCloseSubpath( xPath ); + } +} + +static void AddPolyPolygonToPath( CGMutablePathRef xPath, + const ::basegfx::B2DPolyPolygon& rPolyPoly, + bool bPixelSnap, bool bLineDraw ) +{ + // short circuit if there is nothing to do + const int nPolyCount = rPolyPoly.count(); + if( nPolyCount <= 0 ) + { + return; + } + for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx ) + { + const ::basegfx::B2DPolygon rPolygon = rPolyPoly.getB2DPolygon( nPolyIdx ); + AddPolygonToPath( xPath, rPolygon, true, bPixelSnap, bLineDraw ); + } +} + +sal_Bool AquaSalGraphics::CreateFontSubset( const OUString& rToFile, + const PhysicalFontFace* pFontData, + sal_Int32* pGlyphIDs, sal_uInt8* pEncoding, + sal_Int32* pGlyphWidths, int nGlyphCount, + FontSubsetInfo& rInfo ) +{ + // TODO: move more of the functionality here into the generic subsetter code + + // prepare the requested file name for writing the font-subset file + OUString aSysPath; + if( osl_File_E_None != osl_getSystemPathFromFileURL( rToFile.pData, &aSysPath.pData ) ) + return sal_False; + const rtl_TextEncoding aThreadEncoding = osl_getThreadTextEncoding(); + const OString aToFile( OUStringToOString( aSysPath, aThreadEncoding ) ); + + // get the raw-bytes from the font to be subset + ByteVector aBuffer; + bool bCffOnly = false; + if( !GetRawFontData( pFontData, aBuffer, &bCffOnly ) ) + return sal_False; + + // handle CFF-subsetting + if( bCffOnly ) + { + // provide the raw-CFF data to the subsetter + ByteCount nCffLen = aBuffer.size(); + rInfo.LoadFont( FontSubsetInfo::CFF_FONT, &aBuffer[0], nCffLen ); + + // NOTE: assuming that all glyphids requested on Aqua are fully translated + + // make the subsetter provide the requested subset + FILE* pOutFile = fopen( aToFile.getStr(), "wb" ); +#ifdef __LP64__ + long *pLongGlyphIDs = (long*)alloca(nGlyphCount * sizeof(long)); + for (int i = 0; i < nGlyphCount; i++) + pLongGlyphIDs[i] = pGlyphIDs[i]; + bool bRC = rInfo.CreateFontSubset( FontSubsetInfo::TYPE1_PFB, pOutFile, NULL, + pLongGlyphIDs, pEncoding, nGlyphCount, pGlyphWidths ); +#else + bool bRC = rInfo.CreateFontSubset( FontSubsetInfo::TYPE1_PFB, pOutFile, NULL, + pGlyphIDs, pEncoding, nGlyphCount, pGlyphWidths ); +#endif + fclose( pOutFile ); + return bRC; + } + + // TODO: modernize psprint's horrible fontsubset C-API + // this probably only makes sense after the switch to another SCM + // that can preserve change history after file renames + + // prepare data for psprint's font subsetter + TrueTypeFont* pSftFont = NULL; + int nRC = ::OpenTTFontBuffer( (void*)&aBuffer[0], aBuffer.size(), 0, &pSftFont); + if( nRC != SF_OK ) + return sal_False; + + // get details about the subsetted font + TTGlobalFontInfo aTTInfo; + ::GetTTGlobalFontInfo( pSftFont, &aTTInfo ); + rInfo.m_nFontType = FontSubsetInfo::SFNT_TTF; + rInfo.m_aPSName = OUString( + aTTInfo.psname, std::strlen(aTTInfo.psname), RTL_TEXTENCODING_UTF8 ); + rInfo.m_aFontBBox = Rectangle( Point( aTTInfo.xMin, aTTInfo.yMin ), + Point( aTTInfo.xMax, aTTInfo.yMax ) ); + rInfo.m_nCapHeight = aTTInfo.yMax; // Well ... + rInfo.m_nAscent = aTTInfo.winAscent; + rInfo.m_nDescent = aTTInfo.winDescent; + // mac fonts usually do not have an OS2-table + // => get valid ascent/descent values from other tables + if( !rInfo.m_nAscent ) + rInfo.m_nAscent = +aTTInfo.typoAscender; + if( !rInfo.m_nAscent ) + rInfo.m_nAscent = +aTTInfo.ascender; + if( !rInfo.m_nDescent ) + rInfo.m_nDescent = +aTTInfo.typoDescender; + if( !rInfo.m_nDescent ) + rInfo.m_nDescent = -aTTInfo.descender; + + // subset glyphs and get their properties + // take care that subset fonts require the NotDef glyph in pos 0 + int nOrigCount = nGlyphCount; + sal_uInt16 aShortIDs[ 256 ]; + sal_uInt8 aTempEncs[ 256 ]; + + int nNotDef = -1; + for( int i = 0; i < nGlyphCount; ++i ) + { + aTempEncs[i] = pEncoding[i]; + sal_uInt32 nGlyphIdx = pGlyphIDs[i] & GF_IDXMASK; + if( pGlyphIDs[i] & GF_ISCHAR ) + { + bool bVertical = (pGlyphIDs[i] & GF_ROTMASK) != 0; + nGlyphIdx = ::MapChar( pSftFont, static_cast(nGlyphIdx), bVertical ); + if( nGlyphIdx == 0 && pFontData->IsSymbolFont() ) + { + // #i12824# emulate symbol aliasing U+FXXX <-> U+0XXX + nGlyphIdx = pGlyphIDs[i] & GF_IDXMASK; + nGlyphIdx = (nGlyphIdx & 0xF000) ? (nGlyphIdx & 0x00FF) : (nGlyphIdx | 0xF000 ); + nGlyphIdx = ::MapChar( pSftFont, static_cast(nGlyphIdx), bVertical ); + } + } + aShortIDs[i] = static_cast( nGlyphIdx ); + if( !nGlyphIdx ) + if( nNotDef < 0 ) + nNotDef = i; // first NotDef glyph found + } + + if( nNotDef != 0 ) + { + // add fake NotDef glyph if needed + if( nNotDef < 0 ) + nNotDef = nGlyphCount++; + + // NotDef glyph must be in pos 0 => swap glyphids + aShortIDs[ nNotDef ] = aShortIDs[0]; + aTempEncs[ nNotDef ] = aTempEncs[0]; + aShortIDs[0] = 0; + aTempEncs[0] = 0; + } + DBG_ASSERT( nGlyphCount < 257, "too many glyphs for subsetting" ); + + // TODO: where to get bVertical? + const bool bVertical = false; + + // fill the pGlyphWidths array + // while making sure that the NotDef glyph is at index==0 + TTSimpleGlyphMetrics* pGlyphMetrics = + ::GetTTSimpleGlyphMetrics( pSftFont, aShortIDs, nGlyphCount, bVertical ); + if( !pGlyphMetrics ) + return sal_False; + sal_uInt16 nNotDefAdv = pGlyphMetrics[0].adv; + pGlyphMetrics[0].adv = pGlyphMetrics[nNotDef].adv; + pGlyphMetrics[nNotDef].adv = nNotDefAdv; + for( int i = 0; i < nOrigCount; ++i ) + pGlyphWidths[i] = pGlyphMetrics[i].adv; + free( pGlyphMetrics ); + + // write subset into destination file + nRC = ::CreateTTFromTTGlyphs( pSftFont, aToFile.getStr(), aShortIDs, + aTempEncs, nGlyphCount, 0, NULL, 0 ); + ::CloseTTFont(pSftFont); + return (nRC == SF_OK); +} + +static inline void alignLinePoint( const SalPoint* i_pIn, float& o_fX, float& o_fY ) +{ + o_fX = static_cast(i_pIn->mnX ) + 0.5; + o_fY = static_cast(i_pIn->mnY ) + 0.5; +} + +void AquaSalGraphics::copyBits( const SalTwoRect& rPosAry, SalGraphics *pSrcGraphics ) +{ + if( !pSrcGraphics ) + { + pSrcGraphics = this; + } + //from unix salgdi2.cxx + //[FIXME] find a better way to prevent calc from crashing when width and height are negative + if( rPosAry.mnSrcWidth <= 0 + || rPosAry.mnSrcHeight <= 0 + || rPosAry.mnDestWidth <= 0 + || rPosAry.mnDestHeight <= 0 ) + { + return; + } + + // accelerate trivial operations + /*const*/ AquaSalGraphics* pSrc = static_cast(pSrcGraphics); + const bool bSameGraphics = (this == pSrc) || + (mbWindow && mpFrame && pSrc->mbWindow && (mpFrame == pSrc->mpFrame)); + if( bSameGraphics + && (rPosAry.mnSrcWidth == rPosAry.mnDestWidth) + && (rPosAry.mnSrcHeight == rPosAry.mnDestHeight)) + { + // short circuit if there is nothing to do + if( (rPosAry.mnSrcX == rPosAry.mnDestX) + && (rPosAry.mnSrcY == rPosAry.mnDestY)) + return; + // use copyArea() if source and destination context are identical + copyArea( rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnSrcX, rPosAry.mnSrcY, + rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, 0 ); + return; + } + + ApplyXorContext(); + pSrc->ApplyXorContext(); + + DBG_ASSERT( pSrc->mxLayer!=NULL, "AquaSalGraphics::copyBits() from non-layered graphics" ); + + const CGPoint aDstPoint = { static_cast(+rPosAry.mnDestX - rPosAry.mnSrcX), static_cast(rPosAry.mnDestY - rPosAry.mnSrcY) }; + if( (rPosAry.mnSrcWidth == rPosAry.mnDestWidth && + rPosAry.mnSrcHeight == rPosAry.mnDestHeight) && + (!mnBitmapDepth || (aDstPoint.x + pSrc->mnWidth) <= mnWidth) ) // workaround a Quartz crasher + { + // in XOR mode the drawing context is redirected to the XOR mask + // if source and target are identical then copyBits() paints onto the target context though + CGContextRef xCopyContext = mrContext; + if( mpXorEmulation && mpXorEmulation->IsEnabled() ) + { + if( pSrcGraphics == this ) + { + xCopyContext = mpXorEmulation->GetTargetContext(); + } + } + CGContextSaveGState( xCopyContext ); + const CGRect aDstRect = { { static_cast(rPosAry.mnDestX), static_cast(rPosAry.mnDestY) }, { static_cast(rPosAry.mnDestWidth), static_cast(rPosAry.mnDestHeight) } }; + CGContextClipToRect( xCopyContext, aDstRect ); + + // draw at new destination + // NOTE: flipped drawing gets disabled for this, else the subimage would be drawn upside down + if( pSrc->IsFlipped() ) + { + CGContextTranslateCTM( xCopyContext, 0, +mnHeight ); CGContextScaleCTM( xCopyContext, +1, -1 ); + } + // TODO: pSrc->size() != this->size() + ::CGContextDrawLayerAtPoint( xCopyContext, aDstPoint, pSrc->mxLayer ); + CGContextRestoreGState( xCopyContext ); + // mark the destination rectangle as updated + RefreshRect( aDstRect ); + } + else + { + SalBitmap* pBitmap = pSrc->getBitmap( rPosAry.mnSrcX, rPosAry.mnSrcY, + rPosAry.mnSrcWidth, rPosAry.mnSrcHeight ); + + if( pBitmap ) + { + SalTwoRect aPosAry( rPosAry ); + aPosAry.mnSrcX = 0; + aPosAry.mnSrcY = 0; + drawBitmap( aPosAry, *pBitmap ); + delete pBitmap; + } + } +} + +static void DrawPattern50( void*, CGContextRef rContext ) +{ + static const CGRect aRects[2] = { { {0,0}, { 2, 2 } }, { { 2, 2 }, { 2, 2 } } }; + CGContextAddRects( rContext, aRects, 2 ); + CGContextFillPath( rContext ); +} + +static void getBoundRect( sal_uLong nPoints, const SalPoint *pPtAry, long &rX, long& rY, long& rWidth, long& rHeight ) +{ + long nX1 = pPtAry->mnX; + long nX2 = nX1; + long nY1 = pPtAry->mnY; + long nY2 = nY1; + for( sal_uLong n = 1; n < nPoints; n++ ) + { + if( pPtAry[n].mnX < nX1 ) + { + nX1 = pPtAry[n].mnX; + } + else if( pPtAry[n].mnX > nX2 ) + { + nX2 = pPtAry[n].mnX; + } + if( pPtAry[n].mnY < nY1 ) + { + nY1 = pPtAry[n].mnY; + } + else if( pPtAry[n].mnY > nY2 ) + { + nY2 = pPtAry[n].mnY; + } + } + rX = nX1; + rY = nY1; + rWidth = nX2 - nX1 + 1; + rHeight = nY2 - nY1 + 1; +} + +static SalColor ImplGetROPSalColor( SalROPColor nROPColor ) +{ + SalColor nSalColor; + if ( nROPColor == SAL_ROP_0 ) + { + nSalColor = MAKE_SALCOLOR( 0, 0, 0 ); + } + else + { + nSalColor = MAKE_SALCOLOR( 255, 255, 255 ); + } + return nSalColor; +} + +// apply the XOR mask to the target context if active and dirty +void AquaSalGraphics::ApplyXorContext() +{ + if( !mpXorEmulation ) + { + return; + } + if( mpXorEmulation->UpdateTarget() ) + { + RefreshRect( 0, 0, mnWidth, mnHeight ); // TODO: refresh minimal changerect + } +} + +void AquaSalGraphics::copyArea( long nDstX, long nDstY,long nSrcX, long nSrcY, + long nSrcWidth, long nSrcHeight, sal_uInt16 /*nFlags*/ ) +{ + ApplyXorContext(); + + DBG_ASSERT( mxLayer!=NULL, "AquaSalGraphics::copyArea() for non-layered graphics" ); + + // in XOR mode the drawing context is redirected to the XOR mask + // copyArea() always works on the target context though + CGContextRef xCopyContext = mrContext; + if( mpXorEmulation && mpXorEmulation->IsEnabled() ) + { + xCopyContext = mpXorEmulation->GetTargetContext(); + } + // drawing a layer onto its own context causes trouble on OSX => copy it first + // TODO: is it possible to get rid of this unneeded copy more often? + // e.g. on OSX>=10.5 only this situation causes problems: + // mnBitmapDepth && (aDstPoint.x + pSrc->mnWidth) > mnWidth + CGLayerRef xSrcLayer = mxLayer; + // TODO: if( mnBitmapDepth > 0 ) + { + const CGSize aSrcSize = { static_cast(nSrcWidth), static_cast(nSrcHeight) }; + xSrcLayer = ::CGLayerCreateWithContext( xCopyContext, aSrcSize, NULL ); + const CGContextRef xSrcContext = CGLayerGetContext( xSrcLayer ); + CGPoint aSrcPoint = { static_cast(-nSrcX), static_cast(-nSrcY) }; + if( IsFlipped() ) + { + ::CGContextTranslateCTM( xSrcContext, 0, +nSrcHeight ); + ::CGContextScaleCTM( xSrcContext, +1, -1 ); + aSrcPoint.y = (nSrcY + nSrcHeight) - mnHeight; + } + ::CGContextDrawLayerAtPoint( xSrcContext, aSrcPoint, mxLayer ); + } + + // draw at new destination + const CGPoint aDstPoint = { static_cast(+nDstX), static_cast(+nDstY) }; + ::CGContextDrawLayerAtPoint( xCopyContext, aDstPoint, xSrcLayer ); + + // cleanup + if( xSrcLayer != mxLayer ) + { + CGLayerRelease( xSrcLayer ); + } + // mark the destination rectangle as updated + RefreshRect( nDstX, nDstY, nSrcWidth, nSrcHeight ); + +} + +void AquaSalGraphics::copyResolution( AquaSalGraphics& rGraphics ) +{ + if( !rGraphics.mnRealDPIY && rGraphics.mbWindow && rGraphics.mpFrame ) + { + rGraphics.initResolution( rGraphics.mpFrame->getNSWindow() ); + } + mnRealDPIX = rGraphics.mnRealDPIX; + mnRealDPIY = rGraphics.mnRealDPIY; + mfFakeDPIScale = rGraphics.mfFakeDPIScale; +} + +bool AquaSalGraphics::drawAlphaBitmap( const SalTwoRect& rTR, + const SalBitmap& rSrcBitmap, + const SalBitmap& rAlphaBmp ) +{ + // An image mask can't have a depth > 8 bits (should be 1 to 8 bits) + if( rAlphaBmp.GetBitCount() > 8 ) + { + return false; + } + // are these two tests really necessary? (see vcl/unx/source/gdi/salgdi2.cxx) + // horizontal/vertical mirroring not implemented yet + if( rTR.mnDestWidth < 0 || rTR.mnDestHeight < 0 ) + { + return false; + } + + const QuartzSalBitmap& rSrcSalBmp = static_cast(rSrcBitmap); + const QuartzSalBitmap& rMaskSalBmp = static_cast(rAlphaBmp); + CGImageRef xMaskedImage = rSrcSalBmp.CreateWithMask( rMaskSalBmp, rTR.mnSrcX, + rTR.mnSrcY, rTR.mnSrcWidth, + rTR.mnSrcHeight ); + if( !xMaskedImage ) + { + return false; + } + if ( CheckContext() ) + { + const CGRect aDstRect = { { static_cast(rTR.mnDestX), static_cast(rTR.mnDestY) }, { static_cast(rTR.mnDestWidth), static_cast(rTR.mnDestHeight) } }; + CGContextDrawImage( mrContext, aDstRect, xMaskedImage ); + RefreshRect( aDstRect ); + } + + CGImageRelease(xMaskedImage); + return true; +} + +bool AquaSalGraphics::drawTransformedBitmap( + const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX, const basegfx::B2DPoint& rY, + const SalBitmap& rSrcBitmap, const SalBitmap* pAlphaBmp ) +{ + if( !CheckContext() ) + return true; + + // get the Quartz image + CGImageRef xImage = NULL; + const Size aSize = rSrcBitmap.GetSize(); + const QuartzSalBitmap& rSrcSalBmp = static_cast(rSrcBitmap); + const QuartzSalBitmap* pMaskSalBmp = static_cast(pAlphaBmp); + if( !pMaskSalBmp) + xImage = rSrcSalBmp.CreateCroppedImage( 0, 0, (int)aSize.Width(), (int)aSize.Height() ); + else + xImage = rSrcSalBmp.CreateWithMask( *pMaskSalBmp, 0, 0, (int)aSize.Width(), (int)aSize.Height() ); + if( !xImage ) + return false; + + // setup the image transformation + // using the rNull,rX,rY points as destinations for the (0,0),(0,Width),(Height,0) source points + CGContextSaveGState( mrContext ); + const basegfx::B2DVector aXRel = rX - rNull; + const basegfx::B2DVector aYRel = rY - rNull; + const CGAffineTransform aCGMat = CGAffineTransformMake( + aXRel.getX()/aSize.Width(), aXRel.getY()/aSize.Width(), + aYRel.getX()/aSize.Height(), aYRel.getY()/aSize.Height(), + rNull.getX(), rNull.getY()); + CGContextConcatCTM( mrContext, aCGMat ); + + // draw the transformed image + const CGRect aSrcRect = {{0,0}, {static_cast(aSize.Width()), static_cast(aSize.Height())}}; + CGContextDrawImage( mrContext, aSrcRect, xImage ); + CGImageRelease( xImage ); + // restore the Quartz graphics state + CGContextRestoreGState(mrContext); + + // mark the destination as painted + const CGRect aDstRect = CGRectApplyAffineTransform( aSrcRect, aCGMat ); + RefreshRect( aDstRect ); + return true; +} + + +bool AquaSalGraphics::drawAlphaRect( long nX, long nY, long nWidth, + long nHeight, sal_uInt8 nTransparency ) +{ + if( !CheckContext() ) + { + return true; + } + // save the current state + CGContextSaveGState( mrContext ); + CGContextSetAlpha( mrContext, (100-nTransparency) * (1.0/100) ); + + CGRect aRect = { { static_cast(nX), static_cast(nY) }, { static_cast(nWidth-1), static_cast(nHeight-1) } }; + if( IsPenVisible() ) + { + aRect.origin.x += 0.5; + aRect.origin.y += 0.5; + } + + CGContextBeginPath( mrContext ); + CGContextAddRect( mrContext, aRect ); + CGContextDrawPath( mrContext, kCGPathFill ); + + // restore state + CGContextRestoreGState(mrContext); + RefreshRect( aRect ); + return true; +} + +void AquaSalGraphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap ) +{ + if( !CheckContext() ) + { + return; + } + const QuartzSalBitmap& rBitmap = static_cast(rSalBitmap); + CGImageRef xImage = rBitmap.CreateCroppedImage( (int)rPosAry.mnSrcX, (int)rPosAry.mnSrcY, + (int)rPosAry.mnSrcWidth, (int)rPosAry.mnSrcHeight ); + if( !xImage ) + { + return; + } + const CGRect aDstRect = { { static_cast(rPosAry.mnDestX), static_cast(rPosAry.mnDestY) }, + { static_cast(rPosAry.mnDestWidth), static_cast(rPosAry.mnDestHeight) } }; + CGContextDrawImage( mrContext, aDstRect, xImage ); + CGImageRelease( xImage ); + RefreshRect( aDstRect ); +} + +void AquaSalGraphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap,SalColor ) +{ + OSL_FAIL("not implemented for color masking!"); + drawBitmap( rPosAry, rSalBitmap ); +} + +void AquaSalGraphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap, + const SalBitmap& rTransparentBitmap ) +{ + if( !CheckContext() ) + { + return; + } + const QuartzSalBitmap& rBitmap = static_cast(rSalBitmap); + const QuartzSalBitmap& rMask = static_cast(rTransparentBitmap); + CGImageRef xMaskedImage( rBitmap.CreateWithMask( rMask, rPosAry.mnSrcX, rPosAry.mnSrcY, + rPosAry.mnSrcWidth, rPosAry.mnSrcHeight ) ); + if( !xMaskedImage ) + { + return; + } + const CGRect aDstRect = { { static_cast(rPosAry.mnDestX), static_cast(rPosAry.mnDestY)}, + { static_cast(rPosAry.mnDestWidth), static_cast(rPosAry.mnDestHeight) } }; + CGContextDrawImage( mrContext, aDstRect, xMaskedImage ); + CGImageRelease( xMaskedImage ); + RefreshRect( aDstRect ); +} + +sal_Bool AquaSalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight, + void* pEpsData, sal_uLong nByteCount ) +{ + // convert the raw data to an NSImageRef + NSData* xNSData = [NSData dataWithBytes:(void*)pEpsData length:(int)nByteCount]; + NSImageRep* xEpsImage = [NSEPSImageRep imageRepWithData: xNSData]; + if( !xEpsImage ) + { + return false; + } + // get the target context + if( !CheckContext() ) + { + return false; + } + // NOTE: flip drawing, else the nsimage would be drawn upside down + CGContextSaveGState( mrContext ); +// CGContextTranslateCTM( mrContext, 0, +mnHeight ); + CGContextScaleCTM( mrContext, +1, -1 ); + nY = /*mnHeight*/ - (nY + nHeight); + + // prepare the target context + NSGraphicsContext* pOrigNSCtx = [NSGraphicsContext currentContext]; + [pOrigNSCtx retain]; + + // create new context + NSGraphicsContext* pDrawNSCtx = [NSGraphicsContext graphicsContextWithGraphicsPort: mrContext flipped: IsFlipped()]; + // set it, setCurrentContext also releases the prviously set one + [NSGraphicsContext setCurrentContext: pDrawNSCtx]; + + // draw the EPS + const NSRect aDstRect = { { static_cast(nX), static_cast(nY) }, { static_cast(nWidth), static_cast(nHeight) } }; + const BOOL bOK = [xEpsImage drawInRect: aDstRect]; + + // restore the NSGraphicsContext + [NSGraphicsContext setCurrentContext: pOrigNSCtx]; + [pOrigNSCtx release]; // restore the original retain count + + CGContextRestoreGState( mrContext ); + // mark the destination rectangle as updated + RefreshRect( aDstRect ); + + return bOK; +} + +void AquaSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 ) +{ + if( nX1 == nX2 && nY1 == nY2 ) + { + // #i109453# platform independent code expects at least one pixel to be drawn + drawPixel( nX1, nY1 ); + return; + } + + if( !CheckContext() ) + { + return; + } + CGContextBeginPath( mrContext ); + CGContextMoveToPoint( mrContext, static_cast(nX1)+0.5, static_cast(nY1)+0.5 ); + CGContextAddLineToPoint( mrContext, static_cast(nX2)+0.5, static_cast(nY2)+0.5 ); + CGContextDrawPath( mrContext, kCGPathStroke ); + + Rectangle aRefreshRect( nX1, nY1, nX2, nY2 ); + // Is a call to RefreshRect( aRefreshRect ) missing here? +} + +void AquaSalGraphics::drawMask( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap, SalColor nMaskColor ) +{ + if( !CheckContext() ) + { + return; + } + const QuartzSalBitmap& rBitmap = static_cast(rSalBitmap); + CGImageRef xImage = rBitmap.CreateColorMask( rPosAry.mnSrcX, rPosAry.mnSrcY, + rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, + nMaskColor ); + if( !xImage ) + { + return; + } + const CGRect aDstRect = { { static_cast(rPosAry.mnDestX), static_cast(rPosAry.mnDestY) }, + { static_cast(rPosAry.mnDestWidth), static_cast(rPosAry.mnDestHeight) } }; + CGContextDrawImage( mrContext, aDstRect, xImage ); + CGImageRelease( xImage ); + RefreshRect( aDstRect ); +} + +void AquaSalGraphics::drawPixel( long nX, long nY ) +{ + // draw pixel with current line color + ImplDrawPixel( nX, nY, maLineColor ); +} + +void AquaSalGraphics::drawPixel( long nX, long nY, SalColor nSalColor ) +{ + const RGBAColor aPixelColor( nSalColor ); + ImplDrawPixel( nX, nY, aPixelColor ); +} + +bool AquaSalGraphics::drawPolyLine( + const ::basegfx::B2DPolygon& rPolyLine, + double fTransparency, + const ::basegfx::B2DVector& rLineWidths, + basegfx::B2DLineJoin eLineJoin, + com::sun::star::drawing::LineCap eLineCap) +{ + // short circuit if there is nothing to do + const int nPointCount = rPolyLine.count(); + if( nPointCount <= 0 ) + { + return true; + } + // reject requests that cannot be handled yet + if( rLineWidths.getX() != rLineWidths.getY() ) + { + return false; + } + // #i101491# Aqua does not support B2DLINEJOIN_NONE; return false to use + // the fallback (own geometry preparation) + // #i104886# linejoin-mode and thus the above only applies to "fat" lines + if( (basegfx::B2DLINEJOIN_NONE == eLineJoin) && + (rLineWidths.getX() > 1.3) ) + { + return false; + } + // setup line attributes + CGLineJoin aCGLineJoin = kCGLineJoinMiter; + switch( eLineJoin ) + { + case ::basegfx::B2DLINEJOIN_NONE: aCGLineJoin = /*TODO?*/kCGLineJoinMiter; break; + case ::basegfx::B2DLINEJOIN_MIDDLE: aCGLineJoin = /*TODO?*/kCGLineJoinMiter; break; + case ::basegfx::B2DLINEJOIN_BEVEL: aCGLineJoin = kCGLineJoinBevel; break; + case ::basegfx::B2DLINEJOIN_MITER: aCGLineJoin = kCGLineJoinMiter; break; + case ::basegfx::B2DLINEJOIN_ROUND: aCGLineJoin = kCGLineJoinRound; break; + } + + // setup cap attribute + CGLineCap aCGLineCap(kCGLineCapButt); + + switch(eLineCap) + { + default: // com::sun::star::drawing::LineCap_BUTT: + { + aCGLineCap = kCGLineCapButt; + break; + } + case com::sun::star::drawing::LineCap_ROUND: + { + aCGLineCap = kCGLineCapRound; + break; + } + case com::sun::star::drawing::LineCap_SQUARE: + { + aCGLineCap = kCGLineCapSquare; + break; + } + } + + // setup poly-polygon path + CGMutablePathRef xPath = CGPathCreateMutable(); + AddPolygonToPath( xPath, rPolyLine, rPolyLine.isClosed(), !getAntiAliasB2DDraw(), true ); + + const CGRect aRefreshRect = CGPathGetBoundingBox( xPath ); + // #i97317# workaround for Quartz having problems with drawing small polygons + if( ! ((aRefreshRect.size.width <= 0.125) && (aRefreshRect.size.height <= 0.125)) ) + { + // use the path to prepare the graphics context + CGContextSaveGState( mrContext ); + CGContextAddPath( mrContext, xPath ); + // draw path with antialiased line + CGContextSetShouldAntialias( mrContext, true ); + CGContextSetAlpha( mrContext, 1.0 - fTransparency ); + CGContextSetLineJoin( mrContext, aCGLineJoin ); + CGContextSetLineCap( mrContext, aCGLineCap ); + CGContextSetLineWidth( mrContext, rLineWidths.getX() ); + CGContextDrawPath( mrContext, kCGPathStroke ); + CGContextRestoreGState( mrContext ); + + // mark modified rectangle as updated + RefreshRect( aRefreshRect ); + } + + CGPathRelease( xPath ); + + return true; +} + +sal_Bool AquaSalGraphics::drawPolyLineBezier( sal_uLong, const SalPoint*, const sal_uInt8* ) +{ + return sal_False; +} + +bool AquaSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly, + double fTransparency ) +{ + // short circuit if there is nothing to do + const int nPolyCount = rPolyPoly.count(); + if( nPolyCount <= 0 ) + { + return true; + } + // ignore invisible polygons + if( (fTransparency >= 1.0) || (fTransparency < 0) ) + { + return true; + } + // setup poly-polygon path + CGMutablePathRef xPath = CGPathCreateMutable(); + for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx ) + { + const ::basegfx::B2DPolygon rPolygon = rPolyPoly.getB2DPolygon( nPolyIdx ); + AddPolygonToPath( xPath, rPolygon, true, !getAntiAliasB2DDraw(), IsPenVisible() ); + } + + const CGRect aRefreshRect = CGPathGetBoundingBox( xPath ); + // #i97317# workaround for Quartz having problems with drawing small polygons + if( ! ((aRefreshRect.size.width <= 0.125) && (aRefreshRect.size.height <= 0.125)) ) + { + // use the path to prepare the graphics context + CGContextSaveGState( mrContext ); + CGContextBeginPath( mrContext ); + CGContextAddPath( mrContext, xPath ); + + // draw path with antialiased polygon + CGContextSetShouldAntialias( mrContext, true ); + CGContextSetAlpha( mrContext, 1.0 - fTransparency ); + CGContextDrawPath( mrContext, kCGPathEOFillStroke ); + CGContextRestoreGState( mrContext ); + + // mark modified rectangle as updated + RefreshRect( aRefreshRect ); + } + + CGPathRelease( xPath ); + + return true; +} + +void AquaSalGraphics::drawPolyPolygon( sal_uInt32 nPolyCount, const sal_uInt32 *pPoints, PCONSTSALPOINT *ppPtAry ) +{ + if( nPolyCount <= 0 ) + return; + if( !CheckContext() ) + return; + + // find bound rect + long leftX = 0, topY = 0, maxWidth = 0, maxHeight = 0; + getBoundRect( pPoints[0], ppPtAry[0], leftX, topY, maxWidth, maxHeight ); + for( sal_uLong n = 1; n < nPolyCount; n++ ) + { + long nX = leftX, nY = topY, nW = maxWidth, nH = maxHeight; + getBoundRect( pPoints[n], ppPtAry[n], nX, nY, nW, nH ); + if( nX < leftX ) + { + maxWidth += leftX - nX; + leftX = nX; + } + if( nY < topY ) + { + maxHeight += topY - nY; + topY = nY; + } + if( nX + nW > leftX + maxWidth ) + { + maxWidth = nX + nW - leftX; + } + if( nY + nH > topY + maxHeight ) + { + maxHeight = nY + nH - topY; + } + } + + // prepare drawing mode + CGPathDrawingMode eMode; + if( IsBrushVisible() && IsPenVisible() ) + { + eMode = kCGPathEOFillStroke; + } + else if( IsPenVisible() ) + { + eMode = kCGPathStroke; + } + else if( IsBrushVisible() ) + { + eMode = kCGPathEOFill; + } + else + { + return; + } + // convert to CGPath + CGContextBeginPath( mrContext ); + if( IsPenVisible() ) + { + for( sal_uLong nPoly = 0; nPoly < nPolyCount; nPoly++ ) + { + const sal_uLong nPoints = pPoints[nPoly]; + if( nPoints > 1 ) + { + const SalPoint *pPtAry = ppPtAry[nPoly]; + float fX, fY; + alignLinePoint( pPtAry, fX, fY ); + CGContextMoveToPoint( mrContext, fX, fY ); + pPtAry++; + for( sal_uLong nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++ ) + { + alignLinePoint( pPtAry, fX, fY ); + CGContextAddLineToPoint( mrContext, fX, fY ); + } + CGContextClosePath(mrContext); + } + } + } + else + { + for( sal_uLong nPoly = 0; nPoly < nPolyCount; nPoly++ ) + { + const sal_uLong nPoints = pPoints[nPoly]; + if( nPoints > 1 ) + { + const SalPoint *pPtAry = ppPtAry[nPoly]; + CGContextMoveToPoint( mrContext, pPtAry->mnX, pPtAry->mnY ); + pPtAry++; + for( sal_uLong nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++ ) + { + CGContextAddLineToPoint( mrContext, pPtAry->mnX, pPtAry->mnY ); + } + CGContextClosePath(mrContext); + } + } + } + + CGContextDrawPath( mrContext, eMode ); + + RefreshRect( leftX, topY, maxWidth, maxHeight ); +} + +void AquaSalGraphics::drawPolygon( sal_uLong nPoints, const SalPoint *pPtAry ) +{ + if( nPoints <= 1 ) + return; + if( !CheckContext() ) + return; + + long nX = 0, nY = 0, nWidth = 0, nHeight = 0; + getBoundRect( nPoints, pPtAry, nX, nY, nWidth, nHeight ); + + CGPathDrawingMode eMode; + if( IsBrushVisible() && IsPenVisible() ) + { + eMode = kCGPathEOFillStroke; + } + else if( IsPenVisible() ) + { + eMode = kCGPathStroke; + } + else if( IsBrushVisible() ) + { + eMode = kCGPathEOFill; + } + else + { + return; + } + CGContextBeginPath( mrContext ); + + if( IsPenVisible() ) + { + float fX, fY; + alignLinePoint( pPtAry, fX, fY ); + CGContextMoveToPoint( mrContext, fX, fY ); + pPtAry++; + for( sal_uLong nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++ ) + { + alignLinePoint( pPtAry, fX, fY ); + CGContextAddLineToPoint( mrContext, fX, fY ); + } + } + else + { + CGContextMoveToPoint( mrContext, pPtAry->mnX, pPtAry->mnY ); + pPtAry++; + for( sal_uLong nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++ ) + { + CGContextAddLineToPoint( mrContext, pPtAry->mnX, pPtAry->mnY ); + } + } + + CGContextClosePath( mrContext ); + CGContextDrawPath( mrContext, eMode ); + RefreshRect( nX, nY, nWidth, nHeight ); +} + +sal_Bool AquaSalGraphics::drawPolygonBezier( sal_uLong, const SalPoint*, const sal_uInt8* ) +{ + return sal_False; +} + +sal_Bool AquaSalGraphics::drawPolyPolygonBezier( sal_uInt32, const sal_uInt32*, + const SalPoint* const*, const sal_uInt8* const* ) +{ + return sal_False; +} + +void AquaSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight ) +{ + if( !CheckContext() ) + { + return; + } + CGRect aRect( CGRectMake(nX, nY, nWidth, nHeight) ); + if( IsPenVisible() ) + { + aRect.origin.x += 0.5; + aRect.origin.y += 0.5; + aRect.size.width -= 1; + aRect.size.height -= 1; + } + + if( IsBrushVisible() ) + { + CGContextFillRect( mrContext, aRect ); + } + if( IsPenVisible() ) + { + CGContextStrokeRect( mrContext, aRect ); + } + RefreshRect( nX, nY, nWidth, nHeight ); +} + + +void AquaSalGraphics::drawPolyLine( sal_uLong nPoints, const SalPoint *pPtAry ) +{ + if( nPoints < 1 ) + { + return; + } + if( !CheckContext() ) + { + return; + } + + long nX = 0, nY = 0, nWidth = 0, nHeight = 0; + getBoundRect( nPoints, pPtAry, nX, nY, nWidth, nHeight ); + + float fX, fY; + CGContextBeginPath( mrContext ); + alignLinePoint( pPtAry, fX, fY ); + CGContextMoveToPoint( mrContext, fX, fY ); + pPtAry++; + for( sal_uLong nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++ ) + { + alignLinePoint( pPtAry, fX, fY ); + CGContextAddLineToPoint( mrContext, fX, fY ); + } + CGContextDrawPath( mrContext, kCGPathStroke ); + + RefreshRect( nX, nY, nWidth, nHeight ); +} + +sal_uInt16 AquaSalGraphics::GetBitCount() const +{ + sal_uInt16 nBits = mnBitmapDepth ? mnBitmapDepth : 32;//24; + return nBits; +} + +SalBitmap* AquaSalGraphics::getBitmap( long nX, long nY, long nDX, long nDY ) +{ + DBG_ASSERT( mxLayer, "AquaSalGraphics::getBitmap() with no layer" ); + + ApplyXorContext(); + + QuartzSalBitmap* pBitmap = new QuartzSalBitmap; + if( !pBitmap->Create( mxLayer, mnBitmapDepth, nX, nY, nDX, nDY, !mbWindow ) ) + { + delete pBitmap; + pBitmap = NULL; + } + + return pBitmap; +} + +SystemGraphicsData AquaSalGraphics::GetGraphicsData() const +{ + SystemGraphicsData aRes; + aRes.nSize = sizeof(aRes); + aRes.rCGContext = mrContext; + return aRes; +} + +long AquaSalGraphics::GetGraphicsWidth() const +{ + long w = 0; + if( mrContext && (mbWindow || mbVirDev) ) + { + w = mnWidth; + } + + if( w == 0 ) + { + if( mbWindow && mpFrame ) + { + w = mpFrame->maGeometry.nWidth; + } + } + return w; +} + +SalColor AquaSalGraphics::getPixel( long nX, long nY ) +{ + // return default value on printers or when out of bounds + if( !mxLayer || (nX < 0) || (nX >= mnWidth) || + (nY < 0) || (nY >= mnHeight)) + { + return COL_BLACK; + } + // prepare creation of matching a CGBitmapContext + CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace; + CGBitmapInfo aCGBmpInfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big; +#if defined OSL_BIGENDIAN + struct{ unsigned char b, g, r, a; } aPixel; +#else + struct{ unsigned char a, r, g, b; } aPixel; +#endif + + // create a one-pixel bitmap context + // TODO: is it worth to cache it? + CGContextRef xOnePixelContext = + ::CGBitmapContextCreate( &aPixel, 1, 1, 8, sizeof(aPixel), + aCGColorSpace, aCGBmpInfo ); + + // update this graphics layer + ApplyXorContext(); + + // copy the requested pixel into the bitmap context + if( IsFlipped() ) + { + nY = mnHeight - nY; + } + const CGPoint aCGPoint = { static_cast(-nX), static_cast(-nY) }; + CGContextDrawLayerAtPoint( xOnePixelContext, aCGPoint, mxLayer ); + CGContextRelease( xOnePixelContext ); + + SalColor nSalColor = MAKE_SALCOLOR( aPixel.r, aPixel.g, aPixel.b ); + return nSalColor; +} + +void AquaSalGraphics::GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY ) +{ + if( !mnRealDPIY ) + { + initResolution( (mbWindow && mpFrame) ? mpFrame->getNSWindow() : nil ); + } + + rDPIX = static_cast(mfFakeDPIScale * mnRealDPIX); + rDPIY = static_cast(mfFakeDPIScale * mnRealDPIY); +} + +void AquaSalGraphics::ImplDrawPixel( long nX, long nY, const RGBAColor& rColor ) +{ + if( !CheckContext() ) + { + return; + } + // overwrite the fill color + CGContextSetFillColor( mrContext, rColor.AsArray() ); + // draw 1x1 rect, there is no pixel drawing in Quartz + CGRect aDstRect = { { static_cast(nX), static_cast(nY) }, {1,1}}; + CGContextFillRect( mrContext, aDstRect ); + RefreshRect( aDstRect ); + // reset the fill color + CGContextSetFillColor( mrContext, maFillColor.AsArray() ); +} + +void AquaSalGraphics::initResolution( NSWindow* ) +{ + // #i100617# read DPI only once; there is some kind of weird caching going on + // if the main screen changes + // FIXME: this is really unfortunate and needs to be investigated + + SalData* pSalData = GetSalData(); + if( pSalData->mnDPIX == 0 || pSalData->mnDPIY == 0 ) + { + NSScreen* pScreen = nil; + + /* #i91301# + many woes went into the try to have different resolutions + on different screens. The result of these trials is that OOo is not ready + for that yet, vcl and applications would need to be adapted. + + Unfortunately this is not possible in the 3.0 timeframe. + So let's stay with one resolution for all Windows and VirtualDevices + which is the resolution of the main screen + + This of course also means that measurements are exact only on the main screen. + For activating different resolutions again just comment out the two lines below. + + if( pWin ) + pScreen = [pWin screen]; + */ + if( pScreen == nil ) + { + NSArray* pScreens = [NSScreen screens]; + if( pScreens ) + pScreen = [pScreens objectAtIndex: 0]; + } + + mnRealDPIX = mnRealDPIY = 96; + if( pScreen ) + { + NSDictionary* pDev = [pScreen deviceDescription]; + if( pDev ) + { + NSNumber* pVal = [pDev objectForKey: @"NSScreenNumber"]; + if( pVal ) + { + // FIXME: casting a long to CGDirectDisplayID is evil, but + // Apple suggest to do it this way + const CGDirectDisplayID nDisplayID = (CGDirectDisplayID)[pVal longValue]; + const CGSize aSize = CGDisplayScreenSize( nDisplayID ); // => result is in millimeters + mnRealDPIX = static_cast((CGDisplayPixelsWide( nDisplayID ) * 25.4) / aSize.width); + mnRealDPIY = static_cast((CGDisplayPixelsHigh( nDisplayID ) * 25.4) / aSize.height); + } + else + { + OSL_FAIL( "no resolution found in device description" ); + } + } + else + { + OSL_FAIL( "no device description" ); + } + } + else + { + OSL_FAIL( "no screen found" ); + } + + // #i107076# maintaining size-WYSIWYG-ness causes many problems for + // low-DPI, high-DPI or for mis-reporting devices + // => it is better to limit the calculation result then + static const int nMinDPI = 72; + if( (mnRealDPIX < nMinDPI) || (mnRealDPIY < nMinDPI) ) + { + mnRealDPIX = mnRealDPIY = nMinDPI; + } + static const int nMaxDPI = 200; + if( (mnRealDPIX > nMaxDPI) || (mnRealDPIY > nMaxDPI) ) + { + mnRealDPIX = mnRealDPIY = nMaxDPI; + } + // for OSX any anisotropy reported for the display resolution is best ignored (e.g. TripleHead2Go) + mnRealDPIX = mnRealDPIY = (mnRealDPIX + mnRealDPIY + 1) / 2; + + pSalData->mnDPIX = mnRealDPIX; + pSalData->mnDPIY = mnRealDPIY; + } + else + { + mnRealDPIX = pSalData->mnDPIX; + mnRealDPIY = pSalData->mnDPIY; + } + + mfFakeDPIScale = 1.0; +} + +void AquaSalGraphics::invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags ) +{ + if ( CheckContext() ) + { + CGRect aCGRect = CGRectMake( nX, nY, nWidth, nHeight); + CGContextSaveGState(mrContext); + + if ( nFlags & SAL_INVERT_TRACKFRAME ) + { + const CGFloat dashLengths[2] = { 4.0, 4.0 }; // for drawing dashed line + CGContextSetBlendMode( mrContext, kCGBlendModeDifference ); + CGContextSetRGBStrokeColor ( mrContext, 1.0, 1.0, 1.0, 1.0 ); + CGContextSetLineDash ( mrContext, 0, dashLengths, 2 ); + CGContextSetLineWidth( mrContext, 2.0); + CGContextStrokeRect ( mrContext, aCGRect ); + } + else if ( nFlags & SAL_INVERT_50 ) + { + //CGContextSetAllowsAntialiasing( mrContext, false ); + CGContextSetBlendMode(mrContext, kCGBlendModeDifference); + CGContextAddRect( mrContext, aCGRect ); + Pattern50Fill(); + } + else // just invert + { + CGContextSetBlendMode(mrContext, kCGBlendModeDifference); + CGContextSetRGBFillColor ( mrContext,1.0, 1.0, 1.0 , 1.0 ); + CGContextFillRect ( mrContext, aCGRect ); + } + CGContextRestoreGState( mrContext); + RefreshRect( aCGRect ); + } +} + +void AquaSalGraphics::invert( sal_uLong nPoints, const SalPoint* pPtAry, SalInvert nSalFlags ) +{ + CGPoint* CGpoints ; + if ( CheckContext() ) + { + CGContextSaveGState(mrContext); + CGpoints = makeCGptArray(nPoints,pPtAry); + CGContextAddLines ( mrContext, CGpoints, nPoints ); + if ( nSalFlags & SAL_INVERT_TRACKFRAME ) + { + const CGFloat dashLengths[2] = { 4.0, 4.0 }; // for drawing dashed line + CGContextSetBlendMode( mrContext, kCGBlendModeDifference ); + CGContextSetRGBStrokeColor ( mrContext, 1.0, 1.0, 1.0, 1.0 ); + CGContextSetLineDash ( mrContext, 0, dashLengths, 2 ); + CGContextSetLineWidth( mrContext, 2.0); + CGContextStrokePath ( mrContext ); + } + else if ( nSalFlags & SAL_INVERT_50 ) + { + CGContextSetBlendMode(mrContext, kCGBlendModeDifference); + Pattern50Fill(); + } + else // just invert + { + CGContextSetBlendMode( mrContext, kCGBlendModeDifference ); + CGContextSetRGBFillColor( mrContext, 1.0, 1.0, 1.0, 1.0 ); + CGContextFillPath( mrContext ); + } + const CGRect aRefreshRect = CGContextGetClipBoundingBox(mrContext); + CGContextRestoreGState( mrContext); + delete [] CGpoints; + RefreshRect( aRefreshRect ); + } +} + +void AquaSalGraphics::Pattern50Fill() +{ + static const CGFloat aFillCol[4] = { 1,1,1,1 }; + static const CGPatternCallbacks aCallback = { 0, &DrawPattern50, NULL }; + if( ! GetSalData()->mxP50Space ) + { + GetSalData()->mxP50Space = CGColorSpaceCreatePattern( GetSalData()->mxRGBSpace ); + } + if( ! GetSalData()->mxP50Pattern ) + { + GetSalData()->mxP50Pattern = CGPatternCreate( NULL, CGRectMake( 0, 0, 4, 4 ), + CGAffineTransformIdentity, 4, 4, + kCGPatternTilingConstantSpacing, + false, &aCallback ); + } + CGContextSetFillColorSpace( mrContext, GetSalData()->mxP50Space ); + CGContextSetFillPattern( mrContext, GetSalData()->mxP50Pattern, aFillCol ); + CGContextFillPath( mrContext ); +} + + +void AquaSalGraphics::ResetClipRegion() +{ + // release old path and indicate no clipping + if( mxClipPath ) + { + CGPathRelease( mxClipPath ); + mxClipPath = NULL; + } + if( CheckContext() ) + { + SetState(); + } +} + +void AquaSalGraphics::SetLineColor() +{ + maLineColor.SetAlpha( 0.0 ); // transparent + if( CheckContext() ) + { + CGContextSetStrokeColor( mrContext, maLineColor.AsArray() ); + } +} + +void AquaSalGraphics::SetLineColor( SalColor nSalColor ) +{ + maLineColor = RGBAColor( nSalColor ); + if( CheckContext() ) + { + CGContextSetStrokeColor( mrContext, maLineColor.AsArray() ); + } +} + +void AquaSalGraphics::SetFillColor() +{ + maFillColor.SetAlpha( 0.0 ); // transparent + if( CheckContext() ) + { + CGContextSetFillColor( mrContext, maFillColor.AsArray() ); + } +} + +void AquaSalGraphics::SetFillColor( SalColor nSalColor ) +{ + maFillColor = RGBAColor( nSalColor ); + if( CheckContext() ) + { + CGContextSetFillColor( mrContext, maFillColor.AsArray() ); + } +} + +bool AquaSalGraphics::supportsOperation( OutDevSupportType eType ) const +{ + bool bRet = false; + switch( eType ) + { + case OutDevSupport_TransparentRect: + case OutDevSupport_B2DClip: + case OutDevSupport_B2DDraw: + bRet = true; + break; + default: break; + } + return bRet; +} + +bool AquaSalGraphics::setClipRegion( const Region& i_rClip ) +{ + // release old clip path + if( mxClipPath ) + { + CGPathRelease( mxClipPath ); + mxClipPath = NULL; + } + mxClipPath = CGPathCreateMutable(); + + // set current path, either as polypolgon or sequence of rectangles + if(i_rClip.HasPolyPolygonOrB2DPolyPolygon()) + { + const basegfx::B2DPolyPolygon aClip(i_rClip.GetAsB2DPolyPolygon()); + + AddPolyPolygonToPath( mxClipPath, aClip, !getAntiAliasB2DDraw(), false ); + } + else + { + RectangleVector aRectangles; + i_rClip.GetRegionRectangles(aRectangles); + + for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++) + { + const long nW(aRectIter->Right() - aRectIter->Left() + 1); // uses +1 logic in original + + if(nW) + { + const long nH(aRectIter->Bottom() - aRectIter->Top() + 1); // uses +1 logic in original + + if(nH) + { + CGRect aRect = {{ (CGFloat) aRectIter->Left(), (CGFloat) aRectIter->Top() }, { (CGFloat) nW, (CGFloat) nH }}; + CGPathAddRect( mxClipPath, NULL, aRect ); + } + } + } + } + // set the current path as clip region + if( CheckContext() ) + { + SetState(); + } + return true; +} + +void AquaSalGraphics::SetROPFillColor( SalROPColor nROPColor ) +{ + if( ! mbPrinter ) + SetFillColor( ImplGetROPSalColor( nROPColor ) ); +} + +void AquaSalGraphics::SetROPLineColor( SalROPColor nROPColor ) +{ + if( ! mbPrinter ) + SetLineColor( ImplGetROPSalColor( nROPColor ) ); +} + +void AquaSalGraphics::SetXORMode( bool bSet, bool bInvertOnly ) +{ + // return early if XOR mode remains unchanged + if( mbPrinter ) + { + return; + } + if( ! bSet && mnXorMode == 2 ) + { + CGContextSetBlendMode( mrContext, kCGBlendModeNormal ); + mnXorMode = 0; + return; + } + else if( bSet && bInvertOnly && mnXorMode == 0) + { + CGContextSetBlendMode( mrContext, kCGBlendModeDifference ); + mnXorMode = 2; + return; + } + + if( (mpXorEmulation == NULL) && !bSet ) + { + return; + } + if( (mpXorEmulation != NULL) && (bSet == mpXorEmulation->IsEnabled()) ) + { + return; + } + if( !CheckContext() ) + { + return; + } + // prepare XOR emulation + if( !mpXorEmulation ) + { + mpXorEmulation = new XorEmulation(); + mpXorEmulation->SetTarget( mnWidth, mnHeight, mnBitmapDepth, mrContext, mxLayer ); + } + + // change the XOR mode + if( bSet ) + { + mpXorEmulation->Enable(); + mrContext = mpXorEmulation->GetMaskContext(); + mnXorMode = 1; + } + else + { + mpXorEmulation->UpdateTarget(); + mpXorEmulation->Disable(); + mrContext = mpXorEmulation->GetTargetContext(); + mnXorMode = 0; + } +} + +void AquaSalGraphics::updateResolution() +{ + DBG_ASSERT( mbWindow, "updateResolution on inappropriate graphics" ); + + initResolution( (mbWindow && mpFrame) ? mpFrame->getNSWindow() : nil ); +} + + +// ----------------------------------------------------------- + +XorEmulation::XorEmulation() +: m_xTargetLayer( NULL ) +, m_xTargetContext( NULL ) +, m_xMaskContext( NULL ) +, m_xTempContext( NULL ) +, m_pMaskBuffer( NULL ) +, m_pTempBuffer( NULL ) +, m_nBufferLongs( 0 ) +, m_bIsEnabled( false ) +{} + +XorEmulation::~XorEmulation() +{ + Disable(); + SetTarget( 0, 0, 0, NULL, NULL ); +} + +void XorEmulation::SetTarget( int nWidth, int nHeight, int nTargetDepth, + CGContextRef xTargetContext, CGLayerRef xTargetLayer ) +{ + // prepare to replace old mask+temp context + if( m_xMaskContext ) + { + // cleanup the mask context + CGContextRelease( m_xMaskContext ); + delete[] m_pMaskBuffer; + m_xMaskContext = NULL; + m_pMaskBuffer = NULL; + + // cleanup the temp context if needed + if( m_xTempContext ) + { + CGContextRelease( m_xTempContext ); + delete[] m_pTempBuffer; + m_xTempContext = NULL; + m_pTempBuffer = NULL; + } + } + + // return early if there is nothing more to do + if( !xTargetContext ) + { + return; + } + // retarget drawing operations to the XOR mask + m_xTargetLayer = xTargetLayer; + m_xTargetContext = xTargetContext; + + // prepare creation of matching CGBitmaps + CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace; + CGBitmapInfo aCGBmpInfo = kCGImageAlphaNoneSkipFirst; + int nBitDepth = nTargetDepth; + if( !nBitDepth ) + { + nBitDepth = 32; + } + int nBytesPerRow = (nBitDepth == 16) ? 2 : 4; + const size_t nBitsPerComponent = (nBitDepth == 16) ? 5 : 8; + if( nBitDepth <= 8 ) + { + aCGColorSpace = GetSalData()->mxGraySpace; + aCGBmpInfo = kCGImageAlphaNone; + nBytesPerRow = 1; + } + nBytesPerRow *= nWidth; + m_nBufferLongs = (nHeight * nBytesPerRow + sizeof(sal_uLong)-1) / sizeof(sal_uLong); + + // create a XorMask context + m_pMaskBuffer = new sal_uLong[ m_nBufferLongs ]; + m_xMaskContext = ::CGBitmapContextCreate( m_pMaskBuffer, + nWidth, nHeight, + nBitsPerComponent, nBytesPerRow, + aCGColorSpace, aCGBmpInfo ); + // reset the XOR mask to black + memset( m_pMaskBuffer, 0, m_nBufferLongs * sizeof(sal_uLong) ); + + // a bitmap context will be needed for manual XORing + // create one unless the target context is a bitmap context + if( nTargetDepth ) + m_pTempBuffer = (sal_uLong*)CGBitmapContextGetData( m_xTargetContext ); + if( !m_pTempBuffer ) + { + // create a bitmap context matching to the target context + m_pTempBuffer = new sal_uLong[ m_nBufferLongs ]; + m_xTempContext = ::CGBitmapContextCreate( m_pTempBuffer, + nWidth, nHeight, + nBitsPerComponent, nBytesPerRow, + aCGColorSpace, aCGBmpInfo ); + } + + // initialize XOR mask context for drawing + CGContextSetFillColorSpace( m_xMaskContext, aCGColorSpace ); + CGContextSetStrokeColorSpace( m_xMaskContext, aCGColorSpace ); + CGContextSetShouldAntialias( m_xMaskContext, false ); + + // improve the XorMask's XOR emulation a litte + // NOTE: currently only enabled for monochrome contexts + if( aCGColorSpace == GetSalData()->mxGraySpace ) + { + CGContextSetBlendMode( m_xMaskContext, kCGBlendModeDifference ); + } + // intialize the transformation matrix to the drawing target + const CGAffineTransform aCTM = CGContextGetCTM( xTargetContext ); + CGContextConcatCTM( m_xMaskContext, aCTM ); + if( m_xTempContext ) + { + CGContextConcatCTM( m_xTempContext, aCTM ); + } + // initialize the default XorMask graphics state + CGContextSaveGState( m_xMaskContext ); +} + +bool XorEmulation::UpdateTarget() +{ + if( !IsEnabled() ) + { + return false; + } + // update the temp bitmap buffer if needed + if( m_xTempContext ) + { + CGContextDrawLayerAtPoint( m_xTempContext, CGPointZero, m_xTargetLayer ); + } + // do a manual XOR with the XorMask + // this approach suffices for simple color manipulations + // and also the complex-clipping-XOR-trick used in metafiles + const sal_uLong* pSrc = m_pMaskBuffer; + sal_uLong* pDst = m_pTempBuffer; + for( int i = m_nBufferLongs; --i >= 0;) + { + *(pDst++) ^= *(pSrc++); + } + // write back the XOR results to the target context + if( m_xTempContext ) + { + CGImageRef xXorImage = CGBitmapContextCreateImage( m_xTempContext ); + const int nWidth = (int)CGImageGetWidth( xXorImage ); + const int nHeight = (int)CGImageGetHeight( xXorImage ); + // TODO: update minimal changerect + const CGRect aFullRect = { {0, 0}, { static_cast(nWidth), static_cast(nHeight) } }; + CGContextDrawImage( m_xTargetContext, aFullRect, xXorImage ); + CGImageRelease( xXorImage ); + } + + // reset the XorMask to black again + // TODO: not needed for last update + memset( m_pMaskBuffer, 0, m_nBufferLongs * sizeof(sal_uLong) ); + + // TODO: return FALSE if target was not changed + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/quartz/salgdiutils.cxx b/vcl/quartz/salgdiutils.cxx new file mode 100644 index 000000000000..f31b09a40d12 --- /dev/null +++ b/vcl/quartz/salgdiutils.cxx @@ -0,0 +1,299 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "basebmp/scanlineformats.hxx" +#include "basebmp/color.hxx" + +#include "basegfx/range/b2drectangle.hxx" +#include "basegfx/range/b2irange.hxx" +#include "basegfx/vector/b2ivector.hxx" +#include "basegfx/polygon/b2dpolygon.hxx" +#include "basegfx/polygon/b2dpolygontools.hxx" + +#include "vcl/svapp.hxx" + +#include "quartz/salgdi.h" +#include "osx/salframe.h" +#include "osx/saldata.hxx" + +// ---------------------------------------------------------------------- + +void AquaSalGraphics::SetWindowGraphics( AquaSalFrame* pFrame ) +{ + mpFrame = pFrame; + + mbWindow = true; + mbPrinter = false; + mbVirDev = false; +} + +void AquaSalGraphics::SetPrinterGraphics( CGContextRef xContext, long nDPIX, long nDPIY, double fScale ) +{ + mbWindow = false; + mbPrinter = true; + mbVirDev = false; + + mrContext = xContext; + mfFakeDPIScale = fScale; + mnRealDPIX = nDPIX; + mnRealDPIY = nDPIY; + + // a previously set clip path is now invalid + if( mxClipPath ) + { + CGPathRelease( mxClipPath ); + mxClipPath = NULL; + } + + if( mrContext ) + { + CGContextSetFillColorSpace( mrContext, GetSalData()->mxRGBSpace ); + CGContextSetStrokeColorSpace( mrContext, GetSalData()->mxRGBSpace ); + CGContextSaveGState( mrContext ); + SetState(); + } +} + +void AquaSalGraphics::SetVirDevGraphics( CGLayerRef xLayer, CGContextRef xContext, + int nBitmapDepth ) +{ + mbWindow = false; + mbPrinter = false; + mbVirDev = true; + + // set graphics properties + mxLayer = xLayer; + mrContext = xContext; + mnBitmapDepth = nBitmapDepth; + + // return early if the virdev is being destroyed + if( !xContext ) + return; + + // get new graphics properties + if( !mxLayer ) + { + mnWidth = CGBitmapContextGetWidth( mrContext ); + mnHeight = CGBitmapContextGetHeight( mrContext ); + } + else + { + const CGSize aSize = CGLayerGetSize( mxLayer ); + mnWidth = static_cast(aSize.width); + mnHeight = static_cast(aSize.height); + } + + // prepare graphics for drawing + const CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace; + CGContextSetFillColorSpace( mrContext, aCGColorSpace ); + CGContextSetStrokeColorSpace( mrContext, aCGColorSpace ); + + // re-enable XorEmulation for the new context + if( mpXorEmulation ) + { + mpXorEmulation->SetTarget( mnWidth, mnHeight, mnBitmapDepth, mrContext, mxLayer ); + if( mpXorEmulation->IsEnabled() ) + mrContext = mpXorEmulation->GetMaskContext(); + } + + // initialize stack of CGContext states + CGContextSaveGState( mrContext ); + SetState(); +} + +// ---------------------------------------------------------------------- + +void AquaSalGraphics::InvalidateContext() +{ + UnsetState(); + mrContext = 0; +} + +// ---------------------------------------------------------------------- + +void AquaSalGraphics::UnsetState() +{ + if( mrContext ) + { + CGContextRestoreGState( mrContext ); + mrContext = 0; + } + if( mxClipPath ) + { + CGPathRelease( mxClipPath ); + mxClipPath = NULL; + } +} + +void AquaSalGraphics::SetState() +{ + CGContextRestoreGState( mrContext ); + CGContextSaveGState( mrContext ); + + // setup clipping + if( mxClipPath ) + { + CGContextBeginPath( mrContext ); // discard any existing path + CGContextAddPath( mrContext, mxClipPath ); // set the current path to the clipping path + CGContextClip( mrContext ); // use it for clipping + } + + // set RGB colorspace and line and fill colors + CGContextSetFillColor( mrContext, maFillColor.AsArray() ); + CGContextSetStrokeColor( mrContext, maLineColor.AsArray() ); + CGContextSetShouldAntialias( mrContext, false ); + if( mnXorMode == 2 ) + CGContextSetBlendMode( mrContext, kCGBlendModeDifference ); +} + +// ---------------------------------------------------------------------- + +bool AquaSalGraphics::CheckContext() +{ + if( mbWindow && mpFrame != NULL ) + { + const unsigned int nWidth = mpFrame->maGeometry.nWidth; + const unsigned int nHeight = mpFrame->maGeometry.nHeight; + + CGContextRef rReleaseContext = 0; + CGLayerRef rReleaseLayer = NULL; + + // check if a new drawing context is needed (e.g. after a resize) + if( (unsigned(mnWidth) != nWidth) || (unsigned(mnHeight) != nHeight) ) + { + mnWidth = nWidth; + mnHeight = nHeight; + // prepare to release the corresponding resources + rReleaseContext = mrContext; + rReleaseLayer = mxLayer; + mrContext = NULL; + mxLayer = NULL; + } + + if( !mrContext ) + { + const CGSize aLayerSize = { static_cast(nWidth), static_cast(nHeight) }; + NSGraphicsContext* pNSGContext = [NSGraphicsContext graphicsContextWithWindow: mpFrame->getNSWindow()]; + CGContextRef xCGContext = reinterpret_cast([pNSGContext graphicsPort]); + mxLayer = CGLayerCreateWithContext( xCGContext, aLayerSize, NULL ); + if( mxLayer ) + mrContext = CGLayerGetContext( mxLayer ); + + if( mrContext ) + { + // copy original layer to resized layer + if( rReleaseLayer ) + CGContextDrawLayerAtPoint( mrContext, CGPointZero, rReleaseLayer ); + + CGContextTranslateCTM( mrContext, 0, nHeight ); + CGContextScaleCTM( mrContext, 1.0, -1.0 ); + CGContextSetFillColorSpace( mrContext, GetSalData()->mxRGBSpace ); + CGContextSetStrokeColorSpace( mrContext, GetSalData()->mxRGBSpace ); + CGContextSaveGState( mrContext ); + SetState(); + + // re-enable XOR emulation for the new context + if( mpXorEmulation ) + mpXorEmulation->SetTarget( mnWidth, mnHeight, mnBitmapDepth, mrContext, mxLayer ); + } + } + + if( rReleaseLayer ) + CGLayerRelease( rReleaseLayer ); + else if( rReleaseContext ) + CGContextRelease( rReleaseContext ); + } + + DBG_ASSERT( mrContext || mbPrinter, "<<>> AquaSalGraphics::CheckContext() FAILED!!!!\n" ); + return (mrContext != NULL); +} + +CGContextRef AquaSalGraphics::GetContext() +{ + if(!mrContext) + { + CheckContext(); + } + return mrContext; +} + +void AquaSalGraphics::RefreshRect(float lX, float lY, float lWidth, float lHeight) +{ + if( ! mbWindow ) // view only on Window graphics + return; + + if( mpFrame ) + { + // update a little more around the designated rectangle + // this helps with antialiased rendering + const Rectangle aVclRect(Point(static_cast(lX-1), + static_cast(lY-1) ), + Size( static_cast(lWidth+2), + static_cast(lHeight+2) ) ); + mpFrame->maInvalidRect.Union( aVclRect ); + } +} + +CGPoint* AquaSalGraphics::makeCGptArray(sal_uLong nPoints, const SalPoint* pPtAry) +{ + CGPoint *CGpoints = new CGPoint[nPoints]; + if ( CGpoints ) + { + for(sal_uLong i=0;i([pContext graphicsPort]); + + CGMutablePathRef rClip = mpFrame->getClipPath(); + if( rClip ) + { + CGContextSaveGState( rCGContext ); + CGContextBeginPath( rCGContext ); + CGContextAddPath( rCGContext, rClip ); + CGContextClip( rCGContext ); + } + + ApplyXorContext(); + CGContextDrawLayerAtPoint( rCGContext, CGPointZero, mxLayer ); + if( rClip ) // cleanup clipping + CGContextRestoreGState( rCGContext ); + } + else + DBG_ASSERT( mpFrame->mbInitShow, "UpdateWindow called on uneligible graphics" ); +} + +// ----------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/quartz/salmathutils.cxx b/vcl/quartz/salmathutils.cxx new file mode 100644 index 000000000000..e1222aa63061 --- /dev/null +++ b/vcl/quartz/salmathutils.cxx @@ -0,0 +1,154 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "quartz/salmathutils.hxx" + +#include + +// ======================================================================= + +// ======================================================================= + +#define Swap( x, y ) { x ^= y; y ^= x; x ^= y; } + +// ======================================================================= + +// ======================================================================= + +// Storage free swapping using XOR + +void CSwap ( char &rX, char &rY ) +{ + Swap( rX, rY ); +} // CSwap + +// ----------------------------------------------------------------------- + +// Storage free swapping using XOR + +void UCSwap ( unsigned char &rX, unsigned char &rY ) +{ + Swap( rX, rY ); +} // UCSwap + +// ----------------------------------------------------------------------- + +// Storage free swapping using XOR + +void SSwap ( short &rX, short &rY ) +{ + Swap( rX, rY ); +} // SSwap + +// ----------------------------------------------------------------------- + +// Storage free swapping using XOR + +void USSwap ( unsigned short &rX, unsigned short &rY ) +{ + Swap( rX, rY ); +} // USSwap + +// ----------------------------------------------------------------------- + +// Storage free swapping using XOR + +void LSwap ( long &rX, long &rY ) +{ + Swap( rX, rY ); +} // LSwap + +// ----------------------------------------------------------------------- + +// Storage free swapping using XOR + +void ULSwap ( unsigned long &rX, unsigned long &rY ) +{ + Swap( rX, rY ); +} // ULSwap + +// ======================================================================= + +// ======================================================================= + +// ----------------------------------------------------------------------- +// +// This way of measuring distance is also called the "Manhattan distance." +// Manhattan distance takes advantage of the fact that the sum of the +// lengths of the three components of a 3D vector is a rough approxima- +// tion of the vector's length. +// +// ----------------------------------------------------------------------- + +unsigned long Euclidian2Norm ( const LRectCoorVector pVec ) +{ + unsigned long ndist = 0; + + if ( pVec ) + { + long nDX = 0; + long nDY = 0; + long nDZ = 0; + unsigned long nMax = 0; + unsigned long nMed = 0; + unsigned long nMin = 0; + + // Find |x'-x|, |y'-y|, and |z'-z| from (x,y,z) and (x',y',z') + + nDX = pVec[1].x - pVec[0].x; + nDY = pVec[1].y - pVec[0].y; + nDZ = pVec[1].z - pVec[0].z; + + nMax = (unsigned long)abs( nDX ); + nMed = (unsigned long)abs( nDY ); + nMin = (unsigned long)abs( nDZ ); + + // Sort them (3 compares, 0-3 swaps) + + if ( nMax < nMed ) + { + Swap( nMax, nMed ); + } // if + + if ( nMax < nMin ) + { + Swap( nMax, nMin ); + } // if + + // Approximate Euclidian distance: + // + // d = max + (11/32)*med + (1/4)*min + // + // with +/- 8% error, where the exact formulae for d is + // + // || (x',y',z') - (x,y,z) || = { |x'-x|^2 + |y'-y|^2 + |z'-z|^2 }^(1/2) + + ndist = nMax + ( nMin >> 2UL ) + + ( ( ( nMed << 3UL ) + ( nMed << 1UL ) + nMed ) >> 5UL ); + } // if + + return ndist; +} // RGBDistance + +// ======================================================================= + +// ======================================================================= + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index 4474e2066cc8..5e573d065c90 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -371,7 +371,7 @@ inline void ImplYield( bool i_bWait, bool i_bAllEvents ) vcl::LazyDelete::flush(); // the system timer events will not necessarily come in in non waiting mode - // e.g. on aqua; need to trigger timer checks manually + // e.g. on OS X; need to trigger timer checks manually if( pSVData->maAppData.mbNoYield && !pSVData->mbNoCallTimer ) { do diff --git a/vcl/source/app/svmainhook.cxx b/vcl/source/app/svmainhook.cxx index cd8e55226012..e4799d1608df 100644 --- a/vcl/source/app/svmainhook.cxx +++ b/vcl/source/app/svmainhook.cxx @@ -20,7 +20,7 @@ #include #ifndef MACOSX -// MacOSX implementation of ImplSVMainHook is in aqua/source/app/salinst.cxx +// MacOSX implementation of ImplSVMainHook is in osx/salinst.cxx sal_Bool ImplSVMainHook( int * ) { diff --git a/vcl/source/control/edit.cxx b/vcl/source/control/edit.cxx index d9d17ae52dc7..dee721f0893b 100644 --- a/vcl/source/control/edit.cxx +++ b/vcl/source/control/edit.cxx @@ -501,7 +501,7 @@ void Edit::ImplInvalidateOrRepaint( sal_Int32 nStart, sal_Int32 nEnd ) if( IsPaintTransparent() ) { Invalidate(); - // FIXME: this is currently only on aqua + // FIXME: this is currently only on OS X if( ImplGetSVData()->maNWFData.mbNoFocusRects ) Update(); } @@ -2023,7 +2023,7 @@ void Edit::GetFocus() ImplShowCursor(); - // FIXME: this is currently only on aqua + // FIXME: this is currently only on OS X // check for other platforms that need similar handling if( ImplGetSVData()->maNWFData.mbNoFocusRects && IsNativeWidgetEnabled() && @@ -2069,7 +2069,7 @@ void Edit::LoseFocus() if ( !mpSubEdit ) { - // FIXME: this is currently only on aqua + // FIXME: this is currently only on OS X // check for other platforms that need similar handling if( ImplGetSVData()->maNWFData.mbNoFocusRects && IsNativeWidgetEnabled() && @@ -2492,7 +2492,7 @@ void Edit::Modify() // #i13677# notify edit listeners about caret position change ImplCallEventListeners( VCLEVENT_EDIT_CARETCHANGED ); - // FIXME: this is currently only on aqua + // FIXME: this is currently only on OS X // check for other platforms that need similar handling if( ImplGetSVData()->maNWFData.mbNoFocusRects && IsNativeWidgetEnabled() && diff --git a/vcl/source/control/scrbar.cxx b/vcl/source/control/scrbar.cxx index 3ff834d4c9d3..8c9f1609003f 100644 --- a/vcl/source/control/scrbar.cxx +++ b/vcl/source/control/scrbar.cxx @@ -32,9 +32,9 @@ /* #i77549# HACK: for scrollbars in case of thumb rect, page up and page down rect we - abuse the HitTestNativeControl interface. All theming engines but aqua + abuse the HitTestNativeControl interface. All theming engines but OS X are actually able to draw the thumb according to our internal representation. - However aqua draws a little outside. The canonical way would be to enhance the + However OS X draws a little outside. The canonical way would be to enhance the HitTestNativeControl passing a ScrollbarValue additionally so all necessary information is available in the call. . diff --git a/vcl/source/control/spinfld.cxx b/vcl/source/control/spinfld.cxx index b6aa626d4c1c..f070dfa2cfd4 100644 --- a/vcl/source/control/spinfld.cxx +++ b/vcl/source/control/spinfld.cxx @@ -914,7 +914,7 @@ long SpinField::PreNotify( NotifyEvent& rNEvt ) Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() ); if( pRect != pLastRect || (pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow()) ) { - // FIXME: this is currently only on aqua + // FIXME: this is currently only on OS X // check for other platforms that need similar handling if( ImplGetSVData()->maNWFData.mbNoFocusRects && IsNativeWidgetEnabled() && diff --git a/vcl/source/window/brdwin.cxx b/vcl/source/window/brdwin.cxx index ff0e4ce398ac..27cee445e905 100644 --- a/vcl/source/window/brdwin.cxx +++ b/vcl/source/window/brdwin.cxx @@ -1103,7 +1103,7 @@ void ImplSmallBorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHei } else { - // FIXME: this is currently only on aqua, check with other + // FIXME: this is currently only on OS X, check with other // platforms if( ImplGetSVData()->maNWFData.mbNoFocusRects && !( nBorderStyle & WINDOW_BORDER_NWF ) ) { @@ -1344,9 +1344,9 @@ void ImplSmallBorderWindowView::DrawWindow( sal_uInt16 nDrawFlags, OutputDevice* nState |= CTRL_STATE_FOCUSED; else if( mbNWFBorder ) { - // FIXME: this is curently only on aqua, see if other platforms can profit + // FIXME: this is curently only on OS X, see if other platforms can profit - // FIXME: for aqua focus rings all controls need to support GetNativeControlRegion + // FIXME: for OS X focus rings all controls need to support GetNativeControlRegion // for the dropdown style if( pCtrl->HasFocus() || pCtrl->HasChildPathFocus() ) nState |= CTRL_STATE_FOCUSED; diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index 821ae214b4a2..78995af16b6b 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -370,7 +370,7 @@ void Window::ImplInitAppFontData( Window* pWindow ) pSVData->maGDIData.mnAppFontX = nTextWidth * 10 / 8; pSVData->maGDIData.mnAppFontY = nTextHeight * 10; - // FIXME: this is currently only on aqua, check with other + // FIXME: this is currently only on OS X, check with other // platforms if( pSVData->maNWFData.mbNoFocusRects ) { -- cgit