diff options
Diffstat (limited to 'kcontrol')
23 files changed, 2125 insertions, 20 deletions
diff --git a/kcontrol/input/CMakeLists.txt b/kcontrol/input/CMakeLists.txt index 2fc6f6ce8..81d4a2384 100644 --- a/kcontrol/input/CMakeLists.txt +++ b/kcontrol/input/CMakeLists.txt @@ -17,8 +17,6 @@ else( ) include_directories( core ) endif( ) -add_subdirectory( pics ) - include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BINARY_DIR} @@ -34,7 +32,7 @@ link_directories( ##### other data ################################ tde_create_translated_desktop( - SOURCE mouse.desktop + SOURCE mouse.desktop touchpad.desktop PO_DIR kcontrol-desktops ) @@ -47,18 +45,41 @@ install( FILES mouse_cursor_theme.upd DESTINATION ${KCONF_UPDATE_INSTALL_DIR} ) +install( + DIRECTORY pics/ + DESTINATION ${DATA_INSTALL_DIR}/kcminput/pics + FILES_MATCHING PATTERN *.png +) + +add_subdirectory(icons) + ##### kcm_input (module) ######################## tde_add_kpart( kcm_input AUTOMOC SOURCES - mouse.cpp kmousedlg.ui main.cpp logitechmouse.cpp - logitechmouse_base.ui - LINK themepage-static tdeio-shared ${XCURSOR_LIBRARIES} ${LIBUSB_LIBRARIES} + mouse.cpp kmousedlg.ui main.cpp + logitechmouse.cpp logitechmouse_base.ui + touchpad.cpp touchpad_settings.cpp + LINK + themepage-static tdeio-shared + ${XCURSOR_LIBRARIES} ${LIBUSB_LIBRARIES} + ${XINPUT_LIBRARIES} DESTINATION ${PLUGIN_INSTALL_DIR} ) +##### syndaemon (executable) #################### + +tde_add_executable( syndaemon AUTOMOC + SOURCES + syndaemon.cpp syndaemon_iface.skel + touchpad_settings.cpp + LINK tdecore-shared ${XINPUT_LIBRARIES} + DESTINATION ${BIN_INSTALL_DIR} +) + + ##### kapplymousetheme (executable) ############# tde_add_executable( kapplymousetheme diff --git a/kcontrol/input/icons/CMakeLists.txt b/kcontrol/input/icons/CMakeLists.txt new file mode 100644 index 000000000..546096f2e --- /dev/null +++ b/kcontrol/input/icons/CMakeLists.txt @@ -0,0 +1 @@ +tde_install_icons()
\ No newline at end of file diff --git a/kcontrol/input/icons/cr128-device-input-touchpad.png b/kcontrol/input/icons/cr128-device-input-touchpad.png Binary files differnew file mode 100644 index 000000000..5b5b16553 --- /dev/null +++ b/kcontrol/input/icons/cr128-device-input-touchpad.png diff --git a/kcontrol/input/icons/cr16-device-input-touchpad.png b/kcontrol/input/icons/cr16-device-input-touchpad.png Binary files differnew file mode 100644 index 000000000..bde3c5e48 --- /dev/null +++ b/kcontrol/input/icons/cr16-device-input-touchpad.png diff --git a/kcontrol/input/icons/cr32-device-input-touchpad.png b/kcontrol/input/icons/cr32-device-input-touchpad.png Binary files differnew file mode 100644 index 000000000..6e00abaa4 --- /dev/null +++ b/kcontrol/input/icons/cr32-device-input-touchpad.png diff --git a/kcontrol/input/icons/cr48-device-input-touchpad.png b/kcontrol/input/icons/cr48-device-input-touchpad.png Binary files differnew file mode 100644 index 000000000..7c6a41c56 --- /dev/null +++ b/kcontrol/input/icons/cr48-device-input-touchpad.png diff --git a/kcontrol/input/icons/cr64-device-input-touchpad.png b/kcontrol/input/icons/cr64-device-input-touchpad.png Binary files differnew file mode 100644 index 000000000..b124147fa --- /dev/null +++ b/kcontrol/input/icons/cr64-device-input-touchpad.png diff --git a/kcontrol/input/icons/crsc-device-input-touchpad.svg b/kcontrol/input/icons/crsc-device-input-touchpad.svg new file mode 100644 index 000000000..2802b4716 --- /dev/null +++ b/kcontrol/input/icons/crsc-device-input-touchpad.svg @@ -0,0 +1,485 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Generator: Adobe Illustrator 10.0.3, SVG Export Plug-In . SVG Version: 3.0.0 Build 77) --> +<svg + xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="128.338" + height="128" + viewBox="0 0 128.338 128" + overflow="visible" + enable-background="new 0 0 128.338 128" + xml:space="preserve" + id="svg1704" + sodipodi:version="0.32" + inkscape:version="0.42" + sodipodi:docname="touchpad.svg" + sodipodi:docbase="/home/kombrisn/Project/kdereview/ksynaptics"><metadata + id="metadata2067"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs + id="defs2065"> + + + + + <linearGradient + id="XMLID_1_" + gradientUnits="userSpaceOnUse" + x1="6.1904001" + y1="15.246600" + x2="118.40850" + y2="84.415398" + gradientTransform="matrix(1.000000,0.000000,0.000000,1.043928,0.287175,3.271150)"> + <stop + offset="0" + style="stop-color:#FFFFFF" + id="stop1712" /> + <stop + offset="1" + style="stop-color:#DCDCE0" + id="stop1714" /> + + + + </linearGradient> + + <linearGradient + id="XMLID_2_" + gradientUnits="userSpaceOnUse" + x1="116.84180" + y1="84.442398" + x2="16.851700" + y2="20.812099" + gradientTransform="matrix(1.000000,0.000000,0.000000,1.130136,0.287175,3.541282)"> + <stop + offset="0" + style="stop-color:#FFFFFF" + id="stop1719" /> + <stop + offset="1" + style="stop-color:#DCDCE0" + id="stop1721" /> + + + + </linearGradient> + + + + <linearGradient + id="XMLID_3_" + gradientUnits="userSpaceOnUse" + x1="94.294899" + y1="35.819801" + x2="96.824898" + y2="32.868401" + gradientTransform="matrix(0.985500,-0.169900,0.169900,0.985500,0.979900,-9.081100)"> + <stop + offset="0" + style="stop-color:#97FF86" + id="stop1728" /> + <stop + offset="1" + style="stop-color:#94FF7F" + id="stop1730" /> + + + + </linearGradient> + + + <linearGradient + id="XMLID_4_" + gradientUnits="userSpaceOnUse" + x1="94.387703" + y1="35.655800" + x2="96.723297" + y2="32.931099" + gradientTransform="matrix(0.985500,-0.169900,0.169900,0.985500,0.979900,-9.081100)"> + <stop + offset="0" + style="stop-color:#3DDF00" + id="stop1735" /> + <stop + offset="1" + style="stop-color:#94FF7F" + id="stop1737" /> + + + + </linearGradient> + + + + + <linearGradient + id="XMLID_5_" + gradientUnits="userSpaceOnUse" + x1="64.881302" + y1="55.002399" + x2="64.881302" + y2="-3.4971001" + gradientTransform="matrix(1.000000,0.000000,0.000000,0.919938,0.000000,1.052981)"> + <stop + offset="0" + style="stop-color:#9E9EAC" + id="stop1748" /> + <stop + offset="1" + style="stop-color:#42425B" + id="stop1750" /> + + + + </linearGradient> + + + + + + + + + + + + + + <linearGradient + id="XMLID_18_" + gradientUnits="userSpaceOnUse" + x1="63.074699" + y1="54.390099" + x2="62.435501" + y2="69.409203" + gradientTransform="matrix(1.000000,0.000000,0.000000,1.043928,0.287175,3.271150)"> + <stop + offset="0" + style="stop-color:#FFFFFF" + id="stop1887" /> + <stop + offset="1" + style="stop-color:#FFFFFF;stop-opacity:0" + id="stop1889" /> + + + + </linearGradient> + + + <linearGradient + id="XMLID_20_" + gradientUnits="userSpaceOnUse" + x1="81.798798" + y1="104.17290" + x2="88.452904" + y2="114.22480"> + <stop + offset="0" + style="stop-color:#FFFFFF" + id="stop1905" /> + <stop + offset="1" + style="stop-color:#DCDCE0" + id="stop1907" /> + + + + </linearGradient> + + <linearGradient + id="XMLID_21_" + gradientUnits="userSpaceOnUse" + x1="72.246101" + y1="100.22750" + x2="72.246101" + y2="83.708900"> + <stop + offset="0" + style="stop-color:#9E9E9E" + id="stop1912" /> + <stop + offset="1" + style="stop-color:#616161" + id="stop1914" /> + + + + </linearGradient> + + <linearGradient + id="XMLID_22_" + gradientUnits="userSpaceOnUse" + x1="64.685097" + y1="-1.2637000" + x2="63.526699" + y2="114.37610" + gradientTransform="matrix(1.000000,0.000000,0.000000,1.130136,0.287175,3.541282)"> + <stop + offset="0" + style="stop-color:#9E9EAC" + id="stop1919" /> + <stop + offset="1" + style="stop-color:#42425B" + id="stop1921" /> + + + + </linearGradient> + + <linearGradient + inkscape:collect="always" + xlink:href="#XMLID_5_" + id="linearGradient3115" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.259073,0.000000,0.000000,0.145048,44.66793,81.50629)" + x1="64.881302" + y1="55.002399" + x2="64.881302" + y2="-3.4971001" /><linearGradient + inkscape:collect="always" + xlink:href="#XMLID_5_" + id="linearGradient3119" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.404572,0.000000,0.000000,0.210813,10.52265,95.00541)" + x1="64.881302" + y1="55.002399" + x2="64.881302" + y2="-3.4971001" /></defs><sodipodi:namedview + inkscape:window-height="725" + inkscape:window-width="1016" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + inkscape:zoom="3.4822022" + inkscape:cx="72.564336" + inkscape:cy="56.149095" + inkscape:window-x="0" + inkscape:window-y="25" + inkscape:current-layer="Layer_1" /> + <g + id="Layer_1"> + <path + d="M 127.81817,87.825173 C 129.67917,103.42042 21.989175,123.45549 17.081175,104.65643 C 12.174175,85.855280 2.1931746,29.250351 1.0841746,23.409573 C -0.025825402,17.568794 111.16117,1.8931647 111.81917,6.5772713 C 112.47617,11.261378 125.95317,72.227839 127.81817,87.825173 z " + id="path1716" + style="fill:url(#XMLID_1_)" /><path + d="M 124.82002,86.233211 C 125.79544,93.680770 113.50726,100.54412 78.405838,105.83457 C 29.797840,113.16268 23.126889,113.85833 20.519977,104.00664 C 15.541863,85.199327 5.9298363,31.448190 4.7737780,25.598871 C 3.6187343,19.749533 108.25665,2.3575140 108.96323,7.0548317 C 109.66973,11.748770 122.77228,70.595456 124.82002,86.233211 z " + id="path1723" + style="fill:#d1d1d1;fill-opacity:1.0000000" /><path + id="path1741" + style="fill:#ffffff;stroke:#000000" + d="" /><path + d="M 114.73417,76.613763 C 115.45017,83.738518 30.508175,97.270824 28.334175,89.492570 C 24.565175,76.010462 15.476175,33.639362 15.033175,28.504056 C 14.823175,26.071543 100.47617,13.639662 101.93817,17.161979 C 103.71217,21.441081 113.46517,64.025506 114.73417,76.613763 z " + id="path1743" + style="fill:#d1d1d1;fill-opacity:1.0000000" /><path + d="M 112.96317,76.297478 C 113.74417,80.063057 31.345175,93.277308 30.371175,88.823042 C 29.397175,84.365887 17.551175,29.530614 17.551175,29.530614 L 100.67117,17.956091 C 100.67117,17.956091 112.18317,72.529006 112.96317,76.297478 z " + id="path1745" + style="fill:#f5f5f9" /><path + d="M 100.55617,17.107495 L 16.577175,28.749806 L 29.576175,88.599713 C 30.796175,94.163016 93.202175,82.438115 93.831175,82.314230 C 114.27417,78.285566 113.96517,76.797985 113.76017,75.814588 L 113.76017,75.812667 L 113.76017,75.814588 L 101.31617,17.000897 L 100.55617,17.107495 z M 100.02717,18.758335 C 100.32417,20.162365 112.00617,75.368026 112.11117,75.867407 C 109.52617,78.403689 71.541175,85.378704 46.885175,87.817029 C 33.642175,89.127906 31.482175,88.366349 31.138175,88.139706 C 30.836175,86.757764 20.006175,36.893566 18.523175,30.057801 C 20.184175,29.828278 98.550175,18.962890 100.02717,18.758335 z " + id="path1752" + style="fill:#000000;fill-opacity:1.0000000" /><path + a:adobe-blending-mode="screen" + d="M 105.98917,63.463016 C 105.98917,63.463016 92.840175,40.295114 63.690175,65.440217 C 43.907175,82.504270 28.755175,73.564067 27.010175,64.061187 C 23.959175,47.461682 22.534175,47.426188 21.429175,39.568540 L 100.28317,27.111343 L 105.98917,63.463016 z " + id="path1891" + style="fill:url(#XMLID_18_)" /><path + d="M 0.94217460,22.023236 C 0.26817460,22.617231 0.21417460,23.195568 0.28717460,23.575557 L 1.3971746,29.664791 C 4.3371746,45.885351 12.147175,88.974538 16.296175,104.87879 C 19.460175,116.99567 58.779175,113.52356 84.434175,108.23084 C 106.44117,103.69392 129.60417,95.921879 128.62517,87.721824 C 127.36017,77.145786 120.80717,45.925020 116.47017,25.266721 C 114.43717,15.589505 112.83217,7.9458614 112.62217,6.4551317 C 112.57417,6.1148110 112.36417,5.6502629 111.62217,5.3579630 C 102.72017,1.8461880 7.5561746,16.176193 0.94217460,22.023236 z M 14.952175,19.164960 C 45.879175,12.067291 107.28317,4.7493528 111.05917,6.9760519 C 111.37117,8.9083634 112.84817,15.952792 114.88117,25.630008 C 119.21117,46.260120 125.75517,77.434954 127.01017,87.929566 C 127.68117,93.555292 110.04317,101.21877 84.118175,106.56578 C 53.475175,112.88676 20.315175,113.81585 17.864175,104.43303 C 13.732175,88.593504 5.9331746,45.552337 2.9951746,29.349525 C 2.9951746,29.349525 1.9641746,23.699784 1.9101746,23.400177 C 2.1691746,23.060900 3.8551746,21.710057 14.952175,19.164960 z " + id="path1923" + style="fill:#000000;fill-opacity:1.0000000" /><g + id="g1925"> + <linearGradient + y2="132.29289" + x2="35.785999" + y1="52.338402" + x1="36.586899" + gradientUnits="userSpaceOnUse" + id="XMLID_23_"> + <stop + id="stop1928" + style="stop-color:#9E9EAC" + offset="0" /> + <stop + id="stop1930" + style="stop-color:#42425B" + offset="1" /> + + + + </linearGradient> + + + + <linearGradient + gradientTransform="matrix(0.962300,0.272200,-0.272200,0.962300,33.15460,32.60870)" + y2="51.923401" + x2="30.674400" + y1="38.364300" + x1="8.6763000" + gradientUnits="userSpaceOnUse" + id="XMLID_24_"> + <stop + id="stop1937" + style="stop-color:#FFFFFF" + offset="0" /> + <stop + id="stop1939" + style="stop-color:#DCDCE0" + offset="1" /> + + + + </linearGradient> + + + <linearGradient + gradientTransform="matrix(0.962300,0.272200,-0.272200,0.962300,33.15460,32.60870)" + y2="74.467400" + x2="18.130600" + y1="62.927700" + x1="14.248000" + gradientUnits="userSpaceOnUse" + id="XMLID_25_"> + <stop + id="stop1944" + style="stop-color:#FFFFFF" + offset="0" /> + <stop + id="stop1946" + style="stop-color:#DCDCE0" + offset="1" /> + + + + </linearGradient> + + + + <linearGradient + gradientTransform="matrix(-0.279700,0.981500,-1.218600,-0.347400,50.63740,141.2638)" + y2="22.446800" + x2="-56.447201" + y1="21.737301" + x1="-68.426804" + gradientUnits="userSpaceOnUse" + id="XMLID_26_"> + <stop + id="stop1953" + style="stop-color:#DCDCE0" + offset="0" /> + <stop + id="stop1955" + style="stop-color:#BEBEC2" + offset="1" /> + + + + </linearGradient> + + + <linearGradient + gradientTransform="matrix(-0.274100,0.961700,-0.961700,-0.274100,24.23770,133.5791)" + y2="-1.5967000" + x2="-67.696297" + y1="3.6680000" + x1="-56.356400" + gradientUnits="userSpaceOnUse" + id="XMLID_27_"> + <stop + id="stop1960" + style="stop-color:#0054BF" + offset="0" /> + <stop + id="stop1962" + style="stop-color:#0047BF" + offset="1" /> + + + + </linearGradient> + + + <linearGradient + gradientTransform="matrix(-0.274100,0.961700,-0.816500,-0.232800,9.573000,128.7048)" + y2="-19.257999" + x2="-66.917702" + y1="-14.327600" + x1="-56.297901" + gradientUnits="userSpaceOnUse" + id="XMLID_28_"> + <stop + id="stop1967" + style="stop-color:#0054BF" + offset="0" /> + <stop + id="stop1969" + style="stop-color:#5FA0FF" + offset="1" /> + + + + </linearGradient> + + + <linearGradient + gradientTransform="matrix(-9.010000e-2,0.996000,-0.996000,-9.010000e-2,18.98860,131.3304)" + y2="-15.773900" + x2="-62.960201" + y1="-16.911600" + x1="-65.541496" + gradientUnits="userSpaceOnUse" + id="XMLID_29_"> + <stop + id="stop1974" + style="stop-color:#BFE2FF" + offset="0" /> + <stop + id="stop1976" + style="stop-color:#5FA0FF" + offset="1" /> + + + + </linearGradient> + + </g> + <path + d="M 128.16900,118.23606 L 0.16900000,118.23606 L 0.16900000,-1.7097435e-14 L 128.16900,-1.7097435e-14 L 128.16900,118.23606 z " + id="path2062" + style="fill:none" /> + <path + sodipodi:type="arc" + style="fill:#cccccc;fill-opacity:1.0000000" + id="path3123" + sodipodi:cx="79.111282" + sodipodi:cy="83.275467" + sodipodi:rx="34.713203" + sodipodi:ry="5.3321223" + d="M 113.82449 83.275467 A 34.713203 5.3321223 0 1 1 44.398079,83.275467 A 34.713203 5.3321223 0 1 1 113.82449 83.275467 z" + transform="matrix(1.267730,-0.246140,0.133394,1.354468,-35.04176,4.335442)" /><path + sodipodi:type="arc" + style="fill:#79799c;fill-opacity:1.0000000" + id="path3127" + sodipodi:cx="79.111282" + sodipodi:cy="83.275467" + sodipodi:rx="34.713203" + sodipodi:ry="5.3321223" + d="M 113.82449 83.275467 A 34.713203 5.3321223 0 1 1 44.398079,83.275467 A 34.713203 5.3321223 0 1 1 113.82449 83.275467 z" + transform="matrix(1.216726,-0.238824,0.191990,0.958919,-35.88576,36.67426)" /><rect + style="fill:#cccccc;fill-opacity:1.0000000" + id="rect3857" + width="3.3490131" + height="11.841051" + x="35.321518" + y="104.04992" + transform="matrix(0.991862,-0.127320,0.360903,0.932603,0.000000,0.000000)" /></g> +</svg>
\ No newline at end of file diff --git a/kcontrol/input/main.cpp b/kcontrol/input/main.cpp index d72dd0aa6..71d9ec66f 100644 --- a/kcontrol/input/main.cpp +++ b/kcontrol/input/main.cpp @@ -38,6 +38,8 @@ #endif #include "mouse.h" +#include "touchpad_settings.h" +#include "touchpad.h" extern "C" { @@ -91,6 +93,23 @@ extern "C" delete config; } + + TDE_EXPORT TDECModule *create_touchpad(TQWidget *parent, const char *) + { + return new TouchpadConfig(parent, "kcminput"); + } + + TDE_EXPORT void init_touchpad() + { + TouchpadSettings settings; + settings.apply(); + } + + TDE_EXPORT bool test_touchpad() + { + TouchpadSettings settings; + return settings.foundTouchpad(); + } } diff --git a/kcontrol/input/pics/CMakeLists.txt b/kcontrol/input/pics/CMakeLists.txt deleted file mode 100644 index 0c9331efe..000000000 --- a/kcontrol/input/pics/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -################################################# -# -# (C) 2010-2011 Serghei Amelian -# serghei (DOT) amelian (AT) gmail.com -# -# Improvements and feedback are welcome -# -# This file is released under GPL >= 2 -# -################################################# - -install( FILES - mouse_rh.png mouse_lh.png doubleclick_1.png doubleclick_2.png - DESTINATION ${DATA_INSTALL_DIR}/kcminput/pics ) diff --git a/kcontrol/input/pics/mouse0.png b/kcontrol/input/pics/mouse0.png Binary files differnew file mode 100644 index 000000000..02e708b04 --- /dev/null +++ b/kcontrol/input/pics/mouse0.png diff --git a/kcontrol/input/pics/mouse1.png b/kcontrol/input/pics/mouse1.png Binary files differnew file mode 100644 index 000000000..f3aeea106 --- /dev/null +++ b/kcontrol/input/pics/mouse1.png diff --git a/kcontrol/input/pics/mouse2.png b/kcontrol/input/pics/mouse2.png Binary files differnew file mode 100644 index 000000000..40c34fe59 --- /dev/null +++ b/kcontrol/input/pics/mouse2.png diff --git a/kcontrol/input/pics/mouse3.png b/kcontrol/input/pics/mouse3.png Binary files differnew file mode 100644 index 000000000..74e5c1423 --- /dev/null +++ b/kcontrol/input/pics/mouse3.png diff --git a/kcontrol/input/syndaemon.cpp b/kcontrol/input/syndaemon.cpp new file mode 100644 index 000000000..53d8346ca --- /dev/null +++ b/kcontrol/input/syndaemon.cpp @@ -0,0 +1,201 @@ +/******************************************************************************* + syndaemon - daemon for the Synaptics touchpad driver which disables touchpad + on keyboard input + + Copyright © 2004 Nadeem Hasan <[email protected]> + Stefan Kombrink <[email protected]> + 2024 Mavridis Philippe <[email protected]> + + This program is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + this program. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************************************/ + +// TQt +#include <tqdatetime.h> +#include <tqtimer.h> + +// TDE +#include <ksimpleconfig.h> +#include <tdecmdlineargs.h> +#include <kuniqueapplication.h> +#include <tdeaboutdata.h> +#include <tdelocale.h> +#include <kdebug.h> + +// DCOP +#include <dcopclient.h> + +// tdecm_touchpad +#include "touchpad_settings.h" + +// SynDaemon +#include "syndaemon.h" +#include "syndaemon.moc" + +const unsigned int SynDaemon::TIME_OUT = 150; +const unsigned int SynDaemon::POLL_INTERVAL = 100; +const unsigned int SynDaemon::KEYMAP_SIZE = 32; + +unsigned char* SynDaemon::m_keyboard_mask; + +SynDaemon::SynDaemon() : DCOPObject("syndaemon"), TQObject() +{ + m_typing = false; + m_time = new TQTime(); + d_settings = new TouchpadSettings; + + m_keyboard_mask = new unsigned char[ KEYMAP_SIZE ]; + + // open a connection to the X server + m_display = XOpenDisplay(NULL); + + if (!m_display) kdError() << "Can't open display!" << endl; + + // setup keymap + XModifierKeymap *modifiers; + + for (unsigned int i = 0; i < KEYMAP_SIZE; ++i) + m_keyboard_mask[i] = 0xFF; + + modifiers = XGetModifierMapping(m_display); + for (int i = 0; i < 8 * modifiers->max_keypermod; ++i) + { + KeyCode kc = modifiers->modifiermap[i]; + if (kc != 0) clearBit(m_keyboard_mask, kc); + } + + XFreeModifiermap(modifiers); + + m_poll = new TQTimer(this); + connect(m_poll, TQ_SIGNAL(timeout()), this, TQ_SLOT(poll())); + m_poll->start(POLL_INTERVAL); +} + +SynDaemon::~SynDaemon() +{ + setTouchpadOn(true); + m_poll->stop(); + delete m_keyboard_mask; +} + +void SynDaemon::stop() +{ + kapp->quit(); +} + +void SynDaemon::poll() +{ + // do nothing if the user has explicitly disabled the touchpad in the settings + if (!touchpadEnabled()) return; + + if (hasKeyboardActivity()) + { + m_time->start(); + + if (!m_typing) + { + setTouchpadOn(false); + } + } + + else + { + if (m_typing && (m_time->elapsed() > TIME_OUT)) + { + setTouchpadOn(true); + } + } +} + +bool SynDaemon::touchpadEnabled() +{ + // We can't read from our own TouchpadSettings + // as it contains the currently applied value + // so we revert to this + KSimpleConfig cfg("kcminputrc"); + cfg.setGroup("Touchpad"); + return cfg.readBoolEntry("Enabled", true); +} + +void SynDaemon::setTouchpadOn(bool on) +{ + m_typing = !on; + if (!d_settings->setTouchpadEnabled(on)) + { + kdWarning() << "unable to turn off touchpad!" << endl; + } +} + +void SynDaemon::clearBit(unsigned char *ptr, int bit) +{ + int byteNum = bit / 8; + int bitNum = bit % 8; + ptr[byteNum] &= ~(1 << bitNum); +} + +bool SynDaemon::hasKeyboardActivity() +{ + static unsigned char oldKeyState[KEYMAP_SIZE]; + unsigned char keyState[KEYMAP_SIZE]; + + bool result = false; + + XQueryKeymap(m_display, (char*)keyState); + + // find pressed keys + for (unsigned int i = 0; i < KEYMAP_SIZE; ++i) + { + if ((keyState[i] & ~oldKeyState[i]) & m_keyboard_mask[i]) + { + result = true; + break; + } + } + + // ignore any modifiers + for (unsigned int i = 0; i < KEYMAP_SIZE; ++i) + { + if (keyState[i] & ~m_keyboard_mask[i]) + { + result = false; + break; + } + } + + // back up key states... + for (unsigned int i = 0; i < KEYMAP_SIZE; ++i) + { + oldKeyState[i] = keyState[i]; + } + + return result; +} + +extern "C" TDE_EXPORT int main(int argc, char *argv[]) +{ + TDEAboutData aboutData( "syndaemon", I18N_NOOP("Synaptics helper daemon"), + "0.1", I18N_NOOP("Synaptics helper daemon"), TDEAboutData::License_GPL_V2, + "© 2024 Mavridis Philippe" ); + + aboutData.addAuthor("Nadeem Hasan", I18N_NOOP("Author"), "[email protected]"); + aboutData.addAuthor("Mavridis Philippe", I18N_NOOP("Author"), "[email protected]"); + + TDECmdLineArgs::init(argc, argv, &aboutData); + + TDEApplication app; + app.disableSessionManagement(); + app.dcopClient()->registerAs("syndaemon", false); + + SynDaemon syndaemon; + return app.exec(); +}
\ No newline at end of file diff --git a/kcontrol/input/syndaemon.h b/kcontrol/input/syndaemon.h new file mode 100644 index 000000000..0556345eb --- /dev/null +++ b/kcontrol/input/syndaemon.h @@ -0,0 +1,78 @@ +/******************************************************************************* + syndaemon - daemon for the Synaptics touchpad driver which disables touchpad + on keyboard input + + Copyright © 2004 Nadeem Hasan <[email protected]> + Stefan Kombrink <[email protected]> + 2024 Mavridis Philippe <[email protected]> + + This program is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + this program. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************************************/ + +#ifndef __SYNDAEMON_H__ +#define __SYNDAEMON_H__ + +// TQt +#include <tqobject.h> +#include <tqthread.h> + +// DCOP +#include <dcopobject.h> + +// X11 +#include <X11/Xlib.h> +#undef Bool /* fix problems in --enable-final mode */ +#undef None /* fix problems in --enable-final mode */ + +// Syndaemon +#include "syndaemon_iface.h" + + +class TQTimer; + +class SynDaemon : public TQObject, public virtual SynDaemonIface +{ + TQ_OBJECT + + public: + SynDaemon(); + ~SynDaemon(); + + bool touchpadEnabled(); + + public slots: + void poll(); + void setTouchpadOn(bool on); + virtual void stop(); + + protected: + void clearBit(unsigned char* ptr, int bit); + bool hasKeyboardActivity(); + + private: + TouchpadSettings *d_settings; + + TQTimer *m_poll; + TQTime *m_time; + Display *m_display; + bool m_typing; + + static const unsigned int POLL_INTERVAL; + static const unsigned int TIME_OUT; + static const unsigned int KEYMAP_SIZE; + static unsigned char *m_keyboard_mask; +}; + +#endif + diff --git a/kcontrol/input/syndaemon_iface.h b/kcontrol/input/syndaemon_iface.h new file mode 100644 index 000000000..0f3d33929 --- /dev/null +++ b/kcontrol/input/syndaemon_iface.h @@ -0,0 +1,34 @@ +/******************************************************************************* + syndaemon - daemon for the Synaptics touchpad driver which disables touchpad + on keyboard input + + Copyright © 2024 Mavridis Philippe <[email protected]> + + This program is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + this program. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************************************/ + +#ifndef __SYNDAEMON_IFACE_H__ +#define __SYNDAEMON_IFACE_H__ + +// DCOP +#include <dcopobject.h> + +class SynDaemonIface : virtual public DCOPObject +{ + K_DCOP + k_dcop: + virtual void stop() = 0; +}; + +#endif
\ No newline at end of file diff --git a/kcontrol/input/touchpad.cpp b/kcontrol/input/touchpad.cpp new file mode 100644 index 000000000..d18e3b698 --- /dev/null +++ b/kcontrol/input/touchpad.cpp @@ -0,0 +1,528 @@ +/******************************************************************************* + tdecm_touchpad + A touchpad module for the TDE Control Centre + + Copyright © 2024 Mavridis Philippe <[email protected]> + + This program is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + this program. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************************************/ + +// TQt +#include <tqwhatsthis.h> +#include <tqtooltip.h> +#include <tqtabwidget.h> +#include <tqradiobutton.h> +#include <tqbuttongroup.h> +#include <tqcombobox.h> +#include <tqcheckbox.h> +#include <tqslider.h> +#include <tqlayout.h> +#include <tqlabel.h> + +// TDE +#include <tdeglobal.h> +#include <kiconloader.h> +#include <tdeaboutdata.h> +#include <kdialog.h> +#include <kdebug.h> + +// TouchpadConfig +#include "touchpad_settings.h" +#include "touchpad.h" +#include "touchpad.moc" + + +/******************************* TouchpadConfig *******************************/ +TouchpadConfig::TouchpadConfig(TQWidget *parent, const char *name) +: TDECModule(parent, name), + m_error(nullptr) +{ + TDEGlobal::iconLoader()->addAppDir("kcminput"); + + d_settings = new TouchpadSettings; + d_settings->apply(); + + if (!d_settings->supportedTouchpad()) + { + TQString error_str; + + if (!d_settings->foundTouchpad()) + { + error_str = i18n( + "<qt><h1>Touchpad not found</h1>" + "Please check your system installation.</qt>" + ); + } + + else IF_DRIVER(None) + { + error_str = i18n( + "<qt><h1>Unsupported driver</h1>" + "<p>This module only supports the following drivers:" + "<p>Libinput, Synaptics</qt>" + ); + } + + else error_str = i18n("<qt><h1>Unknown error</h1></qt>"); + + m_error = new TQLabel(error_str, this); + m_error->setAlignment(TQt::AlignCenter); + new TQVBoxLayout(this); + layout()->add(m_error); + return; + } + + initWidgets(); + load(); + + kdDebug() << "managed touchpad: " << d_settings->touchpad().name + << " (xid = " << d_settings->touchpad().id << ")" << endl; + + TDEAboutData* about = new TDEAboutData( + "tdecm_touchpad", + I18N_NOOP("Touchpad"), + 0, 0, + TDEAboutData::License_GPL, + I18N_NOOP("(c) 2024 Mavridis Philippe") + ); + about->addAuthor("Mavridis Philippe", 0, 0); + setAboutData(about); +} + +TouchpadConfig::~TouchpadConfig() +{ + DEL(m_error) + DEL(d_settings); +} + +void TouchpadConfig::initWidgets() +{ + // Create containers + m_container = new TQTabWidget(this); + + TQFrame *touchpadWidget = new TQFrame(this); + touchpadWidget->setMargin(0); + new TQVBoxLayout(touchpadWidget); + + // Enable option + TQFrame *enableCheckBox = new TQFrame(touchpadWidget); + enableCheckBox->setSizePolicy(TQSizePolicy::Maximum, TQSizePolicy::Fixed); + + m_enabled = new TQCheckBox(i18n("Enable touchpad"), enableCheckBox); + TQWhatsThis::add(m_enabled, i18n( + "This option determines whether the touchpad is enabled or disabled" + )); + + // Compute margin for idented checkboxes based on checkbox height + int lmargin = m_enabled->height() / 2; + + // Align the Enable checkbox with the other options below + new TQHBoxLayout(enableCheckBox); + enableCheckBox->layout()->addItem(new TQSpacerItem(lmargin, lmargin, TQSizePolicy::Fixed)); + enableCheckBox->layout()->add(m_enabled); + + // Settings frame + TQFrame *settingsFrame = new TQFrame(touchpadWidget); + TQGridLayout *grid = new TQGridLayout(settingsFrame, 3, 2, KDialog::spacingHint()); + + connect(m_enabled, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed())); + connect(m_enabled, TQ_SIGNAL(toggled(bool)), settingsFrame, TQ_SLOT(setEnabled(bool))); + + // Behaviour + m_behaviour = new TQGroupBox(2, TQt::Vertical, i18n("Behaviour"), settingsFrame); + + m_offWhileTyping = new TQCheckBox(i18n("Disable touchpad while typing"), m_behaviour); + TQWhatsThis::add(m_offWhileTyping, i18n( + "If this option is checked, the touchpad is disabled while you are typing, so as " + "to prevent accidental cursor movement and clicks." + )); + connect(m_offWhileTyping, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed())); + + m_mbEmulation = new TQCheckBox(i18n("Middle button emulation"), m_behaviour); + TQWhatsThis::add(m_mbEmulation, i18n( + "If this option is enabled, a simultaneous left and right button click is " + "automatically transformed into a middle button click." + )); + IF_DRIVER(LibInput) + { + connect(m_mbEmulation, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed())); + } + else + { + DISABLE_UNSUPPORTED_OPTION(m_mbEmulation); + } + + // Speed + m_speed = new TQGroupBox(4, TQt::Vertical, i18n("Speed"), settingsFrame); + + TQLabel *accelLabel = new TQLabel(i18n("Acceleration:"), m_speed); + + m_accel = new TQSlider(-100, 100, 5, 0, TQt::Horizontal, m_speed); + + TQWidget *accelSliderMarkBox = new TQWidget(m_speed); + new TQHBoxLayout(accelSliderMarkBox); + accelSliderMarkBox->layout()->setAutoAdd(true); + + TQLabel *l; + l = new TQLabel(i18n("Slower"), accelSliderMarkBox); + l->setAlignment(TQt::AlignLeft); + l = new TQLabel(i18n("Normal"), accelSliderMarkBox); + l->setAlignment(TQt::AlignHCenter); + l = new TQLabel(i18n("Faster"), accelSliderMarkBox); + l->setAlignment(TQt::AlignRight); + l = nullptr; + + m_accelAdaptive = new TQCheckBox(i18n("Use adaptive profile"), m_speed); + + IF_DRIVER(LibInput) + { + connect(m_accel, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(changed())); + connect(m_accelAdaptive, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed())); + + // check available profiles + TQValueList<bool> accelProfilesAvail = d_settings->getAccelProfilesAvailability(); + if (!accelProfilesAvail.count() || accelProfilesAvail[0] == 0 || accelProfilesAvail[1] == 0) + { + m_accelAdaptive->setEnabled(false); + } + } + else + { + DISABLE_UNSUPPORTED_OPTION(m_speed) + } + + // Tapping + m_tapping = new TQGroupBox(5, TQt::Vertical, i18n("Tapping"), settingsFrame); + + m_tapClick = new TQCheckBox(i18n("Tap to click"), m_tapping); + TQWhatsThis::add(m_tapClick, i18n( + "If this option is checked, a tap on the touchpad is interpreted as a button click." + )); + connect(m_tapClick, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed())); + connect(m_tapClick, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(updateWidgetStates())); + + m_tapDrag = new TQCheckBox(i18n("Tap-and-drag"), m_tapping); + TQWhatsThis::add(m_tapDrag, i18n( + "Tap-and-drag is a tap which is immediately followed by a finger down and that finger " + "being held down emulates a button press. Moving the finger around can thus drag the " + "selected item on the screen." + )); + connect(m_tapDrag, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed())); + connect(m_tapDrag, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(updateWidgetStates())); + + m_tapDragLock = new TQCheckBox(i18n("Tap-and-drag lock"), m_tapping); + TQWhatsThis::add(m_tapDragLock, i18n( + "When enabled, lifting a finger while dragging will not immediately stop dragging." + )); + + IF_DRIVER(LibInput) + { + connect(m_tapDragLock, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed())); + } + else + { + DISABLE_UNSUPPORTED_OPTION(m_tapDragLock); + } + + TQLabel *tapMappingLabel = new TQLabel(i18n("Two-finger tap:"), m_tapping); + m_tapMapping = new TQComboBox(m_tapping); // "lrm" and "lmr" + m_tapMapping->setSizePolicy(TQSizePolicy::Maximum, TQSizePolicy::Fixed); + m_tapMapping->insertItem( + TDEGlobal::iconLoader()->loadIcon("mouse3", TDEIcon::Small), + i18n("Right click (three-finger tap for middle click)"), + 0); + m_tapMapping->insertItem( + TDEGlobal::iconLoader()->loadIcon("mouse2", TDEIcon::Small), + i18n("Middle click (three-finger tap for right click)"), + 1); + connect(m_tapMapping, TQ_SIGNAL(activated(const TQString&)), this, TQ_SLOT(changed())); + + // Scrolling options + m_scrolling = new TQGroupBox(4, TQt::Vertical, i18n("Scrolling options"), settingsFrame); + + m_verScroll = new TQCheckBox(i18n("Vertical scrolling"), m_scrolling); + TQWhatsThis::add(m_verScroll, i18n( + "This option enables/disables the vertical scrolling gesture on the touchpad. " + "(The actual gesture depends on the selected scroll method.) " + "Unless the used driver is Synaptics, disabling vertical scrolling also disables " + "horizontal scrolling." + )); + connect(m_verScroll, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed())); + connect(m_verScroll, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(updateWidgetStates())); + + m_horScroll = new TQCheckBox(i18n("Horizontal scrolling"), m_scrolling); + TQWhatsThis::add(m_horScroll, i18n( + "This option enables/disables the horizontal scrolling gesture on the touchpad. " + "(The actual gesture depends on the selected scroll method.)" + )); + connect(m_horScroll, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed())); + connect(m_horScroll, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(updateWidgetStates())); + + m_naturalScroll = new TQCheckBox(i18n("Reverse scroll direction"), m_scrolling); + TQWhatsThis::add(m_naturalScroll, i18n( + "If this option is checked, the scrolling direction is reversed to resemble natural " + "movement of content. This feature is also called natural scrolling." + )); + connect(m_naturalScroll, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed())); + + m_naturalScrollDirections = new TQFrame(m_scrolling); + TQWhatsThis::add(m_naturalScrollDirections, i18n( + "This option allows you to select the scrolling directions to which reversed scrolling will be applied. " + "It is only available if the Synaptics driver is used." + )); + TQGridLayout *nsdl = new TQGridLayout(m_naturalScrollDirections, 2, 2, KDialog::spacingHint()); + m_horNaturalScroll = new TQCheckBox(i18n("Apply to horizontal scrolling"), m_naturalScrollDirections); + m_verNaturalScroll = new TQCheckBox(i18n("Apply to vertical scrolling"), m_naturalScrollDirections); + nsdl->addItem(new TQSpacerItem(lmargin, lmargin, TQSizePolicy::Fixed), 0, 0); + nsdl->addItem(new TQSpacerItem(lmargin, lmargin, TQSizePolicy::Fixed), 1, 0); + nsdl->addWidget(m_horNaturalScroll, 0, 1); + nsdl->addWidget(m_verNaturalScroll, 1, 1); + + IF_DRIVER(Synaptics) + { + connect(m_horNaturalScroll, TQ_SIGNAL(toggled(bool)), TQ_SLOT(changed())); + connect(m_verNaturalScroll, TQ_SIGNAL(toggled(bool)), TQ_SLOT(changed())); + connect(m_naturalScroll, TQ_SIGNAL(toggled(bool)), TQ_SLOT(updateWidgetStates())); + } + else + { + // Not only disable, but also force checkboxes to be checked on + // so that the user knows that the natural scrolling option applies + // always to both directions + DISABLE_UNSUPPORTED_OPTION(m_naturalScrollDirections); + m_horNaturalScroll->setChecked(true); + m_verNaturalScroll->setChecked(true); + } + + // Scrolling methods + m_scrollMethods = new TQButtonGroup(3, TQt::Vertical, i18n("Scrolling method"), settingsFrame); + TQWhatsThis::add(m_scrollMethods, i18n( + "Here you can select your preferred scrolling method. The two most common options are " + "two-finger scrolling and edge scrolling. Two-finger scrolling entails a movement with " + "two fingers vertically or horizontally upon the surface of the touchpad. Edge scrolling " + "on the other hand tracks movements with one finger along the right or bottom edge of " + "the touchpad." + )); + connect(m_scrollMethods, TQ_SIGNAL(clicked(int)), this, TQ_SLOT(changed())); + + TQStringList scrollMethodLabels; + scrollMethodLabels << i18n("Two-finger") + << i18n("Edge"); + + IF_DRIVER(LibInput) + { + scrollMethodLabels << i18n("Button"); + } + + TQValueList<bool> scrollMethodAvail = d_settings->getScrollMethodsAvailability(); + Q_ASSERT(scrollMethodLabels.count() == scrollMethodAvail.count()); + + for (int i = 0; i < scrollMethodLabels.count(); ++i) + { + TQRadioButton *rad = new TQRadioButton(scrollMethodLabels[i], m_scrollMethods); + rad->setEnabled(scrollMethodAvail[i]); + } + + // Finalize layout + grid->addWidget(m_behaviour, 0, 0); + grid->addWidget(m_speed, 1, 0); + grid->addMultiCellWidget(m_scrolling, 0, 1, 1, 1); + grid->addWidget(m_scrollMethods, 2, 1); + grid->addWidget(m_tapping, 2, 0); + grid->addItem(new TQSpacerItem(10, 10)); + + // Synaptics deprecation warning + IF_DRIVER(Synaptics) + { + TQLabel *l = new TQLabel(i18n( + "<qt><b>Warning:</b> The Synaptics driver has been deprecated.</qt>" + ), settingsFrame); + TQWhatsThis::add(l, i18n( + "<qt><p><b>The Synaptics driver is no longer in active development.</b>" + "<p>While Libinput is the preferred choice for handling input devices, " + "you might still have valid reasons to use the older Synaptics driver " + "in its place. Please bear in mind that you will probably not receive " + "updates and bug fixes from its upstream.</qt>" + )); + grid->addMultiCellWidget(l, 3, 3, 0, 1); + } + + touchpadWidget->layout()->add(enableCheckBox); + touchpadWidget->layout()->add(settingsFrame); + m_container->addTab(touchpadWidget, SmallIconSet("input-touchpad"), d_settings->touchpad().name); + + new TQVBoxLayout(this, KDialog::marginHint()); + layout()->add(m_container); +} + +// We handle more complex UI cases here +void TouchpadConfig::updateWidgetStates() +{ + if (!d_settings->foundTouchpad()) return; + + // Scrolling related options + bool on; + + IF_DRIVER(LibInput) + { + // To disable vertical scrolling under LibInput one has to disable scrolling entirely + // so we mirror this in the UI + on = m_verScroll->isChecked(); + m_horScroll->setEnabled(on); + } + + else + { + // In case we can control both horizontal and vertical scrolling separately, any UI + // changes should be triggered when both are disabled + on = m_verScroll->isChecked() || m_horScroll->isChecked(); + + // Only enable natural scroll directions options when not under LibInput + m_naturalScrollDirections->setEnabled(on && m_naturalScroll->isChecked()); + } + + m_naturalScroll->setEnabled(on); + m_scrollMethods->setEnabled(on); + + // Tapping related options + m_tapDrag->setEnabled(m_tapClick->isChecked()); + + IF_DRIVER(LibInput) + { + m_tapDragLock->setEnabled(m_tapClick->isChecked() && m_tapDrag->isChecked()); + } +} + +void TouchpadConfig::defaults() +{ + load(true); +} + +void TouchpadConfig::load() +{ + load(false); +} + +void TouchpadConfig::load(bool useDefaults) +{ + if (!d_settings->foundTouchpad()) return; + + d_settings->load(); + + m_enabled->setChecked(d_settings->enabled); + + // Behaviour + m_offWhileTyping->setChecked(d_settings->offWhileTyping); + + IF_DRIVER(LibInput) + { + m_mbEmulation->setChecked(d_settings->midButtonEmulation); + } + + // Speed + IF_DRIVER(LibInput) + { + m_accel->setValue(d_settings->accelSpeed); + m_accelAdaptive->setChecked(d_settings->accelProfile == 0); + } + + // Tapping + m_tapClick->setChecked(d_settings->tapClick); + m_tapDrag->setChecked(d_settings->tapDrag); + + IF_DRIVER(LibInput) + { + m_tapDragLock->setChecked(d_settings->tapDragLock); + } + + m_tapMapping->setCurrentItem(d_settings->tapMapping); + + // Scrolling options + m_horScroll->setChecked(d_settings->scrollDirections & TQt::Horizontal); + m_verScroll->setChecked(d_settings->scrollDirections & TQt::Vertical); + m_naturalScroll->setChecked(d_settings->naturalScroll); + IF_DRIVER(Synaptics) + { + m_naturalScrollDirections->setEnabled(d_settings->naturalScroll); + m_horNaturalScroll->setChecked(d_settings->naturalScrollDirections & TQt::Horizontal); + m_verNaturalScroll->setChecked(d_settings->naturalScrollDirections & TQt::Vertical); + } + + IF_DRIVER(LibInput) + { + m_horScroll->setEnabled(m_verScroll->isOn()); + m_naturalScroll->setEnabled(m_verScroll->isOn()); + m_scrollMethods->setEnabled(m_verScroll->isOn()); + } + + // Scrolling method + m_scrollMethods->setButton(d_settings->scrollMethod); +} + +void TouchpadConfig::save() +{ + if (!d_settings->foundTouchpad()) return; + + d_settings->enabled = m_enabled->isChecked(); + + // Behaviour + d_settings->offWhileTyping = m_offWhileTyping->isChecked(); + + IF_DRIVER(LibInput) + { + d_settings->midButtonEmulation = m_mbEmulation->isChecked(); + } + + // Speed + IF_DRIVER(LibInput) + { + d_settings->accelSpeed = m_accel->value(); + d_settings->accelProfile = (m_accelAdaptive->isChecked() ? 0 : 1); + } + + // Tapping + d_settings->tapClick = m_tapClick->isChecked(); + d_settings->tapDrag = m_tapDrag->isChecked(); + + IF_DRIVER(LibInput) + { + d_settings->tapDragLock = m_tapDragLock->isChecked(); + } + + d_settings->tapMapping = m_tapMapping->currentItem(); + + // Scrolling options + int scrollDirections = 0; + if (m_horScroll->isChecked()) scrollDirections |= TQt::Horizontal; + if (m_verScroll->isChecked()) scrollDirections |= TQt::Vertical; + d_settings->scrollDirections = scrollDirections; + + d_settings->naturalScroll = m_naturalScroll->isChecked(); + + int naturalScrollDirections = 0; + if (m_horNaturalScroll->isChecked()) naturalScrollDirections |= TQt::Horizontal; + if (m_verNaturalScroll->isChecked()) naturalScrollDirections |= TQt::Vertical; + d_settings->naturalScrollDirections = naturalScrollDirections; + + // Scrolling method + d_settings->scrollMethod = m_scrollMethods->selectedId(); + + d_settings->save(); + d_settings->apply(); +} + +Touchpad TouchpadConfig::touchpad() +{ + return d_settings->touchpad(); +} diff --git a/kcontrol/input/touchpad.desktop b/kcontrol/input/touchpad.desktop new file mode 100644 index 000000000..d943749c1 --- /dev/null +++ b/kcontrol/input/touchpad.desktop @@ -0,0 +1,16 @@ +[Desktop Entry] +Exec=tdecmshell touchpad +Icon=input-touchpad +Type=Application +X-DocPath=kcontrol/touchpad/index.html + +X-TDE-Library=input +X-TDE-FactoryName=touchpad +X-TDE-Init=touchpad +X-TDE-ParentApp=kcontrol +X-TDE-Test-Module=true + +Name=Touchpad +Comment=Touchpad settings +Keywords=Touchpad;Tap to click;Mouse;Mouse buttons;Input Devices;Button Mapping;Tap;Click;mapping;right handed;left handed; +Categories=Qt;TDE;X-TDE-settings-hardware;
\ No newline at end of file diff --git a/kcontrol/input/touchpad.h b/kcontrol/input/touchpad.h new file mode 100644 index 000000000..088f7164a --- /dev/null +++ b/kcontrol/input/touchpad.h @@ -0,0 +1,97 @@ +/******************************************************************************* + tdecm_touchpad + A touchpad module for the TDE Control Centre + + Copyright © 2024 Mavridis Philippe <[email protected]> + + This program is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + this program. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************************************/ + +#ifndef __TOUCHPAD_H__ +#define __TOUCHPAD_H__ + +// TDE +#include <tdecmodule.h> +#include <tdelocale.h> + +// Macros +#define OPTION_NOT_SUPPORTED I18N_NOOP("This option is not compatible with the currently used driver") +#define DISABLE_UNSUPPORTED_OPTION(optionWidget) \ + optionWidget->setEnabled(false); \ + TQToolTip::add(optionWidget, i18n(OPTION_NOT_SUPPORTED)); + +// Forward definitions +class TQTabWidget; +class TQButtonGroup; +class TQGroupBox; +class TQCheckBox; +class TQComboBox; +class TQSlider; +class TQLabel; +class TQFrame; +class TDEConfig; +class TouchpadSettings; +struct Touchpad; + + +/******************************* TouchpadConfig *******************************/ +class TouchpadConfig : public TDECModule +{ + TQ_OBJECT + + public: + TouchpadConfig(TQWidget *parent, const char *name); + ~TouchpadConfig(); + + void load(); + void load(bool useDefaults); + void save(); + void defaults(); + + Touchpad touchpad(); + + protected: + void initWidgets(); + + protected slots: + void updateWidgetStates(); + + private: + TouchpadSettings *d_settings; + + TQTabWidget *m_container; + TQLabel *m_error; + TQCheckBox *m_enabled; + + TQGroupBox *m_behaviour; + TQCheckBox *m_offWhileTyping, *m_leftHanded, *m_mbEmulation; + + TQGroupBox *m_speed; + TQSlider *m_accel; + TQCheckBox *m_accelAdaptive; + + TQGroupBox *m_tapping; + TQCheckBox *m_tapClick, *m_tapDrag, *m_tapDragLock; + TQComboBox *m_tapMapping; + + TQGroupBox *m_scrolling; + TQCheckBox *m_horScroll, *m_verScroll, *m_naturalScroll, + *m_horNaturalScroll, *m_verNaturalScroll; + + TQFrame *m_naturalScrollDirections; + + TQButtonGroup *m_scrollMethods; +}; + +#endif // __TOUCHPAD_H__ diff --git a/kcontrol/input/touchpad_settings.cpp b/kcontrol/input/touchpad_settings.cpp new file mode 100644 index 000000000..1230efcee --- /dev/null +++ b/kcontrol/input/touchpad_settings.cpp @@ -0,0 +1,409 @@ +/******************************************************************************* + tdecm_touchpad + A touchpad module for the TDE Control Centre + + Copyright © 2024 Mavridis Philippe <[email protected]> + + This program is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + this program. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************************************/ + +// TDE +#include <tdeapplication.h> +#include <tdeconfig.h> +#include <kdebug.h> + +// DCOP +#include <dcopref.h> + +// X11 +#include <X11/extensions/XInput.h> +#include <X11/extensions/XInput2.h> + +// tdecm_touchpad +#include "xiproperty.h" +#include "touchpad_settings.h" + + +/****************************** TouchpadSettings ******************************/ +TouchpadSettings::TouchpadSettings() +: m_foundTouchpad(false) +{ + findTouchpad(); +} + +bool TouchpadSettings::findTouchpad() +{ + Display *display = tqt_xdisplay(); + ATOM(isTouchpad, XI_TOUCHPAD) + ATOM(isLibinput, "libinput Send Events Mode Enabled") + ATOM(isSynaptics, "Synaptics Off") + + int devicesCount; + XDeviceInfo *deviceList = XListInputDevices(display, &devicesCount); + + for (int d = 0; d < devicesCount; ++d) + { + if (deviceList[d].type != isTouchpad) continue; + + m_foundTouchpad = true; + m_touchpad.init(deviceList[d].id, deviceList[d].name); + + int propertiesCount; + Atom *propertiesList = XIListProperties(display, deviceList[d].id, + &propertiesCount); + for (int p = 0; p < propertiesCount; ++p) + { + if (propertiesList[p] == isLibinput) + { + m_touchpad.driver = Touchpad::Driver::LibInput; + break; + } + + else if (propertiesList[p] == isSynaptics) + { + m_touchpad.driver = Touchpad::Driver::Synaptics; + } + } + + XFree(propertiesList); + + if (m_foundTouchpad) break; + } + + XFreeDeviceList(deviceList); + + return m_foundTouchpad; +} + +void TouchpadSettings::load(bool defaults) +{ + TDEConfig cfg("kcminputrc"); + cfg.setGroup("Touchpad"); + cfg.setReadDefaults(defaults); + + enabled = cfg.readBoolEntry("Enabled", true); + + // Behaviour + offWhileTyping = cfg.readBoolEntry("OffWhileTyping", false); + + IF_DRIVER(LibInput) + { + midButtonEmulation = cfg.readBoolEntry("MidButtonEmulation", false); + } + + // Speed + IF_DRIVER(LibInput) + { + accelSpeed = cfg.readNumEntry("AccelSpeed", 0); + accelProfile = cfg.readNumEntry("AccelProfile", 0); + } + + // Tapping + tapClick = cfg.readBoolEntry("TapToClick", true); + tapDrag = cfg.readBoolEntry("TapAndDrag", true); + + IF_DRIVER(LibInput) + { + tapDragLock = cfg.readBoolEntry("TapAndDragLock", false); + } + + tapMapping = cfg.readNumEntry("TapMapping", 0); + + // Scrolling options + int both = TQt::Horizontal | TQt::Vertical; + scrollDirections = cfg.readNumEntry("ScrollDirections", both); + naturalScroll = cfg.readBoolEntry("NaturalScroll", false); + naturalScrollDirections = cfg.readNumEntry("NaturalScrollDirections", both); + + // Scrolling method + scrollMethod = cfg.readNumEntry("ScrollMethod", 0); +} + +void TouchpadSettings::save() +{ + TDEConfig cfg("kcminputrc"); + cfg.setGroup("Touchpad"); + + cfg.writeEntry("Enabled", enabled); + + // Behaviour + cfg.writeEntry("OffWhileTyping", offWhileTyping); + + IF_DRIVER(LibInput) + { + cfg.writeEntry("MidButtonEmulation", midButtonEmulation); + } + + // Speed + cfg.writeEntry("AccelSpeed", accelSpeed); + cfg.writeEntry("AccelProfile", accelProfile); + + // Tapping + cfg.writeEntry("TapToClick", tapClick); + cfg.writeEntry("TapAndDrag", tapDrag); + + IF_DRIVER(LibInput) + { + cfg.writeEntry("TapAndDragLock", tapDragLock); + } + + cfg.writeEntry("TapMapping", tapMapping); + + // Scrolling options + cfg.writeEntry("ScrollDirections", scrollDirections); + cfg.writeEntry("NaturalScroll", naturalScroll); + cfg.writeEntry("NaturalScrollDirections", naturalScrollDirections); + + // Scrolling method + cfg.writeEntry("ScrollMethod", scrollMethod); + + cfg.sync(); +} + +bool TouchpadSettings::setTouchpadEnabled(bool on) +{ + enabled = on; + + XIProperty *prop = nullptr; + int fail = 0; + + IF_DRIVER(LibInput) + { + SET_PROP("Device Enabled", b) + { + prop->b[0] = enabled; + prop->set(); + } + } + + else + IF_DRIVER(Synaptics) + { + SET_PROP("Synaptics Off", b) + { + prop->b[0] = !enabled; + prop->set(); + } + } + + return !fail; +} + +void TouchpadSettings::apply(bool force) +{ + kdDebug() << "applying touchpad settings" << endl; + if (!foundTouchpad()) + { + kdWarning() << "no supported touchpads! settings not applied" << endl; + return; + } + + load(); + + Display *display = tqt_xdisplay(); + XIProperty *prop = nullptr; + int fail = 0; + + if (!setTouchpadEnabled(enabled)) + ++fail; + + IF_DRIVER(LibInput) + { + kdDebug() << "driver: libinput" << endl; + + SET_PROP("libinput Disable While Typing Enabled", b) + { + prop->b[0] = offWhileTyping; + prop->set(); + } + + SET_PROP("libinput Middle Emulation Enabled", b) + { + prop->b[0] = midButtonEmulation; + prop->set(); + } + + SET_PROP("libinput Accel Speed", f) + { + float val = accelSpeed; + val /= 100; + prop->f[0] = val; + prop->set(); + } + + SET_PROP("libinput Accel Profile Enabled", b) + { + prop->b[0] = (accelProfile == 0); + prop->b[1] = (accelProfile == 1); + prop->set(); + } + + SET_PROP("libinput Tapping Enabled", b) + { + prop->b[0] = tapClick; + prop->set(); + } + + SET_PROP("libinput Tapping Drag Enabled", b) + { + prop->b[0] = tapClick && tapDrag; + prop->set(); + } + + SET_PROP("libinput Tapping Drag Lock Enabled", b) + { + prop->b[0] = tapClick && tapDrag && tapDragLock; + prop->set(); + } + + SET_PROP("libinput Tapping Button Mapping Enabled", b) + { + prop->b[0] = (tapMapping == 0); + prop->b[1] = (tapMapping == 1); + prop->set(); + } + + SET_PROP("libinput Horizontal Scroll Enabled", b) + { + prop->b[0] = scrollDirections & TQt::Horizontal; + prop->set(); + } + + SET_PROP("libinput Natural Scrolling Enabled", b) + { + prop->b[0] = naturalScroll; + prop->set(); + } + + SET_PROP("libinput Scroll Method Enabled", b) + { + prop->b[0] = scrollDirections ? (scrollMethod == 0) : 0; // two-finger + prop->b[1] = scrollDirections ? (scrollMethod == 1) : 0; // edge + prop->b[2] = scrollDirections ? (scrollMethod == 2) : 0; // button + prop->set(); + } + } + + else IF_DRIVER(Synaptics) + { + kdDebug() << "driver: synaptics" << endl; + + SET_PROP("Synaptics Tap Action", b) + { + prop->b[0] = 0; + prop->b[1] = 0; + prop->b[2] = 0; + prop->b[3] = 0; + prop->b[4] = tapClick ? 1 : 0; // 1 finger + prop->b[5] = tapClick ? (tapMapping == 0 ? 3 : 2) : 0; // 2 fingers + prop->b[6] = tapClick ? (tapMapping == 0 ? 2 : 3) : 0; // 3 fingers + prop->set(); + } + + SET_PROP("Synaptics Gestures", b) + { + prop->b[0] = tapDrag; + prop->set(); + } + + SET_PROP("Synaptics Edge Scrolling", b) + { + prop->b[0] = scrollMethod == 1 ? (scrollDirections & TQt::Vertical ? 1 : 0) : 0; + prop->b[1] = scrollMethod == 1 ? (scrollDirections & TQt::Horizontal ? 1 : 0) : 0; + prop->b[2] = 0; // corner + prop->set(); + } + + SET_PROP("Synaptics Two-Finger Scrolling", b) + { + prop->b[0] = scrollMethod == 0 ? (scrollDirections & TQt::Vertical ? 1 : 0) : 0; + prop->b[1] = scrollMethod == 0 ? (scrollDirections & TQt::Horizontal ? 1 : 0) : 0; + prop->set(); + } + + SET_PROP("Synaptics Scrolling Distance", i) + { + prop->i[0] = naturalScroll && naturalScrollDirections & TQt::Vertical ? -80 : 80; + prop->i[1] = naturalScroll && naturalScrollDirections & TQt::Horizontal ? -80 : 80; + prop->set(); + } + + // start/stop syndaemon + DCOPRef syndaemon("syndaemon", "syndaemon"); + syndaemon.call("stop()"); + + if (offWhileTyping) + { + kapp->tdeinitExec("syndaemon"); + } + } + + if (fail > 0) + kdWarning() << "some options could not be applied!" << endl; +} + +TQValueList<bool> TouchpadSettings::getScrollMethodsAvailability() +{ + TQValueList<bool> avail; + + IF_DRIVER(LibInput) + { + PROP(propScrollMethodsAvail, "libinput Scroll Methods Available") + for (int i = 0; i < propScrollMethodsAvail.count(); ++i) + { + avail.append(propScrollMethodsAvail[i].toBool()); + } + } + + IF_DRIVER(Synaptics) + { + avail.append(1); // two-finger + avail.append(1); // edge + } + + return avail; +} + +TQValueList<bool> TouchpadSettings::getAccelProfilesAvailability() +{ + TQValueList<bool> avail; + + IF_DRIVER(LibInput) + { + PROP(propAccelProfilesAvail, "libinput Accel Profiles Available") + for (int i = 0; i < propAccelProfilesAvail.count(); ++i) + { + avail.append(propAccelProfilesAvail[i].toBool()); + } + } + + IF_DRIVER(Synaptics) { /* TODO no support yet */ } + + return avail; +} + +Touchpad TouchpadSettings::touchpad() +{ + return m_touchpad; +} + +bool TouchpadSettings::foundTouchpad() +{ + return m_foundTouchpad; +} + +bool TouchpadSettings::supportedTouchpad() +{ + return m_foundTouchpad && m_touchpad.driver != Touchpad::Driver::None; +}
\ No newline at end of file diff --git a/kcontrol/input/touchpad_settings.h b/kcontrol/input/touchpad_settings.h new file mode 100644 index 000000000..8cdfea951 --- /dev/null +++ b/kcontrol/input/touchpad_settings.h @@ -0,0 +1,107 @@ +/******************************************************************************* + tdecm_touchpad + A touchpad module for the TDE Control Centre + + Copyright © 2024 Mavridis Philippe <[email protected]> + + This program is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + this program. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************************************/ + +#ifndef __TOUCHPAD_SETTINGS_H__ +#define __TOUCHPAD_SETTINGS_H__ + +// TQt +#include <tqvaluelist.h> + +// Macros +#define DEL(var) \ + if (var) { delete var; var = nullptr; } + +#define ATOM(var, atom) \ + Atom var = XInternAtom(display, atom, true); + +#define PROP(var, property) \ + XIProperty var = XIProperty(m_touchpad.id, property); + +#define SET_PROP(property, type) \ + DEL(prop) \ + prop = new XIProperty(m_touchpad.id, property); \ + if (prop->type == nullptr) \ + { \ + kdWarning() << "Failed to set property " << property << endl; \ + ++fail; \ + } \ + else + +#define IF_DRIVER(drv) \ + if (touchpad().driver == Touchpad::Driver::drv) + + +/****************************** struct Touchpad *******************************/ +#undef None + +struct Touchpad +{ + enum Driver { None, LibInput, Synaptics }; + + bool valid = false; + unsigned int id; + TQCString name; + Driver driver = Touchpad::Driver::None; + + void init(unsigned int _id, TQCString _name) + { + valid = true; + id = _id; + name = _name; + } +}; + + +/***************************** TouchpadSettings *******************************/ +class TouchpadSettings +{ + public: + TouchpadSettings(); + + void load(bool defaults = false); + void save(); + void apply(bool force = false); + + TQValueList<bool> getScrollMethodsAvailability(); + TQValueList<bool> getAccelProfilesAvailability(); + + bool enabled, tapClick, tapDrag, tapDragLock, tapMapping, offWhileTyping, + leftHandedMode, midButtonEmulation, naturalScroll, scrollMethod; + int scrollDirections, naturalScrollDirections; + + int accelSpeed, accelProfile; + + bool foundTouchpad(); + Touchpad touchpad(); + + // Enable/disable touchpad without applying all settings + bool setTouchpadEnabled(bool on); + + bool supportedTouchpad(); + + protected: + bool findTouchpad(); + + private: + Touchpad m_touchpad; + bool m_foundTouchpad; +}; + +#endif // __TOUCHPAD_SETTINGS_H__
\ No newline at end of file diff --git a/kcontrol/input/xiproperty.h b/kcontrol/input/xiproperty.h new file mode 100644 index 000000000..ddbdf4b16 --- /dev/null +++ b/kcontrol/input/xiproperty.h @@ -0,0 +1,123 @@ +/******************************************************************************* + XIGetProperty/XIChangeProperty wrapper + + Copyright © 2013 Alexandr Mezin <[email protected]> + Copyright © 2024 Mavridis Philippe <[email protected]> + + This program is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free Software + Foundation, either version 2 of the License, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + this program. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************************************/ + +#ifndef __XI_PROPERTY_H__ +#define __XI_PROPERTY_H__ + +// TQt +#include <tqobject.h> // tqt_xdisplay() +#include <tqvariant.h> + +// X11 +#include <X11/Xatom.h> + + +class XIProperty +{ + public: + XIProperty() + : device(-1), + type(0), + format(0), + num_items(0), + data(0), + b(nullptr), + i(nullptr), + f(nullptr) + {} + + XIProperty(int device, TQCString propertyName) + : device(device), + type(0), + format(0), + num_items(0), + data(0), + b(nullptr), + i(nullptr), + f(nullptr) + { + Display *disp = tqt_xdisplay(); + + property = XInternAtom(disp, propertyName, true); + + unsigned char *ptr = nullptr; + unsigned long bytes_after; + + XIGetProperty(disp, device, property, 0, 1000, False, AnyPropertyType, + &type, &format, &num_items, &bytes_after, &ptr); + + data = ptr; + + if (format == CHAR_BIT && type == XA_INTEGER) + { + b = reinterpret_cast<char *>(data); + } + + if (format == sizeof(int) * CHAR_BIT + && (type == XA_INTEGER || type == XA_CARDINAL)) + { + i = reinterpret_cast<int *>(data); + } + + Atom floatType = XInternAtom(disp, "FLOAT", true); + + if (format == sizeof(float) * CHAR_BIT && floatType && type == floatType) + { + f = reinterpret_cast<float *>(data); + } + } + + ~XIProperty() + { + XFree(data); + } + + TQVariant operator[](int offset) + { + if (offset >= num_items) return TQVariant(); + + if (b) return TQVariant(static_cast<int>(b[offset])); + if (i) return TQVariant(i[offset]); + if (f) return TQVariant(f[offset]); + + return TQVariant(); + } + + void set() + { + XIChangeProperty(tqt_xdisplay(), device, property, type, format, XIPropModeReplace, + data, num_items); + } + + int count() { return num_items; } + + public: + char *b; + int *i; + float *f; + + private: + Atom property, type; + int device, format; + unsigned long num_items; + unsigned char *data; +}; + +#endif // __XI_PROPERTY_H__
\ No newline at end of file |