From 4da1db3bd49d1ea04031da9900be3dfc76442dd1 Mon Sep 17 00:00:00 2001 From: DanyLE Date: Tue, 11 Mar 2025 00:00:28 +0100 Subject: [PATCH] Add base support to virtual keyboard wayland extension protocol --- meson.build | 24 +- protocols/virtual-keyboard-unstable-v1.xml | 113 ++ resources/default.keymap | 1461 ++++++++++++++++++++ resources/login-shell/gresource.xml | 1 + resources/session-shell/gresource.xml | 6 + src/background.c | 2 +- src/background.h | 4 +- src/base.h | 1 + src/foreign.c | 50 +- src/foreign.h | 15 +- src/launcher.c | 8 +- src/launcher.h | 4 +- src/login-shell.c | 41 +- src/login-shell.h | 3 +- src/login.c | 2 + src/session-lock.c | 8 +- src/session-lock.h | 6 +- src/session-shell.c | 273 ++++ src/session-shell.h | 20 + src/session.c | 18 +- src/shell.c | 268 +--- src/shell.h | 34 +- src/virtual-keyboard.c | 220 +++ src/virtual-keyboard.h | 13 +- src/wayland.c | 49 +- src/wayland.h | 2 +- 26 files changed, 2320 insertions(+), 326 deletions(-) create mode 100644 protocols/virtual-keyboard-unstable-v1.xml create mode 100644 resources/default.keymap create mode 100644 resources/session-shell/gresource.xml create mode 100644 src/session-shell.c create mode 100644 src/session-shell.h diff --git a/meson.build b/meson.build index 2e722ed..8bb4b95 100644 --- a/meson.build +++ b/meson.build @@ -17,6 +17,7 @@ add_project_arguments( gtk = dependency('gtk4') wayland_client = dependency('wayland-client', version: '>=1.10.0') +xkbcommon = dependency('xkbcommon') # wayland_scanner is required, but we can find it without pkg-config wayland_scanner = find_program('wayland-scanner') @@ -52,24 +53,31 @@ endforeach gnome=import('gnome') base = [ - 'src/base.c' + 'src/base.c', + 'src/shell.c', + 'src/wayland.c', + 'src/virtual-keyboard.c', + wayland_targets ] dm_src = [ base, 'src/launcher.c', 'src/background.c', - 'src/shell.c', + 'src/session-shell.c', 'src/foreign.c', 'src/session-lock.c', - 'src/wayland.c', - 'src/session.c', - wayland_targets] + 'src/session.c'] + +buil_dep = [gtk, gtk_layer_shell, wayland_client, xkbcommon] + +session_resource = gnome.compile_resources('session-resources','resources/session-shell/gresource.xml') executable( 'diya-shell', dm_src, - dependencies: [gtk, gtk_layer_shell, wayland_client]) + session_resource, + dependencies: buil_dep) login_src = [ base, @@ -77,10 +85,10 @@ login_src = [ 'src/login.c' ] -login_resource = gnome.compile_resources('resources','resources/login-shell/gresource.xml') +login_resource = gnome.compile_resources('login-resources','resources/login-shell/gresource.xml') executable( 'diya-login-shell', login_src, login_resource, - dependencies: [gtk, gtk_layer_shell, wayland_client]) \ No newline at end of file + dependencies: buil_dep) \ No newline at end of file diff --git a/protocols/virtual-keyboard-unstable-v1.xml b/protocols/virtual-keyboard-unstable-v1.xml new file mode 100644 index 0000000..5095c91 --- /dev/null +++ b/protocols/virtual-keyboard-unstable-v1.xml @@ -0,0 +1,113 @@ + + + + Copyright © 2008-2011 Kristian Høgsberg + Copyright © 2010-2013 Intel Corporation + Copyright © 2012-2013 Collabora, Ltd. + Copyright © 2018 Purism SPC + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + + The virtual keyboard provides an application with requests which emulate + the behaviour of a physical keyboard. + + This interface can be used by clients on its own to provide raw input + events, or it can accompany the input method protocol. + + + + + Provide a file descriptor to the compositor which can be + memory-mapped to provide a keyboard mapping description. + + Format carries a value from the keymap_format enumeration. + + + + + + + + + + + + + A key was pressed or released. + The time argument is a timestamp with millisecond granularity, with an + undefined base. All requests regarding a single object must share the + same clock. + + Keymap must be set before issuing this request. + + State carries a value from the key_state enumeration. + + + + + + + + + Notifies the compositor that the modifier and/or group state has + changed, and it should update state. + + The client should use wl_keyboard.modifiers event to synchronize its + internal state with seat state. + + Keymap must be set before issuing this request. + + + + + + + + + + + + + + + A virtual keyboard manager allows an application to provide keyboard + input events as if they came from a physical keyboard. + + + + + + + + + Creates a new virtual keyboard associated to a seat. + + If the compositor enables a keyboard to perform arbitrary actions, it + should present an error when an untrusted client requests a new + keyboard. + + + + + + diff --git a/resources/default.keymap b/resources/default.keymap new file mode 100644 index 0000000..d9f9140 --- /dev/null +++ b/resources/default.keymap @@ -0,0 +1,1461 @@ +xkb_keymap { +xkb_keycodes "(unnamed)" { + minimum = 8; + maximum = 255; + = 9; + = 10; + = 11; + = 12; + = 13; + = 14; + = 15; + = 16; + = 17; + = 18; + = 19; + = 20; + = 21; + = 22; + = 23; + = 24; + = 25; + = 26; + = 27; + = 28; + = 29; + = 30; + = 31; + = 32; + = 33; + = 34; + = 35; + = 36; + = 37; + = 38; + = 39; + = 40; + = 41; + = 42; + = 43; + = 44; + = 45; + = 46; + = 47; + = 48; + = 49; + = 50; + = 51; + = 52; + = 53; + = 54; + = 55; + = 56; + = 57; + = 58; + = 59; + = 60; + = 61; + = 62; + = 63; + = 64; + = 65; + = 66; + = 67; + = 68; + = 69; + = 70; + = 71; + = 72; + = 73; + = 74; + = 75; + = 76; + = 77; + = 78; + = 79; + = 80; + = 81; + = 82; + = 83; + = 84; + = 85; + = 86; + = 87; + = 88; + = 89; + = 90; + = 91; + = 92; + = 94; + = 95; + = 96; + = 97; + = 98; + = 99; + = 100; + = 101; + = 102; + = 103; + = 104; + = 105; + = 106; + = 107; + = 108; + = 109; + = 110; + = 111; + = 112; + = 113; + = 114; + = 115; + = 116; + = 117; + = 118; + = 119; + = 120; + = 121; + = 122; + = 123; + = 124; + = 125; + = 126; + = 127; + = 128; + = 129; + = 130; + = 131; + = 132; + = 133; + = 134; + = 135; + = 136; + = 137; + = 138; + = 139; + = 140; + = 141; + = 142; + = 143; + = 144; + = 145; + = 146; + = 147; + = 148; + = 149; + = 150; + = 151; + = 152; + = 153; + = 154; + = 155; + = 156; + = 157; + = 158; + = 159; + = 160; + = 161; + = 162; + = 163; + = 164; + = 165; + = 166; + = 167; + = 168; + = 169; + = 170; + = 171; + = 172; + = 173; + = 174; + = 175; + = 176; + = 177; + = 178; + = 179; + = 180; + = 181; + = 182; + = 183; + = 184; + = 185; + = 186; + = 187; + = 188; + = 189; + = 190; + = 191; + = 192; + = 193; + = 194; + = 195; + = 196; + = 197; + = 198; + = 199; + = 200; + = 201; + = 202; + = 203; + = 204; + = 205; + = 206; + = 207; + = 208; + = 209; + = 210; + = 211; + = 212; + = 213; + = 214; + = 215; + = 216; + = 217; + = 218; + = 219; + = 220; + = 221; + = 222; + = 223; + = 224; + = 225; + = 226; + = 227; + = 228; + = 229; + = 230; + = 231; + = 232; + = 233; + = 234; + = 235; + = 236; + = 237; + = 238; + = 239; + = 240; + = 241; + = 242; + = 243; + = 244; + = 245; + = 246; + = 247; + = 248; + = 249; + = 250; + = 251; + = 252; + = 253; + = 254; + = 255; + indicator 1 = "Caps Lock"; + indicator 2 = "Num Lock"; + indicator 3 = "Scroll Lock"; + indicator 4 = "Compose"; + indicator 5 = "Kana"; + indicator 6 = "Sleep"; + indicator 7 = "Suspend"; + indicator 8 = "Mute"; + indicator 9 = "Misc"; + indicator 10 = "Mail"; + indicator 11 = "Charging"; + indicator 12 = "Shift Lock"; + indicator 13 = "Group 2"; + indicator 14 = "Mouse Keys"; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; + alias = ; +}; + +xkb_types "(unnamed)" { + virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; + + type "ONE_LEVEL" { + modifiers= none; + level_name[Level1]= "Any"; + }; + type "TWO_LEVEL" { + modifiers= Shift; + map[Shift]= Level2; + level_name[Level1]= "Base"; + level_name[Level2]= "Shift"; + }; + type "ALPHABETIC" { + modifiers= Shift+Lock; + map[Shift]= Level2; + map[Lock]= Level2; + level_name[Level1]= "Base"; + level_name[Level2]= "Caps"; + }; + type "SHIFT+ALT" { + modifiers= Shift+Alt; + map[Shift+Alt]= Level2; + level_name[Level1]= "Base"; + level_name[Level2]= "Shift+Alt"; + }; + type "PC_SUPER_LEVEL2" { + modifiers= Mod4; + map[Mod4]= Level2; + level_name[Level1]= "Base"; + level_name[Level2]= "Super"; + }; + type "PC_CONTROL_LEVEL2" { + modifiers= Control; + map[Control]= Level2; + level_name[Level1]= "Base"; + level_name[Level2]= "Control"; + }; + type "PC_LCONTROL_LEVEL2" { + modifiers= LControl; + map[LControl]= Level2; + level_name[Level1]= "Base"; + level_name[Level2]= "LControl"; + }; + type "PC_RCONTROL_LEVEL2" { + modifiers= RControl; + map[RControl]= Level2; + level_name[Level1]= "Base"; + level_name[Level2]= "RControl"; + }; + type "PC_ALT_LEVEL2" { + modifiers= Alt; + map[Alt]= Level2; + level_name[Level1]= "Base"; + level_name[Level2]= "Alt"; + }; + type "PC_LALT_LEVEL2" { + modifiers= LAlt; + map[LAlt]= Level2; + level_name[Level1]= "Base"; + level_name[Level2]= "LAlt"; + }; + type "PC_RALT_LEVEL2" { + modifiers= RAlt; + map[RAlt]= Level2; + level_name[Level1]= "Base"; + level_name[Level2]= "RAlt"; + }; + type "CTRL+ALT" { + modifiers= Shift+Control+Alt+LevelThree; + map[Shift]= Level2; + preserve[Shift]= Shift; + map[LevelThree]= Level3; + map[Shift+LevelThree]= Level4; + preserve[Shift+LevelThree]= Shift; + map[Control+Alt]= Level5; + level_name[Level1]= "Base"; + level_name[Level2]= "Shift"; + level_name[Level3]= "Alt Base"; + level_name[Level4]= "Shift Alt"; + level_name[Level5]= "Ctrl+Alt"; + }; + type "LOCAL_EIGHT_LEVEL" { + modifiers= Shift+Lock+Control+LevelThree; + map[Shift]= Level2; + map[Lock]= Level2; + map[LevelThree]= Level3; + map[Shift+Lock+LevelThree]= Level3; + map[Shift+LevelThree]= Level4; + map[Lock+LevelThree]= Level4; + map[Control]= Level5; + map[Shift+Lock+Control]= Level5; + map[Shift+Control]= Level6; + map[Lock+Control]= Level6; + map[Control+LevelThree]= Level7; + map[Shift+Lock+Control+LevelThree]= Level7; + map[Shift+Control+LevelThree]= Level8; + map[Lock+Control+LevelThree]= Level8; + level_name[Level1]= "Base"; + level_name[Level2]= "Shift"; + level_name[Level3]= "Level3"; + level_name[Level4]= "Shift Level3"; + level_name[Level5]= "Ctrl"; + level_name[Level6]= "Shift Ctrl"; + level_name[Level7]= "Level3 Ctrl"; + level_name[Level8]= "Shift Level3 Ctrl"; + }; + type "THREE_LEVEL" { + modifiers= Shift+LevelThree; + map[Shift]= Level2; + map[LevelThree]= Level3; + map[Shift+LevelThree]= Level3; + level_name[Level1]= "Base"; + level_name[Level2]= "Shift"; + level_name[Level3]= "Level3"; + }; + type "EIGHT_LEVEL" { + modifiers= Shift+LevelThree+LevelFive; + map[Shift]= Level2; + map[LevelThree]= Level3; + map[Shift+LevelThree]= Level4; + map[LevelFive]= Level5; + map[Shift+LevelFive]= Level6; + map[LevelThree+LevelFive]= Level7; + map[Shift+LevelThree+LevelFive]= Level8; + level_name[Level1]= "Base"; + level_name[Level2]= "Shift"; + level_name[Level3]= "Alt Base"; + level_name[Level4]= "Shift Alt"; + level_name[Level5]= "X"; + level_name[Level6]= "X Shift"; + level_name[Level7]= "X Alt Base"; + level_name[Level8]= "X Shift Alt"; + }; + type "EIGHT_LEVEL_ALPHABETIC" { + modifiers= Shift+Lock+LevelThree+LevelFive; + map[Shift]= Level2; + map[Lock]= Level2; + map[LevelThree]= Level3; + map[Shift+LevelThree]= Level4; + map[Lock+LevelThree]= Level4; + map[Shift+Lock+LevelThree]= Level3; + map[LevelFive]= Level5; + map[Shift+LevelFive]= Level6; + map[Lock+LevelFive]= Level6; + map[LevelThree+LevelFive]= Level7; + map[Shift+LevelThree+LevelFive]= Level8; + map[Lock+LevelThree+LevelFive]= Level8; + map[Shift+Lock+LevelThree+LevelFive]= Level7; + level_name[Level1]= "Base"; + level_name[Level2]= "Shift"; + level_name[Level3]= "Alt Base"; + level_name[Level4]= "Shift Alt"; + level_name[Level5]= "X"; + level_name[Level6]= "X Shift"; + level_name[Level7]= "X Alt Base"; + level_name[Level8]= "X Shift Alt"; + }; + type "EIGHT_LEVEL_LEVEL_FIVE_LOCK" { + modifiers= Shift+Lock+NumLock+LevelThree+LevelFive; + map[Shift]= Level2; + map[LevelThree]= Level3; + map[Shift+LevelThree]= Level4; + map[LevelFive]= Level5; + map[Shift+LevelFive]= Level6; + preserve[Shift+LevelFive]= Shift; + map[LevelThree+LevelFive]= Level7; + map[Shift+LevelThree+LevelFive]= Level8; + map[NumLock]= Level5; + map[Shift+NumLock]= Level6; + preserve[Shift+NumLock]= Shift; + map[NumLock+LevelThree]= Level7; + map[Shift+NumLock+LevelThree]= Level8; + map[Shift+NumLock+LevelFive]= Level2; + map[NumLock+LevelThree+LevelFive]= Level3; + map[Shift+NumLock+LevelThree+LevelFive]= Level4; + map[Shift+Lock]= Level2; + map[Lock+LevelThree]= Level3; + map[Shift+Lock+LevelThree]= Level4; + map[Lock+LevelFive]= Level5; + map[Shift+Lock+LevelFive]= Level6; + preserve[Shift+Lock+LevelFive]= Shift; + map[Lock+LevelThree+LevelFive]= Level7; + map[Shift+Lock+LevelThree+LevelFive]= Level8; + map[Lock+NumLock]= Level5; + map[Shift+Lock+NumLock]= Level6; + preserve[Shift+Lock+NumLock]= Shift; + map[Lock+NumLock+LevelThree]= Level7; + map[Shift+Lock+NumLock+LevelThree]= Level8; + map[Shift+Lock+NumLock+LevelFive]= Level2; + map[Lock+NumLock+LevelThree+LevelFive]= Level3; + map[Shift+Lock+NumLock+LevelThree+LevelFive]= Level4; + level_name[Level1]= "Base"; + level_name[Level2]= "Shift"; + level_name[Level3]= "Alt Base"; + level_name[Level4]= "Shift Alt"; + level_name[Level5]= "X"; + level_name[Level6]= "X Shift"; + level_name[Level7]= "X Alt Base"; + level_name[Level8]= "X Shift Alt"; + }; + type "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK" { + modifiers= Shift+Lock+NumLock+LevelThree+LevelFive; + map[Shift]= Level2; + map[LevelThree]= Level3; + map[Shift+LevelThree]= Level4; + map[LevelFive]= Level5; + map[Shift+LevelFive]= Level6; + preserve[Shift+LevelFive]= Shift; + map[LevelThree+LevelFive]= Level7; + map[Shift+LevelThree+LevelFive]= Level8; + map[NumLock]= Level5; + map[Shift+NumLock]= Level6; + preserve[Shift+NumLock]= Shift; + map[NumLock+LevelThree]= Level7; + map[Shift+NumLock+LevelThree]= Level8; + map[Shift+NumLock+LevelFive]= Level2; + map[NumLock+LevelThree+LevelFive]= Level3; + map[Shift+NumLock+LevelThree+LevelFive]= Level4; + map[Lock]= Level2; + map[Lock+LevelThree]= Level3; + map[Shift+Lock+LevelThree]= Level4; + map[Lock+LevelFive]= Level5; + map[Shift+Lock+LevelFive]= Level6; + map[Lock+LevelThree+LevelFive]= Level7; + map[Shift+Lock+LevelThree+LevelFive]= Level8; + map[Lock+NumLock]= Level5; + map[Shift+Lock+NumLock]= Level6; + map[Lock+NumLock+LevelThree]= Level7; + map[Shift+Lock+NumLock+LevelThree]= Level8; + map[Lock+NumLock+LevelFive]= Level2; + map[Lock+NumLock+LevelThree+LevelFive]= Level4; + map[Shift+Lock+NumLock+LevelThree+LevelFive]= Level3; + level_name[Level1]= "Base"; + level_name[Level2]= "Shift"; + level_name[Level3]= "Alt Base"; + level_name[Level4]= "Shift Alt"; + level_name[Level5]= "X"; + level_name[Level6]= "X Shift"; + level_name[Level7]= "X Alt Base"; + level_name[Level8]= "X Shift Alt"; + }; + type "EIGHT_LEVEL_SEMIALPHABETIC" { + modifiers= Shift+Lock+LevelThree+LevelFive; + map[Shift]= Level2; + map[Lock]= Level2; + map[LevelThree]= Level3; + map[Shift+LevelThree]= Level4; + map[Lock+LevelThree]= Level3; + preserve[Lock+LevelThree]= Lock; + map[Shift+Lock+LevelThree]= Level4; + preserve[Shift+Lock+LevelThree]= Lock; + map[LevelFive]= Level5; + map[Shift+LevelFive]= Level6; + map[Lock+LevelFive]= Level6; + preserve[Lock+LevelFive]= Lock; + map[Shift+Lock+LevelFive]= Level6; + preserve[Shift+Lock+LevelFive]= Lock; + map[LevelThree+LevelFive]= Level7; + map[Shift+LevelThree+LevelFive]= Level8; + map[Lock+LevelThree+LevelFive]= Level7; + preserve[Lock+LevelThree+LevelFive]= Lock; + map[Shift+Lock+LevelThree+LevelFive]= Level8; + preserve[Shift+Lock+LevelThree+LevelFive]= Lock; + level_name[Level1]= "Base"; + level_name[Level2]= "Shift"; + level_name[Level3]= "Alt Base"; + level_name[Level4]= "Shift Alt"; + level_name[Level5]= "X"; + level_name[Level6]= "X Shift"; + level_name[Level7]= "X Alt Base"; + level_name[Level8]= "X Shift Alt"; + }; + type "FOUR_LEVEL" { + modifiers= Shift+LevelThree; + map[Shift]= Level2; + map[LevelThree]= Level3; + map[Shift+LevelThree]= Level4; + level_name[Level1]= "Base"; + level_name[Level2]= "Shift"; + level_name[Level3]= "Alt Base"; + level_name[Level4]= "Shift Alt"; + }; + type "FOUR_LEVEL_ALPHABETIC" { + modifiers= Shift+Lock+LevelThree; + map[Shift]= Level2; + map[Lock]= Level2; + map[LevelThree]= Level3; + map[Shift+LevelThree]= Level4; + map[Lock+LevelThree]= Level4; + map[Shift+Lock+LevelThree]= Level3; + level_name[Level1]= "Base"; + level_name[Level2]= "Shift"; + level_name[Level3]= "Alt Base"; + level_name[Level4]= "Shift Alt"; + }; + type "FOUR_LEVEL_SEMIALPHABETIC" { + modifiers= Shift+Lock+LevelThree; + map[Shift]= Level2; + map[Lock]= Level2; + map[LevelThree]= Level3; + map[Shift+LevelThree]= Level4; + map[Lock+LevelThree]= Level3; + preserve[Lock+LevelThree]= Lock; + map[Shift+Lock+LevelThree]= Level4; + preserve[Shift+Lock+LevelThree]= Lock; + level_name[Level1]= "Base"; + level_name[Level2]= "Shift"; + level_name[Level3]= "Alt Base"; + level_name[Level4]= "Shift Alt"; + }; + type "FOUR_LEVEL_MIXED_KEYPAD" { + modifiers= Shift+NumLock+LevelThree; + map[NumLock]= Level2; + map[Shift]= Level2; + map[LevelThree]= Level3; + map[NumLock+LevelThree]= Level3; + map[Shift+LevelThree]= Level4; + map[Shift+NumLock+LevelThree]= Level4; + level_name[Level1]= "Base"; + level_name[Level2]= "Number"; + level_name[Level3]= "Alt Base"; + level_name[Level4]= "Shift Alt"; + }; + type "FOUR_LEVEL_X" { + modifiers= Shift+Control+Alt+LevelThree; + map[LevelThree]= Level2; + map[Shift+LevelThree]= Level3; + map[Control+Alt]= Level4; + level_name[Level1]= "Base"; + level_name[Level2]= "Alt Base"; + level_name[Level3]= "Shift Alt"; + level_name[Level4]= "Ctrl+Alt"; + }; + type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" { + modifiers= Shift+Lock+LevelThree; + map[Shift]= Level2; + map[Lock]= Level4; + preserve[Lock]= Lock; + map[LevelThree]= Level3; + map[Shift+LevelThree]= Level4; + map[Lock+LevelThree]= Level3; + preserve[Lock+LevelThree]= Lock; + map[Shift+Lock+LevelThree]= Level3; + level_name[Level1]= "Base"; + level_name[Level2]= "Shift"; + level_name[Level3]= "AltGr Base"; + level_name[Level4]= "Shift AltGr"; + }; + type "FOUR_LEVEL_PLUS_LOCK" { + modifiers= Shift+Lock+LevelThree; + map[Shift]= Level2; + map[LevelThree]= Level3; + map[Shift+LevelThree]= Level4; + map[Lock]= Level5; + map[Shift+Lock]= Level2; + map[Lock+LevelThree]= Level3; + map[Shift+Lock+LevelThree]= Level4; + level_name[Level1]= "Base"; + level_name[Level2]= "Shift"; + level_name[Level3]= "Alt Base"; + level_name[Level4]= "Shift Alt"; + level_name[Level5]= "Lock"; + }; + type "KEYPAD" { + modifiers= Shift+NumLock; + map[Shift]= Level2; + map[NumLock]= Level2; + level_name[Level1]= "Base"; + level_name[Level2]= "Number"; + }; + type "FOUR_LEVEL_KEYPAD" { + modifiers= Shift+NumLock+LevelThree; + map[Shift]= Level2; + map[NumLock]= Level2; + map[LevelThree]= Level3; + map[Shift+LevelThree]= Level4; + map[NumLock+LevelThree]= Level4; + map[Shift+NumLock+LevelThree]= Level3; + level_name[Level1]= "Base"; + level_name[Level2]= "Number"; + level_name[Level3]= "Alt Base"; + level_name[Level4]= "Alt Number"; + }; +}; + +xkb_compatibility "(unnamed)" { + virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; + + interpret.useModMapMods= AnyLevel; + interpret.repeat= False; + interpret ISO_Level2_Latch+Exactly(Shift) { + useModMapMods=level1; + action= LatchMods(modifiers=Shift,clearLocks,latchToLock); + }; + interpret Shift_Lock+AnyOf(Shift+Lock) { + action= LockMods(modifiers=Shift); + }; + interpret Num_Lock+AnyOf(all) { + virtualModifier= NumLock; + action= LockMods(modifiers=NumLock); + }; + interpret ISO_Level3_Shift+AnyOf(all) { + virtualModifier= LevelThree; + useModMapMods=level1; + action= SetMods(modifiers=LevelThree,clearLocks); + }; + interpret ISO_Level3_Latch+AnyOf(all) { + virtualModifier= LevelThree; + useModMapMods=level1; + action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); + }; + interpret ISO_Level3_Lock+AnyOf(all) { + virtualModifier= LevelThree; + useModMapMods=level1; + action= LockMods(modifiers=LevelThree); + }; + interpret Alt_L+AnyOf(all) { + virtualModifier= Alt; + action= SetMods(modifiers=modMapMods,clearLocks); + }; + interpret Alt_R+AnyOf(all) { + virtualModifier= Alt; + action= SetMods(modifiers=modMapMods,clearLocks); + }; + interpret Meta_L+AnyOf(all) { + virtualModifier= Meta; + action= SetMods(modifiers=modMapMods,clearLocks); + }; + interpret Meta_R+AnyOf(all) { + virtualModifier= Meta; + action= SetMods(modifiers=modMapMods,clearLocks); + }; + interpret Super_L+AnyOf(all) { + virtualModifier= Super; + action= SetMods(modifiers=modMapMods,clearLocks); + }; + interpret Super_R+AnyOf(all) { + virtualModifier= Super; + action= SetMods(modifiers=modMapMods,clearLocks); + }; + interpret Hyper_L+AnyOf(all) { + virtualModifier= Hyper; + action= SetMods(modifiers=modMapMods,clearLocks); + }; + interpret Hyper_R+AnyOf(all) { + virtualModifier= Hyper; + action= SetMods(modifiers=modMapMods,clearLocks); + }; + interpret Scroll_Lock+AnyOf(all) { + virtualModifier= ScrollLock; + action= LockMods(modifiers=modMapMods); + }; + interpret ISO_Level5_Shift+AnyOf(all) { + virtualModifier= LevelFive; + useModMapMods=level1; + action= SetMods(modifiers=LevelFive,clearLocks); + }; + interpret ISO_Level5_Latch+AnyOf(all) { + virtualModifier= LevelFive; + useModMapMods=level1; + action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); + }; + interpret ISO_Level5_Lock+AnyOf(all) { + virtualModifier= LevelFive; + useModMapMods=level1; + action= LockMods(modifiers=LevelFive); + }; + interpret Mode_switch+AnyOfOrNone(all) { + virtualModifier= AltGr; + useModMapMods=level1; + action= SetGroup(group=+1); + }; + interpret ISO_Level3_Shift+AnyOfOrNone(all) { + action= SetMods(modifiers=LevelThree,clearLocks); + }; + interpret ISO_Level3_Latch+AnyOfOrNone(all) { + action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); + }; + interpret ISO_Level3_Lock+AnyOfOrNone(all) { + action= LockMods(modifiers=LevelThree); + }; + interpret ISO_Group_Latch+AnyOfOrNone(all) { + virtualModifier= AltGr; + useModMapMods=level1; + action= LatchGroup(group=2); + }; + interpret ISO_Next_Group+AnyOfOrNone(all) { + virtualModifier= AltGr; + useModMapMods=level1; + action= LockGroup(group=+1); + }; + interpret ISO_Prev_Group+AnyOfOrNone(all) { + virtualModifier= AltGr; + useModMapMods=level1; + action= LockGroup(group=-1); + }; + interpret ISO_First_Group+AnyOfOrNone(all) { + action= LockGroup(group=1); + }; + interpret ISO_Last_Group+AnyOfOrNone(all) { + action= LockGroup(group=2); + }; + interpret KP_1+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=-1,y=+1); + }; + interpret KP_End+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=-1,y=+1); + }; + interpret KP_2+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=+0,y=+1); + }; + interpret KP_Down+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=+0,y=+1); + }; + interpret KP_3+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=+1,y=+1); + }; + interpret KP_Next+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=+1,y=+1); + }; + interpret KP_4+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=-1,y=+0); + }; + interpret KP_Left+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=-1,y=+0); + }; + interpret KP_6+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=+1,y=+0); + }; + interpret KP_Right+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=+1,y=+0); + }; + interpret KP_7+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=-1,y=-1); + }; + interpret KP_Home+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=-1,y=-1); + }; + interpret KP_8+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=+0,y=-1); + }; + interpret KP_Up+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=+0,y=-1); + }; + interpret KP_9+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=+1,y=-1); + }; + interpret KP_Prior+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=+1,y=-1); + }; + interpret KP_5+AnyOfOrNone(all) { + repeat= True; + action= PtrBtn(button=default); + }; + interpret KP_Begin+AnyOfOrNone(all) { + repeat= True; + action= PtrBtn(button=default); + }; + interpret KP_F2+AnyOfOrNone(all) { + repeat= True; + action= SetPtrDflt(affect=button,button=1); + }; + interpret KP_Divide+AnyOfOrNone(all) { + repeat= True; + action= SetPtrDflt(affect=button,button=1); + }; + interpret KP_F3+AnyOfOrNone(all) { + repeat= True; + action= SetPtrDflt(affect=button,button=2); + }; + interpret KP_Multiply+AnyOfOrNone(all) { + repeat= True; + action= SetPtrDflt(affect=button,button=2); + }; + interpret KP_F4+AnyOfOrNone(all) { + repeat= True; + action= SetPtrDflt(affect=button,button=3); + }; + interpret KP_Subtract+AnyOfOrNone(all) { + repeat= True; + action= SetPtrDflt(affect=button,button=3); + }; + interpret KP_Separator+AnyOfOrNone(all) { + repeat= True; + action= PtrBtn(button=default,count=2); + }; + interpret KP_Add+AnyOfOrNone(all) { + repeat= True; + action= PtrBtn(button=default,count=2); + }; + interpret KP_0+AnyOfOrNone(all) { + repeat= True; + action= LockPtrBtn(button=default,affect=lock); + }; + interpret KP_Insert+AnyOfOrNone(all) { + repeat= True; + action= LockPtrBtn(button=default,affect=lock); + }; + interpret KP_Decimal+AnyOfOrNone(all) { + repeat= True; + action= LockPtrBtn(button=default,affect=unlock); + }; + interpret KP_Delete+AnyOfOrNone(all) { + repeat= True; + action= LockPtrBtn(button=default,affect=unlock); + }; + interpret F25+AnyOfOrNone(all) { + repeat= True; + action= SetPtrDflt(affect=button,button=1); + }; + interpret F26+AnyOfOrNone(all) { + repeat= True; + action= SetPtrDflt(affect=button,button=2); + }; + interpret F27+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=-1,y=-1); + }; + interpret F29+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=+1,y=-1); + }; + interpret F31+AnyOfOrNone(all) { + repeat= True; + action= PtrBtn(button=default); + }; + interpret F33+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=-1,y=+1); + }; + interpret F35+AnyOfOrNone(all) { + repeat= True; + action= MovePtr(x=+1,y=+1); + }; + interpret Pointer_Button_Dflt+AnyOfOrNone(all) { + action= PtrBtn(button=default); + }; + interpret Pointer_Button1+AnyOfOrNone(all) { + action= PtrBtn(button=1); + }; + interpret Pointer_Button2+AnyOfOrNone(all) { + action= PtrBtn(button=2); + }; + interpret Pointer_Button3+AnyOfOrNone(all) { + action= PtrBtn(button=3); + }; + interpret Pointer_DblClick_Dflt+AnyOfOrNone(all) { + action= PtrBtn(button=default,count=2); + }; + interpret Pointer_DblClick1+AnyOfOrNone(all) { + action= PtrBtn(button=1,count=2); + }; + interpret Pointer_DblClick2+AnyOfOrNone(all) { + action= PtrBtn(button=2,count=2); + }; + interpret Pointer_DblClick3+AnyOfOrNone(all) { + action= PtrBtn(button=3,count=2); + }; + interpret Pointer_Drag_Dflt+AnyOfOrNone(all) { + action= LockPtrBtn(button=default); + }; + interpret Pointer_Drag1+AnyOfOrNone(all) { + action= LockPtrBtn(button=1); + }; + interpret Pointer_Drag2+AnyOfOrNone(all) { + action= LockPtrBtn(button=2); + }; + interpret Pointer_Drag3+AnyOfOrNone(all) { + action= LockPtrBtn(button=3); + }; + interpret Pointer_EnableKeys+AnyOfOrNone(all) { + action= LockControls(controls=MouseKeys); + }; + interpret Pointer_Accelerate+AnyOfOrNone(all) { + action= LockControls(controls=MouseKeysAccel); + }; + interpret Pointer_DfltBtnNext+AnyOfOrNone(all) { + action= SetPtrDflt(affect=button,button=+1); + }; + interpret Pointer_DfltBtnPrev+AnyOfOrNone(all) { + action= SetPtrDflt(affect=button,button=-1); + }; + interpret AccessX_Enable+AnyOfOrNone(all) { + action= LockControls(controls=AccessXKeys); + }; + interpret AccessX_Feedback_Enable+AnyOfOrNone(all) { + action= LockControls(controls=AccessXFeedback); + }; + interpret RepeatKeys_Enable+AnyOfOrNone(all) { + action= LockControls(controls=RepeatKeys); + }; + interpret SlowKeys_Enable+AnyOfOrNone(all) { + action= LockControls(controls=SlowKeys); + }; + interpret BounceKeys_Enable+AnyOfOrNone(all) { + action= LockControls(controls=BounceKeys); + }; + interpret StickyKeys_Enable+AnyOfOrNone(all) { + action= LockControls(controls=StickyKeys); + }; + interpret MouseKeys_Enable+AnyOfOrNone(all) { + action= LockControls(controls=MouseKeys); + }; + interpret MouseKeys_Accel_Enable+AnyOfOrNone(all) { + action= LockControls(controls=MouseKeysAccel); + }; + interpret Overlay1_Enable+AnyOfOrNone(all) { + action= LockControls(controls=none); + }; + interpret Overlay2_Enable+AnyOfOrNone(all) { + action= LockControls(controls=none); + }; + interpret AudibleBell_Enable+AnyOfOrNone(all) { + action= LockControls(controls=AudibleBell); + }; + interpret Terminate_Server+AnyOfOrNone(all) { + action= Terminate(); + }; + interpret Alt_L+AnyOfOrNone(all) { + action= SetMods(modifiers=Alt,clearLocks); + }; + interpret Alt_R+AnyOfOrNone(all) { + action= SetMods(modifiers=Alt,clearLocks); + }; + interpret Meta_L+AnyOfOrNone(all) { + action= SetMods(modifiers=Meta,clearLocks); + }; + interpret Meta_R+AnyOfOrNone(all) { + action= SetMods(modifiers=Meta,clearLocks); + }; + interpret Super_L+AnyOfOrNone(all) { + action= SetMods(modifiers=Super,clearLocks); + }; + interpret Super_R+AnyOfOrNone(all) { + action= SetMods(modifiers=Super,clearLocks); + }; + interpret Hyper_L+AnyOfOrNone(all) { + action= SetMods(modifiers=Hyper,clearLocks); + }; + interpret Hyper_R+AnyOfOrNone(all) { + action= SetMods(modifiers=Hyper,clearLocks); + }; + interpret Shift_L+AnyOfOrNone(all) { + action= SetMods(modifiers=Shift,clearLocks); + }; + interpret XF86Switch_VT_1+AnyOfOrNone(all) { + repeat= True; + action= SwitchScreen(screen=1,!same); + }; + interpret XF86Switch_VT_2+AnyOfOrNone(all) { + repeat= True; + action= SwitchScreen(screen=2,!same); + }; + interpret XF86Switch_VT_3+AnyOfOrNone(all) { + repeat= True; + action= SwitchScreen(screen=3,!same); + }; + interpret XF86Switch_VT_4+AnyOfOrNone(all) { + repeat= True; + action= SwitchScreen(screen=4,!same); + }; + interpret XF86Switch_VT_5+AnyOfOrNone(all) { + repeat= True; + action= SwitchScreen(screen=5,!same); + }; + interpret XF86Switch_VT_6+AnyOfOrNone(all) { + repeat= True; + action= SwitchScreen(screen=6,!same); + }; + interpret XF86Switch_VT_7+AnyOfOrNone(all) { + repeat= True; + action= SwitchScreen(screen=7,!same); + }; + interpret XF86Switch_VT_8+AnyOfOrNone(all) { + repeat= True; + action= SwitchScreen(screen=8,!same); + }; + interpret XF86Switch_VT_9+AnyOfOrNone(all) { + repeat= True; + action= SwitchScreen(screen=9,!same); + }; + interpret XF86Switch_VT_10+AnyOfOrNone(all) { + repeat= True; + action= SwitchScreen(screen=10,!same); + }; + interpret XF86Switch_VT_11+AnyOfOrNone(all) { + repeat= True; + action= SwitchScreen(screen=11,!same); + }; + interpret XF86Switch_VT_12+AnyOfOrNone(all) { + repeat= True; + action= SwitchScreen(screen=12,!same); + }; + interpret XF86LogGrabInfo+AnyOfOrNone(all) { + repeat= True; + action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x47,data[3]=0x72,data[4]=0x62,data[5]=0x73,data[6]=0x00); + }; + interpret XF86LogWindowTree+AnyOfOrNone(all) { + repeat= True; + action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x57,data[3]=0x69,data[4]=0x6e,data[5]=0x73,data[6]=0x00); + }; + interpret XF86Next_VMode+AnyOfOrNone(all) { + repeat= True; + action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); + }; + interpret XF86Prev_VMode+AnyOfOrNone(all) { + repeat= True; + action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); + }; + interpret ISO_Level5_Shift+AnyOfOrNone(all) { + action= SetMods(modifiers=LevelFive,clearLocks); + }; + interpret ISO_Level5_Latch+AnyOfOrNone(all) { + action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); + }; + interpret ISO_Level5_Lock+AnyOfOrNone(all) { + action= LockMods(modifiers=LevelFive); + }; + interpret Caps_Lock+AnyOfOrNone(all) { + action= LockMods(modifiers=Lock); + }; + interpret Any+Exactly(Lock) { + action= LockMods(modifiers=Lock); + }; + interpret Any+AnyOf(all) { + action= SetMods(modifiers=modMapMods,clearLocks); + }; + indicator "Caps Lock" { + whichModState= locked; + modifiers= Lock; + }; + indicator "Num Lock" { + whichModState= locked; + modifiers= NumLock; + }; + indicator "Scroll Lock" { + whichModState= locked; + modifiers= ScrollLock; + }; + indicator "Shift Lock" { + whichModState= locked; + modifiers= Shift; + }; + indicator "Group 2" { + groups= 0xfe; + }; + indicator "Mouse Keys" { + controls= MouseKeys; + }; +}; + +xkb_symbols "(unnamed)" { + name[group1]="English (US)"; + + key { [ Escape ] }; + key { [ 1, exclam ] }; + key { [ 2, at ] }; + key { [ 3, numbersign ] }; + key { [ 4, dollar ] }; + key { [ 5, percent ] }; + key { [ 6, asciicircum ] }; + key { [ 7, ampersand ] }; + key { [ 8, asterisk ] }; + key { [ 9, parenleft ] }; + key { [ 0, parenright ] }; + key { [ minus, underscore ] }; + key { [ equal, plus ] }; + key { [ BackSpace, BackSpace ] }; + key { [ Tab, ISO_Left_Tab ] }; + key { [ q, Q, 1 ] }; + key { [ w, W, 2 ] }; + key { [ e, E, 3 ] }; + key { [ r, R, 4 ] }; + key { [ t, T, 5 ] }; + key { [ y, Y, 6 ] }; + key { [ u, U, 7 ] }; + key { [ i, I, 8 ] }; + key { [ o, O, 9 ] }; + key { [ p, P, 0 ] }; + key { [ bracketleft, braceleft ] }; + key { [ bracketright, braceright ] }; + key { [ Return ] }; + key { [ Control_L ] }; + key { [ a, A, minus ] }; + key { [ s, S, at ] }; + key { [ d, D, asterisk ] }; + key { [ f, F, asciicircum ] }; + key { [ g, G, colon ] }; + key { [ h, H, semicolon ] }; + key { [ j, J, parenleft ] }; + key { [ k, K, parenright ] }; + key { [ l, L, asciitilde ] }; + key { [ semicolon, colon ] }; + key { [ apostrophe, quotedbl ] }; + key { [ grave, asciitilde ] }; + key { [ Shift_L ] }; + key { [ backslash, bar ] }; + key { [ z, Z, slash ] }; + key { [ x, X, apostrophe ] }; + key { [ c, C, quotedbl ] }; + key { [ v, V, plus ] }; + key { [ b, B, equal ] }; + key { [ n, N, question ] }; + key { [ m, M, exclam ] }; + key { [ comma, less, backslash] }; + key { [ period, greater, bar ] }; + key { [ slash, question ] }; + key { [ Shift_R ] }; + key { + type= "CTRL+ALT", + symbols[Group1]= [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86ClearGrab ] + }; + key { [ Alt_L, Meta_L ] }; + key { [ space ] }; + key { [ Caps_Lock ] }; + key { + type= "CTRL+ALT", + symbols[Group1]= [ F1, F1, F1, F1, XF86Switch_VT_1 ] + }; + key { + type= "CTRL+ALT", + symbols[Group1]= [ F2, F2, F2, F2, XF86Switch_VT_2 ] + }; + key { + type= "CTRL+ALT", + symbols[Group1]= [ F3, F3, F3, F3, XF86Switch_VT_3 ] + }; + key { + type= "CTRL+ALT", + symbols[Group1]= [ F4, F4, F4, F4, XF86Switch_VT_4 ] + }; + key { + type= "CTRL+ALT", + symbols[Group1]= [ F5, F5, F5, F5, XF86Switch_VT_5 ] + }; + key { + type= "CTRL+ALT", + symbols[Group1]= [ F6, F6, F6, F6, XF86Switch_VT_6 ] + }; + key { + type= "CTRL+ALT", + symbols[Group1]= [ F7, F7, F7, F7, XF86Switch_VT_7 ] + }; + key { + type= "CTRL+ALT", + symbols[Group1]= [ F8, F8, F8, F8, XF86Switch_VT_8 ] + }; + key { + type= "CTRL+ALT", + symbols[Group1]= [ F9, F9, F9, F9, XF86Switch_VT_9 ] + }; + key { + type= "CTRL+ALT", + symbols[Group1]= [ F10, F10, F10, F10, XF86Switch_VT_10 ] + }; + key { [ Num_Lock ] }; + key { [ Scroll_Lock ] }; + key { [ KP_Home, KP_7 ] }; + key { [ KP_Up, KP_8 ] }; + key { [ KP_Prior, KP_9 ] }; + key { + type= "CTRL+ALT", + symbols[Group1]= [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86Prev_VMode ] + }; + key { [ KP_Left, KP_4 ] }; + key { [ KP_Begin, KP_5 ] }; + key { [ KP_Right, KP_6 ] }; + key { + type= "CTRL+ALT", + symbols[Group1]= [ KP_Add, KP_Add, KP_Add, KP_Add, XF86Next_VMode ] + }; + key { [ KP_End, KP_1 ] }; + key { [ KP_Down, KP_2 ] }; + key { [ KP_Next, KP_3 ] }; + key { [ KP_Insert, KP_0 ] }; + key { [ KP_Delete, KP_Decimal ] }; + key { [ ISO_Level3_Shift ] }; + key { [ less, greater, bar, brokenbar ] }; + key { + type= "CTRL+ALT", + symbols[Group1]= [ F11, F11, F11, F11, XF86Switch_VT_11 ] + }; + key { + type= "CTRL+ALT", + symbols[Group1]= [ F12, F12, F12, F12, XF86Switch_VT_12 ] + }; + key { [ Katakana ] }; + key { [ Hiragana ] }; + key { [ Henkan_Mode ] }; + key { [ Hiragana_Katakana ] }; + key { [ Muhenkan ] }; + key { [ KP_Enter ] }; + key { [ Control_R ] }; + key { + type= "CTRL+ALT", + symbols[Group1]= [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86Ungrab ] + }; + key { + type= "PC_ALT_LEVEL2", + symbols[Group1]= [ Print, Sys_Req ] + }; + key { + type= "TWO_LEVEL", + symbols[Group1]= [ Alt_R, Meta_R ] + }; + key { [ Linefeed ] }; + key { [ Home ] }; + key { [ Up ] }; + key { [ Prior ] }; + key { [ Left ] }; + key { [ Right ] }; + key { [ End ] }; + key { [ Down ] }; + key { [ Next ] }; + key { [ Insert ] }; + key { [ Delete ] }; + key { [ XF86AudioMute ] }; + key { [ XF86AudioLowerVolume ] }; + key { [ XF86AudioRaiseVolume ] }; + key { [ XF86PowerOff ] }; + key { [ KP_Equal ] }; + key { [ plusminus ] }; + key { + type= "PC_CONTROL_LEVEL2", + symbols[Group1]= [ Pause, Break ] + }; + key { [ XF86LaunchA ] }; + key { [ KP_Decimal, KP_Decimal ] }; + key { [ Hangul ] }; + key { [ Hangul_Hanja ] }; + key { [ Super_L ] }; + key { [ Super_R ] }; + key { [ Menu ] }; + key { [ Cancel ] }; + key { [ Redo ] }; + key { [ SunProps ] }; + key { [ Undo ] }; + key { [ SunFront ] }; + key { [ XF86Copy ] }; + key { [ XF86Open ] }; + key { [ XF86Paste ] }; + key { [ Find ] }; + key { [ XF86Cut ] }; + key { [ Help ] }; + key { [ XF86MenuKB ] }; + key { [ XF86Calculator ] }; + key { [ XF86Sleep ] }; + key { [ XF86WakeUp ] }; + key { [ XF86Explorer ] }; + key { [ XF86Send ] }; + key { [ XF86Xfer ] }; + key { [ XF86Launch1 ] }; + key { [ XF86Launch2 ] }; + key { [ XF86WWW ] }; + key { [ XF86DOS ] }; + key { [ XF86ScreenSaver ] }; + key { [ XF86RotateWindows ] }; + key { [ XF86TaskPane ] }; + key { [ XF86Mail ] }; + key { [ XF86Favorites ] }; + key { [ XF86MyComputer ] }; + key { [ XF86Back ] }; + key { [ XF86Forward ] }; + key { [ XF86Eject ] }; + key { [ XF86Eject, XF86Eject ] }; + key { [ XF86AudioNext ] }; + key { [ XF86AudioPlay, XF86AudioPause ] }; + key { [ XF86AudioPrev ] }; + key { [ XF86AudioStop, XF86Eject ] }; + key { [ XF86AudioRecord ] }; + key { [ XF86AudioRewind ] }; + key { [ XF86Phone ] }; + key { [ XF86Tools ] }; + key { [ XF86HomePage ] }; + key { [ XF86Reload ] }; + key { [ XF86Close ] }; + key { [ XF86ScrollUp ] }; + key { [ XF86ScrollDown ] }; + key { [ parenleft ] }; + key { [ parenright ] }; + key { [ XF86New ] }; + key { [ Redo ] }; + key { [ XF86Tools ] }; + key { [ XF86Launch5 ] }; + key { [ XF86Launch6 ] }; + key { [ XF86Launch7 ] }; + key { [ XF86Launch8 ] }; + key { [ XF86Launch9 ] }; + key { [ XF86AudioMicMute ] }; + key { [ XF86TouchpadToggle ] }; + key { [ XF86TouchpadOn ] }; + key { [ XF86TouchpadOff ] }; + key { [ Mode_switch ] }; + key { [ NoSymbol, Alt_L ] }; + key { [ NoSymbol, Meta_L ] }; + key { [ NoSymbol, Super_L ] }; + key { [ NoSymbol, Hyper_L ] }; + key { [ XF86AudioPlay ] }; + key { [ XF86AudioPause ] }; + key { [ XF86Launch3 ] }; + key { [ XF86Launch4 ] }; + key { [ XF86LaunchB ] }; + key { [ XF86Suspend ] }; + key { [ XF86Close ] }; + key { [ XF86AudioPlay ] }; + key { [ XF86AudioForward ] }; + key { [ Print ] }; + key { [ XF86WebCam ] }; + key { [ XF86AudioPreset ] }; + key { [ XF86Mail ] }; + key { [ XF86Messenger ] }; + key { [ XF86Search ] }; + key { [ XF86Go ] }; + key { [ XF86Finance ] }; + key { [ XF86Game ] }; + key { [ XF86Shop ] }; + key { [ Cancel ] }; + key { [ XF86MonBrightnessDown ] }; + key { [ XF86MonBrightnessUp ] }; + key { [ XF86AudioMedia ] }; + key { [ XF86Display ] }; + key { [ XF86KbdLightOnOff ] }; + key { [ XF86KbdBrightnessDown ] }; + key { [ XF86KbdBrightnessUp ] }; + key { [ XF86Send ] }; + key { [ XF86Reply ] }; + key { [ XF86MailForward ] }; + key { [ XF86Save ] }; + key { [ XF86Documents ] }; + key { [ XF86Battery ] }; + key { [ XF86Bluetooth ] }; + key { [ XF86WLAN ] }; + key { [ XF86UWB ] }; + key { [ XF86WWAN ] }; + key { [ XF86RFKill ] }; + modifier_map Shift { , }; + modifier_map Lock { }; + modifier_map Control { , }; + modifier_map Mod1 { , , }; + modifier_map Mod2 { }; + modifier_map Mod4 { , , , }; + modifier_map Mod5 { , }; +}; + +}; \ No newline at end of file diff --git a/resources/login-shell/gresource.xml b/resources/login-shell/gresource.xml index 59deb2f..56990bb 100644 --- a/resources/login-shell/gresource.xml +++ b/resources/login-shell/gresource.xml @@ -2,5 +2,6 @@ resources/login-shell/login-shell.css + resources/default.keymap \ No newline at end of file diff --git a/resources/session-shell/gresource.xml b/resources/session-shell/gresource.xml new file mode 100644 index 0000000..845bda4 --- /dev/null +++ b/resources/session-shell/gresource.xml @@ -0,0 +1,6 @@ + + + + resources/default.keymap + + \ No newline at end of file diff --git a/src/background.c b/src/background.c index c8f539c..f1f75d6 100644 --- a/src/background.c +++ b/src/background.c @@ -9,7 +9,7 @@ static void on_background_destroy(GtkWindow *window, GApplication *_data) //g_application_quit (G_APPLICATION (gtk_window_get_application (window))); } -void diya_shell_init_background(DiyaShell * shell) +void diya_session_shell_init_background(DiyaSessionShell * shell) { GtkApplication * app; g_object_get(shell, "application", &app, NULL); diff --git a/src/background.h b/src/background.h index f3e5fe3..d7f6817 100644 --- a/src/background.h +++ b/src/background.h @@ -1,8 +1,8 @@ #ifndef DIYA_SHELL_BACKGROUND_H #define DIYA_SHELL_BACKGROUND_H -#include "shell.h" +#include "session-shell.h" -void diya_shell_init_background(DiyaShell * shell); +void diya_session_shell_init_background(DiyaSessionShell * shell); #endif \ No newline at end of file diff --git a/src/base.h b/src/base.h index d701ed8..e94ae37 100644 --- a/src/base.h +++ b/src/base.h @@ -2,6 +2,7 @@ #define DIYA_OBJECT_H #include +#include /** * Base class object diff --git a/src/foreign.c b/src/foreign.c index 2bcdd77..54496d2 100644 --- a/src/foreign.c +++ b/src/foreign.c @@ -1,5 +1,6 @@ #include #include +#include "wlr-foreign-toplevel-management-unstable-v1.h" #include "foreign.h" /** @@ -19,7 +20,7 @@ enum static GParamSpec *win_properties[N_PROPERTIES] = {0}; struct _DiyaForeignWindow { - DiyaObject parent; + DiyaShellObject parent; gchar * appid; gpointer handle; gchar* title; @@ -155,9 +156,9 @@ static void toplevel_handle_title(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, const char *title) { - DiyaShell *shell = (DiyaShell *)data; + DiyaSessionShell *shell = (DiyaSessionShell *)data; assert(shell); - DiyaForeignWindow *win = diya_shell_get_window(shell, handle); + DiyaForeignWindow *win = diya_session_shell_get_window(shell, handle); assert(win); g_object_set(win, "title", title, NULL); g_debug("New title for: %s", diya_object_to_string(win)); @@ -166,9 +167,9 @@ static void toplevel_handle_app_id(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, const char *app_id) { - DiyaShell *shell = (DiyaShell *)data; + DiyaSessionShell *shell = (DiyaSessionShell *)data; assert(shell); - DiyaForeignWindow *win = diya_shell_get_window(shell, handle); + DiyaForeignWindow *win = diya_session_shell_get_window(shell, handle); assert(win); g_object_set(win, "appid", app_id, NULL); g_debug("New appid for: %s", diya_object_to_string(win)); @@ -186,9 +187,9 @@ static void toplevel_handle_state(void *data, struct wl_array *state) { uint32_t *entry; - DiyaShell *shell = (DiyaShell *)data; + DiyaSessionShell *shell = (DiyaSessionShell *)data; assert(shell); - DiyaForeignWindow *win = diya_shell_get_window(shell, handle); + DiyaForeignWindow *win = diya_session_shell_get_window(shell, handle); assert(win); enum diya_win_state wstate = DIYA_WIN_STATE_NONE; wl_array_for_each(entry, state) switch (*entry) @@ -211,21 +212,21 @@ static void toplevel_handle_state(void *data, static void toplevel_handle_done(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle) { - DiyaShell *shell = (DiyaShell *)data; + DiyaSessionShell *shell = (DiyaSessionShell *)data; assert(shell); - DiyaForeignWindow *win = diya_shell_get_window(shell, handle); + DiyaForeignWindow *win = diya_session_shell_get_window(shell, handle); assert(win); g_signal_emit_by_name(shell, "foreign-window-changed", (void *)win); } static void toplevel_handle_closed(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle) { - DiyaShell *shell = (DiyaShell *)data; + DiyaSessionShell *shell = (DiyaSessionShell *)data; assert(shell); - DiyaForeignWindow *win = diya_shell_get_window(shell, handle); + DiyaForeignWindow *win = diya_session_shell_get_window(shell, handle); assert(win); g_signal_emit_by_name(shell, "foreign-window-removed", (void *)win); - diya_shell_remove_window(shell, win); + diya_session_shell_remove_window(shell, win); zwlr_foreign_toplevel_handle_v1_destroy(handle); } static void toplevel_handle_parent(void *data, @@ -237,10 +238,10 @@ static void toplevel_handle_parent(void *data, return; } assert(handle != parent); - DiyaShell *shell = (DiyaShell *)data; + DiyaSessionShell *shell = (DiyaSessionShell *)data; assert(shell); - DiyaForeignWindow *child_win = diya_shell_get_window(shell, handle); - DiyaForeignWindow *parent_win = diya_shell_get_window(shell, parent); + DiyaForeignWindow *child_win = diya_session_shell_get_window(shell, handle); + DiyaForeignWindow *parent_win = diya_session_shell_get_window(shell, parent); assert(child_win); assert(parent_win); assert(child_win != parent_win); @@ -260,11 +261,11 @@ static const struct zwlr_foreign_toplevel_handle_v1_listener g_toplevel_impl = { .parent = toplevel_handle_parent }; -static DiyaForeignWindow * diya_shell_foreign_window_new(DiyaShell* shell, gpointer handle) +static DiyaForeignWindow * diya_session_shell_foreign_window_new(DiyaSessionShell* shell, gpointer handle) { DiyaForeignWindow *win = DIYA_FOREIGN_WINDOW(g_object_new(DIYA_TYPE_FOREIGN_WINDOW,"handle", handle, "shell", shell, NULL)); //g_object_set(win, "shell", shell, NULL); - diya_shell_add_window(shell, win); + diya_session_shell_add_window(shell, win); g_debug("Add new window 0x%" PRIXPTR, (uintptr_t)handle); return win; } @@ -272,9 +273,9 @@ static DiyaForeignWindow * diya_shell_foreign_window_new(DiyaShell* shell, gpoin static void toplevel_manager_handle_toplevel(void *data, struct zwlr_foreign_toplevel_manager_v1 *toplevel_manager, struct zwlr_foreign_toplevel_handle_v1 *tl) { (void) toplevel_manager; - DiyaShell *shell = (DiyaShell *)data; + DiyaSessionShell *shell = (DiyaSessionShell *)data; assert(shell); - DiyaForeignWindow *win = diya_shell_get_window(shell, tl); + DiyaForeignWindow *win = diya_session_shell_get_window(shell, tl); if (win) { @@ -282,15 +283,15 @@ static void toplevel_manager_handle_toplevel(void *data, struct zwlr_foreign_top return; } // TODO: different between windows - win = diya_shell_foreign_window_new(shell, tl); + win = diya_session_shell_foreign_window_new(shell, tl); zwlr_foreign_toplevel_handle_v1_add_listener(tl, &g_toplevel_impl, data); } static void toplevel_manager_handle_finished(void *data, struct zwlr_foreign_toplevel_manager_v1 *toplevel_manager) { - DiyaShell *shell = (DiyaShell *)data; - diya_shell_remove_all_windows(shell); + DiyaSessionShell *shell = (DiyaSessionShell *)data; + diya_session_shell_remove_all_windows(shell); // remove table entry zwlr_foreign_toplevel_manager_v1_destroy(toplevel_manager); } @@ -301,8 +302,9 @@ static const struct zwlr_foreign_toplevel_manager_v1_listener g_toplevel_manager .finished = toplevel_manager_handle_finished, }; -void diya_shell_foreign_toplevel_register(struct wl_registry *registry, uint32_t name, DiyaShell *shell) +void diya_session_shell_foreign_toplevel_register(struct wl_registry *registry, uint32_t name, DiyaShell *shell) { + DiyaSessionShell* session_shell = DIYA_SESSION_SHELL(shell); g_toplevel_manager = wl_registry_bind(registry, name, &zwlr_foreign_toplevel_manager_v1_interface, 3); - zwlr_foreign_toplevel_manager_v1_add_listener(g_toplevel_manager, &g_toplevel_manager_impl, (void *)shell); + zwlr_foreign_toplevel_manager_v1_add_listener(g_toplevel_manager, &g_toplevel_manager_impl, (void *)session_shell); } \ No newline at end of file diff --git a/src/foreign.h b/src/foreign.h index 1a370ca..2a65a20 100644 --- a/src/foreign.h +++ b/src/foreign.h @@ -1,7 +1,16 @@ #ifndef DIYA_SHELL_FOREIGN_H #define DIYA_SHELL_FOREIGN_H -#include "wlr-foreign-toplevel-management-unstable-v1.h" -#include "shell.h" +#include "session-shell.h" + +enum diya_win_state +{ + DIYA_WIN_STATE_NONE = 0, + DIYA_WIN_STATE_MINIMIZE = 1 << 0, + DIYA_WIN_STATE_MAXIMIZE = 1 << 1, + DIYA_WIN_STATE_FULLSCREEN = 1 << 2, + DIYA_WIN_STATE_FOCUS = 1 << 3, +}; + +void diya_session_shell_foreign_toplevel_register(struct wl_registry *registry, uint32_t name, DiyaShell * shell); -void diya_shell_foreign_toplevel_register(struct wl_registry *registry, uint32_t name, DiyaShell * shell); #endif \ No newline at end of file diff --git a/src/launcher.c b/src/launcher.c index f4885d2..6e52b1d 100644 --- a/src/launcher.c +++ b/src/launcher.c @@ -12,7 +12,7 @@ static void on_launcher_destroy(GtkWindow *window, GApplication *_data) //g_application_quit (G_APPLICATION (gtk_window_get_application (window))); } -static void on_foreign_window_change(DiyaShell* shell, DiyaForeignWindow * win, gpointer data) +static void on_foreign_window_change(DiyaSessionShell* shell, DiyaForeignWindow * win, gpointer data) { (void) data; assert(win); @@ -20,7 +20,7 @@ static void on_foreign_window_change(DiyaShell* shell, DiyaForeignWindow * win, g_warning("on_foreign_window_change: WINDOW CHANGE %s, shell %s", diya_object_to_string(DIYA_OBJECT(win)), diya_object_to_string(DIYA_OBJECT(shell))); } -static void on_foreign_window_removed(DiyaShell* shell, DiyaForeignWindow * win, gpointer data) +static void on_foreign_window_removed(DiyaSessionShell* shell, DiyaForeignWindow * win, gpointer data) { (void) data; assert(win); @@ -32,10 +32,10 @@ static void session_lock(GtkWidget *widget,gpointer data) { (void) widget; g_warning("Enter session lock"); - diya_shell_lock(data); + diya_session_shell_lock(data); } -void diya_shell_launcher_init(DiyaShell * shell) +void diya_session_shell_launcher_init(DiyaSessionShell * shell) { assert(shell); GtkApplication * app; diff --git a/src/launcher.h b/src/launcher.h index 7452b15..df477b9 100644 --- a/src/launcher.h +++ b/src/launcher.h @@ -1,9 +1,9 @@ #ifndef DIYA_SHELL_LAUNCHER_H #define DIYA_SHELL_LAUNCHER_H -#include "shell.h" +#include "session-shell.h" -void diya_shell_launcher_init(DiyaShell * shell); +void diya_session_shell_launcher_init(DiyaSessionShell * shell); #endif \ No newline at end of file diff --git a/src/login-shell.c b/src/login-shell.c index 84347c4..3d1532f 100644 --- a/src/login-shell.c +++ b/src/login-shell.c @@ -1,17 +1,17 @@ -#include "login-shell.h" - #include #include - #include +#include "login-shell.h" +#include "virtual-keyboard.h" + #define DBUS_SERVER_NAME "dev.iohub.diya.SessionManager" #define DBUS_SERVER_PATH "/dev/iohub/diya/SessionManager" #define DBUS_SERVER_ERROR_NAME "dev.iohub.diya.SessionManager.Error" struct _DiyaLoginShell { - DiyaObject parent_object; + DiyaShell parent_object; GtkApplication *app; GtkSessionLockInstance *lock; GtkWidget *username; @@ -20,7 +20,7 @@ struct _DiyaLoginShell guint bus_watch_id; }; -G_DEFINE_FINAL_TYPE(DiyaLoginShell, diya_login_shell, DIYA_TYPE_OBJECT); +G_DEFINE_FINAL_TYPE(DiyaLoginShell, diya_login_shell, DIYA_TYPE_SHELL); static void diya_login_shell_dispose(GObject *object) { @@ -67,6 +67,11 @@ static void diya_login_shell_class_init(DiyaLoginShellClass *class) gobject_class->dispose = diya_login_shell_dispose; // gobject_class->set_property = diya_lock_session_set_property; // gobject_class->get_property = diya_lock_session_get_property; + + + //DiyaShellClass *base_shell_class = DIYA_SHELL_CLASS(class) + //base_shell_class->foreign_register = diya_session_shell_foreign_toplevel_register; + base_class->to_string = diya_login_shell_to_string; } @@ -169,6 +174,23 @@ static void do_login(GtkButton *button, DiyaLoginShell *self) // g_application_quit(G_APPLICATION(self->app)); } +static void open_vkb(GtkButton *button, DiyaLoginShell *self) +{ + (void) button; + DiyaVirtualKeyboard* vkb = diya_virtual_keyboard_new(DIYA_SHELL(self), NULL); + if(!vkb) + { + return; + } + g_warning("Sending A to: %s", diya_object_to_string(DIYA_OBJECT(vkb))); + diya_virtual_keyboard_send_key(vkb,30, VKB_KEY_STATE_PRESSED); + g_usleep(10000); + diya_virtual_keyboard_send_key(vkb,30, VKB_KEY_STATE_RELEASED); + g_usleep(10000); + // send example key + g_object_unref(vkb); +} + DiyaLoginShell *diya_login_shell_new() { return g_object_new(DIYA_TYPE_LOGIN_SHELL, NULL); @@ -232,10 +254,12 @@ void diya_login_shell_attach(DiyaLoginShell *self, GtkApplication *app) gtk_box_append(GTK_BOX(box), password_box); - GtkWidget *button = gtk_button_new_with_label("Login"); g_signal_connect(self->username, "activate", G_CALLBACK(do_login), self); g_signal_connect(self->password, "activate", G_CALLBACK(do_login), self); + + GtkWidget *button = gtk_button_new_with_label("Login"); g_signal_connect(button, "clicked", G_CALLBACK(do_login), self); + //gtk_widget_set_can_focus(GTK_WIDGET(button), false); gtk_box_append(GTK_BOX(box), button); // Not displayed, but allows testing that creating popups doesn't crash GTK @@ -245,6 +269,11 @@ void diya_login_shell_attach(DiyaLoginShell *self, GtkApplication *app) gtk_box_append(GTK_BOX(box), self->status); gtk_widget_add_css_class(self->status, "status"); + button = gtk_button_new_with_label("Show virtual keyboard"); + g_signal_connect(button, "clicked", G_CALLBACK(open_vkb), self); + gtk_widget_set_can_focus(GTK_WIDGET(button), false); + gtk_box_append(GTK_BOX(box), button); + gtk_window_set_child(GTK_WINDOW(gtk_window), box); gtk_window_present(gtk_window); diff --git a/src/login-shell.h b/src/login-shell.h index 9f14305..614d0ea 100644 --- a/src/login-shell.h +++ b/src/login-shell.h @@ -3,9 +3,10 @@ #include #include "base.h" +#include "shell.h" #define DIYA_TYPE_LOGIN_SHELL (diya_login_shell_get_type()) -G_DECLARE_FINAL_TYPE(DiyaLoginShell, diya_login_shell, DIYA, LOGIN_SHELL, DiyaObject); +G_DECLARE_FINAL_TYPE(DiyaLoginShell, diya_login_shell, DIYA, LOGIN_SHELL, DiyaShell); DiyaLoginShell *diya_login_shell_new(); diff --git a/src/login.c b/src/login.c index d40d28e..1e6c814 100644 --- a/src/login.c +++ b/src/login.c @@ -2,6 +2,7 @@ #include #include "login-shell.h" +#include "wayland.h" static gchar **g_shell_argv; @@ -31,6 +32,7 @@ static gboolean restart(gpointer d) static void startup(GtkApplication *app, DiyaLoginShell* shell) { + diya_shell_wayland_init(DIYA_SHELL(shell)); g_unix_signal_add(SIGHUP, (GSourceFunc)restart, NULL); g_unix_signal_add(SIGINT,(GSourceFunc)g_application_quit,(void*)app); diya_login_shell_attach(shell, app); diff --git a/src/session-lock.c b/src/session-lock.c index 78a51b6..8cb4559 100644 --- a/src/session-lock.c +++ b/src/session-lock.c @@ -3,14 +3,14 @@ #include #include "session-lock.h" -static void unlock_session(GtkButton *button, DiyaShell *shell) +static void unlock_session(GtkButton *button, DiyaSessionShell *shell) { (void)button; assert(shell); - diya_shell_unlock(shell); + diya_session_shell_unlock(shell); } -void diya_shell_lock(DiyaShell* shell) +void diya_session_shell_lock(DiyaSessionShell* shell) { assert(shell); GtkSessionLockInstance * lock; @@ -60,7 +60,7 @@ void diya_shell_lock(DiyaShell* shell) gtk_window_present(gtk_window); } } -void diya_shell_unlock(DiyaShell* shell) +void diya_session_shell_unlock(DiyaSessionShell* shell) { assert(shell); GtkSessionLockInstance * lock; diff --git a/src/session-lock.h b/src/session-lock.h index e6099e1..72fb423 100644 --- a/src/session-lock.h +++ b/src/session-lock.h @@ -1,9 +1,9 @@ #ifndef DIYA_SESSION_LOCK_H #define DIYA_SESSION_LOCK_H -#include "shell.h" +#include "session-shell.h" -void diya_shell_lock(DiyaShell* shell); -void diya_shell_unlock(DiyaShell* shell); +void diya_session_shell_lock(DiyaSessionShell* shell); +void diya_session_shell_unlock(DiyaSessionShell* shell); #endif \ No newline at end of file diff --git a/src/session-shell.c b/src/session-shell.c new file mode 100644 index 0000000..50ff3a3 --- /dev/null +++ b/src/session-shell.c @@ -0,0 +1,273 @@ +#include "session-shell.h" + +#include +#include +#include "shell.h" +#include "foreign.h" + +#define SHELL_DESCRIPTION "Diya GTK shell for wayland (diyac)" + +enum +{ + NO_PROP, + SHELL_APP, + SHELL_BACKGROUND_WIDGET, + SHELL_LAUNCHPAD_WIDGET, + SHELL_LOCK_SESSION, + SHELL_WINDOWS, + N_PROPERTIES +}; + +static GParamSpec *shell_properties[N_PROPERTIES] = {0}; + +struct _DiyaSessionShell +{ + DiyaShell parent; + GtkApplication* app; + GtkWindow* background; + GtkWindow* launcher; + GHashTable* windows; + GtkSessionLockInstance* lock; +}; +G_DEFINE_FINAL_TYPE(DiyaSessionShell, diya_session_shell, DIYA_TYPE_SHELL) + +static void diya_session_shell_dispose(GObject* object) +{ + DiyaSessionShell * self = DIYA_SESSION_SHELL(object); + g_hash_table_destroy(self->windows); + g_debug("diya_session_shell_dispose"); + if(self->lock) + { + g_object_unref(self->lock); + } + G_OBJECT_CLASS(diya_session_shell_parent_class)->dispose(object); +} + +static void diya_session_shell_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + DiyaSessionShell * self = DIYA_SESSION_SHELL(object); + switch (property_id) + { + case SHELL_APP: + self->app = g_value_get_pointer(value); + assert(self->app); + break; + case SHELL_BACKGROUND_WIDGET: + self->background = g_value_get_pointer(value); + break; + case SHELL_LAUNCHPAD_WIDGET: + self->launcher = g_value_get_pointer(value); + break; + case SHELL_WINDOWS: + //self->windows = g_value_get_pointer(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void diya_session_shell_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + DiyaSessionShell * self = DIYA_SESSION_SHELL(object); + switch (property_id) + { + case SHELL_APP: + g_value_set_pointer(value, self->app); + break; + case SHELL_BACKGROUND_WIDGET: + g_value_set_pointer(value, self->background); + break; + case SHELL_LAUNCHPAD_WIDGET: + assert(self->launcher); + g_value_set_pointer(value, self->launcher); + break; + case SHELL_LOCK_SESSION: + assert(self->lock); + g_value_set_pointer(value, self->lock); + break; + case SHELL_WINDOWS: + g_value_set_pointer(value, self->windows); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static const gchar* diya_session_shell_to_string(DiyaObject* object) +{ + (void) object; + return SHELL_DESCRIPTION; +} + +static void diya_session_shell_class_init(DiyaSessionShellClass *class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(class); + DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class); + + DiyaShellClass *base_shell_class = DIYA_SHELL_CLASS(class); + base_shell_class->foreign_register = diya_session_shell_foreign_toplevel_register; + + base_class->to_string = diya_session_shell_to_string; + gobject_class->dispose = diya_session_shell_dispose; + gobject_class->set_property = diya_session_shell_set_property; + gobject_class->get_property = diya_session_shell_get_property; + + shell_properties[SHELL_APP] = g_param_spec_pointer("application", NULL, "Shell application", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + shell_properties[SHELL_BACKGROUND_WIDGET] = g_param_spec_pointer("background", NULL, "Shell background widget", G_PARAM_READWRITE ); + shell_properties[SHELL_LAUNCHPAD_WIDGET] = g_param_spec_pointer("launchpad", NULL, "Shell launchpad", G_PARAM_READWRITE ); + shell_properties[SHELL_LOCK_SESSION] = g_param_spec_pointer("session-lock", NULL, "Shell lock session", G_PARAM_READABLE ); + shell_properties[SHELL_WINDOWS] = g_param_spec_pointer("windows", NULL, "Shell foreign windows", G_PARAM_READABLE); + + g_object_class_install_properties (gobject_class, N_PROPERTIES, shell_properties); + + g_signal_new("foreign-window-changed", + DIYA_TYPE_SESSION_SHELL, + G_SIGNAL_DETAILED | + G_SIGNAL_ACTION | + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + G_TYPE_POINTER); + g_signal_new("foreign-window-removed", + DIYA_TYPE_SESSION_SHELL, + G_SIGNAL_DETAILED | + G_SIGNAL_ACTION | + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + G_TYPE_POINTER); + g_signal_new("session-locked", + DIYA_TYPE_SESSION_SHELL, + G_SIGNAL_DETAILED | + G_SIGNAL_ACTION | + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); + g_signal_new("session-unlocked", + DIYA_TYPE_SESSION_SHELL, + G_SIGNAL_DETAILED | + G_SIGNAL_ACTION | + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); +} + +static void on_session_locked(GtkSessionLockInstance *lock, DiyaSessionShell *shell) { + (void)lock; + assert(shell); + g_message("Session locked successfully"); + g_signal_emit_by_name(shell, "session-locked"); +} + +/* +static void failed(GtkSessionLockInstance *lock, void *data) { + (void)lock; + (void)data; + + g_critical("The session could not be locked"); + g_application_quit(G_APPLICATION(app)); +} +*/ + +static void on_session_unlocked(GtkSessionLockInstance *lock, DiyaSessionShell *shell) { + (void)lock; + assert(shell); + g_message("Session unlocked"); + g_signal_emit_by_name(shell, "session-unlocked"); +} + +static void diya_session_shell_init(DiyaSessionShell *self) +{ + //self->app = NULL; + self->background = NULL; + self->launcher = NULL; + self->lock = gtk_session_lock_instance_new(); + g_signal_connect(self->lock, "locked", G_CALLBACK(on_session_locked), self); + // g_signal_connect(lock, "failed", G_CALLBACK(failed), NULL); + g_signal_connect(self->lock, "unlocked", G_CALLBACK(on_session_unlocked), self); + self->windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref); +} + +DiyaForeignWindow* diya_session_shell_get_window(DiyaSessionShell * shell, gpointer handle) +{ + return g_hash_table_lookup(shell->windows, handle); +} +gboolean diya_session_shell_add_window(DiyaSessionShell * shell, DiyaForeignWindow * win) +{ + gpointer handle; + g_object_get(win, "handle", &handle, NULL); + assert(handle); + return g_hash_table_insert(shell->windows,handle, win); +} + +gboolean diya_session_shell_remove_window(DiyaSessionShell * shell, DiyaForeignWindow * win) +{ + gpointer handle; + g_object_get(win, "handle", &handle, NULL); + assert(handle); + return g_hash_table_remove(shell->windows,handle); +} + +void diya_session_shell_remove_all_windows(DiyaSessionShell * shell) +{ + g_hash_table_destroy(shell->windows); + shell->windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref); +} + +DiyaSessionShell * diya_session_shell_new(GtkApplication * app) +{ + return DIYA_SESSION_SHELL(g_object_new(DIYA_TYPE_SESSION_SHELL,"application",app, NULL)); +} +/* +static void on_orientation_changed (GtkWindow *window, WindowOrientation orientation, ToplevelData *data) +{ + (void)window; + GtkOrientation orient_toplevel, orient_sub; + orient_toplevel = GTK_ORIENTATION_HORIZONTAL; + orient_sub = GTK_ORIENTATION_VERTICAL; + + switch (orientation) { + case WINDOW_ORIENTATION_HORIZONTAL: + orient_toplevel = GTK_ORIENTATION_HORIZONTAL; + orient_sub = GTK_ORIENTATION_HORIZONTAL; + break; + case WINDOW_ORIENTATION_VERTICAL: + orient_toplevel = GTK_ORIENTATION_VERTICAL; + orient_sub = GTK_ORIENTATION_VERTICAL; + break; + case WINDOW_ORIENTATION_NONE: + orient_toplevel = GTK_ORIENTATION_HORIZONTAL; + orient_sub = GTK_ORIENTATION_VERTICAL; + break; + } + gtk_orientable_set_orientation (GTK_ORIENTABLE (data->toplevel_box), orient_toplevel); + gtk_orientable_set_orientation (GTK_ORIENTABLE (data->first_box), orient_sub); + gtk_orientable_set_orientation (GTK_ORIENTABLE (data->second_box), orient_sub); + //gtk_window_resize (window, 1, 1); // force the window to shrink to the smallest size it can +} +*/ + +/* +static void before_destroy (GtkWidget *win, GtkCssProvider *provider) { + GdkDisplay *display = gdk_display_get_default (); + gtk_style_context_remove_provider_for_display (display, GTK_STYLE_PROVIDER (provider)); +} +*/ diff --git a/src/session-shell.h b/src/session-shell.h new file mode 100644 index 0000000..3b68808 --- /dev/null +++ b/src/session-shell.h @@ -0,0 +1,20 @@ +#ifndef DIYA_SESSION_SHELL_H +#define DIYA_SESSION_SHELL_H + +#include +#include "shell.h" +#include "base.h" + +#define DIYA_TYPE_SESSION_SHELL (diya_session_shell_get_type ()) +G_DECLARE_FINAL_TYPE (DiyaSessionShell, diya_session_shell, DIYA, SESSION_SHELL, DiyaShell) + +#define DIYA_TYPE_FOREIGN_WINDOW (diya_foreign_window_get_type ()) +G_DECLARE_FINAL_TYPE (DiyaForeignWindow, diya_foreign_window, DIYA, FOREIGN_WINDOW, DiyaShellObject) + +DiyaForeignWindow* diya_session_shell_get_window(DiyaSessionShell * shell, gpointer handle); +gboolean diya_session_shell_add_window(DiyaSessionShell * shell, DiyaForeignWindow * win); +gboolean diya_session_shell_remove_window(DiyaSessionShell * shell, DiyaForeignWindow * win); +void diya_session_shell_remove_all_windows(DiyaSessionShell * shell); + +DiyaSessionShell * diya_session_shell_new(GtkApplication * app); +#endif \ No newline at end of file diff --git a/src/session.c b/src/session.c index 6f602ec..3ef1a26 100644 --- a/src/session.c +++ b/src/session.c @@ -14,8 +14,8 @@ static void activate(GtkApplication *app, void *data) (void)app; (void)data; - DiyaShell *shell = data; - diya_shell_lock(shell); + DiyaSessionShell *shell = data; + diya_session_shell_lock(shell); } static gboolean restart(gpointer d) @@ -37,11 +37,11 @@ static gboolean restart(gpointer d) static void startup(GtkApplication *app, void *data) { - DiyaShell *shell = data; + DiyaSessionShell *shell = data; - diya_shell_launcher_init(shell); - diya_shell_wayland_init(shell); - diya_shell_init_background(shell); + diya_session_shell_launcher_init(shell); + diya_session_shell_init_background(shell); + diya_shell_wayland_init(DIYA_SHELL(shell)); GtkCssProvider *provider = gtk_css_provider_new(); const char *css = "#launcher {background-color: red;} #background {background-image:url(\"file:///etc/xdg/labwc/wpp.jpg\");background-size: cover;}"; @@ -57,14 +57,14 @@ static void startup(GtkApplication *app, void *data) g_unix_signal_add(SIGINT,(GSourceFunc)g_application_quit,(void*)app); } -static void session_locked(DiyaShell* shell, void* data) +static void session_locked(DiyaSessionShell* shell, void* data) { (void)data; assert(shell); g_warning("session_locked callback triggered"); } -static void session_unlocked(DiyaShell* shell, void* data) +static void session_unlocked(DiyaSessionShell* shell, void* data) { (void)data; assert(shell); @@ -79,7 +79,7 @@ int main(int argc, char *argv[]) g_shell_argv[i] = argv[i]; } GtkApplication *app = gtk_application_new("dev.iohub.diya.shell", G_APPLICATION_DEFAULT_FLAGS); - DiyaShell *shell = diya_shell_new(app); + DiyaSessionShell *shell = diya_session_shell_new(app); g_signal_connect(app, "startup", G_CALLBACK(startup), (void *)shell); g_signal_connect(app, "activate", G_CALLBACK(activate), (void *)shell); g_signal_connect(shell, "session-locked", G_CALLBACK(session_locked), NULL); diff --git a/src/shell.c b/src/shell.c index 31f8ada..fbdc50e 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1,47 +1,35 @@ -#include -#include #include "shell.h" - -#define SHELL_DESCRIPTION "Diya GTK shell for wayland (diyac)" - +#include "wayland.h" +#include "virtual-keyboard.h" enum { NO_PROP, - SHELL_APP, - SHELL_BACKGROUND_WIDGET, - SHELL_LAUNCHPAD_WIDGET, - SHELL_LOCK_SESSION, - SHELL_WINDOWS, - SHELL_WAYLAND, + PROP_SHELL_WAYLAND, N_PROPERTIES }; static GParamSpec *shell_properties[N_PROPERTIES] = {0}; -struct _DiyaShell + +typedef struct _DiyaShellPrivate { - DiyaObject parent; - GtkApplication* app; - GtkWindow* background; - GtkWindow* launcher; - GHashTable* windows; - GtkSessionLockInstance* lock; + DiyaObject parent; DiyaWayland * wayland; -}; -G_DEFINE_FINAL_TYPE(DiyaShell, diya_shell, DIYA_TYPE_OBJECT) + DiyaVirtualKeyboard* vkb; +} DiyaShellPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE(DiyaShell, diya_shell, DIYA_TYPE_OBJECT); + + static void diya_shell_dispose(GObject* object) { + g_debug("diya_shell_dispose: %s", diya_object_to_string(object)); DiyaShell * self = DIYA_SHELL(object); - g_hash_table_destroy(self->windows); - g_debug("diya_shell_dispose"); - if(self->wayland) + DiyaShellPrivate* priv = diya_shell_get_instance_private(self); + if(priv->wayland) { - g_object_unref(self->wayland); - } - if(self->lock) - { - g_object_unref(self->lock); + g_object_unref(priv->wayland); } G_OBJECT_CLASS(diya_shell_parent_class)->dispose(object); } @@ -49,23 +37,12 @@ static void diya_shell_dispose(GObject* object) static void diya_shell_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { DiyaShell * self = DIYA_SHELL(object); + DiyaShellPrivate* priv = diya_shell_get_instance_private(self); + switch (property_id) { - case SHELL_APP: - self->app = g_value_get_pointer(value); - assert(self->app); - break; - case SHELL_BACKGROUND_WIDGET: - self->background = g_value_get_pointer(value); - break; - case SHELL_LAUNCHPAD_WIDGET: - self->launcher = g_value_get_pointer(value); - break; - case SHELL_WAYLAND: - self->wayland = g_value_get_pointer(value); - break; - case SHELL_WINDOWS: - //self->windows = g_value_get_pointer(value); + case PROP_SHELL_WAYLAND: + priv->wayland = g_value_get_pointer(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -76,27 +53,11 @@ static void diya_shell_set_property(GObject *object, guint property_id, const GV static void diya_shell_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { DiyaShell * self = DIYA_SHELL(object); + DiyaShellPrivate* priv = diya_shell_get_instance_private(self); switch (property_id) { - case SHELL_APP: - g_value_set_pointer(value, self->app); - break; - case SHELL_BACKGROUND_WIDGET: - g_value_set_pointer(value, self->background); - break; - case SHELL_LAUNCHPAD_WIDGET: - assert(self->launcher); - g_value_set_pointer(value, self->launcher); - break; - case SHELL_LOCK_SESSION: - assert(self->lock); - g_value_set_pointer(value, self->lock); - break; - case SHELL_WAYLAND: - g_value_set_pointer(value, self->wayland); - break; - case SHELL_WINDOWS: - g_value_set_pointer(value, self->windows); + case PROP_SHELL_WAYLAND: + g_value_set_pointer(value, priv->wayland); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -104,145 +65,11 @@ static void diya_shell_get_property(GObject *object, guint property_id, GValue * } } -static const gchar* diya_shell_to_string(DiyaObject* object) -{ - (void) object; - return SHELL_DESCRIPTION; -} - -static void diya_shell_class_init(DiyaShellClass *class) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(class); - DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class); - - base_class->to_string = diya_shell_to_string; - gobject_class->dispose = diya_shell_dispose; - gobject_class->set_property = diya_shell_set_property; - gobject_class->get_property = diya_shell_get_property; - - shell_properties[SHELL_APP] = g_param_spec_pointer("application", NULL, "Shell application", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - shell_properties[SHELL_BACKGROUND_WIDGET] = g_param_spec_pointer("background", NULL, "Shell background widget", G_PARAM_READWRITE ); - shell_properties[SHELL_LAUNCHPAD_WIDGET] = g_param_spec_pointer("launchpad", NULL, "Shell launchpad", G_PARAM_READWRITE ); - shell_properties[SHELL_LOCK_SESSION] = g_param_spec_pointer("session-lock", NULL, "Shell lock session", G_PARAM_READABLE ); - shell_properties[SHELL_WINDOWS] = g_param_spec_pointer("windows", NULL, "Shell foreign windows", G_PARAM_READABLE); - shell_properties[SHELL_WAYLAND] = g_param_spec_pointer("wayland", NULL, "Shell wayland", G_PARAM_READWRITE ); - - g_object_class_install_properties (gobject_class, N_PROPERTIES, shell_properties); - - g_signal_new("foreign-window-changed", - DIYA_TYPE_SHELL, - G_SIGNAL_DETAILED | - G_SIGNAL_ACTION | - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 1, - G_TYPE_POINTER); - g_signal_new("foreign-window-removed", - DIYA_TYPE_SHELL, - G_SIGNAL_DETAILED | - G_SIGNAL_ACTION | - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 1, - G_TYPE_POINTER); - g_signal_new("session-locked", - DIYA_TYPE_SHELL, - G_SIGNAL_DETAILED | - G_SIGNAL_ACTION | - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 0); - g_signal_new("session-unlocked", - DIYA_TYPE_SHELL, - G_SIGNAL_DETAILED | - G_SIGNAL_ACTION | - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 0); -} - -static void on_session_locked(GtkSessionLockInstance *lock, DiyaShell *shell) { - (void)lock; - assert(shell); - g_message("Session locked successfully"); - g_signal_emit_by_name(shell, "session-locked"); -} - -/* -static void failed(GtkSessionLockInstance *lock, void *data) { - (void)lock; - (void)data; - - g_critical("The session could not be locked"); - g_application_quit(G_APPLICATION(app)); -} -*/ - -static void on_session_unlocked(GtkSessionLockInstance *lock, DiyaShell *shell) { - (void)lock; - assert(shell); - g_message("Session unlocked"); - g_signal_emit_by_name(shell, "session-unlocked"); -} static void diya_shell_init(DiyaShell *self) { - //self->app = NULL; - self->background = NULL; - self->launcher = NULL; - self->wayland = NULL; - self->lock = gtk_session_lock_instance_new(); - g_signal_connect(self->lock, "locked", G_CALLBACK(on_session_locked), self); - // g_signal_connect(lock, "failed", G_CALLBACK(failed), NULL); - g_signal_connect(self->lock, "unlocked", G_CALLBACK(on_session_unlocked), self); - self->windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref); -} - -DiyaForeignWindow* diya_shell_get_window(DiyaShell * shell, gpointer handle) -{ - return g_hash_table_lookup(shell->windows, handle); -} -gboolean diya_shell_add_window(DiyaShell * shell, DiyaForeignWindow * win) -{ - gpointer handle; - g_object_get(win, "handle", &handle, NULL); - assert(handle); - return g_hash_table_insert(shell->windows,handle, win); -} - -gboolean diya_shell_remove_window(DiyaShell * shell, DiyaForeignWindow * win) -{ - gpointer handle; - g_object_get(win, "handle", &handle, NULL); - assert(handle); - return g_hash_table_remove(shell->windows,handle); -} - -void diya_shell_remove_all_windows(DiyaShell * shell) -{ - g_hash_table_destroy(shell->windows); - shell->windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref); -} - -DiyaShell * diya_shell_new(GtkApplication * app) -{ - return DIYA_SHELL(g_object_new(DIYA_TYPE_SHELL,"application",app, NULL)); + DiyaShellPrivate* priv = diya_shell_get_instance_private(self); + priv->wayland = NULL; } DiyaWayland * diya_shell_get_wayland(DiyaShell* shell) @@ -252,38 +79,17 @@ DiyaWayland * diya_shell_get_wayland(DiyaShell* shell) assert(DIYA_IS_WAYLAND(wayland)); return wayland; } -/* -static void on_orientation_changed (GtkWindow *window, WindowOrientation orientation, ToplevelData *data) + +static void diya_shell_class_init(DiyaShellClass *class) { - (void)window; - GtkOrientation orient_toplevel, orient_sub; - orient_toplevel = GTK_ORIENTATION_HORIZONTAL; - orient_sub = GTK_ORIENTATION_VERTICAL; + GObjectClass *gobject_class = G_OBJECT_CLASS(class); + gobject_class->dispose = diya_shell_dispose; + gobject_class->set_property = diya_shell_set_property; + gobject_class->get_property = diya_shell_get_property; - switch (orientation) { - case WINDOW_ORIENTATION_HORIZONTAL: - orient_toplevel = GTK_ORIENTATION_HORIZONTAL; - orient_sub = GTK_ORIENTATION_HORIZONTAL; - break; - case WINDOW_ORIENTATION_VERTICAL: - orient_toplevel = GTK_ORIENTATION_VERTICAL; - orient_sub = GTK_ORIENTATION_VERTICAL; - break; - case WINDOW_ORIENTATION_NONE: - orient_toplevel = GTK_ORIENTATION_HORIZONTAL; - orient_sub = GTK_ORIENTATION_VERTICAL; - break; - } - gtk_orientable_set_orientation (GTK_ORIENTABLE (data->toplevel_box), orient_toplevel); - gtk_orientable_set_orientation (GTK_ORIENTABLE (data->first_box), orient_sub); - gtk_orientable_set_orientation (GTK_ORIENTABLE (data->second_box), orient_sub); - //gtk_window_resize (window, 1, 1); // force the window to shrink to the smallest size it can -} -*/ - -/* -static void before_destroy (GtkWidget *win, GtkCssProvider *provider) { - GdkDisplay *display = gdk_display_get_default (); - gtk_style_context_remove_provider_for_display (display, GTK_STYLE_PROVIDER (provider)); -} -*/ + class->foreign_register = NULL; + class->virtual_keyboard_register = diya_virtual_keyboard_register; + + shell_properties[PROP_SHELL_WAYLAND] = g_param_spec_pointer("wayland", NULL, "Shell wayland", G_PARAM_READWRITE); // + g_object_class_install_properties (gobject_class, N_PROPERTIES, shell_properties); +} \ No newline at end of file diff --git a/src/shell.h b/src/shell.h index d67eb41..200d215 100644 --- a/src/shell.h +++ b/src/shell.h @@ -1,31 +1,27 @@ #ifndef DIYA_SHELL_H #define DIYA_SHELL_H -#include +#include #include "base.h" -enum diya_win_state -{ - DIYA_WIN_STATE_NONE = 0, - DIYA_WIN_STATE_MINIMIZE = 1 << 0, - DIYA_WIN_STATE_MAXIMIZE = 1 << 1, - DIYA_WIN_STATE_FULLSCREEN = 1 << 2, - DIYA_WIN_STATE_FOCUS = 1 << 3, -}; - -#define DIYA_TYPE_SHELL (diya_shell_get_type ()) -G_DECLARE_FINAL_TYPE (DiyaShell, diya_shell, DIYA, SHELL, DiyaObject) +#define DIYA_TYPE_SHELL (diya_shell_get_type()) +G_DECLARE_DERIVABLE_TYPE(DiyaShell, diya_shell, DIYA, SHELL, DiyaObject) #define DIYA_TYPE_WAYLAND (diya_wayland_get_type ()) G_DECLARE_FINAL_TYPE (DiyaWayland, diya_wayland, DIYA, WAYLAND, DiyaShellObject) -#define DIYA_TYPE_FOREIGN_WINDOW (diya_foreign_window_get_type ()) -G_DECLARE_FINAL_TYPE (DiyaForeignWindow, diya_foreign_window, DIYA, FOREIGN_WINDOW, DiyaShellObject) +struct wl_registry; -DiyaForeignWindow* diya_shell_get_window(DiyaShell * shell, gpointer handle); -gboolean diya_shell_add_window(DiyaShell * shell, DiyaForeignWindow * win); -gboolean diya_shell_remove_window(DiyaShell * shell, DiyaForeignWindow * win); -void diya_shell_remove_all_windows(DiyaShell * shell); +typedef void (*wl_protocol_manager_register_t)(struct wl_registry*, uint32_t,DiyaShell*); -DiyaShell * diya_shell_new(GtkApplication * app); +struct _DiyaShellClass +{ + DiyaObjectClass parent_class; + wl_protocol_manager_register_t foreign_register; + wl_protocol_manager_register_t virtual_keyboard_register; +}; + +void diya_shell_wayland_init(DiyaShell *shell); DiyaWayland * diya_shell_get_wayland(DiyaShell* shell); + + #endif \ No newline at end of file diff --git a/src/virtual-keyboard.c b/src/virtual-keyboard.c index e69de29..8bc658b 100644 --- a/src/virtual-keyboard.c +++ b/src/virtual-keyboard.c @@ -0,0 +1,220 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "virtual-keyboard-unstable-v1.h" +#include "virtual-keyboard.h" +#include "wayland.h" + +static struct zwp_virtual_keyboard_manager_v1 *g_virtual_keyboard_manager = NULL; + +struct _DiyaVirtualKeyboard +{ + DiyaShellObject parent; + struct zwp_virtual_keyboard_v1 *keyboard; +}; + +G_DEFINE_FINAL_TYPE(DiyaVirtualKeyboard, diya_virtual_keyboard, DIYA_TYPE_SHELL_OBJECT); + +static void diya_virtual_keyboard_dispose(GObject *object) +{ + DiyaVirtualKeyboard *self = DIYA_VIRTUAL_KEYBOARD(object); + g_debug("diya_virtual_keyboard_dispose"); + if (self->keyboard) + { + zwp_virtual_keyboard_v1_destroy(self->keyboard); + } + G_OBJECT_CLASS(diya_virtual_keyboard_parent_class)->dispose(object); +} + +static void diya_virtual_keyboard_init(DiyaVirtualKeyboard *self) +{ + self->keyboard = NULL; +} + +static const gchar *diya_virtual_keyboard_to_string(DiyaObject *object) +{ + (void)object; + return "Diya virtual keyboard instance"; +} + +static void diya_virtual_keyboard_class_init(DiyaVirtualKeyboardClass *class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(class); + DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class); + + gobject_class->dispose = diya_virtual_keyboard_dispose; + // gobject_class->set_property = diya_lock_session_set_property; + // gobject_class->get_property = diya_lock_session_get_property; + base_class->to_string = diya_virtual_keyboard_to_string; +} + +/* +static void randname(char *buf) +{ + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + long r = ts.tv_nsec; + for (int i = 0; i < 6; ++i) + { + buf[i] = 'A' + (r & 15) + (r & 16) * 2; + r >>= 5; + } +} +*/ + +static int create_keymap_fd(off_t size) +{ + static const char name[] = "/diya-shell-keymap-XXXXXX"; + const char *base; + char *path; + int fd; + int ret; + // randname(name + sizeof(name) - 7); + base = getenv("XDG_RUNTIME_DIR"); + if (!base) + { + errno = ENOENT; + return -1; + } + path = malloc(strlen(base) + sizeof(name) + 1); + if (!path) + return -1; + + strcpy(path, base); + strcat(path, name); + g_debug("Create temp file for keymap: %s", path); + + fd = mkstemp(path); + if (fd >= 0) + { + long flags; + flags = fcntl(fd, F_GETFD); + if (flags == -1) + { + g_critical("fcntl Unable to F_GETFD: %s", strerror(errno)); + close(fd); + fd = -1; + } + else if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) + { + g_critical("fcntl Unable to F_SETFD(FD_CLOEXEC): %s", strerror(errno)); + close(fd); + fd = -1; + } + unlink(path); + } + else + { + g_critical("mkstemp Unable to create temp file %s: %s", path, strerror(errno)); + } + free(path); + + if (fd < 0) + return -1; + do + { + ret = ftruncate(fd, size); + } while (ret < 0 && errno == EINTR); + if (ret < 0) + { + close(fd); + return -1; + } + + return fd; +} + +DiyaVirtualKeyboard *diya_virtual_keyboard_new(DiyaShell *shell, const gchar *keymap_file) +{ + gchar *content = NULL; + GError *error = NULL; + GBytes *bytes = NULL; + gsize len = 0; + + if (keymap_file) + { + g_file_get_contents(keymap_file, &content, &len, &error); + if (error != NULL) + { + g_critical("diya_virtual_keyboard_new: Unable to read file %s: %s", keymap_file, error->message); + g_error_free(error); + return NULL; + } + } + else + { + g_warning("No keymap file specified.Loading default keymap from resource"); + GBytes *bytes = g_resources_lookup_data("/dev/iohub/diya/shell/default.keymap", 0, &error); + if (error != NULL) + { + g_critical("Unable to read keymap file from resource %s", error->message); + g_error_free(error); + return NULL; + } + content = (gchar*)g_bytes_get_data(bytes, &len); + } + + int fd = create_keymap_fd(len); + if (fd == -1) + { + g_critical("diya_virtual_keyboard_new: create temp file"); + if(bytes) + { + g_bytes_unref(bytes); + content = NULL; + } + if(content) + { + g_free(content); + } + } + + void *ptr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (ptr == (void *)-1) + { + g_critical("diya_virtual_keyboard_new: error mmap: %s", strerror(errno)); + close(fd); + if(bytes) + { + g_bytes_unref(bytes); + content = NULL; + } + if(content) + { + g_free(content); + } + } + + strcpy((char *)ptr, content); + + DiyaVirtualKeyboard *vkb = g_object_new(DIYA_TYPE_VIRTUAL_KEYBOARD, "shell", shell, NULL); + DiyaWayland *wayland = diya_shell_get_wayland(shell); + struct wl_seat *seat = diya_wayland_get_seat(wayland); + vkb->keyboard = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(g_virtual_keyboard_manager, seat); + zwp_virtual_keyboard_v1_keymap(vkb->keyboard, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fd, len); + + + return vkb; +} + +void diya_virtual_keyboard_register(struct wl_registry *registry, uint32_t name, DiyaShell *shell) +{ + (void)shell; + g_virtual_keyboard_manager = wl_registry_bind(registry, name, &zwp_virtual_keyboard_manager_v1_interface, 1); +} + +void diya_virtual_keyboard_send_key(DiyaVirtualKeyboard *self, uint32_t key, diya_vkb_state_t state) +{ + GDateTime *now = g_date_time_new_now_local(); + uint32_t current_time_ms = g_date_time_get_microsecond(now) / 1000; + g_date_time_unref(now); + zwp_virtual_keyboard_v1_key(self->keyboard, current_time_ms, key, (uint32_t)state); +} \ No newline at end of file diff --git a/src/virtual-keyboard.h b/src/virtual-keyboard.h index 6d6e050..38932a7 100644 --- a/src/virtual-keyboard.h +++ b/src/virtual-keyboard.h @@ -1,8 +1,19 @@ #ifndef DIYA_VIRTUAL_KEYBOARD_H #define DIYA_VIRTUAL_KEYBOARD_H -#include "virtual-keyboard-unstable-v1.h" #include "shell.h" +typedef enum +{ + VKB_KEY_STATE_RELEASED = 0 /*WL_KEYBOARD_KEY_STATE_RELEASED*/, + VKB_KEY_STATE_PRESSED = 1 /*WL_KEYBOARD_KEY_STATE_PRESSED*/, +} diya_vkb_state_t; +#define DIYA_TYPE_VIRTUAL_KEYBOARD (diya_virtual_keyboard_get_type ()) +G_DECLARE_FINAL_TYPE (DiyaVirtualKeyboard, diya_virtual_keyboard, DIYA, VIRTUAL_KEYBOARD, DiyaShellObject) + +DiyaVirtualKeyboard* diya_virtual_keyboard_new(DiyaShell* shell, const gchar* keymap_file); + +void diya_virtual_keyboard_register(struct wl_registry *registry, uint32_t name, DiyaShell *shell); +void diya_virtual_keyboard_send_key(DiyaVirtualKeyboard* vkb, uint32_t key, diya_vkb_state_t state); #endif \ No newline at end of file diff --git a/src/wayland.c b/src/wayland.c index d9fd3f0..66c586c 100644 --- a/src/wayland.c +++ b/src/wayland.c @@ -1,15 +1,17 @@ #include #include #include +#include "wlr-foreign-toplevel-management-unstable-v1.h" +#include "virtual-keyboard-unstable-v1.h" #include "wayland.h" -#include "foreign.h" struct _DiyaWayland { - DiyaObject parent; + DiyaShellObject parent; struct wl_compositor * compositor; struct wl_shm * shm; + struct wl_seat * seat; }; G_DEFINE_FINAL_TYPE(DiyaWayland, diya_wayland, DIYA_TYPE_SHELL_OBJECT) @@ -17,7 +19,7 @@ static void diya_wayland_dispose(GObject* object) { (void) object; //DiyaWayland * self = DIYA_WAYLAND(object); - g_debug("diya_wayland_dispose"); + g_debug("diya_wayland_dispose: %s", diya_object_to_string(object)); G_OBJECT_CLASS(diya_wayland_parent_class)->dispose(object); } @@ -25,17 +27,24 @@ static void diya_wayland_init(DiyaWayland * self) { self->compositor = NULL; self->shm = NULL; + self->seat = NULL; +} + +static const gchar* diya_wayland_to_string(DiyaObject* object) +{ + (void) object; + return "DiyaWayland - wayland client handle object"; } static void diya_wayland_class_init(DiyaWaylandClass *class) { GObjectClass *gobject_class = G_OBJECT_CLASS(class); - //DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class); + DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class); gobject_class->dispose = diya_wayland_dispose; //gobject_class->set_property = diya_lock_session_set_property; //gobject_class->get_property = diya_lock_session_get_property; - //base_class->to_string = diya_lock_session_to_string; + base_class->to_string = diya_wayland_to_string; } @@ -52,18 +61,34 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam */ (void) version; DiyaShell * shell = data; + DiyaShellClass * class = DIYA_SHELL_GET_CLASS(shell); DiyaWayland * wayland; g_object_get(shell, "wayland", &wayland, NULL); assert(DIYA_IS_WAYLAND(wayland)); g_debug("WAYLAND GLOBAL: %s", interface); + if (g_strcmp0(interface, zwlr_foreign_toplevel_manager_v1_interface.name) == 0) { - diya_shell_foreign_toplevel_register(registry, name, data); + if(class->foreign_register) + { + //diya_session_shell_foreign_toplevel_register(registry, name, data); + g_debug("Wayland: register shell foreign top level manager"); + class->foreign_register(registry, name, data); + } + } + if (g_strcmp0(interface, zwp_virtual_keyboard_manager_v1_interface.name) == 0) + { + if(class->virtual_keyboard_register) + { + //diya_session_shell_foreign_toplevel_register(registry, name, data); + g_debug("Wayland: register virtual keyboard manager"); + class->virtual_keyboard_register(registry, name, data); + } } /* else if(!g_strcmp0(interface, ext_session_lock_manager_v1_interface.name)) { - diya_shell_session_lock_register(registry, name); + diya_session_shell_session_lock_register(registry, name); } */ else if (strcmp(interface, wl_compositor_interface.name) == 0) @@ -74,6 +99,10 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam { wayland->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); } + else if (strcmp(interface, wl_seat_interface.name) == 0) + { + wayland->seat = wl_registry_bind(registry, name, &wl_seat_interface, 7); + } } static void handle_global_remove(void *data, struct wl_registry *registry, @@ -143,3 +172,9 @@ struct wl_shm_pool * diya_wayland_create_shm_pool(DiyaWayland * self, int fd, gu assert(self->shm); return wl_shm_create_pool(self->shm, fd, size); } + +struct wl_seat* diya_wayland_get_seat(DiyaWayland* self) +{ + assert(self->seat); + return self->seat; +} \ No newline at end of file diff --git a/src/wayland.h b/src/wayland.h index 8cf547f..28347fb 100644 --- a/src/wayland.h +++ b/src/wayland.h @@ -3,8 +3,8 @@ #include "shell.h" -void diya_shell_wayland_init(DiyaShell *shell); struct wl_surface* diya_wayland_create_surface(DiyaWayland * self); struct wl_output* diya_wayland_get_output(DiyaWayland * self, int index); struct wl_shm_pool * diya_wayland_create_shm_pool(DiyaWayland * self, int fd, guint size); +struct wl_seat* diya_wayland_get_seat(DiyaWayland* self); #endif \ No newline at end of file