Warning, /plasma/breeze-plymouth/breeze/breeze.script.cmake is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-FileCopyrightText: 2012-2016 Harald Sitter <sitter@kde.org> 0003 SPDX-FileCopyrightText: 2009 Canonical Ltd. 0004 SPDX-FileContributor: Alberto Milone <alberto.milone@canonical.com> 0005 Based on the example provided with the "script plugin" written by: 0006 SPDX-FileContributor: Charlie Brej <cbrej@cs.man.ac.uk> 0007 0008 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0009 */ 0010 0011 /** 0012 * 16bit debug override. Comment out to see what everything looks like on a 16bit 0013 * framebuffer/output. 0014 */ 0015 // Window.GetBitsPerPixel = fun() { return 4; }; 0016 0017 // -------------------------------- Assets ---------------------------------- // 0018 0019 global.title.text = "@DISTRO_NAME@ @DISTRO_VERSION@"; 0020 global.defaults.font.default = "Noto Sans 12"; 0021 global.defaults.font.title = "Noto Sans 14"; 0022 0023 global.assets = []; 0024 if (Window.GetBitsPerPixel() == 4) { 0025 assets.logo = "images/16bit/@DISTRO_LOGO@.logo.png"; 0026 assets.text_input = "images/16bit/text-input.png"; 0027 0028 assets.spinner_base = "images/16bit/spinner"; 0029 } else { 0030 assets.logo = "images/@DISTRO_LOGO@.logo.png"; 0031 assets.text_input = "images/text-input.png"; 0032 0033 assets.spinner_base = "images/spinner"; 0034 } 0035 0036 // -------------------------------- Colors ---------------------------------- // 0037 /** 0038 * General purpuse Color container to hold red, green, blue as any value 0039 * (real advisable). 0040 */ 0041 Color = fun(red, green, blue) { 0042 local.color = []; 0043 color.red = red; 0044 color.green = green; 0045 color.blue = blue; 0046 return color | global.Color; 0047 } | []; 0048 0049 global.colors = []; 0050 colors.black = Color(0, 0, 0); 0051 colors.icon_blue = Color(0.1137, 0.6000, 0.9529); 0052 colors.plasma_blue = Color(0.2392, 0.6824, 0.913); 0053 colors.paper_white = Color(0.9882, 0.9882, 0.9882); 0054 colors.charcoal_grey = Color(0.1922, 0.2118, 0.2314); 0055 colors.cardboard_grey = Color(0.9373, 0.9412, 0.9451); 0056 0057 colors.neon_blue = Color(0.1608, 0.5020, 0.7255); 0058 colors.neon_green = Color(0.1020, 0.7373, 0.6118); 0059 0060 global.palette = []; 0061 palette.background.top = colors.@BACKGROUND_TOP_COLOR@; 0062 palette.background.bottom = colors.@BACKGROUND_BOTTOM_COLOR@; 0063 palette.text.normal = colors.cardboard_grey; 0064 palette.text.tinted = colors.cardboard_grey; 0065 palette.text.action = colors.cardboard_grey; 0066 palette.text.contrast = colors.charcoal_grey; // Inverse essentially 0067 0068 /** 0069 * Helper overload to apply background colors from global.palette to the Window 0070 */ 0071 Window.ApplyBackgroundColors = fun() { 0072 Window.SetBackgroundTopColor(palette.background.top.red, 0073 palette.background.top.green, 0074 palette.background.top.blue); 0075 if (Window.GetBitsPerPixel() == 4) { // Force no gradient on 16bit. 0076 Window.SetBackgroundBottomColor(palette.background.top.red, 0077 palette.background.top.green, 0078 palette.background.top.blue); 0079 } else { 0080 Window.SetBackgroundBottomColor(palette.background.bottom.red, 0081 palette.background.bottom.green, 0082 palette.background.bottom.blue); 0083 } 0084 }; 0085 0086 // ------------------------------- Classes ---------------------------------- // 0087 0088 /** 0089 * class SpriteImage : Sprite { 0090 * Image image, # Image instance created by and for the Sprite 0091 * int width, # Image width 0092 * int height, # Image height 0093 * }; 0094 */ 0095 0096 /** 0097 * General purpose sprite-image combination. 0098 * The type itself is a Sprite that has an image property through which the image 0099 * powering the sprite may be accessed. 0100 * Members of the sprite are only updated on initial creation, any future changes 0101 * to the actually used image need to be reflected manually 0102 */ 0103 SpriteImage = fun(asset) { 0104 local.sprite = Sprite(); 0105 sprite.image = Image(asset); 0106 sprite.width = sprite.image.GetWidth(); 0107 sprite.height = sprite.image.GetHeight(); 0108 sprite.SetImage(sprite.image); 0109 return sprite | global.SpriteImage; 0110 } | Sprite; 0111 0112 SpriteImage.SetSpriteImage = fun(image) { 0113 this.image = image; 0114 this.width = image.GetWidth(); 0115 this.height = image.GetHeight(); 0116 this.SetImage(this.image); 0117 }; 0118 0119 // --------------------------------- Debug ---------------------------------- // 0120 // TODO: it may be handy to move all debug methods into a separate file 0121 // and configure_file them into the master script iff explicitly enabled. 0122 // This would reduce the script size and possibly eval time. Although 0123 // in the grand scheme of things I am not sure this script takes up a lot of 0124 // resources to begin with. 0125 debugsprite = Sprite(); 0126 debugsprite_bottom = Sprite(); 0127 debugsprite_medium = Sprite(); 0128 0129 // are we currently prompting for a password? 0130 prompt_active = 0; 0131 0132 /** 0133 * General purpose function to create an image from a string. 0134 * \param text the string to print 0135 * \param color the color the string should use in the image 0136 * \returns Image containg the text 0137 */ 0138 fun WriteText(text, color, font) { 0139 if (!color) { 0140 color = palette.text.normal; 0141 } 0142 if (!font) { 0143 font = defaults.font.default; 0144 } 0145 return Image.Text(text, color.red, color.green, color.blue, 1, font); 0146 } 0147 0148 /** Create regular text image. \see WriteText */ 0149 fun ImageToText (text, font) { 0150 return WriteText(text, color, font); 0151 } 0152 0153 String.ToImage = fun(color, font) { 0154 return WriteText(this, color, font); 0155 }; 0156 0157 /** Create tinted text image. \see WriteText */ 0158 fun ImageToTintedText (text) { 0159 return WriteText(text, palette.text.tinted); 0160 } 0161 0162 /** Create action text image. \see WriteText */ 0163 fun ImageToActionText (text) { 0164 return WriteText(text, palette.text.action); 0165 } 0166 0167 fun Debug(text) { 0168 debugsprite.SetImage(ImageToText (text)); 0169 debugsprite.SetPosition(0, 0, 1); 0170 } 0171 0172 fun DebugBottom(text) { 0173 debugsprite_bottom.SetImage(ImageToText(text)); 0174 debugsprite_bottom.SetPosition(0, (Window.GetHeight (0) - 20), 1); 0175 } 0176 0177 fun DebugMedium(text) { 0178 debugsprite_medium.SetImage(ImageToText (text)); 0179 debugsprite_medium.SetPosition(0, (Window.GetHeight (0) - 60), 1); 0180 } 0181 0182 /** 0183 * Debug helper to simulate something like a log on the right hand side of 0184 * the display. There is a global ActionStack which gets .Log("foo")'d into 0185 * which essentially prepends the string to an internal string buffer which 0186 * is then rendered into a sprite. 0187 * The buffer is not ever emptied so this basically is growing memory 0188 * consumption. And it's offset placing from the rigth side is also getting 0189 * increasingly wrong as the largest ever logged line dictates the offset. 0190 */ 0191 Logger = fun() { 0192 local.logger = []; 0193 local.logger.log = ""; 0194 local.logger.sprite = Sprite(); 0195 return logger | global.Logger; 0196 } | []; 0197 0198 Logger.Log = fun(text) { 0199 log = text + "\n" + log; 0200 Print(); 0201 }; 0202 0203 Logger.Print = fun() { 0204 sprite.SetImage(ImageToText(log)); 0205 sprite.SetPosition(Window.GetMaxWidth() - sprite.GetImage().GetWidth() - 16, 0, 1); 0206 }; 0207 global.logger = Logger(); 0208 0209 /** 0210 * Calulates the Y of the label "box". That is, the top most point at which 0211 * we should put elements that are meant to go below the logo/spinner/whatevs 0212 * as to not overlap with the aforementioned. This includes message display, 0213 * password prompt and so forth. 0214 */ 0215 fun TextYOffset() { 0216 // Put the 1st line below the logo. 0217 local.y = spin.GetY() + spin.GetHeight(); 0218 local.text_height = first_line_height * 7.5; 0219 // The maximum Y we may end at, if we exceed this we'll try to scoot up 0220 // a bit. This includes the Window offset itself as we position ourselves 0221 // relative to the Spinner which is relative to the Logo which is relative 0222 // to the center of the window TAKING INTO ACCOUNT the y offset of the 0223 // window! 0224 local.max_y = Window.GetHeight() + Window.GetY(); 0225 0226 if (y + text_height > max_y) { 0227 y = max_y - text_height; 0228 } else { 0229 y = y + ((max_y - y - text_height) / 2); 0230 } 0231 0232 // This basically undoes whatever went on above, to a degree... 0233 // If the y would overlap with the Spinner (bottom most element of the 0234 // static cruft) we move it further down so that at least half a line of 0235 // space is between the spinner and our y. 0236 if (y < spin.GetY() + spin.GetHeight() + first_line_height / 2) { 0237 y = spin.GetY() + spin.GetHeight() + first_line_height / 2; 0238 } 0239 0240 return y; 0241 } 0242 0243 Window.GetMaxWidth = fun() { 0244 width = 0; 0245 for (i = 0; Window.GetWidth(i); i++) { 0246 width = Math.Max(width, Window.GetWidth(i)); 0247 } 0248 return width; 0249 }; 0250 0251 Window.GetMaxHeight = fun() { 0252 height = 0; 0253 for (i = 0; Window.GetHeight(i); i++) { 0254 height = Math.Max(height, Window.GetHeight(i)); 0255 } 0256 return height; 0257 }; 0258 0259 // --------------------------------- String --------------------------------- // 0260 # This is the equivalent for strstr() 0261 fun StringString(string, substring) { 0262 start = 0; 0263 while (String(string).CharAt (start)) { 0264 walk = 0; 0265 while (String(substring).CharAt (walk) == String(string).CharAt (start + walk) ) { 0266 walk++; 0267 if (!String(substring).CharAt (walk)) return start; 0268 } 0269 start++; 0270 } 0271 0272 return NULL; 0273 } 0274 0275 fun StringLength (string) { 0276 index = 0; 0277 while (String(string).CharAt(index)) 0278 index++; 0279 return index; 0280 } 0281 0282 // String.Length = fun(string) { 0283 // index = 0; 0284 // while (String(string).CharAt(index)) 0285 // index++; 0286 // return index; 0287 // }; 0288 0289 fun StringCopy (source, beginning, end) { 0290 local.destination = ""; 0291 for (index = beginning; 0292 (((end == NULL) || (index <= end) ) && (String(source).CharAt(index))); 0293 index++) { 0294 local.destination += String(source).CharAt(index); 0295 } 0296 0297 return local.destination; 0298 } 0299 0300 fun StringReplace (source, pattern, replacement) { 0301 local.found = StringString(source, pattern); 0302 if (local.found == NULL) { 0303 return source; 0304 } 0305 0306 local.new_string = StringCopy (source, 0, local.found - 1) + 0307 replacement + 0308 StringCopy (source, local.found + StringLength(pattern), NULL); 0309 0310 return local.new_string; 0311 } 0312 0313 # it makes sense to use it only for 0314 # numbers up to 100 0315 fun StringToInteger (str) { 0316 int = -1; 0317 for (i=0; i<=100; i++) { 0318 if (i+"" == str) { 0319 int = i; 0320 break; 0321 } 0322 } 0323 return int; 0324 } 0325 0326 // ------------------------------ Background -------------------------------- // 0327 Window.ApplyBackgroundColors(); 0328 global.backgroundApplied = false; 0329 0330 // --------------------------------- Logo ----------------------------------- // 0331 0332 Logo = fun() { 0333 local.logo = SpriteImage(assets.logo); 0334 logo.x = Window.GetX() + Window.GetWidth() / 2 - logo.width / 2; 0335 logo.y = Window.GetY() + Window.GetHeight() / 2 - logo.height / 2; 0336 logo.z = 1000; 0337 logo.SetPosition(logo.x, logo.y, logo.z); 0338 0339 logo.name = Sprite(title.text.ToImage(NULL, defaults.font.title)); 0340 logo.name.x = Window.GetX() + Window.GetWidth() / 2 - logo.name.GetImage().GetWidth() / 2; 0341 logo.name.y = logo.y + logo.height + logo.name.GetImage().GetHeight() / 2; 0342 logo.name.z = logo.z; 0343 logo.name.SetPosition(logo.name.x, logo.name.y, logo.z); 0344 0345 logo.height = logo.height + logo.name.GetImage().GetHeight() ; 0346 0347 return logo | global.Logo; 0348 } | SpriteImage; 0349 0350 Logo.SetOpacity_ = fun(o) { 0351 o = Math.Clamp(o, 0.0, 1.0); 0352 this.SetOpacity(o); 0353 this.name.SetOpacity(o); 0354 }; 0355 0356 logo = Logo(); 0357 logo.SetOpacity_(0); 0358 0359 0360 // ----------------------------- Busy Animation ----------------------------- // 0361 0362 Spinner = fun() { 0363 // FIXME: try to use this= 0364 spinner = global.Spinner | []; 0365 spinner.count = 360; 0366 spinner.current_idx = 0; 0367 spinner.last_time = 0; 0368 spinner.steps = 10.0; // We render degrees in increments of 10 to save disk. 0369 spinner.duration = 1.5; // Seconds per rotation. 0370 for (i = 0; i <= spinner.count; ++i) { 0371 if (i % spinner.steps != 0) { 0372 continue; 0373 } 0374 spinner[i] = SpriteImage(assets.spinner_base + "/spinner" + i + ".png"); 0375 center_offset = (logo.width / 2) - (spinner[i].width / 2); 0376 top_offset = logo.height + spinner[i].height; 0377 spinner[i].SetPosition(logo.GetX() + center_offset, logo.GetY() + top_offset, logo.GetZ()); 0378 spinner[i].SetOpacity(0); 0379 } 0380 return spinner; 0381 } | []; 0382 0383 Spinner.Animate = fun(time) { 0384 degrees = Math.Int(((2 * Math.Pi / duration) * time) * (180 / Math.Pi)); 0385 new = degrees % count; 0386 old = current_idx; 0387 if (Math.Int(new) < Math.Int((old + steps) % count)) { 0388 // Every $steps degrees we can render a frame, all others we skip. 0389 return; 0390 } 0391 // We set a second new which is now a correct index bump by coercing it 0392 // into a multiple of 10. 0393 new = Math.Int(new / steps) * steps; 0394 // Debug("going from " + old + " to " + new); 0395 // dps = time - last_time; 0396 // DebugMedium("dps " + dps*35); 0397 // last_time = time; 0398 this[old].SetOpacity(0); 0399 this[new].SetOpacity(1); 0400 current_idx = new; 0401 return this; 0402 }; 0403 0404 Spinner.GetY = fun() { 0405 return this[0].GetY(); 0406 }; 0407 0408 Spinner.GetHeight = fun() { 0409 return this[0].height; 0410 }; 0411 0412 global.spin = Spinner(); 0413 0414 // ---------------------------- State & Spacing ----------------------------- // 0415 0416 message_notification[0].image = ImageToTintedText (""); 0417 message_notification[1].image = ImageToTintedText (""); 0418 fsck_notification.image = ImageToActionText (""); 0419 0420 status = "normal"; 0421 0422 // use a fixed string with ascending and descending stems to calibrate the 0423 // bounding box for the first message, so the messages below don't move up 0424 // and down according to *their* height. 0425 first_line_height = ImageToTintedText ("AfpqtM").GetHeight(); 0426 0427 // if the user has a 640x480 or 800x600 display, we can't quite fit everything 0428 // (including passphrase prompts) with the target spacing, so scoot the text up 0429 // a bit if needed. 0430 top_of_the_text = TextYOffset(); 0431 0432 // ----------------------------- Boot Progress ------------------------------ // 0433 0434 /** 0435 * Implement boot progress callback 0436 * \param time time elapsed since boot start (real, seconds) 0437 * \param progress boot progress in % (real 0.0 to 1.0) 0438 */ 0439 fun boot_progress_cb(time, progress) { 0440 spin.Animate(time); 0441 logo.SetOpacity_(time * 2.0); 0442 } 0443 Plymouth.SetBootProgressFunction (boot_progress_cb); 0444 0445 #-----------------------------------------Label utility functions--------------------- 0446 0447 # label should be either a string or NULL 0448 # Images for n lines will be created and returned as items of the 0449 # message_label array 0450 # 0451 fun get_message_label (label, is_fake, is_action_line) { 0452 # Debug("Get Label position"); 0453 0454 if (is_fake) 0455 # Create a fake label so as to get the y coordinate of 0456 # a standard-length label. 0457 local.message_image = ImageToTintedText ("This is a fake message"); 0458 else 0459 local.message_image = (is_action_line) && ImageToActionText (label) || ImageToTintedText (label); 0460 0461 local.message_label = []; 0462 message_label.width = message_image.GetWidth (); 0463 message_label.height = message_image.GetHeight (); 0464 0465 # Center the line horizontally 0466 message_label.x = Window.GetX () + Window.GetWidth () / 2 - message_label.width / 2; 0467 0468 message_label.y = top_of_the_text + first_line_height/2; 0469 0470 # Put the 2nd line below the fsck line 0471 if (is_action_line) { 0472 local.fsck_label.y = message_label.y + (first_line_height + first_line_height / 2); 0473 message_label.y = local.fsck_label.y + (first_line_height * 2); 0474 } 0475 0476 # Debug("action label x = " + message_label.x + " y = " + message_label.y ); 0477 0478 # message_debug = "msg_x = " + message_label.x + " msg_y = " + message_label.y + 0479 # "msg_width = " + message_label.width + " msg_height = " + 0480 # message_label.height + " message = " + label; 0481 # Debug(message_debug); 0482 0483 return message_label; 0484 0485 } 0486 0487 # Create an fsck label and/or get its position 0488 fun get_fsck_label (label, is_fake) { 0489 # Debug("Get Label position"); 0490 local.fsck_label = global.progress_label; 0491 0492 if (is_fake) 0493 fsck_label.image = ImageToTintedText ("This is a fake message"); 0494 else 0495 fsck_label.image = ImageToTintedText (label); 0496 0497 fsck_label.width = fsck_label.image.GetWidth (); 0498 fsck_label.height = fsck_label.image.GetHeight (); 0499 0500 # Centre the label horizontally 0501 fsck_label.x = Window.GetX () + Window.GetWidth () / 2 - fsck_label.width / 2; 0502 0503 local.first_label = get_message_label (label, 1, 0); 0504 0505 # Place the label below the 1st message line 0506 fsck_label.y = local.first_label.y + local.first_label.height + first_line_height / 2; 0507 0508 # message_debug = "msg_x = " + fsck_label.x + " msg_y = " + fsck_label.y + 0509 # "msg_width = " + fsck_label.width + " msg_height = " + 0510 # fsck_label.height + " message = " + label; 0511 # Debug(message_debug); 0512 0513 return fsck_label; 0514 } 0515 0516 #-----------------------------------------Message stuff -------------------------------- 0517 # 0518 0519 # Set up a message label 0520 # 0521 # NOTE: this is called when doing something like 'plymouth message "hello world"' 0522 # 0523 fun setup_message (message_text, x, y, z, index) { 0524 # Debug("Message setup"); 0525 global.message_notification[index].image = 0526 (index) && ImageToActionText (message_text) || ImageToTintedText (message_text); 0527 0528 # Set up the text message, if any 0529 message_notification[index].x = x; 0530 message_notification[index].y = y; 0531 message_notification[index].z = z; 0532 0533 message_notification[index].sprite = Sprite (); 0534 message_notification[index].sprite.SetImage (message_notification[index].image); 0535 message_notification[index].sprite.SetX (message_notification[index].x); 0536 message_notification[index].sprite.SetY (message_notification[index].y); 0537 message_notification[index].sprite.SetZ (message_notification[index].z); 0538 0539 } 0540 0541 fun show_message (index) { 0542 if (global.message_notification[index].sprite) global.message_notification[index].sprite.SetOpacity(1); 0543 } 0544 0545 fun hide_message (index) { 0546 if (global.message_notification[index].sprite) global.message_notification[index].sprite.SetOpacity(0); 0547 } 0548 0549 # the callback function is called when new message should be displayed. 0550 # First arg is message to display. 0551 fun message_callback (message) 0552 { 0553 // DebugMedium("Message callback " + message); 0554 is_fake = 0; 0555 if (!message || (message == "")) is_fake = 1; 0556 0557 local.substring = "keys:"; 0558 0559 # Look for the "keys:" prefix 0560 local.keys = StringString(message, local.substring); 0561 0562 local.is_action_line = (keys != NULL); 0563 #Debug("keys " + local.keys + " substring length = " + StringLength(local.substring); 0564 0565 # Get the message without the "keys:" prefix 0566 if (keys != NULL) 0567 message = StringCopy (message, keys + StringLength(local.substring), NULL); 0568 0569 // Get the message without the "fsckd-cancel-msg" prefix as we don't support i18n 0570 substring = "fsckd-cancel-msg:"; 0571 keys = StringString(message, substring); 0572 if (keys != NULL) 0573 message = StringCopy(message, keys + StringLength(substring), NULL); 0574 0575 local.label.is_fake = is_fake; 0576 label = get_message_label(message, is_fake, is_action_line); 0577 label.z = 10000; 0578 0579 setup_message (message, label.x, label.y, label.z, is_action_line); 0580 if (prompt_active && local.is_action_line) 0581 hide_message (is_action_line); 0582 else 0583 show_message (is_action_line); 0584 } 0585 Plymouth.SetMessageFunction (message_callback); 0586 0587 0588 #-----------------------------------------Display Password stuff ----------------------- 0589 # 0590 0591 fun password_dialog_setup (message_label) { 0592 # Debug("Password dialog setup"); 0593 0594 local.bullet_image = WriteText("•", palette.text.contrast); 0595 local.entry = []; 0596 entry.image = Image (assets.text_input); 0597 0598 # Hide the normal labels 0599 prompt_active = 1; 0600 if (message_notification[1].sprite) hide_message (1); 0601 0602 # Set the prompt label 0603 label = get_message_label(message_label, 0, 1); 0604 label.z = 10000; 0605 0606 setup_message (message_label, label.x, label.y, label.z, 2); 0607 show_message (2); 0608 0609 # Set up the text entry which contains the bullets 0610 entry.sprite = Sprite (); 0611 entry.sprite.SetImage (entry.image); 0612 0613 # Centre the box horizontally 0614 entry.x = Window.GetX () + Window.GetWidth () / 2 - entry.image.GetWidth () / 2; 0615 0616 # Put the entry below the second label. 0617 entry.y = message_notification[2].y + label.height + entry.image.GetHeight() / 2; 0618 0619 #Debug ("entry x = " + entry.x + ", y = " + entry.y); 0620 entry.z = 10000; 0621 entry.sprite.SetX (entry.x); 0622 entry.sprite.SetY (entry.y); 0623 entry.sprite.SetZ (entry.z); 0624 0625 global.password_dialog = local; 0626 } 0627 0628 fun password_dialog_opacity (opacity) { 0629 # Debug("Password dialog opacity"); 0630 global.password_dialog.opacity = opacity; 0631 local = global.password_dialog; 0632 0633 # You can make the box translucent with a float 0634 # entry.sprite.SetOpacity (0.3); 0635 entry.sprite.SetOpacity (opacity); 0636 label.sprite.SetOpacity (opacity); 0637 0638 if (bullets) { 0639 for (index = 0; bullets[index]; index++) { 0640 bullets[index].sprite.SetOpacity (opacity); 0641 } 0642 } 0643 } 0644 0645 0646 # The callback function is called when the display should display a password dialog. 0647 # First arg is prompt string, the second is the number of bullets. 0648 fun display_password_callback (prompt, bullets) { 0649 global.status = "password"; 0650 if (!global.password_dialog) 0651 password_dialog_setup(prompt); 0652 password_dialog_opacity (1); 0653 bullet_width = password_dialog.bullet_image.GetWidth(); 0654 bullet_y = password_dialog.entry.y + 0655 password_dialog.entry.image.GetHeight () / 2 - 0656 password_dialog.bullet_image.GetHeight () / 2; 0657 margin = bullet_width; 0658 spaces = Math.Int((password_dialog.entry.image.GetWidth () - (margin * 2)) / bullet_width); 0659 bullets_area.width = (margin * 2) + (spaces * bullet_width); 0660 bullets_area.x = Window.GetX () + Window.GetWidth () / 2 - bullets_area.width / 2; 0661 if (bullets > spaces) 0662 bullets = spaces; 0663 for (index = 0; password_dialog.bullets[index] || index < bullets; index++){ 0664 if (!password_dialog.bullets[index]) { 0665 password_dialog.bullets[index].sprite = Sprite(); 0666 password_dialog.bullets[index].sprite.SetImage (password_dialog.bullet_image); 0667 password_dialog.bullets[index].x = bullets_area.x + margin + index * bullet_width; 0668 password_dialog.bullets[index].sprite.SetX (password_dialog.bullets[index].x); 0669 password_dialog.bullets[index].y = bullet_y; 0670 password_dialog.bullets[index].sprite.SetY (password_dialog.bullets[index].y); 0671 password_dialog.bullets[index].z = password_dialog.entry.z + 1; 0672 password_dialog.bullets[index].sprite.SetZ (password_dialog.bullets[index].z); 0673 } 0674 0675 password_dialog.bullets[index].sprite.SetOpacity (0); 0676 0677 if (index < bullets) { 0678 password_dialog.bullets[index].sprite.SetOpacity (1); 0679 } 0680 } 0681 } 0682 Plymouth.SetDisplayPasswordFunction(display_password_callback); 0683 0684 #----------------------------------------- FSCK Counter -------------------------------- 0685 0686 # Initialise the counter 0687 fun init_fsck_count () { 0688 # The number of fsck checks in this cycle 0689 global.counter.total = 0; 0690 # The number of fsck checks already performed + the current one 0691 global.counter.current = 1; 0692 # The previous fsck 0693 global.counter.last = 0; 0694 } 0695 0696 # Increase the total counter 0697 fun increase_fsck_count () { 0698 global.counter.total++; 0699 } 0700 0701 fun increase_current_fsck_count () { 0702 global.counter.last = global.counter.current++; 0703 } 0704 0705 # Clear the counter 0706 fun clear_fsck_count () { 0707 global.counter = NULL; 0708 init_fsck_count (); 0709 } 0710 0711 // ----------------------------------------- Progress Label ------------------------------ 0712 0713 0714 # Change the opacity level of a progress label 0715 # 0716 # opacity = 1 -> show 0717 # opacity = 0 -> hide 0718 # opacity = 0.3 (or any other float) -> translucent 0719 # 0720 fun set_progress_label_opacity (opacity) { 0721 # the label 0722 progress_label.sprite.SetOpacity (opacity); 0723 0724 # Make the slot available again when hiding the bar 0725 # So that another bar can take its place 0726 if (opacity == 0) { 0727 progress_label.is_available = 1; 0728 progress_label.device = ""; 0729 } 0730 } 0731 0732 # Set up a new Progress Bar 0733 # 0734 # TODO: Make it possible to reuse (rather than recreate) a bar 0735 # if .is_available = 1. Ideally this would just reset the 0736 # label, the associated 0737 # device and the image size of the sprite. 0738 0739 fun init_progress_label (device, status_string) { 0740 # Make the slot unavailable 0741 global.progress_label.is_available = 0; 0742 progress_label.progress = 0; 0743 progress_label.device = device; 0744 progress_label.status_string = status_string; 0745 } 0746 0747 # See if the progress label is keeping track of the fsck 0748 # of "device" 0749 # 0750 fun device_has_progress_label (device) { 0751 #DebugBottom ("label device = " + progress_label.device + " checking device " + device); 0752 return (progress_label.device == device); 0753 } 0754 0755 # Update the Progress bar which corresponds to index 0756 # 0757 fun update_progress_label (progress) { 0758 # If progress is NULL then we just refresh the label. 0759 # This happens when only counter.total has changed. 0760 if (progress != NULL) { 0761 progress_label.progress = progress; 0762 0763 #Debug("device " + progress_label.device + " progress " + progress); 0764 0765 # If progress >= 100% hide the label and make it available again 0766 if (progress >= 100) { 0767 set_progress_label_opacity (0); 0768 0769 # See if we any other fsck check is complete 0770 # and, if so, hide the progress bars and the labels 0771 on_fsck_completed (); 0772 0773 return 0; 0774 } 0775 } 0776 # Update progress label here 0777 # 0778 # FIXME: the queue logic from this theme should really be moved into mountall 0779 # instead of using string replacement to deal with localised strings. 0780 label = StringReplace (progress_label.status_string[0], "%1$d", global.counter.current); 0781 label = StringReplace (label, "%2$d", global.counter.total); 0782 label = StringReplace (label, "%3$d", progress_label.progress); 0783 label = StringReplace (label, "%%", "%"); 0784 0785 progress_label = get_fsck_label (label, 0); 0786 #progress_label.progress = progress; 0787 0788 progress_label.sprite = Sprite (progress_label.image); 0789 0790 # Set up the bar 0791 progress_label.sprite.SetPosition(progress_label.x, progress_label.y, 1); 0792 0793 set_progress_label_opacity (1); 0794 0795 } 0796 0797 # Refresh the label so as to update counters 0798 fun refresh_progress_label () { 0799 update_progress_label (NULL); 0800 } 0801 0802 #----------------------------------------- FSCK Queue ---------------------------------- 0803 0804 # Initialise the fsck queue 0805 fun init_queue () { 0806 global.fsck_queue[0].device; 0807 global.fsck_queue[0].progress; 0808 global.fsck_queue.counter = 0; 0809 global.fsck_queue.biggest_item = 0; 0810 } 0811 0812 fun clear_queue () { 0813 global.fsck_queue = NULL; 0814 init_queue (); 0815 } 0816 0817 # Return either the device index in the queue or -1 0818 fun queue_look_up_by_device (device) { 0819 for (i=0; i <= fsck_queue.biggest_item; i++) { 0820 if ((fsck_queue[i]) && (fsck_queue[i].device == device)) 0821 return i; 0822 } 0823 return -1; 0824 } 0825 0826 # Keep track of an fsck process in the queue 0827 fun add_fsck_to_queue (device, progress) { 0828 # Look for an empty slot in the queue 0829 for (i=0; global.fsck_queue[i].device; i++) { 0830 continue; 0831 } 0832 local.index = i; 0833 0834 # Set device and progress 0835 global.fsck_queue[local.index].device = device; 0836 global.fsck_queue[local.index].progress = progress; 0837 0838 # Increase the queue counter 0839 global.fsck_queue.counter++; 0840 0841 # Update the max index of the array for iterations 0842 if (local.index > global.fsck_queue.biggest_item) 0843 global.fsck_queue.biggest_item = local.index; 0844 0845 #DebugMedium ("Adding " + device + " at " + local.index); 0846 } 0847 0848 fun is_queue_empty () { 0849 return (fsck_queue.counter == 0); 0850 } 0851 0852 fun is_progress_label_available () { 0853 return (progress_label.is_available == 1); 0854 } 0855 0856 0857 # This should cover the case in which the fsck checks in 0858 # the queue are completed before the ones showed in the 0859 # progress label 0860 fun on_queued_fsck_completed () { 0861 if (!is_queue_empty ()) 0862 return; 0863 0864 # Hide the extra label, if any 0865 #if (progress_bar.extra_label.sprite) 0866 # progress_bar.extra_label.sprite.SetOpacity(0); 0867 } 0868 0869 fun remove_fsck_from_queue (index) { 0870 # Free memory which was previously allocated for 0871 # device and progress 0872 global.fsck_queue[index].device = NULL; 0873 global.fsck_queue[index].progress = NULL; 0874 0875 # Decrease the queue counter 0876 global.fsck_queue.counter--; 0877 0878 # See if there are other processes in the queue 0879 # if not, clear the extra_label 0880 on_queued_fsck_completed (); 0881 } 0882 0883 fun on_fsck_completed () { 0884 # We have moved on to tracking the next fsck 0885 increase_current_fsck_count (); 0886 0887 if (!is_progress_label_available ()) 0888 return; 0889 0890 if (!is_queue_empty ()) 0891 return; 0892 0893 # Hide the progress label 0894 if (progress_label.sprite) 0895 progress_label.sprite.SetOpacity (0); 0896 0897 # Clear the queue 0898 clear_queue (); 0899 0900 # Clear the fsck counter 0901 clear_fsck_count (); 0902 } 0903 0904 # Update an fsck process that we keep track of in the queue 0905 fun update_progress_in_queue (index, device, progress) { 0906 # If the fsck is complete, remove it from the queue 0907 if (progress >= 100) { 0908 remove_fsck_from_queue (index); 0909 on_queued_fsck_completed (); 0910 return; 0911 } 0912 0913 global.fsck_queue[index].device = device; 0914 global.fsck_queue[index].progress = progress; 0915 0916 } 0917 0918 # TODO: Move it to some function 0919 # Create an empty queue 0920 #init_queue (); 0921 0922 0923 #----------------------------------------- FSCK Functions ------------------------------ 0924 0925 0926 # Either add a new bar for fsck checks or update an existing bar 0927 # 0928 # NOTE: no more than "progress_bar.max_number" bars are allowed 0929 # 0930 fun fsck_check (device, progress, status_string) { 0931 0932 # The 1st time this will take place 0933 if (!global.progress_label) { 0934 # Increase the fsck counter 0935 increase_fsck_count (); 0936 0937 # Set up a new label for the check 0938 init_progress_label (device, status_string); 0939 update_progress_label (progress); 0940 0941 return; 0942 } 0943 0944 0945 if (device_has_progress_label (device)) { 0946 // Update the progress of the existing label 0947 update_progress_label (progress); 0948 } 0949 else { 0950 // See if there's already a slot in the queue for the device 0951 local.queue_device_index = queue_look_up_by_device(device); 0952 0953 // See if the progress_label is available 0954 if (progress_label.is_available) { 0955 # If the fsck check for the device was in the queue, then 0956 # remove it from the queue 0957 if (local.queue_device_index >= 0) { 0958 remove_fsck_from_queue (index); 0959 } 0960 else { 0961 # Increase the fsck counter 0962 increase_fsck_count (); 0963 } 0964 0965 // Set up a new label for the check 0966 init_progress_label (device, status_string); 0967 update_progress_label (progress); 0968 0969 } 0970 # If the progress_label is not available 0971 else { 0972 0973 # If the fsck check for the device is already in the queue 0974 # just update its progress in the queue 0975 if (local.queue_device_index >= 0) { 0976 #DebugMedium("Updating queue at " + local.queue_device_index + " for device " + device); 0977 update_progress_in_queue (local.queue_device_index, device, progress); 0978 } 0979 # Otherwise add the check to the queue 0980 else { 0981 #DebugMedium("Adding device " + device + " to queue at " + local.queue_device_index); 0982 add_fsck_to_queue (device, progress); 0983 0984 # Increase the fsck counter 0985 increase_fsck_count (); 0986 0987 refresh_progress_label (); 0988 } 0989 0990 } 0991 } 0992 } 0993 0994 0995 #-----------------------------------------Update Status stuff -------------------------- 0996 # 0997 # The update_status_callback is what we can use to pass plymouth whatever we want so 0998 # as to make use of features which are available only in this program (as opposed to 0999 # being available for any theme for the script plugin). 1000 # 1001 # Example: 1002 # 1003 # Thanks to the current implementation, some scripts can call "plymouth --update=fsck:sda1:40" 1004 # and this program will know that 1) we're performing and fsck check, 2) we're checking sda1, 1005 # 3) the program should set the label progress to 40% 1006 # 1007 # Other features can be easily added by parsing the string that we pass plymouth with "--update" 1008 # 1009 fun update_status_callback (status) { 1010 // Debug(" STATUS:" + status); 1011 if (!status) return; 1012 1013 string_it = 0; 1014 update_strings[string_it] = ""; 1015 1016 for (i=0; (String(status).CharAt(i) != ""); i++) { 1017 local.temp_char = String(status).CharAt(i); 1018 if (temp_char != ":") 1019 update_strings[string_it] += temp_char; 1020 else 1021 update_strings[++string_it] = ""; 1022 } 1023 1024 // Let's assume that we're dealing with these strings fsck:sda1:40 1025 if ((string_it >= 2) && (update_strings[0] == "fsck")) { 1026 1027 device = update_strings[1]; 1028 progress = update_strings[2]; 1029 status_string[0] = update_strings[3]; # "Checking disk %1$d of %2$d (%3$d %% complete)" 1030 if (!status_string[0]) 1031 status_string[0] = "Checking disk %1$d of %2$d (%3$d %% complete)"; 1032 1033 if ((device != "") && (progress != "")) { 1034 progress = StringToInteger (progress); 1035 1036 # Make sure that the fsck_queue is initialised 1037 if (!global.fsck_queue) 1038 init_queue (); 1039 1040 # Make sure that the fsck counter is initialised 1041 if (!global.counter) 1042 init_fsck_count (); 1043 1044 # if (!global.progress_bar.extra_label.sprite) 1045 # create_extra_fsck_label (); 1046 1047 # Keep track of the fsck check 1048 fsck_check (device, progress, status_string); 1049 } 1050 1051 } 1052 1053 # systemd-fsckd pass fsckd:<number_devices>:<progress>:<l10n_string> 1054 if (update_strings[0] == "fsckd") { 1055 number_devices = StringToInteger(update_strings[1]); 1056 1057 if (number_devices > 0) { 1058 label = update_strings[3]; 1059 1060 progress_label = get_fsck_label (label, 0); 1061 progress_label.sprite = Sprite (progress_label.image); 1062 progress_label.sprite.SetPosition(progress_label.x, progress_label.y, 1); 1063 progress_label.sprite.SetOpacity (1); 1064 } else { 1065 if (progress_label.sprite) 1066 progress_label.sprite.SetOpacity (0); 1067 } 1068 } 1069 1070 } 1071 Plymouth.SetUpdateStatusFunction (update_status_callback); 1072 1073 /** 1074 * Calling Plymouth.SetRefreshFunction with a function will set that function to be 1075 * called up to 50 times every second, e.g. 1076 * 1077 * NOTE: if a refresh function is not set, Plymouth doesn't seem to be able to update 1078 * the screen correctly 1079 */ 1080 fun refresh_callback() { 1081 // With some nvidia systems when using the script theme the initial 1082 // background drawing happens too soon, so we do an additional "fallback" 1083 // draw run when the first refresh callback arrives. This should make sure 1084 // that we always have a background drawn. 1085 if (!global.backgroundApplied) { 1086 global.backgroundApplied = true; 1087 Window.ApplyBackgroundColors(); 1088 } 1089 } 1090 Plymouth.SetRefreshFunction(refresh_callback); 1091 1092 /** 1093 * The callback function is called when the display should return to normal 1094 */ 1095 fun display_normal_callback() { 1096 global.status = "normal"; 1097 if (global.password_dialog) { 1098 password_dialog_opacity (0); 1099 global.password_dialog = NULL; 1100 if (message_notification[2].sprite) hide_message(2); 1101 prompt_active = 0; 1102 } 1103 1104 if (message_notification[1].sprite) 1105 show_message (1); 1106 } 1107 Plymouth.SetDisplayNormalFunction (display_normal_callback); 1108 1109 /** 1110 * Switch to final state. 1111 */ 1112 fun quit_callback() { 1113 logo.SetOpacity_(0); 1114 } 1115 Plymouth.SetQuitFunction(quit_callback); 1116 1117 // kate: space-indent on; indent-width 2; mixedindent off; indent-mode cstyle; hl JavaScript;